feat: update gitea vendor
runner nix smoke / nix label and flake smoke (push) Failing after 1m28s

This commit is contained in:
2026-09-26 21:18:24 +00:00
parent c439c1b948
commit d9b2a4e787
3538 changed files with 116131 additions and 44340 deletions
+7 -7
View File
@@ -9,13 +9,13 @@ import (
"image/png"
"io"
"code.gitea.io/gitea/models/avatars"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/avatar"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"gitea.dev/models/avatars"
"gitea.dev/models/db"
"gitea.dev/modules/avatar"
"gitea.dev/modules/httplib"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
"gitea.dev/modules/storage"
)
// CustomAvatarRelativePath returns user custom avatar relative path.
@@ -8,10 +8,10 @@ import (
"strings"
"testing"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/test"
"gitea.dev/models/unittest"
"gitea.dev/modules/setting"
"gitea.dev/modules/storage"
"gitea.dev/modules/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+3 -22
View File
@@ -6,8 +6,8 @@ package user
import (
"context"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/util"
"xorm.io/builder"
"xorm.io/xorm/schemas"
@@ -69,7 +69,7 @@ func GetBadgeUsers(ctx context.Context, opts *GetBadgeUsersOptions) ([]*User, in
Where("badge.slug=?", opts.BadgeSlug)
if opts.Page > 0 {
sess = db.SetSessionPagination(sess, opts)
db.SetSessionPagination(sess, opts)
}
users := make([]*User, 0, opts.PageSize)
@@ -212,12 +212,6 @@ func RemoveUserBadges(ctx context.Context, u *User, badges []*Badge) error {
})
}
// RemoveAllUserBadges removes all badges from a user.
func RemoveAllUserBadges(ctx context.Context, u *User) error {
_, err := db.GetEngine(ctx).Where("user_id=?", u.ID).Delete(&UserBadge{})
return err
}
// SearchBadgeOptions represents the options when finding badges
type SearchBadgeOptions struct {
db.ListOptions
@@ -258,16 +252,3 @@ func (opts *SearchBadgeOptions) ToOrders() string {
func SearchBadges(ctx context.Context, opts *SearchBadgeOptions) ([]*Badge, int64, error) {
return db.FindAndCount[Badge](ctx, opts)
}
// GetBadgeByID returns a specific badge by ID
func GetBadgeByID(ctx context.Context, id int64) (*Badge, error) {
badge := new(Badge)
has, err := db.GetEngine(ctx).ID(id).Get(badge)
if err != nil {
return nil, err
}
if !has {
return nil, util.NewNotExistErrorf("badge does not exist [id: %d]", id)
}
return badge, nil
}
@@ -6,10 +6,10 @@ package user_test
import (
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/util"
"github.com/stretchr/testify/assert"
)
+5 -5
View File
@@ -6,10 +6,10 @@ package user
import (
"context"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/container"
"gitea.dev/modules/timeutil"
"gitea.dev/modules/util"
"xorm.io/builder"
)
@@ -90,7 +90,7 @@ func GetBlocking(ctx context.Context, blockerID, blockeeID int64) (*Blocking, er
return nil, err
}
if len(blocks) == 0 {
return nil, nil //nolint:nilnil // return nil to indicate that the object does not exist
return nil, util.NewNotExistErrorf("blocking record doesn't exist")
}
return blocks[0], nil
}
@@ -11,13 +11,13 @@ import (
"strings"
"time"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
"gitea.dev/models/db"
"gitea.dev/modules/base"
"gitea.dev/modules/log"
"gitea.dev/modules/optional"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
"gitea.dev/modules/validation"
"xorm.io/builder"
)
@@ -147,11 +147,6 @@ func InsertEmailAddress(ctx context.Context, email *EmailAddress) (*EmailAddress
return email, nil
}
func UpdateEmailAddress(ctx context.Context, email *EmailAddress) error {
_, err := db.GetEngine(ctx).ID(email.ID).AllCols().Update(email)
return err
}
// ValidateEmail check if email is a valid & allowed address
func ValidateEmail(email string) error {
if err := validateEmailBasic(email); err != nil {
@@ -353,8 +348,8 @@ func VerifyActiveEmailCode(ctx context.Context, code, email string) *EmailAddres
opts := &TimeLimitCodeOptions{Purpose: TimeLimitCodeActivateEmail, NewEmail: email}
data := makeTimeLimitCodeHashData(opts, user)
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
emailAddress := &EmailAddress{UID: user.ID, Email: email}
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {
emailAddress, has, _ := db.Get[EmailAddress](ctx, builder.Eq{"uid": user.ID, "email": email})
if has {
return emailAddress
}
}
@@ -7,10 +7,10 @@ import (
"slices"
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/optional"
"gitea.dev/models/db"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/optional"
"github.com/stretchr/testify/assert"
)
+1 -22
View File
@@ -6,7 +6,7 @@ package user
import (
"fmt"
"code.gitea.io/gitea/modules/util"
"gitea.dev/modules/util"
)
// ErrUserAlreadyExist represents a "user already exists" error.
@@ -71,27 +71,6 @@ func (err ErrUserProhibitLogin) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrUserInactive represents a "ErrUserInactive" kind of error.
type ErrUserInactive struct {
UID int64
Name string
}
// IsErrUserInactive checks if an error is a ErrUserInactive
func IsErrUserInactive(err error) bool {
_, ok := err.(ErrUserInactive)
return ok
}
func (err ErrUserInactive) Error() string {
return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name)
}
// Unwrap unwraps this error as a ErrPermission error
func (err ErrUserInactive) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrUserIsNotLocal represents a "ErrUserIsNotLocal" kind of error.
type ErrUserIsNotLocal struct {
UID int64
@@ -8,8 +8,8 @@ import (
"fmt"
"time"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/util"
"xorm.io/builder"
)
@@ -21,12 +21,6 @@ type ErrExternalLoginUserAlreadyExist struct {
LoginSourceID int64
}
// IsErrExternalLoginUserAlreadyExist checks if an error is a ExternalLoginUserAlreadyExist.
func IsErrExternalLoginUserAlreadyExist(err error) bool {
_, ok := err.(ErrExternalLoginUserAlreadyExist)
return ok
}
func (err ErrExternalLoginUserAlreadyExist) Error() string {
return fmt.Sprintf("external login user already exists [externalID: %s, userID: %d, loginSourceID: %d]", err.ExternalID, err.UserID, err.LoginSourceID)
}
@@ -41,12 +35,6 @@ type ErrExternalLoginUserNotExist struct {
LoginSourceID int64
}
// IsErrExternalLoginUserNotExist checks if an error is a ExternalLoginUserNotExist.
func IsErrExternalLoginUserNotExist(err error) bool {
_, ok := err.(ErrExternalLoginUserNotExist)
return ok
}
func (err ErrExternalLoginUserNotExist) Error() string {
return fmt.Sprintf("external login user link does not exists [userID: %d, loginSourceID: %d]", err.UserID, err.LoginSourceID)
}
@@ -92,8 +80,11 @@ func init() {
}
// GetExternalLogin checks if a externalID in loginSourceID scope already exists
func GetExternalLogin(ctx context.Context, externalLoginUser *ExternalLoginUser) (bool, error) {
return db.GetEngine(ctx).Get(externalLoginUser)
func GetExternalLogin(ctx context.Context, loginSourceID int64, externalID string) (*ExternalLoginUser, bool, error) {
return db.Get[ExternalLoginUser](ctx, builder.Eq{
"external_id": externalID,
"login_source_id": loginSourceID,
})
}
// LinkExternalToUser link the external user to the user
@@ -130,6 +121,12 @@ func RemoveAllAccountLinks(ctx context.Context, user *User) error {
return err
}
// RemoveExternalLoginByExternalID removes a specific external login link by its provider-side identifier.
func RemoveExternalLoginByExternalID(ctx context.Context, loginSourceID int64, externalID string) error {
_, err := db.GetEngine(ctx).Where("external_id=? AND login_source_id=?", externalID, loginSourceID).Delete(new(ExternalLoginUser))
return err
}
// GetUserIDByExternalUserID get user id according to provider and userID
func GetUserIDByExternalUserID(ctx context.Context, provider, userID string) (int64, error) {
var id int64
+5 -3
View File
@@ -6,8 +6,10 @@ package user
import (
"context"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/timeutil"
"gitea.dev/models/db"
"gitea.dev/modules/timeutil"
"xorm.io/builder"
)
// Follow represents relations of user and their followers.
@@ -24,7 +26,7 @@ func init() {
// IsFollowing returns true if user is following followID.
func IsFollowing(ctx context.Context, userID, followID int64) bool {
has, _ := db.GetEngine(ctx).Get(&Follow{UserID: userID, FollowID: followID})
has, _ := db.Exist[Follow](ctx, builder.Eq{"user_id": userID, "follow_id": followID})
return has
}
@@ -6,8 +6,8 @@ package user_test
import (
"testing"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"github.com/stretchr/testify/assert"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"fmt"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"gitea.dev/models/auth"
"gitea.dev/models/db"
)
// UserList is a list of user.
@@ -6,12 +6,12 @@ package user_test
import (
"testing"
"code.gitea.io/gitea/models/unittest"
"gitea.dev/models/unittest"
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/user"
_ "gitea.dev/models"
_ "gitea.dev/models/actions"
_ "gitea.dev/models/activities"
_ "gitea.dev/models/user"
)
func TestMain(m *testing.M) {
@@ -7,8 +7,8 @@ import (
"context"
"strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/util"
"xorm.io/builder"
)
+5 -3
View File
@@ -7,8 +7,10 @@ import (
"context"
"fmt"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/util"
"xorm.io/builder"
)
// UserOpenID is the list of all OpenID identities of a user.
@@ -43,7 +45,7 @@ func isOpenIDUsed(ctx context.Context, uri string) (bool, error) {
return true, nil
}
return db.GetEngine(ctx).Get(&UserOpenID{URI: uri})
return db.Exist[UserOpenID](ctx, builder.Eq{"uri": uri})
}
// ErrOpenIDAlreadyUsed represents a "OpenIDAlreadyUsed" kind of error.
@@ -6,9 +6,9 @@ package user_test
import (
"testing"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+6 -4
View File
@@ -8,8 +8,10 @@ import (
"fmt"
"strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/util"
"xorm.io/builder"
)
// ErrUserRedirectNotExist represents a "UserRedirectNotExist" kind of error.
@@ -50,8 +52,8 @@ func init() {
// LookupUserRedirect look up userID if a user has a redirect name
func LookupUserRedirect(ctx context.Context, userName string) (int64, error) {
userName = strings.ToLower(userName)
redirect := &Redirect{LowerName: userName}
if has, err := db.GetEngine(ctx).Get(redirect); err != nil {
redirect, has, err := db.Get[Redirect](ctx, builder.Eq{"lower_name": userName})
if err != nil {
return 0, err
} else if !has {
return 0, ErrUserRedirectNotExist{Name: userName}
@@ -6,8 +6,8 @@ package user_test
import (
"testing"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"github.com/stretchr/testify/assert"
)
+9 -9
View File
@@ -9,13 +9,12 @@ import (
"slices"
"strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/structs"
"gitea.dev/models/db"
"gitea.dev/modules/container"
"gitea.dev/modules/optional"
"gitea.dev/modules/structs"
"xorm.io/builder"
"xorm.io/xorm"
)
// AdminUserOrderByMap represents all possible admin user search orders
@@ -65,7 +64,7 @@ func (opts *SearchUserOptions) ApplyPublicOnly(publicOnly bool) {
}
}
func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) *xorm.Session {
func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) db.Session {
var cond builder.Cond
cond = builder.In("type", opts.Types)
if opts.IncludeReserved {
@@ -173,14 +172,15 @@ func SearchUsers(ctx context.Context, opts SearchUserOptions) (users []*User, _
opts.OrderBy = db.SearchOrderByAlphabetically
}
sessQuery := opts.toSearchQueryBase(ctx).OrderBy(opts.OrderBy.String())
sessQuery := opts.toSearchQueryBase(ctx)
defer sessQuery.Close()
sessQuery.OrderBy(opts.OrderBy.String())
if opts.Page > 0 {
sessQuery = db.SetSessionPagination(sessQuery, &opts)
db.SetSessionPagination(sessQuery, &opts)
}
// the sql may contain JOIN, so we must only select User related columns
sessQuery = sessQuery.Select("`user`.*")
sessQuery.Select("`user`.*")
users = make([]*User, 0, opts.PageSize)
return users, count, sessQuery.Find(&users)
}
+6 -13
View File
@@ -10,11 +10,11 @@ import (
"strconv"
"strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/json"
setting_module "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
"gitea.dev/modules/cache"
"gitea.dev/modules/json"
setting_module "gitea.dev/modules/setting"
"gitea.dev/modules/util"
"xorm.io/builder"
"xorm.io/xorm/convert"
@@ -53,12 +53,6 @@ func (err ErrUserSettingIsNotExist) Unwrap() error {
return util.ErrNotExist
}
// IsErrUserSettingIsNotExist return true if err is ErrSettingIsNotExist
func IsErrUserSettingIsNotExist(err error) bool {
_, ok := err.(ErrUserSettingIsNotExist)
return ok
}
// genSettingCacheKey returns the cache key for some configuration
func genSettingCacheKey(userID int64, key string) string {
return fmt.Sprintf("user_%d.setting.%s", userID, key)
@@ -134,8 +128,7 @@ func GetUserSetting(ctx context.Context, userID int64, key string, def ...string
return "", err
}
setting := &Setting{UserID: userID, SettingKey: key}
has, err := db.GetEngine(ctx).Get(setting)
setting, has, err := db.Get[Setting](ctx, builder.Eq{"user_id": userID, "setting_key": key})
if err != nil {
return "", err
}
@@ -6,8 +6,8 @@ package user_test
import (
"testing"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"github.com/stretchr/testify/assert"
)
+55 -85
View File
@@ -21,24 +21,24 @@ import (
"time"
"unicode"
_ "image/jpeg" // Needed for jpeg support
"gitea.dev/models/auth"
"gitea.dev/models/db"
"gitea.dev/modules/auth/openid"
"gitea.dev/modules/auth/password/hash"
"gitea.dev/modules/base"
"gitea.dev/modules/container"
"gitea.dev/modules/git"
"gitea.dev/modules/htmlutil"
"gitea.dev/modules/httplib"
"gitea.dev/modules/log"
"gitea.dev/modules/optional"
"gitea.dev/modules/setting"
"gitea.dev/modules/structs"
"gitea.dev/modules/timeutil"
"gitea.dev/modules/util"
"gitea.dev/modules/validation"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/auth/openid"
"code.gitea.io/gitea/modules/auth/password/hash"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/htmlutil"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
_ "image/jpeg" // Needed for jpeg support
"golang.org/x/text/runes"
"golang.org/x/text/transform"
@@ -244,12 +244,15 @@ func (u *User) IsOAuth2() bool {
return u.LoginType == auth.OAuth2
}
// MaxCreationLimit returns the number of repositories a user is allowed to create
// MaxCreationLimit returns the number of repositories a user or an organization is allowed to create
func (u *User) MaxCreationLimit() int {
if u.MaxRepoCreation <= -1 {
return setting.Repository.MaxCreationLimit
if u.MaxRepoCreation > -1 {
return u.MaxRepoCreation
}
return u.MaxRepoCreation
if u.IsOrganization() {
return setting.Repository.OrgMaxCreationLimit
}
return setting.Repository.UserMaxCreationLimit
}
// CanCreateRepoIn checks whether the doer(u) can create a repository in the owner
@@ -264,13 +267,11 @@ func (u *User) CanCreateRepoIn(owner *User) bool {
return true
}
const noLimit = -1
if owner.MaxRepoCreation == noLimit {
if setting.Repository.MaxCreationLimit == noLimit {
return true
}
return owner.NumRepos < setting.Repository.MaxCreationLimit
limit := owner.MaxCreationLimit()
if limit == noLimit {
return true
}
return owner.NumRepos < owner.MaxRepoCreation
return owner.NumRepos < limit
}
// CanCreateOrganization returns true if user can create organisation.
@@ -339,7 +340,7 @@ func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListO
And(isUserVisibleToViewerCond(viewer))
if listOptions.Page > 0 {
sess = db.SetSessionPagination(sess, &listOptions)
db.SetSessionPagination(sess, &listOptions)
users := make([]*User, 0, listOptions.PageSize)
count, err := sess.FindAndCount(&users)
@@ -361,7 +362,7 @@ func GetUserFollowing(ctx context.Context, u, viewer *User, listOptions db.ListO
And(isUserVisibleToViewerCond(viewer))
if listOptions.Page > 0 {
sess = db.SetSessionPagination(sess, &listOptions)
db.SetSessionPagination(sess, &listOptions)
users := make([]*User, 0, listOptions.PageSize)
count, err := sess.FindAndCount(&users)
@@ -532,10 +533,7 @@ const SaltByteLength = 16
// GetUserSalt returns a random user salt token.
func GetUserSalt() (string, error) {
rBytes, err := util.CryptoRandomBytes(SaltByteLength)
if err != nil {
return "", err
}
rBytes := util.CryptoRandomBytes(SaltByteLength)
// Returns a 32-byte long string.
return hex.EncodeToString(rBytes), nil
}
@@ -625,6 +623,7 @@ var (
"sitemap.xml", // search engine sitemap
"ssh_info", // agit info
"swagger.v1.json",
"openapi3.v1.json",
"ghost", // reserved name for deleted users (id: -1)
"gitea-actions", // gitea builtin user (id: -2)
@@ -1149,14 +1148,7 @@ func GetUsersBySource(ctx context.Context, s *auth.Source) ([]*User, error) {
return users, err
}
// UserCommit represents a commit with validation of user.
type UserCommit struct { //revive:disable-line:exported
User *User
*git.Commit
}
// ValidateCommitWithEmail check if author's e-mail of commit is corresponding to a user.
func ValidateCommitWithEmail(ctx context.Context, c *git.Commit) *User {
func GetUserByGitAuthor(ctx context.Context, c *git.Commit) *User {
if c.Author == nil {
return nil
}
@@ -1167,33 +1159,6 @@ func ValidateCommitWithEmail(ctx context.Context, c *git.Commit) *User {
return u
}
// ValidateCommitsWithEmails checks if authors' e-mails of commits are corresponding to users.
func ValidateCommitsWithEmails(ctx context.Context, oldCommits []*git.Commit) ([]*UserCommit, error) {
var (
newCommits = make([]*UserCommit, 0, len(oldCommits))
emailSet = make(container.Set[string])
)
for _, c := range oldCommits {
if c.Author != nil {
emailSet.Add(c.Author.Email)
}
}
emailUserMap, err := GetUsersByEmails(ctx, emailSet.Values())
if err != nil {
return nil, err
}
for _, c := range oldCommits {
user := emailUserMap.GetByEmail(c.Author.Email) // FIXME: why ValidateCommitsWithEmails uses "Author", but ParseCommitsWithSignature uses "Committer"?
newCommits = append(newCommits, &UserCommit{
User: user,
Commit: c,
})
}
return newCommits, nil
}
type EmailUserMap struct {
m map[string]*User
}
@@ -1204,7 +1169,7 @@ func (eum *EmailUserMap) GetByEmail(email string) *User {
func GetUsersByEmails(ctx context.Context, emails []string) (*EmailUserMap, error) {
if len(emails) == 0 {
return nil, nil //nolint:nilnil // return nil when there are no emails to look up
return &EmailUserMap{}, nil
}
needCheckEmails := make(container.Set[string])
@@ -1311,8 +1276,7 @@ func GetUserByEmail(ctx context.Context, email string) (*User, error) {
email = strings.ToLower(email)
// Otherwise, check in alternative list for activated email addresses
emailAddress := &EmailAddress{LowerEmail: email, IsActivated: true}
has, err := db.GetEngine(ctx).Get(emailAddress)
emailAddress, has, err := db.Get[EmailAddress](ctx, builder.Eq{"lower_email": email, "is_activated": true})
if err != nil {
return nil, err
}
@@ -1332,13 +1296,29 @@ func GetUserByEmail(ctx context.Context, email string) (*User, error) {
return nil, ErrUserNotExist{Name: email}
}
func GetIndividualUser(ctx context.Context, user *User) (bool, error) {
// FIXME: the design is wrong, empty User fields won't apply, this function should be removed in the future
has, err := db.GetEngine(ctx).Get(user)
func GetIndividualUserByPrimaryEmail(ctx context.Context, email string) (*User, error) {
email = strings.ToLower(strings.TrimSpace(email))
if len(email) == 0 {
return nil, ErrUserNotExist{Name: email}
}
user, has, err := db.Get[User](ctx, builder.Eq{"email": email, "type": UserTypeIndividual})
if err != nil {
return nil, err
}
if !has {
return nil, ErrUserNotExist{Name: email}
}
return user, nil
}
func GetIndividualUserByLoginSource(ctx context.Context, loginType auth.Type, loginSource int64, loginName string) (*User, bool, error) {
user, has, err := db.Get[User](ctx, builder.Eq{"login_type": loginType, "login_source": loginSource, "login_name": loginName})
if has && user.Type != UserTypeIndividual {
has = false
user = nil
}
return has, err
return user, has, err
}
// GetUserByOpenID returns the user object by given OpenID if exists.
@@ -1472,16 +1452,6 @@ func IsUserVisibleToViewer(ctx context.Context, u, viewer *User) bool {
return false
}
// CountWrongUserType count OrgUser who have wrong type
func CountWrongUserType(ctx context.Context) (int64, error) {
return db.GetEngine(ctx).Where(builder.Eq{"type": 0}.And(builder.Neq{"num_teams": 0})).Count(new(User))
}
// FixWrongUserType fix OrgUser who have wrong type
func FixWrongUserType(ctx context.Context) (int64, error) {
return db.GetEngine(ctx).Where(builder.Eq{"type": 0}.And(builder.Neq{"num_teams": 0})).Cols("type").NoAutoTime().Update(&User{Type: 1})
}
func GetOrderByName() string {
if setting.UI.DefaultShowFullName {
return "full_name, name"
@@ -6,7 +6,7 @@ package user
import (
"context"
"code.gitea.io/gitea/models/db"
"gitea.dev/models/db"
)
func GetUsersMapByIDs(ctx context.Context, userIDs []int64) (map[int64]*User, error) {
@@ -7,7 +7,7 @@ import (
"strconv"
"strings"
"code.gitea.io/gitea/modules/structs"
"gitea.dev/modules/structs"
)
const (
+49 -13
View File
@@ -10,17 +10,17 @@ import (
"testing"
"time"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password/hash"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/timeutil"
"gitea.dev/models/auth"
"gitea.dev/models/db"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/auth/password/hash"
"gitea.dev/modules/container"
"gitea.dev/modules/optional"
"gitea.dev/modules/setting"
"gitea.dev/modules/structs"
"gitea.dev/modules/test"
"gitea.dev/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -674,12 +674,18 @@ func TestGetInactiveUsers(t *testing.T) {
func TestCanCreateRepo(t *testing.T) {
defer test.MockVariableValue(&setting.Repository.MaxCreationLimit)()
defer test.MockVariableValue(&setting.Repository.UserMaxCreationLimit)()
defer test.MockVariableValue(&setting.Repository.OrgMaxCreationLimit)()
const noLimit = -1
doerActions := user_model.NewActionsUser()
doerNormal := &user_model.User{ID: 2}
doerAdmin := &user_model.User{ID: 1, IsAdmin: true}
orgOwner := func(numRepos, maxRepoCreation int) *user_model.User {
return &user_model.User{ID: 3, Type: user_model.UserTypeOrganization, NumRepos: numRepos, MaxRepoCreation: maxRepoCreation}
}
t.Run("NoGlobalLimit", func(t *testing.T) {
setting.Repository.MaxCreationLimit = noLimit
setting.Repository.UserMaxCreationLimit = noLimit
setting.Repository.OrgMaxCreationLimit = noLimit
assert.False(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 10, MaxRepoCreation: 0}))
assert.True(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 10, MaxRepoCreation: 100}))
@@ -693,7 +699,8 @@ func TestCanCreateRepo(t *testing.T) {
})
t.Run("GlobalLimit50", func(t *testing.T) {
setting.Repository.MaxCreationLimit = 50
setting.Repository.UserMaxCreationLimit = 50
setting.Repository.OrgMaxCreationLimit = 50
assert.True(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 10, MaxRepoCreation: noLimit}))
assert.False(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 60, MaxRepoCreation: noLimit})) // limited by global limit
@@ -707,4 +714,33 @@ func TestCanCreateRepo(t *testing.T) {
assert.True(t, doerAdmin.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 10, MaxRepoCreation: 100}))
assert.True(t, doerAdmin.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 60, MaxRepoCreation: 100}))
})
t.Run("UserBlockedOrgsUnlimited", func(t *testing.T) {
// User and org limits are independent: a deployment can block personal repos while leaving orgs unrestricted.
setting.Repository.UserMaxCreationLimit = 0
setting.Repository.OrgMaxCreationLimit = noLimit
// regular user is blocked
assert.False(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 0, MaxRepoCreation: noLimit}))
// per-user override grants individual exceptions even when the global user limit is 0
assert.True(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 3, MaxRepoCreation: 5}))
assert.False(t, doerNormal.CanCreateRepoIn(&user_model.User{ID: 2, NumRepos: 5, MaxRepoCreation: 5}))
// organization can create unlimited repos
assert.True(t, doerNormal.CanCreateRepoIn(orgOwner(10, noLimit)))
assert.True(t, doerNormal.CanCreateRepoIn(orgOwner(999, noLimit)))
// per-org override still wins over the global org limit
assert.False(t, doerNormal.CanCreateRepoIn(orgOwner(5, 5)))
})
t.Run("OrgGlobalLimitWithPerOrgOverride", func(t *testing.T) {
setting.Repository.UserMaxCreationLimit = noLimit
setting.Repository.OrgMaxCreationLimit = 10
assert.True(t, doerNormal.CanCreateRepoIn(orgOwner(5, noLimit)))
assert.False(t, doerNormal.CanCreateRepoIn(orgOwner(10, noLimit)))
// per-org override bypasses the global org limit
assert.True(t, doerNormal.CanCreateRepoIn(orgOwner(10, 100)))
})
}
@@ -6,7 +6,7 @@ package user
import (
"context"
"code.gitea.io/gitea/models/db"
"gitea.dev/models/db"
)
func IncrUserRepoNum(ctx context.Context, userID int64) error {