Compare commits

..

No commits in common. "6f231a7980dd22f686c04d86fb79e1885ad31f6a" and "dc5f2cf5906ec2f87ad47ea4724cc245c401eef6" have entirely different histories.

33 changed files with 649 additions and 344 deletions

File diff suppressed because one or more lines are too long

View File

@ -950,7 +950,7 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
if c.IsSet("auth-type") {
conf.Auth = c.String("auth-type")
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
if !contains(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
}
conf.Auth = c.String("auth-type")

View File

@ -409,6 +409,15 @@ func runDump(ctx *cli.Context) error {
return nil
}
func contains(slice []string, s string) bool {
for _, v := range slice {
if v == s {
return true
}
}
return false
}
// addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath
func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error {
absPath, err := filepath.Abs(absPath)
@ -429,7 +438,7 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA
currentAbsPath := path.Join(absPath, file.Name())
currentInsidePath := path.Join(insidePath, file.Name())
if file.IsDir() {
if !util.SliceContainsString(excludeAbsPath, currentAbsPath) {
if !contains(excludeAbsPath, currentAbsPath) {
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
return err
}

57
go.mod
View File

@ -23,6 +23,7 @@ require (
github.com/denisenkom/go-mssqldb v0.12.2
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
github.com/duo-labs/webauthn v0.0.0-20220815211337-00c9fb5711f5
github.com/dustin/go-humanize v1.0.0
github.com/editorconfig/editorconfig-core-go/v2 v2.4.5
github.com/emirpasic/gods v1.18.1
@ -43,12 +44,11 @@ require (
github.com/go-sql-driver/mysql v1.6.0
github.com/go-swagger/go-swagger v0.30.3
github.com/go-testfixtures/testfixtures/v3 v3.8.1
github.com/go-webauthn/webauthn v0.6.0
github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/golang-jwt/jwt/v4 v4.4.2
github.com/google/go-github/v45 v45.2.0
github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40
github.com/google/uuid v1.3.0
@ -82,7 +82,7 @@ require (
github.com/santhosh-tekuri/jsonschema/v5 v5.0.1
github.com/sergi/go-diff v1.2.0
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
github.com/stretchr/testify v1.8.1
github.com/stretchr/testify v1.8.0
github.com/syndtr/goleveldb v1.0.0
github.com/tstranex/u2f v1.0.0
github.com/unrolled/render v1.5.0
@ -95,11 +95,11 @@ require (
github.com/yuin/goldmark-meta v1.1.0
go.jolheiser.com/hcaptcha v0.0.4
go.jolheiser.com/pwn v0.0.3
golang.org/x/crypto v0.4.0
golang.org/x/net v0.3.0
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891
golang.org/x/net v0.2.0
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
golang.org/x/sys v0.3.0
golang.org/x/text v0.5.0
golang.org/x/sys v0.2.0
golang.org/x/text v0.4.0
golang.org/x/tools v0.1.12
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
@ -127,6 +127,7 @@ require (
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/bits-and-blooms/bitset v1.3.3 // indirect
github.com/blevesearch/bleve_index_api v1.0.4 // indirect
github.com/blevesearch/geo v0.1.15 // indirect
@ -145,8 +146,14 @@ require (
github.com/blevesearch/zapx/v15 v15.3.6 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cloudflare/cfssl v1.6.1 // indirect
github.com/cloudflare/circl v1.2.0 // indirect
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
github.com/couchbase/gomemcached v0.1.2 // indirect
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 // indirect
@ -155,7 +162,11 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/fullstorydev/grpcurl v1.8.1 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-ap/errors v0.0.0-20220917143055-4283ea5dae18 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
@ -172,25 +183,35 @@ require (
github.com/go-openapi/strfmt v0.21.3 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-openapi/validate v0.22.0 // indirect
github.com/go-webauthn/revoke v0.1.6 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/certificate-transparency-go v1.1.2-0.20210511102531-373a877eec92 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.3.3 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/jhump/protoreflect v1.8.2 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
@ -230,13 +251,16 @@ require (
github.com/shopspring/decimal v1.2.0 // indirect
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/cobra v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.12.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/subosito/gotenv v1.3.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/toqueteos/webbrowser v1.2.0 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/unknwon/com v1.0.1 // indirect
@ -246,7 +270,18 @@ require (
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/api/v3 v3.5.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
go.etcd.io/etcd/client/v2 v2.305.4 // indirect
go.etcd.io/etcd/client/v3 v3.5.4 // indirect
go.etcd.io/etcd/etcdctl/v3 v3.5.0-alpha.0 // indirect
go.etcd.io/etcd/pkg/v3 v3.5.0-alpha.0 // indirect
go.etcd.io/etcd/raft/v3 v3.5.0-alpha.0 // indirect
go.etcd.io/etcd/server/v3 v3.5.0-alpha.0 // indirect
go.etcd.io/etcd/tests/v3 v3.5.0-alpha.0 // indirect
go.etcd.io/etcd/v3 v3.5.0-alpha.0 // indirect
go.mongodb.org/mongo-driver v1.10.1 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
@ -254,10 +289,14 @@ require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1

413
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -409,14 +409,14 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
sshKeySplit := strings.Split(v, " ")
if len(sshKeySplit) > 1 {
key := strings.Join(sshKeySplit[:2], " ")
if !util.SliceContainsString(providedKeys, key) {
if !util.ExistsInSlice(key, providedKeys) {
providedKeys = append(providedKeys, key)
}
}
}
// Check if Public Key sync is needed
if util.SliceSortedEqual(giteaKeys, providedKeys) {
if util.IsEqualSlice(giteaKeys, providedKeys) {
log.Trace("synchronizePublicKeys[%s]: Public Keys are already in sync for %s (Source:%v/DB:%v)", s.Name, usr.Name, len(providedKeys), len(giteaKeys))
return false
}
@ -425,7 +425,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
// Add new Public SSH Keys that doesn't already exist in DB
var newKeys []string
for _, key := range providedKeys {
if !util.SliceContainsString(giteaKeys, key) {
if !util.ExistsInSlice(key, giteaKeys) {
newKeys = append(newKeys, key)
}
}
@ -436,7 +436,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
// Mark keys from DB that no longer exist in the source for deletion
var giteaKeysToDelete []string
for _, giteaKey := range giteaKeys {
if !util.SliceContainsString(providedKeys, giteaKey) {
if !util.ExistsInSlice(giteaKey, providedKeys) {
log.Trace("synchronizePublicKeys[%s]: Marking Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey)
giteaKeysToDelete = append(giteaKeysToDelete, giteaKey)
}

View File

@ -69,13 +69,13 @@ func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool {
if ip != nil && ip.IsLoopback() {
// strip port
uri.Host = uri.Hostname()
if util.SliceContainsString(app.RedirectURIs, uri.String(), true) {
if util.IsStringInSlice(uri.String(), app.RedirectURIs, true) {
return true
}
}
}
}
return util.SliceContainsString(app.RedirectURIs, redirectURI, true)
return util.IsStringInSlice(redirectURI, app.RedirectURIs, true)
}
// Base32 characters, but lowercased.

View File

@ -12,7 +12,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/duo-labs/webauthn/webauthn"
"xorm.io/xorm"
)

View File

@ -9,7 +9,7 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/unittest"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/duo-labs/webauthn/webauthn"
"github.com/stretchr/testify/assert"
)

View File

@ -342,7 +342,7 @@ func IsProtectedBranch(ctx context.Context, repoID int64, branchName string) (bo
// updateApprovalWhitelist checks whether the user whitelist changed and returns a whitelist with
// the users from newWhitelist which have explicit read or write access to the repo.
func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
hasUsersChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist)
hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
if !hasUsersChanged {
return currentWhitelist, nil
}
@ -363,7 +363,7 @@ func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, c
// updateUserWhitelist checks whether the user whitelist changed and returns a whitelist with
// the users from newWhitelist which have write access to the repo.
func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
hasUsersChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist)
hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
if !hasUsersChanged {
return currentWhitelist, nil
}
@ -392,7 +392,7 @@ func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, curre
// updateTeamWhitelist checks whether the team whitelist changed and returns a whitelist with
// the teams from newWhitelist which have write access to the repo.
func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
hasTeamsChanged := !util.SliceSortedEqual(currentWhitelist, newWhitelist)
hasTeamsChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
if !hasTeamsChanged {
return currentWhitelist, nil
}
@ -404,7 +404,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre
whitelist = make([]int64, 0, len(teams))
for i := range teams {
if util.SliceContains(newWhitelist, teams[i].ID) {
if util.IsInt64InSlice(teams[i].ID, newWhitelist) {
whitelist = append(whitelist, teams[i].ID)
}
}

View File

@ -155,7 +155,7 @@ func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multi
var requestAssignees []string
// Keeping the old assigning method for compatibility reasons
if oneAssignee != "" && !util.SliceContainsString(multipleAssignees, oneAssignee) {
if oneAssignee != "" && !util.IsStringInSlice(oneAssignee, multipleAssignees) {
requestAssignees = append(requestAssignees, oneAssignee)
}

View File

@ -1529,7 +1529,7 @@ func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool {
log.Error(err.Error())
return false
}
return util.SliceContains(userIDs, user.ID)
return util.IsInt64InSlice(user.ID, userIDs)
}
// UpdateIssueMentions updates issue-user relations for mentioned users.
@ -2023,7 +2023,7 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro
Find(&userIDs); err != nil {
return nil, fmt.Errorf("get poster IDs: %w", err)
}
if !util.SliceContains(userIDs, issue.PosterID) {
if !util.IsInt64InSlice(issue.PosterID, userIDs) {
return append(userIDs, issue.PosterID), nil
}
return userIDs, nil

View File

@ -398,13 +398,20 @@ func DeleteTeam(t *organization.Team) error {
return fmt.Errorf("findProtectedBranches: %w", err)
}
for _, p := range protections {
lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistTeamIDs), len(p.ApprovalsWhitelistTeamIDs), len(p.MergeWhitelistTeamIDs)
p.WhitelistTeamIDs = util.SliceRemoveAll(p.WhitelistTeamIDs, t.ID)
p.ApprovalsWhitelistTeamIDs = util.SliceRemoveAll(p.ApprovalsWhitelistTeamIDs, t.ID)
p.MergeWhitelistTeamIDs = util.SliceRemoveAll(p.MergeWhitelistTeamIDs, t.ID)
if lenIDs != len(p.WhitelistTeamIDs) ||
lenApprovalIDs != len(p.ApprovalsWhitelistTeamIDs) ||
lenMergeIDs != len(p.MergeWhitelistTeamIDs) {
var matched1, matched2, matched3 bool
if len(p.WhitelistTeamIDs) != 0 {
p.WhitelistTeamIDs, matched1 = util.RemoveIDFromList(
p.WhitelistTeamIDs, t.ID)
}
if len(p.ApprovalsWhitelistTeamIDs) != 0 {
p.ApprovalsWhitelistTeamIDs, matched2 = util.RemoveIDFromList(
p.ApprovalsWhitelistTeamIDs, t.ID)
}
if len(p.MergeWhitelistTeamIDs) != 0 {
p.MergeWhitelistTeamIDs, matched3 = util.RemoveIDFromList(
p.MergeWhitelistTeamIDs, t.ID)
}
if matched1 || matched2 || matched3 {
if _, err = sess.ID(p.ID).Cols(
"whitelist_team_i_ds",
"merge_whitelist_team_i_ds",

View File

@ -141,13 +141,20 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
break
}
for _, p := range protections {
lenIDs, lenApprovalIDs, lenMergeIDs := len(p.WhitelistUserIDs), len(p.ApprovalsWhitelistUserIDs), len(p.MergeWhitelistUserIDs)
p.WhitelistUserIDs = util.SliceRemoveAll(p.WhitelistUserIDs, u.ID)
p.ApprovalsWhitelistUserIDs = util.SliceRemoveAll(p.ApprovalsWhitelistUserIDs, u.ID)
p.MergeWhitelistUserIDs = util.SliceRemoveAll(p.MergeWhitelistUserIDs, u.ID)
if lenIDs != len(p.WhitelistUserIDs) ||
lenApprovalIDs != len(p.ApprovalsWhitelistUserIDs) ||
lenMergeIDs != len(p.MergeWhitelistUserIDs) {
var matched1, matched2, matched3 bool
if len(p.WhitelistUserIDs) != 0 {
p.WhitelistUserIDs, matched1 = util.RemoveIDFromList(
p.WhitelistUserIDs, u.ID)
}
if len(p.ApprovalsWhitelistUserIDs) != 0 {
p.ApprovalsWhitelistUserIDs, matched2 = util.RemoveIDFromList(
p.ApprovalsWhitelistUserIDs, u.ID)
}
if len(p.MergeWhitelistUserIDs) != 0 {
p.MergeWhitelistUserIDs, matched3 = util.RemoveIDFromList(
p.MergeWhitelistUserIDs, u.ID)
}
if matched1 || matched2 || matched3 {
if _, err = e.ID(p.ID).Cols(
"whitelist_user_i_ds",
"merge_whitelist_user_i_ds",

View File

@ -6,13 +6,14 @@ package webauthn
import (
"encoding/binary"
"encoding/gob"
"net/url"
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/webauthn"
)
// WebAuthn represents the global WebAuthn instance
@ -22,13 +23,13 @@ var WebAuthn *webauthn.WebAuthn
func Init() {
gob.Register(&webauthn.SessionData{})
appURL, _ := protocol.FullyQualifiedOrigin(setting.AppURL)
appURL, _ := url.Parse(setting.AppURL)
WebAuthn = &webauthn.WebAuthn{
Config: &webauthn.Config{
RPDisplayName: setting.AppName,
RPID: setting.Domain,
RPOrigin: appURL,
RPOrigin: protocol.FullyQualifiedOrigin(appURL),
AuthenticatorSelection: protocol.AuthenticatorSelection{
UserVerification: "discouraged",
},

View File

@ -170,7 +170,7 @@ func LoadRepoConfig() {
}
for _, f := range customFiles {
if !util.SliceContainsString(files, f, true) {
if !util.IsStringInSlice(f, files, true) {
files = append(files, f)
}
}
@ -200,12 +200,12 @@ func LoadRepoConfig() {
// Filter out invalid names and promote preferred licenses.
sortedLicenses := make([]string, 0, len(Licenses))
for _, name := range setting.Repository.PreferredLicenses {
if util.SliceContainsString(Licenses, name, true) {
if util.IsStringInSlice(name, Licenses, true) {
sortedLicenses = append(sortedLicenses, name)
}
}
for _, name := range Licenses {
if !util.SliceContainsString(setting.Repository.PreferredLicenses, name, true) {
if !util.IsStringInSlice(name, setting.Repository.PreferredLicenses, true) {
sortedLicenses = append(sortedLicenses, name)
}
}

View File

@ -12,7 +12,6 @@ import (
"code.gitea.io/gitea/modules/log"
shellquote "github.com/kballard/go-shellquote"
ini "gopkg.in/ini.v1"
)
// Mailer represents mail service.
@ -50,8 +49,8 @@ type Mailer struct {
// MailService the global mailer
var MailService *Mailer
func parseMailerConfig(rootCfg *ini.File) {
sec := rootCfg.Section("mailer")
func newMailService() {
sec := Cfg.Section("mailer")
// Check mailer setting.
if !sec.Key("ENABLED").MustBool() {
return
@ -71,14 +70,9 @@ func parseMailerConfig(rootCfg *ini.File) {
if sec.HasKey("HOST") && !sec.HasKey("SMTP_ADDR") {
givenHost := sec.Key("HOST").String()
addr, port, err := net.SplitHostPort(givenHost)
if err != nil && strings.Contains(err.Error(), "missing port in address") {
addr = givenHost
} else if err != nil {
if err != nil {
log.Fatal("Invalid mailer.HOST (%s): %v", givenHost, err)
}
if addr == "" {
addr = "127.0.0.1"
}
sec.Key("SMTP_ADDR").MustString(addr)
sec.Key("SMTP_PORT").MustString(port)
}
@ -178,9 +172,6 @@ func parseMailerConfig(rootCfg *ini.File) {
default:
log.Error("unable to infer unspecified mailer.PROTOCOL from mailer.SMTP_PORT = %q, assume using smtps", MailService.SMTPPort)
MailService.Protocol = "smtps"
if MailService.SMTPPort == "" {
MailService.SMTPPort = "465"
}
}
}
}

View File

@ -1,43 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"testing"
"github.com/stretchr/testify/assert"
ini "gopkg.in/ini.v1"
)
func TestParseMailerConfig(t *testing.T) {
iniFile := ini.Empty()
kases := map[string]*Mailer{
"smtp.mydomain.com": {
SMTPAddr: "smtp.mydomain.com",
SMTPPort: "465",
},
"smtp.mydomain.com:123": {
SMTPAddr: "smtp.mydomain.com",
SMTPPort: "123",
},
":123": {
SMTPAddr: "127.0.0.1",
SMTPPort: "123",
},
}
for host, kase := range kases {
t.Run(host, func(t *testing.T) {
iniFile.DeleteSection("mailer")
sec := iniFile.Section("mailer")
sec.NewKey("ENABLED", "true")
sec.NewKey("HOST", host)
// Check mailer setting
parseMailerConfig(iniFile)
assert.EqualValues(t, kase.SMTPAddr, MailService.SMTPAddr)
assert.EqualValues(t, kase.SMTPPort, MailService.SMTPPort)
})
}
}

View File

@ -1340,7 +1340,7 @@ func NewServices() {
newCacheService()
newSessionService()
newCORSService()
parseMailerConfig(Cfg)
newMailService()
newRegisterMailService()
newNotifyMailService()
newProxyService()
@ -1357,5 +1357,5 @@ func NewServices() {
// NewServicesForInstall initializes the services for install
func NewServicesForInstall() {
newService()
parseMailerConfig(Cfg)
newMailService()
}

92
modules/util/compare.go Normal file
View File

@ -0,0 +1,92 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package util
import (
"sort"
"strings"
)
// Int64Slice attaches the methods of Interface to []int64, sorting in increasing order.
type Int64Slice []int64
func (p Int64Slice) Len() int { return len(p) }
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// IsSliceInt64Eq returns if the two slice has the same elements but different sequences.
func IsSliceInt64Eq(a, b []int64) bool {
if len(a) != len(b) {
return false
}
sort.Sort(Int64Slice(a))
sort.Sort(Int64Slice(b))
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
// ExistsInSlice returns true if string exists in slice.
func ExistsInSlice(target string, slice []string) bool {
i := sort.Search(len(slice),
func(i int) bool { return slice[i] == target })
return i < len(slice)
}
// IsStringInSlice sequential searches if string exists in slice.
func IsStringInSlice(target string, slice []string, insensitive ...bool) bool {
caseInsensitive := false
if len(insensitive) != 0 && insensitive[0] {
caseInsensitive = true
target = strings.ToLower(target)
}
for i := 0; i < len(slice); i++ {
if caseInsensitive {
if strings.ToLower(slice[i]) == target {
return true
}
} else {
if slice[i] == target {
return true
}
}
}
return false
}
// IsInt64InSlice sequential searches if int64 exists in slice.
func IsInt64InSlice(target int64, slice []int64) bool {
for i := 0; i < len(slice); i++ {
if slice[i] == target {
return true
}
}
return false
}
// IsEqualSlice returns true if slices are equal.
func IsEqualSlice(target, source []string) bool {
if len(target) != len(source) {
return false
}
if (target == nil) != (source == nil) {
return false
}
sort.Strings(target)
sort.Strings(source)
for i, v := range target {
if v != source[i] {
return false
}
}
return true
}

View File

@ -1,90 +1,17 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Most of the functions in this file can have better implementations with "golang.org/x/exp/slices".
// However, "golang.org/x/exp" is experimental and unreliable, we shouldn't use it.
// So lets waiting for the "slices" has be promoted to the main repository one day.
package util
import "strings"
// SliceContains returns true if the target exists in the slice.
func SliceContains[T comparable](slice []T, target T) bool {
return SliceContainsFunc(slice, func(t T) bool { return t == target })
}
// SliceContainsFunc returns true if any element in the slice satisfies the targetFunc.
func SliceContainsFunc[T any](slice []T, targetFunc func(T) bool) bool {
for _, v := range slice {
if targetFunc(v) {
return true
// RemoveIDFromList removes the given ID from the slice, if found.
// It does not preserve order, and assumes the ID is unique.
func RemoveIDFromList(list []int64, id int64) ([]int64, bool) {
n := len(list) - 1
for i, item := range list {
if item == id {
list[i] = list[n]
return list[:n], true
}
}
return false
}
// SliceContainsString sequential searches if string exists in slice.
func SliceContainsString(slice []string, target string, insensitive ...bool) bool {
if len(insensitive) != 0 && insensitive[0] {
target = strings.ToLower(target)
return SliceContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target })
}
return SliceContains(slice, target)
}
// SliceSortedEqual returns true if the two slices will be equal when they get sorted.
// It doesn't require that the slices have been sorted, and it doesn't sort them either.
func SliceSortedEqual[T comparable](s1, s2 []T) bool {
if len(s1) != len(s2) {
return false
}
counts := make(map[T]int, len(s1))
for _, v := range s1 {
counts[v]++
}
for _, v := range s2 {
counts[v]--
}
for _, v := range counts {
if v != 0 {
return false
}
}
return true
}
// SliceEqual returns true if the two slices are equal.
func SliceEqual[T comparable](s1, s2 []T) bool {
if len(s1) != len(s2) {
return false
}
for i, v := range s1 {
if s2[i] != v {
return false
}
}
return true
}
// SliceRemoveAll removes all the target elements from the slice.
func SliceRemoveAll[T comparable](slice []T, target T) []T {
return SliceRemoveAllFunc(slice, func(t T) bool { return t == target })
}
// SliceRemoveAllFunc removes all elements which satisfy the targetFunc from the slice.
func SliceRemoveAllFunc[T comparable](slice []T, targetFunc func(T) bool) []T {
idx := 0
for _, v := range slice {
if targetFunc(v) {
continue
}
slice[idx] = v
idx++
}
return slice[:idx]
return list, false
}

View File

@ -1,88 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package util
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSliceContains(t *testing.T) {
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 2))
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 0))
assert.True(t, SliceContains([]int{2, 0, 2, 3}, 3))
assert.True(t, SliceContains([]string{"2", "0", "2", "3"}, "0"))
assert.True(t, SliceContains([]float64{2, 0, 2, 3}, 0))
assert.True(t, SliceContains([]bool{false, true, false}, true))
assert.False(t, SliceContains([]int{2, 0, 2, 3}, 4))
assert.False(t, SliceContains([]int{}, 4))
assert.False(t, SliceContains(nil, 4))
}
func TestSliceContainsString(t *testing.T) {
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "a"))
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "b"))
assert.True(t, SliceContainsString([]string{"c", "b", "a", "b"}, "A", true))
assert.True(t, SliceContainsString([]string{"C", "B", "A", "B"}, "a", true))
assert.False(t, SliceContainsString([]string{"c", "b", "a", "b"}, "z"))
assert.False(t, SliceContainsString([]string{"c", "b", "a", "b"}, "A"))
assert.False(t, SliceContainsString([]string{}, "a"))
assert.False(t, SliceContainsString(nil, "a"))
}
func TestSliceSortedEqual(t *testing.T) {
assert.True(t, SliceSortedEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3}))
assert.True(t, SliceSortedEqual([]int{3, 0, 2, 2}, []int{2, 0, 2, 3}))
assert.True(t, SliceSortedEqual([]int{}, []int{}))
assert.True(t, SliceSortedEqual([]int(nil), nil))
assert.True(t, SliceSortedEqual([]int(nil), []int{}))
assert.True(t, SliceSortedEqual([]int{}, []int{}))
assert.True(t, SliceSortedEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"}))
assert.True(t, SliceSortedEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3}))
assert.True(t, SliceSortedEqual([]bool{false, true, false}, []bool{false, true, false}))
assert.False(t, SliceSortedEqual([]int{2, 0, 2}, []int{2, 0, 2, 3}))
assert.False(t, SliceSortedEqual([]int{}, []int{2, 0, 2, 3}))
assert.False(t, SliceSortedEqual(nil, []int{2, 0, 2, 3}))
assert.False(t, SliceSortedEqual([]int{2, 0, 2, 4}, []int{2, 0, 2, 3}))
assert.False(t, SliceSortedEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3}))
}
func TestSliceEqual(t *testing.T) {
assert.True(t, SliceEqual([]int{2, 0, 2, 3}, []int{2, 0, 2, 3}))
assert.True(t, SliceEqual([]int{}, []int{}))
assert.True(t, SliceEqual([]int(nil), nil))
assert.True(t, SliceEqual([]int(nil), []int{}))
assert.True(t, SliceEqual([]int{}, []int{}))
assert.True(t, SliceEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"}))
assert.True(t, SliceEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3}))
assert.True(t, SliceEqual([]bool{false, true, false}, []bool{false, true, false}))
assert.False(t, SliceEqual([]int{3, 0, 2, 2}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{2, 0, 2}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual(nil, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{2, 0, 2, 4}, []int{2, 0, 2, 3}))
assert.False(t, SliceEqual([]int{2, 0, 0, 3}, []int{2, 0, 2, 3}))
}
func TestSliceRemoveAll(t *testing.T) {
assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 0), []int{2, 2, 3})
assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 2), []int{0, 3})
assert.Equal(t, SliceRemoveAll([]int{0, 0, 0, 0}, 0), []int{})
assert.Equal(t, SliceRemoveAll([]int{2, 0, 2, 3}, 4), []int{2, 0, 2, 3})
assert.Equal(t, SliceRemoveAll([]int{}, 0), []int{})
assert.Equal(t, SliceRemoveAll([]int(nil), 0), []int(nil))
assert.Equal(t, SliceRemoveAll([]int{}, 0), []int{})
assert.Equal(t, SliceRemoveAll([]string{"2", "0", "2", "3"}, "0"), []string{"2", "2", "3"})
assert.Equal(t, SliceRemoveAll([]float64{2, 0, 2, 3}, 0), []float64{2, 2, 3})
assert.Equal(t, SliceRemoveAll([]bool{false, true, false}, true), []bool{false, false})
}

View File

@ -107,11 +107,11 @@ func toAPIHook(ctx *context.APIContext, repoLink string, hook *webhook.Webhook)
}
func issuesHook(events []string, event string) bool {
return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventIssues), true)
return util.IsStringInSlice(event, events, true) || util.IsStringInSlice(string(webhook_module.HookEventIssues), events, true)
}
func pullHook(events []string, event string) bool {
return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventPullRequest), true)
return util.IsStringInSlice(event, events, true) || util.IsStringInSlice(string(webhook_module.HookEventPullRequest), events, true)
}
// addHook add the hook specified by `form`, `orgID` and `repoID`. If there is
@ -130,15 +130,15 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
HookEvent: &webhook_module.HookEvent{
ChooseEvents: true,
HookEvents: webhook_module.HookEvents{
Create: util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true),
Delete: util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true),
Fork: util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true),
Create: util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true),
Delete: util.IsStringInSlice(string(webhook_module.HookEventDelete), form.Events, true),
Fork: util.IsStringInSlice(string(webhook_module.HookEventFork), form.Events, true),
Issues: issuesHook(form.Events, "issues_only"),
IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)),
IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)),
IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)),
IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)),
Push: util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true),
Push: util.IsStringInSlice(string(webhook_module.HookEventPush), form.Events, true),
PullRequest: pullHook(form.Events, "pull_request_only"),
PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)),
PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)),
@ -146,9 +146,9 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)),
PullRequestReview: pullHook(form.Events, "pull_request_review"),
PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)),
Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true),
Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true),
Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true),
Wiki: util.IsStringInSlice(string(webhook_module.HookEventWiki), form.Events, true),
Repository: util.IsStringInSlice(string(webhook_module.HookEventRepository), form.Events, true),
Release: util.IsStringInSlice(string(webhook_module.HookEventRelease), form.Events, true),
},
BranchFilter: form.BranchFilter,
},
@ -277,14 +277,14 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
w.PushOnly = false
w.SendEverything = false
w.ChooseEvents = true
w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true)
w.Push = util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true)
w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true)
w.Delete = util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true)
w.Fork = util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true)
w.Repository = util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true)
w.Wiki = util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true)
w.Release = util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true)
w.Create = util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true)
w.Push = util.IsStringInSlice(string(webhook_module.HookEventPush), form.Events, true)
w.Create = util.IsStringInSlice(string(webhook_module.HookEventCreate), form.Events, true)
w.Delete = util.IsStringInSlice(string(webhook_module.HookEventDelete), form.Events, true)
w.Fork = util.IsStringInSlice(string(webhook_module.HookEventFork), form.Events, true)
w.Repository = util.IsStringInSlice(string(webhook_module.HookEventRepository), form.Events, true)
w.Wiki = util.IsStringInSlice(string(webhook_module.HookEventWiki), form.Events, true)
w.Release = util.IsStringInSlice(string(webhook_module.HookEventRelease), form.Events, true)
w.BranchFilter = form.BranchFilter
err := w.SetHeaderAuthorization(form.AuthorizationHeader)

View File

@ -16,8 +16,8 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/externalaccount"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/webauthn"
)
var tplWebAuthn base.TplName = "user/auth/webauthn"

View File

@ -139,7 +139,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
viewType := ctx.FormString("type")
sortType := ctx.FormString("sort")
types := []string{"all", "your_repositories", "assigned", "created_by", "mentioned", "review_requested"}
if !util.SliceContainsString(types, viewType, true) {
if !util.IsStringInSlice(viewType, types, true) {
viewType = "all"
}
@ -3087,7 +3087,7 @@ func updateAttachments(ctx *context.Context, item interface{}, files []string) e
return fmt.Errorf("unknown Type: %T", content)
}
for i := 0; i < len(attachments); i++ {
if util.SliceContainsString(files, attachments[i].UUID) {
if util.IsStringInSlice(attachments[i].UUID, files) {
continue
}
if err := repo_model.DeleteAttachment(attachments[i], true); err != nil {

View File

@ -110,7 +110,7 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) {
func checkHookType(ctx *context.Context) string {
hookType := strings.ToLower(ctx.Params(":type"))
if !util.SliceContainsString(setting.Webhook.Types, hookType, true) {
if !util.IsStringInSlice(hookType, setting.Webhook.Types, true) {
ctx.NotFound("checkHookType", nil)
return ""
}

View File

@ -214,7 +214,7 @@ func NotificationSubscriptions(ctx *context.Context) {
ctx.Data["SortType"] = sortType
state := ctx.FormString("state")
if !util.SliceContainsString([]string{"all", "open", "closed"}, state, true) {
if !util.IsStringInSlice(state, []string{"all", "open", "closed"}, true) {
state = "all"
}
ctx.Data["State"] = state

View File

@ -413,7 +413,7 @@ func UpdateUserLang(ctx *context.Context) {
ctx.Data["PageIsSettingsAppearance"] = true
if len(form.Language) != 0 {
if !util.SliceContainsString(setting.Langs, form.Language) {
if !util.IsStringInSlice(form.Language, setting.Langs) {
ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language))
ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
return

View File

@ -15,8 +15,8 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/webauthn"
)
// WebAuthnRegister initializes the webauthn registration procedure

View File

@ -246,7 +246,7 @@ func (source *Source) getMappedMemberships(l *ldap.Conn, uid string) (map[string
membershipsToAdd := map[string][]string{}
membershipsToRemove := map[string][]string{}
for group, memberships := range ldapGroupsToTeams {
isUserInGroup := util.SliceContainsString(usersLdapGroups, group)
isUserInGroup := util.IsStringInSlice(group, usersLdapGroups)
if isUserInGroup {
for org, teams := range memberships {
membershipsToAdd[org] = teams

View File

@ -23,7 +23,7 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str
idx := strings.Index(userName, "@")
if idx == -1 {
return nil, user_model.ErrUserNotExist{Name: userName}
} else if !util.SliceContainsString(strings.Split(source.AllowedDomains, ","), userName[idx+1:], true) {
} else if !util.IsStringInSlice(userName[idx+1:], strings.Split(source.AllowedDomains, ","), true) {
return nil, user_model.ErrUserNotExist{Name: userName}
}
}

View File

@ -35,7 +35,7 @@ const (
)
func nameAllowed(name string) error {
if util.SliceContainsString(reservedWikiNames, name) {
if util.IsStringInSlice(name, reservedWikiNames) {
return repo_model.ErrWikiReservedName{
Title: name,
}

View File

@ -38,7 +38,7 @@ func TestAPIRepoTeams(t *testing.T) {
if assert.Len(t, teams, 2) {
assert.EqualValues(t, "Owners", teams[0].Name)
assert.True(t, teams[0].CanCreateOrgRepo)
assert.True(t, util.SliceSortedEqual(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units))
assert.True(t, util.IsEqualSlice(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units))
assert.EqualValues(t, "owner", teams[0].Permission)
assert.EqualValues(t, "test_team", teams[1].Name)