mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01:00 
			
		
		
		
	Remove GetByBean method because sometimes it's danger when query condition parameter is zero and also introduce new generic methods (#28220)
The function `GetByBean` has an obvious defect that when the fields are
empty values, it will be ignored. Then users will get a wrong result
which is possibly used to make a security problem.
To avoid the possibility, this PR removed function `GetByBean` and all
references.
And some new generic functions have been introduced to be used.
The recommand usage like below.
```go
// if query an object according id
obj, err := db.GetByID[Object](ctx, id)
// query with other conditions
obj, err := db.Get[Object](ctx, builder.Eq{"a": a, "b":b})
```
			
			
This commit is contained in:
		@@ -131,24 +131,22 @@ func AddDeployKey(ctx context.Context, repoID int64, name, content string, readO
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	defer committer.Close()
 | 
						defer committer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pkey := &PublicKey{
 | 
						pkey, exist, err := db.Get[PublicKey](ctx, builder.Eq{"fingerprint": fingerprint})
 | 
				
			||||||
		Fingerprint: fingerprint,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, pkey)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						} else if exist {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if has {
 | 
					 | 
				
			||||||
		if pkey.Type != KeyTypeDeploy {
 | 
							if pkey.Type != KeyTypeDeploy {
 | 
				
			||||||
			return nil, ErrKeyAlreadyExist{0, fingerprint, ""}
 | 
								return nil, ErrKeyAlreadyExist{0, fingerprint, ""}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// First time use this deploy key.
 | 
							// First time use this deploy key.
 | 
				
			||||||
		pkey.Mode = accessMode
 | 
							pkey = &PublicKey{
 | 
				
			||||||
		pkey.Type = KeyTypeDeploy
 | 
								Fingerprint: fingerprint,
 | 
				
			||||||
		pkey.Content = content
 | 
								Mode:        accessMode,
 | 
				
			||||||
		pkey.Name = name
 | 
								Type:        KeyTypeDeploy,
 | 
				
			||||||
 | 
								Content:     content,
 | 
				
			||||||
 | 
								Name:        name,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if err = addKey(ctx, pkey); err != nil {
 | 
							if err = addKey(ctx, pkey); err != nil {
 | 
				
			||||||
			return nil, fmt.Errorf("addKey: %w", err)
 | 
								return nil, fmt.Errorf("addKey: %w", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -164,11 +162,10 @@ func AddDeployKey(ctx context.Context, repoID int64, name, content string, readO
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetDeployKeyByID returns deploy key by given ID.
 | 
					// GetDeployKeyByID returns deploy key by given ID.
 | 
				
			||||||
func GetDeployKeyByID(ctx context.Context, id int64) (*DeployKey, error) {
 | 
					func GetDeployKeyByID(ctx context.Context, id int64) (*DeployKey, error) {
 | 
				
			||||||
	key := new(DeployKey)
 | 
						key, exist, err := db.GetByID[DeployKey](ctx, id)
 | 
				
			||||||
	has, err := db.GetEngine(ctx).ID(id).Get(key)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrDeployKeyNotExist{id, 0, 0}
 | 
							return nil, ErrDeployKeyNotExist{id, 0, 0}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return key, nil
 | 
						return key, nil
 | 
				
			||||||
@@ -176,14 +173,10 @@ func GetDeployKeyByID(ctx context.Context, id int64) (*DeployKey, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetDeployKeyByRepo returns deploy key by given public key ID and repository ID.
 | 
					// GetDeployKeyByRepo returns deploy key by given public key ID and repository ID.
 | 
				
			||||||
func GetDeployKeyByRepo(ctx context.Context, keyID, repoID int64) (*DeployKey, error) {
 | 
					func GetDeployKeyByRepo(ctx context.Context, keyID, repoID int64) (*DeployKey, error) {
 | 
				
			||||||
	key := &DeployKey{
 | 
						key, exist, err := db.Get[DeployKey](ctx, builder.Eq{"key_id": keyID, "repo_id": repoID})
 | 
				
			||||||
		KeyID:  keyID,
 | 
					 | 
				
			||||||
		RepoID: repoID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, key)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrDeployKeyNotExist{0, keyID, repoID}
 | 
							return nil, ErrDeployKeyNotExist{0, keyID, repoID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return key, nil
 | 
						return key, nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/ssh"
 | 
						"golang.org/x/crypto/ssh"
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ___________.__                                         .__        __
 | 
					// ___________.__                                         .__        __
 | 
				
			||||||
@@ -31,9 +32,7 @@ import (
 | 
				
			|||||||
// checkKeyFingerprint only checks if key fingerprint has been used as public key,
 | 
					// checkKeyFingerprint only checks if key fingerprint has been used as public key,
 | 
				
			||||||
// it is OK to use same key as deploy key for multiple repositories/users.
 | 
					// it is OK to use same key as deploy key for multiple repositories/users.
 | 
				
			||||||
func checkKeyFingerprint(ctx context.Context, fingerprint string) error {
 | 
					func checkKeyFingerprint(ctx context.Context, fingerprint string) error {
 | 
				
			||||||
	has, err := db.GetByBean(ctx, &PublicKey{
 | 
						has, err := db.Exist[PublicKey](ctx, builder.Eq{"fingerprint": fingerprint})
 | 
				
			||||||
		Fingerprint: fingerprint,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if has {
 | 
						} else if has {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models/db"
 | 
						"code.gitea.io/gitea/models/db"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Session represents a session compatible for go-chi session
 | 
					// Session represents a session compatible for go-chi session
 | 
				
			||||||
@@ -33,34 +35,28 @@ func UpdateSession(ctx context.Context, key string, data []byte) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ReadSession reads the data for the provided session
 | 
					// ReadSession reads the data for the provided session
 | 
				
			||||||
func ReadSession(ctx context.Context, key string) (*Session, error) {
 | 
					func ReadSession(ctx context.Context, key string) (*Session, error) {
 | 
				
			||||||
	session := Session{
 | 
					 | 
				
			||||||
		Key: key,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx, committer, err := db.TxContext(ctx)
 | 
						ctx, committer, err := db.TxContext(ctx)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer committer.Close()
 | 
						defer committer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if has, err := db.GetByBean(ctx, &session); err != nil {
 | 
						session, exist, err := db.Get[Session](ctx, builder.Eq{"key": key})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		session.Expiry = timeutil.TimeStampNow()
 | 
							session.Expiry = timeutil.TimeStampNow()
 | 
				
			||||||
		if err := db.Insert(ctx, &session); err != nil {
 | 
							if err := db.Insert(ctx, &session); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &session, committer.Commit()
 | 
						return session, committer.Commit()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ExistSession checks if a session exists
 | 
					// ExistSession checks if a session exists
 | 
				
			||||||
func ExistSession(ctx context.Context, key string) (bool, error) {
 | 
					func ExistSession(ctx context.Context, key string) (bool, error) {
 | 
				
			||||||
	session := Session{
 | 
						return db.Exist[Session](ctx, builder.Eq{"key": key})
 | 
				
			||||||
		Key: key,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return db.GetEngine(ctx).Get(&session)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DestroySession destroys a session
 | 
					// DestroySession destroys a session
 | 
				
			||||||
@@ -79,17 +75,13 @@ func RegenerateSession(ctx context.Context, oldKey, newKey string) (*Session, er
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	defer committer.Close()
 | 
						defer committer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if has, err := db.GetByBean(ctx, &Session{
 | 
						if has, err := db.Exist[Session](ctx, builder.Eq{"key": newKey}); err != nil {
 | 
				
			||||||
		Key: newKey,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if has {
 | 
						} else if has {
 | 
				
			||||||
		return nil, fmt.Errorf("session Key: %s already exists", newKey)
 | 
							return nil, fmt.Errorf("session Key: %s already exists", newKey)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if has, err := db.GetByBean(ctx, &Session{
 | 
						if has, err := db.Exist[Session](ctx, builder.Eq{"key": oldKey}); err != nil {
 | 
				
			||||||
		Key: oldKey,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !has {
 | 
				
			||||||
		if err := db.Insert(ctx, &Session{
 | 
							if err := db.Insert(ctx, &Session{
 | 
				
			||||||
@@ -104,14 +96,13 @@ func RegenerateSession(ctx context.Context, oldKey, newKey string) (*Session, er
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s := Session{
 | 
						s, _, err := db.Get[Session](ctx, builder.Eq{"key": newKey})
 | 
				
			||||||
		Key: newKey,
 | 
						if err != nil {
 | 
				
			||||||
	}
 | 
							// is not exist, it should be impossible
 | 
				
			||||||
	if _, err := db.GetByBean(ctx, &s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &s, committer.Commit()
 | 
						return s, committer.Commit()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CountSessions returns the number of sessions
 | 
					// CountSessions returns the number of sessions
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -265,10 +265,10 @@ func IsSSPIEnabled(ctx context.Context) bool {
 | 
				
			|||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exist, err := db.Exists[Source](ctx, FindSourcesOptions{
 | 
						exist, err := db.Exist[Source](ctx, FindSourcesOptions{
 | 
				
			||||||
		IsActive:  util.OptionalBoolTrue,
 | 
							IsActive:  util.OptionalBoolTrue,
 | 
				
			||||||
		LoginType: SSPI,
 | 
							LoginType: SSPI,
 | 
				
			||||||
	})
 | 
						}.ToConds())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error("Active SSPI Sources: %v", err)
 | 
							log.Error("Active SSPI Sources: %v", err)
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,9 +173,44 @@ func Exec(ctx context.Context, sqlAndArgs ...any) (sql.Result, error) {
 | 
				
			|||||||
	return GetEngine(ctx).Exec(sqlAndArgs...)
 | 
						return GetEngine(ctx).Exec(sqlAndArgs...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetByBean filled empty fields of the bean according non-empty fields to query in database.
 | 
					func Get[T any](ctx context.Context, cond builder.Cond) (object *T, exist bool, err error) {
 | 
				
			||||||
func GetByBean(ctx context.Context, bean any) (bool, error) {
 | 
						if !cond.IsValid() {
 | 
				
			||||||
	return GetEngine(ctx).Get(bean)
 | 
							return nil, false, ErrConditionRequired{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var bean T
 | 
				
			||||||
 | 
						has, err := GetEngine(ctx).Where(cond).NoAutoCondition().Get(&bean)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, false, err
 | 
				
			||||||
 | 
						} else if !has {
 | 
				
			||||||
 | 
							return nil, false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &bean, true, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetByID[T any](ctx context.Context, id int64) (object *T, exist bool, err error) {
 | 
				
			||||||
 | 
						var bean T
 | 
				
			||||||
 | 
						has, err := GetEngine(ctx).ID(id).NoAutoCondition().Get(&bean)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, false, err
 | 
				
			||||||
 | 
						} else if !has {
 | 
				
			||||||
 | 
							return nil, false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &bean, true, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Exist[T any](ctx context.Context, cond builder.Cond) (bool, error) {
 | 
				
			||||||
 | 
						if !cond.IsValid() {
 | 
				
			||||||
 | 
							return false, ErrConditionRequired{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var bean T
 | 
				
			||||||
 | 
						return GetEngine(ctx).Where(cond).NoAutoCondition().Exist(&bean)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExistByID[T any](ctx context.Context, id int64) (bool, error) {
 | 
				
			||||||
 | 
						var bean T
 | 
				
			||||||
 | 
						return GetEngine(ctx).ID(id).NoAutoCondition().Exist(&bean)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteByBean deletes all records according non-empty fields of the bean as conditions.
 | 
					// DeleteByBean deletes all records according non-empty fields of the bean as conditions.
 | 
				
			||||||
@@ -264,8 +299,3 @@ func inTransaction(ctx context.Context) (*xorm.Session, bool) {
 | 
				
			|||||||
		return nil, false
 | 
							return nil, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func Exists[T any](ctx context.Context, opts FindOptions) (bool, error) {
 | 
					 | 
				
			||||||
	var bean T
 | 
					 | 
				
			||||||
	return GetEngine(ctx).Where(opts.ToConds()).Exist(&bean)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,3 +72,21 @@ func (err ErrNotExist) Error() string {
 | 
				
			|||||||
func (err ErrNotExist) Unwrap() error {
 | 
					func (err ErrNotExist) Unwrap() error {
 | 
				
			||||||
	return util.ErrNotExist
 | 
						return util.ErrNotExist
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ErrConditionRequired represents an error which require condition.
 | 
				
			||||||
 | 
					type ErrConditionRequired struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsErrConditionRequired checks if an error is an ErrConditionRequired
 | 
				
			||||||
 | 
					func IsErrConditionRequired(err error) bool {
 | 
				
			||||||
 | 
						_, ok := err.(ErrConditionRequired)
 | 
				
			||||||
 | 
						return ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (err ErrConditionRequired) Error() string {
 | 
				
			||||||
 | 
						return "condition is required"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unwrap unwraps this as a ErrNotExist err
 | 
				
			||||||
 | 
					func (err ErrConditionRequired) Unwrap() error {
 | 
				
			||||||
 | 
						return util.ErrInvalidArgument
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,11 +31,11 @@ func TestIterate(t *testing.T) {
 | 
				
			|||||||
	assert.EqualValues(t, cnt, repoUnitCnt)
 | 
						assert.EqualValues(t, cnt, repoUnitCnt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
 | 
						err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
 | 
				
			||||||
		reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
 | 
							has, err := db.ExistByID[repo_model.RepoUnit](ctx, repoUnit.ID)
 | 
				
			||||||
		has, err := db.GetByBean(ctx, &reopUnit2)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		} else if !has {
 | 
							}
 | 
				
			||||||
 | 
							if !has {
 | 
				
			||||||
			return db.ErrNotExist{Resource: "repo_unit", ID: repoUnit.ID}
 | 
								return db.ErrNotExist{Resource: "repo_unit", ID: repoUnit.ID}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		assert.EqualValues(t, repoUnit.RepoID, repoUnit.RepoID)
 | 
							assert.EqualValues(t, repoUnit.RepoID, repoUnit.RepoID)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -135,7 +135,7 @@ var ErrLFSObjectNotExist = db.ErrNotExist{Resource: "LFS Meta object"}
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
 | 
					// NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
 | 
				
			||||||
// if it is not already present.
 | 
					// if it is not already present.
 | 
				
			||||||
func NewLFSMetaObject(ctx context.Context, m *LFSMetaObject) (*LFSMetaObject, error) {
 | 
					func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMetaObject, error) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx, committer, err := db.TxContext(ctx)
 | 
						ctx, committer, err := db.TxContext(ctx)
 | 
				
			||||||
@@ -144,16 +144,15 @@ func NewLFSMetaObject(ctx context.Context, m *LFSMetaObject) (*LFSMetaObject, er
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	defer committer.Close()
 | 
						defer committer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	has, err := db.GetByBean(ctx, m)
 | 
						m, exist, err := db.Get[LFSMetaObject](ctx, builder.Eq{"repository_id": repoID, "oid": p.Oid})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						} else if exist {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if has {
 | 
					 | 
				
			||||||
		m.Existing = true
 | 
							m.Existing = true
 | 
				
			||||||
		return m, committer.Commit()
 | 
							return m, committer.Commit()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m = &LFSMetaObject{Pointer: p, RepositoryID: repoID}
 | 
				
			||||||
	if err = db.Insert(ctx, m); err != nil {
 | 
						if err = db.Insert(ctx, m); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/gobwas/glob"
 | 
						"github.com/gobwas/glob"
 | 
				
			||||||
	"github.com/gobwas/glob/syntax"
 | 
						"github.com/gobwas/glob/syntax"
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ErrBranchIsProtected = errors.New("branch is protected")
 | 
					var ErrBranchIsProtected = errors.New("branch is protected")
 | 
				
			||||||
@@ -274,12 +275,11 @@ func (protectBranch *ProtectedBranch) IsUnprotectedFile(patterns []glob.Glob, pa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetProtectedBranchRuleByName getting protected branch rule by name
 | 
					// GetProtectedBranchRuleByName getting protected branch rule by name
 | 
				
			||||||
func GetProtectedBranchRuleByName(ctx context.Context, repoID int64, ruleName string) (*ProtectedBranch, error) {
 | 
					func GetProtectedBranchRuleByName(ctx context.Context, repoID int64, ruleName string) (*ProtectedBranch, error) {
 | 
				
			||||||
	rel := &ProtectedBranch{RepoID: repoID, RuleName: ruleName}
 | 
						// branch_name is legacy name, it actually is rule name
 | 
				
			||||||
	has, err := db.GetByBean(ctx, rel)
 | 
						rel, exist, err := db.Get[ProtectedBranch](ctx, builder.Eq{"repo_id": repoID, "branch_name": ruleName})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						} else if !exist {
 | 
				
			||||||
	if !has {
 | 
					 | 
				
			||||||
		return nil, nil
 | 
							return nil, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return rel, nil
 | 
						return rel, nil
 | 
				
			||||||
@@ -287,12 +287,10 @@ func GetProtectedBranchRuleByName(ctx context.Context, repoID int64, ruleName st
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetProtectedBranchRuleByID getting protected branch rule by rule ID
 | 
					// GetProtectedBranchRuleByID getting protected branch rule by rule ID
 | 
				
			||||||
func GetProtectedBranchRuleByID(ctx context.Context, repoID, ruleID int64) (*ProtectedBranch, error) {
 | 
					func GetProtectedBranchRuleByID(ctx context.Context, repoID, ruleID int64) (*ProtectedBranch, error) {
 | 
				
			||||||
	rel := &ProtectedBranch{ID: ruleID, RepoID: repoID}
 | 
						rel, exist, err := db.Get[ProtectedBranch](ctx, builder.Eq{"repo_id": repoID, "id": ruleID})
 | 
				
			||||||
	has, err := db.GetByBean(ctx, rel)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						} else if !exist {
 | 
				
			||||||
	if !has {
 | 
					 | 
				
			||||||
		return nil, nil
 | 
							return nil, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return rel, nil
 | 
						return rel, nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,8 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/models/db"
 | 
						"code.gitea.io/gitea/models/db"
 | 
				
			||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IssueAssignees saves all issue assignees
 | 
					// IssueAssignees saves all issue assignees
 | 
				
			||||||
@@ -59,7 +61,7 @@ func GetAssigneeIDsByIssue(ctx context.Context, issueID int64) ([]int64, error)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// IsUserAssignedToIssue returns true when the user is assigned to the issue
 | 
					// IsUserAssignedToIssue returns true when the user is assigned to the issue
 | 
				
			||||||
func IsUserAssignedToIssue(ctx context.Context, issue *Issue, user *user_model.User) (isAssigned bool, err error) {
 | 
					func IsUserAssignedToIssue(ctx context.Context, issue *Issue, user *user_model.User) (isAssigned bool, err error) {
 | 
				
			||||||
	return db.GetByBean(ctx, &IssueAssignees{IssueID: issue.ID, AssigneeID: user.ID})
 | 
						return db.Exist[IssueAssignees](ctx, builder.Eq{"assignee_id": user.ID, "issue_id": issue.ID})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToggleIssueAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
 | 
					// ToggleIssueAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -304,15 +304,11 @@ func GetLabelInRepoByName(ctx context.Context, repoID int64, labelName string) (
 | 
				
			|||||||
		return nil, ErrRepoLabelNotExist{0, repoID}
 | 
							return nil, ErrRepoLabelNotExist{0, repoID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l := &Label{
 | 
						l, exist, err := db.Get[Label](ctx, builder.Eq{"name": labelName, "repo_id": repoID})
 | 
				
			||||||
		Name:   labelName,
 | 
					 | 
				
			||||||
		RepoID: repoID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, l)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrRepoLabelNotExist{0, l.RepoID}
 | 
							return nil, ErrRepoLabelNotExist{0, repoID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return l, nil
 | 
						return l, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -323,15 +319,11 @@ func GetLabelInRepoByID(ctx context.Context, repoID, labelID int64) (*Label, err
 | 
				
			|||||||
		return nil, ErrRepoLabelNotExist{labelID, repoID}
 | 
							return nil, ErrRepoLabelNotExist{labelID, repoID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l := &Label{
 | 
						l, exist, err := db.Get[Label](ctx, builder.Eq{"id": labelID, "repo_id": repoID})
 | 
				
			||||||
		ID:     labelID,
 | 
					 | 
				
			||||||
		RepoID: repoID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, l)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrRepoLabelNotExist{l.ID, l.RepoID}
 | 
							return nil, ErrRepoLabelNotExist{labelID, repoID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return l, nil
 | 
						return l, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -408,15 +400,11 @@ func GetLabelInOrgByName(ctx context.Context, orgID int64, labelName string) (*L
 | 
				
			|||||||
		return nil, ErrOrgLabelNotExist{0, orgID}
 | 
							return nil, ErrOrgLabelNotExist{0, orgID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l := &Label{
 | 
						l, exist, err := db.Get[Label](ctx, builder.Eq{"name": labelName, "org_id": orgID})
 | 
				
			||||||
		Name:  labelName,
 | 
					 | 
				
			||||||
		OrgID: orgID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, l)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrOrgLabelNotExist{0, l.OrgID}
 | 
							return nil, ErrOrgLabelNotExist{0, orgID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return l, nil
 | 
						return l, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -427,15 +415,11 @@ func GetLabelInOrgByID(ctx context.Context, orgID, labelID int64) (*Label, error
 | 
				
			|||||||
		return nil, ErrOrgLabelNotExist{labelID, orgID}
 | 
							return nil, ErrOrgLabelNotExist{labelID, orgID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l := &Label{
 | 
						l, exist, err := db.Get[Label](ctx, builder.Eq{"id": labelID, "org_id": orgID})
 | 
				
			||||||
		ID:    labelID,
 | 
					 | 
				
			||||||
		OrgID: orgID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, l)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrOrgLabelNotExist{l.ID, l.OrgID}
 | 
							return nil, ErrOrgLabelNotExist{labelID, orgID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return l, nil
 | 
						return l, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -660,13 +660,10 @@ func GetPullRequestByIssueIDWithNoAttributes(ctx context.Context, issueID int64)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetPullRequestByIssueID returns pull request by given issue ID.
 | 
					// GetPullRequestByIssueID returns pull request by given issue ID.
 | 
				
			||||||
func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest, error) {
 | 
					func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest, error) {
 | 
				
			||||||
	pr := &PullRequest{
 | 
						pr, exist, err := db.Get[PullRequest](ctx, builder.Eq{"issue_id": issueID})
 | 
				
			||||||
		IssueID: issueID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, pr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""}
 | 
							return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return pr, pr.LoadAttributes(ctx)
 | 
						return pr, pr.LoadAttributes(ctx)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -162,7 +162,7 @@ func NewTeam(ctx context.Context, t *organization.Team) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	has, err := db.GetEngine(ctx).ID(t.OrgID).Get(new(user_model.User))
 | 
						has, err := db.ExistByID[user_model.User](ctx, t.OrgID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -171,10 +171,10 @@ func NewTeam(ctx context.Context, t *organization.Team) (err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.LowerName = strings.ToLower(t.Name)
 | 
						t.LowerName = strings.ToLower(t.Name)
 | 
				
			||||||
	has, err = db.GetEngine(ctx).
 | 
						has, err = db.Exist[organization.Team](ctx, builder.Eq{
 | 
				
			||||||
		Where("org_id=?", t.OrgID).
 | 
							"org_id":     t.OrgID,
 | 
				
			||||||
		And("lower_name=?", t.LowerName).
 | 
							"lower_name": t.LowerName,
 | 
				
			||||||
		Get(new(organization.Team))
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -232,20 +232,20 @@ func UpdateTeam(ctx context.Context, t *organization.Team, authChanged, includeA
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer committer.Close()
 | 
						defer committer.Close()
 | 
				
			||||||
	sess := db.GetEngine(ctx)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.LowerName = strings.ToLower(t.Name)
 | 
						t.LowerName = strings.ToLower(t.Name)
 | 
				
			||||||
	has, err := sess.
 | 
						has, err := db.Exist[organization.Team](ctx, builder.Eq{
 | 
				
			||||||
		Where("org_id=?", t.OrgID).
 | 
							"org_id":     t.OrgID,
 | 
				
			||||||
		And("lower_name=?", t.LowerName).
 | 
							"lower_name": t.LowerName,
 | 
				
			||||||
		And("id!=?", t.ID).
 | 
						}.And(builder.Neq{"id": t.ID}),
 | 
				
			||||||
		Get(new(organization.Team))
 | 
						)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if has {
 | 
						} else if has {
 | 
				
			||||||
		return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName}
 | 
							return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess := db.GetEngine(ctx)
 | 
				
			||||||
	if _, err = sess.ID(t.ID).Cols("name", "lower_name", "description",
 | 
						if _, err = sess.ID(t.ID).Cols("name", "lower_name", "description",
 | 
				
			||||||
		"can_create_org_repo", "authorize", "includes_all_repositories").Update(t); err != nil {
 | 
							"can_create_org_repo", "authorize", "includes_all_repositories").Update(t); err != nil {
 | 
				
			||||||
		return fmt.Errorf("update: %w", err)
 | 
							return fmt.Errorf("update: %w", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,8 @@ import (
 | 
				
			|||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ___________
 | 
					// ___________
 | 
				
			||||||
@@ -203,14 +205,10 @@ func IsUsableTeamName(name string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetTeam returns team by given team name and organization.
 | 
					// GetTeam returns team by given team name and organization.
 | 
				
			||||||
func GetTeam(ctx context.Context, orgID int64, name string) (*Team, error) {
 | 
					func GetTeam(ctx context.Context, orgID int64, name string) (*Team, error) {
 | 
				
			||||||
	t := &Team{
 | 
						t, exist, err := db.Get[Team](ctx, builder.Eq{"org_id": orgID, "lower_name": strings.ToLower(name)})
 | 
				
			||||||
		OrgID:     orgID,
 | 
					 | 
				
			||||||
		LowerName: strings.ToLower(name),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, t)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrTeamNotExist{orgID, 0, name}
 | 
							return nil, ErrTeamNotExist{orgID, 0, name}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return t, nil
 | 
						return t, nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,8 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/models/perm"
 | 
						"code.gitea.io/gitea/models/perm"
 | 
				
			||||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
						repo_model "code.gitea.io/gitea/models/repo"
 | 
				
			||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Access represents the highest access level of a user to the repository. The only access type
 | 
					// Access represents the highest access level of a user to the repository. The only access type
 | 
				
			||||||
@@ -51,9 +53,11 @@ func accessLevel(ctx context.Context, user *user_model.User, repo *repo_model.Re
 | 
				
			|||||||
		return perm.AccessModeOwner, nil
 | 
							return perm.AccessModeOwner, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	a := &Access{UserID: userID, RepoID: repo.ID}
 | 
						a, exist, err := db.Get[Access](ctx, builder.Eq{"user_id": userID, "repo_id": repo.ID})
 | 
				
			||||||
	if has, err := db.GetByBean(ctx, a); !has || err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return mode, err
 | 
							return mode, err
 | 
				
			||||||
 | 
						} else if !exist {
 | 
				
			||||||
 | 
							return mode, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return a.Mode, nil
 | 
						return a.Mode, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,8 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting/config"
 | 
						"code.gitea.io/gitea/modules/setting/config"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Setting struct {
 | 
					type Setting struct {
 | 
				
			||||||
@@ -36,16 +38,17 @@ func init() {
 | 
				
			|||||||
const keyRevision = "revision"
 | 
					const keyRevision = "revision"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetRevision(ctx context.Context) int {
 | 
					func GetRevision(ctx context.Context) int {
 | 
				
			||||||
	revision := &Setting{SettingKey: keyRevision}
 | 
						revision, exist, err := db.Get[Setting](ctx, builder.Eq{"setting_key": keyRevision})
 | 
				
			||||||
	if has, err := db.GetByBean(ctx, revision); err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0
 | 
							return 0
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		err = db.Insert(ctx, &Setting{SettingKey: keyRevision, Version: 1})
 | 
							err = db.Insert(ctx, &Setting{SettingKey: keyRevision, Version: 1})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return 0
 | 
								return 0
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 1
 | 
							return 1
 | 
				
			||||||
	} else if revision.Version <= 0 || revision.Version >= math.MaxInt-1 {
 | 
						}
 | 
				
			||||||
 | 
						if revision.Version <= 0 || revision.Version >= math.MaxInt-1 {
 | 
				
			||||||
		_, err = db.Exec(ctx, "UPDATE system_setting SET version=1 WHERE setting_key=?", keyRevision)
 | 
							_, err = db.Exec(ctx, "UPDATE system_setting SET version=1 WHERE setting_key=?", keyRevision)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return 0
 | 
								return 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,14 +41,11 @@ func TestSettings(t *testing.T) {
 | 
				
			|||||||
	assert.EqualValues(t, "false", settings[keyName])
 | 
						assert.EqualValues(t, "false", settings[keyName])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// setting the same value should not trigger DuplicateKey error, and the "version" should be increased
 | 
						// setting the same value should not trigger DuplicateKey error, and the "version" should be increased
 | 
				
			||||||
	setting := &system.Setting{SettingKey: keyName}
 | 
					 | 
				
			||||||
	_, err = db.GetByBean(db.DefaultContext, setting)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	assert.EqualValues(t, 2, setting.Version)
 | 
					 | 
				
			||||||
	err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "false"})
 | 
						err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "false"})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	setting = &system.Setting{SettingKey: keyName}
 | 
					
 | 
				
			||||||
	_, err = db.GetByBean(db.DefaultContext, setting)
 | 
						rev, settings, err = system.GetAllSettings(db.DefaultContext)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.EqualValues(t, 3, setting.Version)
 | 
						assert.Len(t, settings, 2)
 | 
				
			||||||
 | 
						assert.EqualValues(t, 4, rev)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -527,12 +527,13 @@ func ActivateUserEmail(ctx context.Context, userID int64, email string, activate
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Activate/deactivate a user's secondary email address
 | 
						// Activate/deactivate a user's secondary email address
 | 
				
			||||||
	// First check if there's another user active with the same address
 | 
						// First check if there's another user active with the same address
 | 
				
			||||||
	addr := EmailAddress{UID: userID, LowerEmail: strings.ToLower(email)}
 | 
						addr, exist, err := db.Get[EmailAddress](ctx, builder.Eq{"uid": userID, "lower_email": strings.ToLower(email)})
 | 
				
			||||||
	if has, err := db.GetByBean(ctx, &addr); err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return fmt.Errorf("no such email: %d (%s)", userID, email)
 | 
							return fmt.Errorf("no such email: %d (%s)", userID, email)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if addr.IsActivated == activate {
 | 
						if addr.IsActivated == activate {
 | 
				
			||||||
		// Already in the desired state; no action
 | 
							// Already in the desired state; no action
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -544,25 +545,26 @@ func ActivateUserEmail(ctx context.Context, userID int64, email string, activate
 | 
				
			|||||||
			return ErrEmailAlreadyUsed{Email: email}
 | 
								return ErrEmailAlreadyUsed{Email: email}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err = updateActivation(ctx, &addr, activate); err != nil {
 | 
						if err = updateActivation(ctx, addr, activate); err != nil {
 | 
				
			||||||
		return fmt.Errorf("unable to updateActivation() for %d:%s: %w", addr.ID, addr.Email, err)
 | 
							return fmt.Errorf("unable to updateActivation() for %d:%s: %w", addr.ID, addr.Email, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Activate/deactivate a user's primary email address and account
 | 
						// Activate/deactivate a user's primary email address and account
 | 
				
			||||||
	if addr.IsPrimary {
 | 
						if addr.IsPrimary {
 | 
				
			||||||
		user := User{ID: userID, Email: email}
 | 
							user, exist, err := db.Get[User](ctx, builder.Eq{"id": userID, "email": email})
 | 
				
			||||||
		if has, err := db.GetByBean(ctx, &user); err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		} else if !has {
 | 
							} else if !exist {
 | 
				
			||||||
			return fmt.Errorf("no user with ID: %d and Email: %s", userID, email)
 | 
								return fmt.Errorf("no user with ID: %d and Email: %s", userID, email)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// The user's activation state should be synchronized with the primary email
 | 
							// The user's activation state should be synchronized with the primary email
 | 
				
			||||||
		if user.IsActive != activate {
 | 
							if user.IsActive != activate {
 | 
				
			||||||
			user.IsActive = activate
 | 
								user.IsActive = activate
 | 
				
			||||||
			if user.Rands, err = GetUserSalt(); err != nil {
 | 
								if user.Rands, err = GetUserSalt(); err != nil {
 | 
				
			||||||
				return fmt.Errorf("unable to generate salt: %w", err)
 | 
									return fmt.Errorf("unable to generate salt: %w", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if err = UpdateUserCols(ctx, &user, "is_active", "rands"); err != nil {
 | 
								if err = UpdateUserCols(ctx, user, "is_active", "rands"); err != nil {
 | 
				
			||||||
				return fmt.Errorf("unable to updateUserCols() for user ID: %d: %w", userID, err)
 | 
									return fmt.Errorf("unable to updateUserCols() for user ID: %d: %w", userID, err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,9 +98,10 @@ func GetExternalLogin(ctx context.Context, externalLoginUser *ExternalLoginUser)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// LinkExternalToUser link the external user to the user
 | 
					// LinkExternalToUser link the external user to the user
 | 
				
			||||||
func LinkExternalToUser(ctx context.Context, user *User, externalLoginUser *ExternalLoginUser) error {
 | 
					func LinkExternalToUser(ctx context.Context, user *User, externalLoginUser *ExternalLoginUser) error {
 | 
				
			||||||
	has, err := db.GetEngine(ctx).Where("external_id=? AND login_source_id=?", externalLoginUser.ExternalID, externalLoginUser.LoginSourceID).
 | 
						has, err := db.Exist[ExternalLoginUser](ctx, builder.Eq{
 | 
				
			||||||
		NoAutoCondition().
 | 
							"external_id":     externalLoginUser.ExternalID,
 | 
				
			||||||
		Exist(externalLoginUser)
 | 
							"login_source_id": externalLoginUser.LoginSourceID,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if has {
 | 
						} else if has {
 | 
				
			||||||
@@ -145,9 +146,10 @@ func GetUserIDByExternalUserID(ctx context.Context, provider, userID string) (in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// UpdateExternalUserByExternalID updates an external user's information
 | 
					// UpdateExternalUserByExternalID updates an external user's information
 | 
				
			||||||
func UpdateExternalUserByExternalID(ctx context.Context, external *ExternalLoginUser) error {
 | 
					func UpdateExternalUserByExternalID(ctx context.Context, external *ExternalLoginUser) error {
 | 
				
			||||||
	has, err := db.GetEngine(ctx).Where("external_id=? AND login_source_id=?", external.ExternalID, external.LoginSourceID).
 | 
						has, err := db.Exist[ExternalLoginUser](ctx, builder.Eq{
 | 
				
			||||||
		NoAutoCondition().
 | 
							"external_id":     external.ExternalID,
 | 
				
			||||||
		Exist(external)
 | 
							"login_source_id": external.LoginSourceID,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !has {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ import (
 | 
				
			|||||||
	webhook_module "code.gitea.io/gitea/modules/webhook"
 | 
						webhook_module "code.gitea.io/gitea/modules/webhook"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gouuid "github.com/google/uuid"
 | 
						gouuid "github.com/google/uuid"
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//   ___ ___                __   ___________              __
 | 
					//   ___ ___                __   ___________              __
 | 
				
			||||||
@@ -150,14 +151,10 @@ func UpdateHookTask(ctx context.Context, t *HookTask) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ReplayHookTask copies a hook task to get re-delivered
 | 
					// ReplayHookTask copies a hook task to get re-delivered
 | 
				
			||||||
func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask, error) {
 | 
					func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask, error) {
 | 
				
			||||||
	task := &HookTask{
 | 
						task, exist, err := db.Get[HookTask](ctx, builder.Eq{"hook_id": hookID, "uuid": uuid})
 | 
				
			||||||
		HookID: hookID,
 | 
					 | 
				
			||||||
		UUID:   uuid,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := db.GetByBean(ctx, task)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrHookTaskNotExist{
 | 
							return nil, ErrHookTaskNotExist{
 | 
				
			||||||
			HookID: hookID,
 | 
								HookID: hookID,
 | 
				
			||||||
			UUID:   uuid,
 | 
								UUID:   uuid,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,24 +11,27 @@ import (
 | 
				
			|||||||
	access_model "code.gitea.io/gitea/models/perm/access"
 | 
						access_model "code.gitea.io/gitea/models/perm/access"
 | 
				
			||||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
						repo_model "code.gitea.io/gitea/models/repo"
 | 
				
			||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func AddCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
 | 
					func AddCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
 | 
				
			||||||
	return db.WithTx(ctx, func(ctx context.Context) error {
 | 
						return db.WithTx(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		collaboration := &repo_model.Collaboration{
 | 
							has, err := db.Exist[repo_model.Collaboration](ctx, builder.Eq{
 | 
				
			||||||
			RepoID: repo.ID,
 | 
								"repo_id": repo.ID,
 | 
				
			||||||
			UserID: u.ID,
 | 
								"user_id": u.ID,
 | 
				
			||||||
		}
 | 
							})
 | 
				
			||||||
 | 
					 | 
				
			||||||
		has, err := db.GetByBean(ctx, collaboration)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		} else if has {
 | 
							} else if has {
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		collaboration.Mode = perm.AccessModeWrite
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err = db.Insert(ctx, collaboration); err != nil {
 | 
							if err = db.Insert(ctx, &repo_model.Collaboration{
 | 
				
			||||||
 | 
								RepoID: repo.ID,
 | 
				
			||||||
 | 
								UserID: u.ID,
 | 
				
			||||||
 | 
								Mode:   perm.AccessModeWrite,
 | 
				
			||||||
 | 
							}); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -409,7 +409,7 @@ func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Re
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			defer content.Close()
 | 
								defer content.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			_, err := git_model.NewLFSMetaObject(ctx, &git_model.LFSMetaObject{Pointer: p, RepositoryID: repo.ID})
 | 
								_, err := git_model.NewLFSMetaObject(ctx, repo.ID, p)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, p, err)
 | 
									log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, p, err)
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
@@ -456,7 +456,7 @@ func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Re
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if exist {
 | 
							if exist {
 | 
				
			||||||
			log.Trace("Repo[%-v]: LFS object %-v already present; creating meta object", repo, pointerBlob.Pointer)
 | 
								log.Trace("Repo[%-v]: LFS object %-v already present; creating meta object", repo, pointerBlob.Pointer)
 | 
				
			||||||
			_, err := git_model.NewLFSMetaObject(ctx, &git_model.LFSMetaObject{Pointer: pointerBlob.Pointer, RepositoryID: repo.ID})
 | 
								_, err := git_model.NewLFSMetaObject(ctx, repo.ID, pointerBlob.Pointer)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, pointerBlob.Pointer, err)
 | 
									log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, pointerBlob.Pointer, err)
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,7 +232,7 @@ func BatchHandler(ctx *context.Context) {
 | 
				
			|||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if accessible {
 | 
									if accessible {
 | 
				
			||||||
					_, err := git_model.NewLFSMetaObject(ctx, &git_model.LFSMetaObject{Pointer: p, RepositoryID: repository.ID})
 | 
										_, err := git_model.NewLFSMetaObject(ctx, repository.ID, p)
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						log.Error("Unable to create LFS MetaObject [%s] for %s/%s. Error: %v", p.Oid, rc.User, rc.Repo, err)
 | 
											log.Error("Unable to create LFS MetaObject [%s] for %s/%s. Error: %v", p.Oid, rc.User, rc.Repo, err)
 | 
				
			||||||
						writeStatus(ctx, http.StatusInternalServerError)
 | 
											writeStatus(ctx, http.StatusInternalServerError)
 | 
				
			||||||
@@ -325,7 +325,7 @@ func UploadHandler(ctx *context.Context) {
 | 
				
			|||||||
			log.Error("Error putting LFS MetaObject [%s] into content store. Error: %v", p.Oid, err)
 | 
								log.Error("Error putting LFS MetaObject [%s] into content store. Error: %v", p.Oid, err)
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		_, err := git_model.NewLFSMetaObject(ctx, &git_model.LFSMetaObject{Pointer: p, RepositoryID: repository.ID})
 | 
							_, err := git_model.NewLFSMetaObject(ctx, repository.ID, p)
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -127,9 +127,7 @@ func createLFSMetaObjectsFromCatFileBatch(ctx context.Context, catFileBatchReade
 | 
				
			|||||||
		// OK we have a pointer that is associated with the head repo
 | 
							// OK we have a pointer that is associated with the head repo
 | 
				
			||||||
		// and is actually a file in the LFS
 | 
							// and is actually a file in the LFS
 | 
				
			||||||
		// Therefore it should be associated with the base repo
 | 
							// Therefore it should be associated with the base repo
 | 
				
			||||||
		meta := &git_model.LFSMetaObject{Pointer: pointer}
 | 
							if _, err := git_model.NewLFSMetaObject(ctx, pr.BaseRepoID, pointer); err != nil {
 | 
				
			||||||
		meta.RepositoryID = pr.BaseRepoID
 | 
					 | 
				
			||||||
		if _, err := git_model.NewLFSMetaObject(ctx, meta); err != nil {
 | 
					 | 
				
			||||||
			_ = catFileBatchReader.CloseWithError(err)
 | 
								_ = catFileBatchReader.CloseWithError(err)
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -438,7 +438,7 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if lfsMetaObject != nil {
 | 
						if lfsMetaObject != nil {
 | 
				
			||||||
		// We have an LFS object - create it
 | 
							// We have an LFS object - create it
 | 
				
			||||||
		lfsMetaObject, err = git_model.NewLFSMetaObject(ctx, lfsMetaObject)
 | 
							lfsMetaObject, err = git_model.NewLFSMetaObject(ctx, lfsMetaObject.RepositoryID, lfsMetaObject.Pointer)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,7 +143,7 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
 | 
				
			|||||||
		if infos[i].lfsMetaObject == nil {
 | 
							if infos[i].lfsMetaObject == nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		infos[i].lfsMetaObject, err = git_model.NewLFSMetaObject(ctx, infos[i].lfsMetaObject)
 | 
							infos[i].lfsMetaObject, err = git_model.NewLFSMetaObject(ctx, infos[i].lfsMetaObject.RepositoryID, infos[i].lfsMetaObject.Pointer)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			// OK Now we need to cleanup
 | 
								// OK Now we need to cleanup
 | 
				
			||||||
			return cleanUpAfterFailure(ctx, &infos, t, err)
 | 
								return cleanUpAfterFailure(ctx, &infos, t, err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,7 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string
 | 
				
			|||||||
	pointer, err := lfs.GeneratePointer(bytes.NewReader(*content))
 | 
						pointer, err := lfs.GeneratePointer(bytes.NewReader(*content))
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = git_model.NewLFSMetaObject(db.DefaultContext, &git_model.LFSMetaObject{Pointer: pointer, RepositoryID: repositoryID})
 | 
						_, err = git_model.NewLFSMetaObject(db.DefaultContext, repositoryID, pointer)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	contentStore := lfs.NewContentStore()
 | 
						contentStore := lfs.NewContentStore()
 | 
				
			||||||
	exist, err := contentStore.Exists(pointer)
 | 
						exist, err := contentStore.Exists(pointer)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string
 | 
				
			|||||||
	pointer, err := lfs.GeneratePointer(bytes.NewReader(*content))
 | 
						pointer, err := lfs.GeneratePointer(bytes.NewReader(*content))
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = git_model.NewLFSMetaObject(db.DefaultContext, &git_model.LFSMetaObject{Pointer: pointer, RepositoryID: repositoryID})
 | 
						_, err = git_model.NewLFSMetaObject(db.DefaultContext, repositoryID, pointer)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	contentStore := lfs.NewContentStore()
 | 
						contentStore := lfs.NewContentStore()
 | 
				
			||||||
	exist, err := contentStore.Exists(pointer)
 | 
						exist, err := contentStore.Exists(pointer)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user