aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/conf/mocks.go9
-rw-r--r--internal/db/pull.go27
-rw-r--r--internal/db/repo.go12
-rw-r--r--internal/db/user.go35
-rw-r--r--internal/db/users.go86
-rw-r--r--internal/db/users_test.go107
-rw-r--r--internal/repoutil/repoutil.go13
-rw-r--r--internal/repoutil/repoutil_test.go36
-rw-r--r--internal/route/lfs/mocks_test.go124
-rw-r--r--internal/route/org/setting.go7
-rw-r--r--internal/route/user/setting.go6
11 files changed, 394 insertions, 68 deletions
diff --git a/internal/conf/mocks.go b/internal/conf/mocks.go
index 2c10c1ce..51d1fb14 100644
--- a/internal/conf/mocks.go
+++ b/internal/conf/mocks.go
@@ -5,6 +5,7 @@
package conf
import (
+ "sync"
"testing"
)
@@ -24,11 +25,15 @@ func SetMockAuth(t *testing.T, otps AuthOpts) {
})
}
+var mockServer sync.Mutex
+
func SetMockServer(t *testing.T, opts ServerOpts) {
+ mockServer.Lock()
before := Server
Server = opts
t.Cleanup(func() {
Server = before
+ mockServer.Unlock()
})
}
@@ -40,11 +45,15 @@ func SetMockSSH(t *testing.T, opts SSHOpts) {
})
}
+var mockRepository sync.Mutex
+
func SetMockRepository(t *testing.T, opts RepositoryOpts) {
+ mockRepository.Lock()
before := Repository
Repository = opts
t.Cleanup(func() {
Repository = before
+ mockRepository.Unlock()
})
}
diff --git a/internal/db/pull.go b/internal/db/pull.go
index e2f55361..b0f723fa 100644
--- a/internal/db/pull.go
+++ b/internal/db/pull.go
@@ -9,7 +9,6 @@ import (
"fmt"
"os"
"path/filepath"
- "strings"
"time"
"github.com/unknwon/com"
@@ -45,28 +44,28 @@ const (
// PullRequest represents relation between pull request and repositories.
type PullRequest struct {
- ID int64
+ ID int64 `gorm:"primaryKey"`
Type PullRequestType
Status PullRequestStatus
- IssueID int64 `xorm:"INDEX"`
- Issue *Issue `xorm:"-" json:"-"`
+ IssueID int64 `xorm:"INDEX" gorm:"index"`
+ Issue *Issue `xorm:"-" json:"-" gorm:"-"`
Index int64
HeadRepoID int64
- HeadRepo *Repository `xorm:"-" json:"-"`
+ HeadRepo *Repository `xorm:"-" json:"-" gorm:"-"`
BaseRepoID int64
- BaseRepo *Repository `xorm:"-" json:"-"`
+ BaseRepo *Repository `xorm:"-" json:"-" gorm:"-"`
HeadUserName string
HeadBranch string
BaseBranch string
- MergeBase string `xorm:"VARCHAR(40)"`
+ MergeBase string `xorm:"VARCHAR(40)" gorm:"type:VARCHAR(40)"`
HasMerged bool
- MergedCommitID string `xorm:"VARCHAR(40)"`
+ MergedCommitID string `xorm:"VARCHAR(40)" gorm:"type:VARCHAR(40)"`
MergerID int64
- Merger *User `xorm:"-" json:"-"`
- Merged time.Time `xorm:"-" json:"-"`
+ Merger *User `xorm:"-" json:"-" gorm:"-"`
+ Merged time.Time `xorm:"-" json:"-" gorm:"-"`
MergedUnix int64
}
@@ -823,14 +822,6 @@ func AddTestPullRequestTask(doer *User, repoID int64, branch string, isSync bool
}
}
-func ChangeUsernameInPullRequests(oldUserName, newUserName string) error {
- pr := PullRequest{
- HeadUserName: strings.ToLower(newUserName),
- }
- _, err := x.Cols("head_user_name").Where("head_user_name = ?", strings.ToLower(oldUserName)).Update(pr)
- return err
-}
-
// checkAndUpdateStatus checks if pull request is possible to leaving checking status,
// and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() {
diff --git a/internal/db/repo.go b/internal/db/repo.go
index f9e19468..8abe47ed 100644
--- a/internal/db/repo.go
+++ b/internal/db/repo.go
@@ -1444,7 +1444,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
return fmt.Errorf("rename repository directory: %v", err)
}
- deleteRepoLocalCopy(repo)
+ deleteRepoLocalCopy(repo.ID)
// Rename remote wiki repository to new path and delete local copy.
wikiPath := WikiPath(owner.Name, repo.Name)
@@ -1458,10 +1458,10 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
return sess.Commit()
}
-func deleteRepoLocalCopy(repo *Repository) {
- repoWorkingPool.CheckIn(com.ToStr(repo.ID))
- defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
- RemoveAllWithNotice("Delete repository local copy", repo.LocalCopyPath())
+func deleteRepoLocalCopy(repoID int64) {
+ repoWorkingPool.CheckIn(com.ToStr(repoID))
+ defer repoWorkingPool.CheckOut(com.ToStr(repoID))
+ RemoveAllWithNotice(fmt.Sprintf("Delete repository %d local copy", repoID), repoutil.RepositoryLocalPath(repoID))
}
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
@@ -1497,7 +1497,7 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
}
- deleteRepoLocalCopy(repo)
+ deleteRepoLocalCopy(repo.ID)
return nil
}
diff --git a/internal/db/user.go b/internal/db/user.go
index 922a340a..5d75bfca 100644
--- a/internal/db/user.go
+++ b/internal/db/user.go
@@ -12,7 +12,6 @@ import (
"strings"
"time"
- "github.com/unknwon/com"
log "unknwon.dev/clog/v2"
"xorm.io/xorm"
@@ -57,40 +56,6 @@ func (u *User) getOrganizationCount(e Engine) (int64, error) {
return e.Where("uid=?", u.ID).Count(new(OrgUser))
}
-// ChangeUserName changes all corresponding setting from old user name to new one.
-func ChangeUserName(u *User, newUserName string) (err error) {
- if err = isUsernameAllowed(newUserName); err != nil {
- return err
- }
-
- if Users.IsUsernameUsed(context.TODO(), newUserName) {
- return ErrUserAlreadyExist{args: errutil.Args{"name": newUserName}}
- }
-
- if err = ChangeUsernameInPullRequests(u.Name, newUserName); err != nil {
- return fmt.Errorf("ChangeUsernameInPullRequests: %v", err)
- }
-
- // Delete all local copies of repositories and wikis the user owns.
- if err = x.Where("owner_id=?", u.ID).Iterate(new(Repository), func(idx int, bean interface{}) error {
- repo := bean.(*Repository)
- deleteRepoLocalCopy(repo)
- // TODO: By the same reasoning, shouldn't we also sync access to the local wiki path?
- RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
- return nil
- }); err != nil {
- return fmt.Errorf("delete repository and wiki local copy: %v", err)
- }
-
- // Rename or create user base directory
- baseDir := repoutil.UserPath(u.Name)
- newBaseDir := repoutil.UserPath(newUserName)
- if com.IsExist(baseDir) {
- return os.Rename(baseDir, newBaseDir)
- }
- return os.MkdirAll(newBaseDir, os.ModePerm)
-}
-
func updateUser(e Engine, u *User) error {
// Organization does not need email
if !u.IsOrganization() {
diff --git a/internal/db/users.go b/internal/db/users.go
index f12eca09..12fa90a2 100644
--- a/internal/db/users.go
+++ b/internal/db/users.go
@@ -24,6 +24,7 @@ import (
"gogs.io/gogs/internal/dbutil"
"gogs.io/gogs/internal/errutil"
"gogs.io/gogs/internal/osutil"
+ "gogs.io/gogs/internal/repoutil"
"gogs.io/gogs/internal/strutil"
"gogs.io/gogs/internal/tool"
"gogs.io/gogs/internal/userutil"
@@ -45,11 +46,17 @@ type UsersStore interface {
// When the "loginSourceID" is positive, it tries to authenticate via given
// login source and creates a new user when not yet exists in the database.
Authenticate(ctx context.Context, username, password string, loginSourceID int64) (*User, error)
+ // ChangeUsername changes the username of the given user and updates all
+ // references to the old username. It returns ErrNameNotAllowed if the given
+ // name or pattern of the name is not allowed as a username, or
+ // ErrUserAlreadyExist when another user with same name already exists.
+ ChangeUsername(ctx context.Context, userID int64, newUsername string) error
// Count returns the total number of users.
Count(ctx context.Context) int64
// Create creates a new user and persists to database. It returns
- // ErrUserAlreadyExist when a user with same name already exists, or
- // ErrEmailAlreadyUsed if the email has been used by another user.
+ // ErrNameNotAllowed if the given name or pattern of the name is not allowed as
+ // a username, or ErrUserAlreadyExist when a user with same name already exists,
+ // or ErrEmailAlreadyUsed if the email has been used by another user.
Create(ctx context.Context, username, email string, opts CreateUserOptions) (*User, error)
// DeleteCustomAvatar deletes the current user custom avatar and falls back to
// use look up avatar by email.
@@ -188,6 +195,81 @@ func (db *users) Authenticate(ctx context.Context, login, password string, login
)
}
+func (db *users) ChangeUsername(ctx context.Context, userID int64, newUsername string) error {
+ err := isUsernameAllowed(newUsername)
+ if err != nil {
+ return err
+ }
+
+ if db.IsUsernameUsed(ctx, newUsername) {
+ return ErrUserAlreadyExist{
+ args: errutil.Args{
+ "name": newUsername,
+ },
+ }
+ }
+
+ user, err := db.GetByID(ctx, userID)
+ if err != nil {
+ return errors.Wrap(err, "get user")
+ }
+
+ return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+ err := tx.Model(&User{}).
+ Where("id = ?", user.ID).
+ Updates(map[string]any{
+ "lower_name": strings.ToLower(newUsername),
+ "name": newUsername,
+ }).Error
+ if err != nil {
+ return errors.Wrap(err, "update user name")
+ }
+
+ // Update all references to the user name in pull requests
+ err = tx.Model(&PullRequest{}).
+ Where("head_user_name = ?", user.LowerName).
+ Update("head_user_name", strings.ToLower(newUsername)).
+ Error
+ if err != nil {
+ return errors.Wrap(err, `update "pull_request.head_user_name"`)
+ }
+
+ // Delete local copies of repositories and their wikis that are owned by the user
+ rows, err := tx.Model(&Repository{}).Where("owner_id = ?", user.ID).Rows()
+ if err != nil {
+ return errors.Wrap(err, "iterate repositories")
+ }
+ defer func() { _ = rows.Close() }()
+
+ for rows.Next() {
+ var repo struct {
+ ID int64
+ }
+ err = tx.ScanRows(rows, &repo)
+ if err != nil {
+ return errors.Wrap(err, "scan rows")
+ }
+
+ deleteRepoLocalCopy(repo.ID)
+ RemoveAllWithNotice(fmt.Sprintf("Delete repository %d wiki local copy", repo.ID), repoutil.RepositoryLocalWikiPath(repo.ID))
+ }
+ if err = rows.Err(); err != nil {
+ return errors.Wrap(err, "check rows.Err")
+ }
+
+ // Rename user directory if exists
+ userPath := repoutil.UserPath(user.Name)
+ if osutil.IsExist(userPath) {
+ newUserPath := repoutil.UserPath(newUsername)
+ err = os.Rename(userPath, newUserPath)
+ if err != nil {
+ return errors.Wrap(err, "rename user directory")
+ }
+ }
+ return nil
+ })
+}
+
func (db *users) Count(ctx context.Context) int64 {
var count int64
db.WithContext(ctx).Model(&User{}).Where("type = ?", UserTypeIndividual).Count(&count)
diff --git a/internal/db/users_test.go b/internal/db/users_test.go
index 40006330..697bad8f 100644
--- a/internal/db/users_test.go
+++ b/internal/db/users_test.go
@@ -8,6 +8,7 @@ import (
"context"
"fmt"
"os"
+ "path/filepath"
"strings"
"testing"
"time"
@@ -17,10 +18,12 @@ import (
"gorm.io/gorm"
"gogs.io/gogs/internal/auth"
+ "gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/dbtest"
"gogs.io/gogs/internal/dbutil"
"gogs.io/gogs/internal/errutil"
"gogs.io/gogs/internal/osutil"
+ "gogs.io/gogs/internal/repoutil"
"gogs.io/gogs/internal/userutil"
"gogs.io/gogs/public"
)
@@ -79,7 +82,7 @@ func TestUsers(t *testing.T) {
}
t.Parallel()
- tables := []interface{}{new(User), new(EmailAddress), new(Repository), new(Follow)}
+ tables := []interface{}{new(User), new(EmailAddress), new(Repository), new(Follow), new(PullRequest)}
db := &users{
DB: dbtest.NewDB(t, "users", tables...),
}
@@ -89,6 +92,7 @@ func TestUsers(t *testing.T) {
test func(t *testing.T, db *users)
}{
{"Authenticate", usersAuthenticate},
+ {"ChangeUsername", usersChangeUsername},
{"Count", usersCount},
{"Create", usersCreate},
{"DeleteCustomAvatar", usersDeleteCustomAvatar},
@@ -212,6 +216,107 @@ func usersAuthenticate(t *testing.T, db *users) {
})
}
+func usersChangeUsername(t *testing.T, db *users) {
+ ctx := context.Background()
+
+ alice, err := db.Create(
+ ctx,
+ "alice",
+ "alice@example.com",
+ CreateUserOptions{
+ Activated: true,
+ },
+ )
+ require.NoError(t, err)
+
+ t.Run("name not allowed", func(t *testing.T) {
+ err := db.ChangeUsername(ctx, alice.ID, "-")
+ wantErr := ErrNameNotAllowed{
+ args: errutil.Args{
+ "reason": "reserved",
+ "name": "-",
+ },
+ }
+ assert.Equal(t, wantErr, err)
+ })
+
+ t.Run("name already exists", func(t *testing.T) {
+ err := db.ChangeUsername(ctx, alice.ID, alice.Name)
+ wantErr := ErrUserAlreadyExist{
+ args: errutil.Args{
+ "name": alice.Name,
+ },
+ }
+ assert.Equal(t, wantErr, err)
+ })
+
+ tempRepositoryRoot := filepath.Join(os.TempDir(), "usersChangeUsername-tempRepositoryRoot")
+ conf.SetMockRepository(
+ t,
+ conf.RepositoryOpts{
+ Root: tempRepositoryRoot,
+ },
+ )
+ err = os.RemoveAll(tempRepositoryRoot)
+ require.NoError(t, err)
+ defer func() { _ = os.RemoveAll(tempRepositoryRoot) }()
+
+ tempServerAppDataPath := filepath.Join(os.TempDir(), "usersChangeUsername-tempServerAppDataPath")
+ conf.SetMockServer(
+ t,
+ conf.ServerOpts{
+ AppDataPath: tempServerAppDataPath,
+ },
+ )
+ err = os.RemoveAll(tempServerAppDataPath)
+ require.NoError(t, err)
+ defer func() { _ = os.RemoveAll(tempServerAppDataPath) }()
+
+ repo, err := NewReposStore(db.DB).Create(
+ ctx,
+ alice.ID,
+ CreateRepoOptions{
+ Name: "test-repo-1",
+ },
+ )
+ require.NoError(t, err)
+
+ // TODO: Use PullRequests.Create to replace SQL hack when the method is available.
+ err = db.Exec(`INSERT INTO pull_request (head_user_name) VALUES (?)`, alice.Name).Error
+ require.NoError(t, err)
+
+ err = os.MkdirAll(repoutil.UserPath(alice.Name), os.ModePerm)
+ require.NoError(t, err)
+ err = os.MkdirAll(repoutil.RepositoryLocalPath(repo.ID), os.ModePerm)
+ require.NoError(t, err)
+ err = os.MkdirAll(repoutil.RepositoryLocalWikiPath(repo.ID), os.ModePerm)
+ require.NoError(t, err)
+
+ // Make sure mock data is set up correctly
+ assert.True(t, osutil.IsExist(repoutil.UserPath(alice.Name)))
+ assert.True(t, osutil.IsExist(repoutil.RepositoryLocalPath(repo.ID)))
+ assert.True(t, osutil.IsExist(repoutil.RepositoryLocalWikiPath(repo.ID)))
+
+ const newUsername = "alice-new"
+ err = db.ChangeUsername(ctx, alice.ID, newUsername)
+ require.NoError(t, err)
+
+ // TODO: Use PullRequests.GetByID to replace SQL hack when the method is available.
+ var headUserName string
+ err = db.Select("head_user_name").Table("pull_request").Row().Scan(&headUserName)
+ require.NoError(t, err)
+ assert.Equal(t, headUserName, newUsername)
+
+ assert.True(t, osutil.IsExist(repoutil.UserPath(newUsername)))
+ assert.False(t, osutil.IsExist(repoutil.UserPath(alice.Name)))
+ assert.False(t, osutil.IsExist(repoutil.RepositoryLocalPath(repo.ID)))
+ assert.False(t, osutil.IsExist(repoutil.RepositoryLocalWikiPath(repo.ID)))
+
+ alice, err = db.GetByID(ctx, alice.ID)
+ require.NoError(t, err)
+ assert.Equal(t, newUsername, alice.Name)
+}
+
func usersCount(t *testing.T, db *users) {
ctx := context.Background()
diff --git a/internal/repoutil/repoutil.go b/internal/repoutil/repoutil.go
index 658f896f..bb5afc08 100644
--- a/internal/repoutil/repoutil.go
+++ b/internal/repoutil/repoutil.go
@@ -7,6 +7,7 @@ package repoutil
import (
"fmt"
"path/filepath"
+ "strconv"
"strings"
"gogs.io/gogs/internal/conf"
@@ -60,3 +61,15 @@ func UserPath(user string) string {
func RepositoryPath(owner, repo string) string {
return filepath.Join(UserPath(owner), strings.ToLower(repo)+".git")
}
+
+// RepositoryLocalPath returns the absolute path of the repository local copy
+// with the given ID.
+func RepositoryLocalPath(repoID int64) string {
+ return filepath.Join(conf.Server.AppDataPath, "tmp", "local-repo", strconv.FormatInt(repoID, 10))
+}
+
+// RepositoryLocalWikiPath returns the absolute path of the repository local
+// wiki copy with the given ID.
+func RepositoryLocalWikiPath(repoID int64) string {
+ return filepath.Join(conf.Server.AppDataPath, "tmp", "local-wiki", strconv.FormatInt(repoID, 10))
+}
diff --git a/internal/repoutil/repoutil_test.go b/internal/repoutil/repoutil_test.go
index 232ecc52..cd0e7e44 100644
--- a/internal/repoutil/repoutil_test.go
+++ b/internal/repoutil/repoutil_test.go
@@ -125,3 +125,39 @@ func TestRepositoryPath(t *testing.T) {
want := "/home/git/gogs-repositories/alice/example.git"
assert.Equal(t, want, got)
}
+
+func TestRepositoryLocalPath(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("Skipping testing on Windows")
+ return
+ }
+
+ conf.SetMockServer(
+ t,
+ conf.ServerOpts{
+ AppDataPath: "data",
+ },
+ )
+
+ got := RepositoryLocalPath(1)
+ want := "data/tmp/local-repo/1"
+ assert.Equal(t, want, got)
+}
+
+func TestRepositoryLocalWikiPath(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("Skipping testing on Windows")
+ return
+ }
+
+ conf.SetMockServer(
+ t,
+ conf.ServerOpts{
+ AppDataPath: "data",
+ },
+ )
+
+ got := RepositoryLocalWikiPath(1)
+ want := "data/tmp/local-wiki/1"
+ assert.Equal(t, want, got)
+}
diff --git a/internal/route/lfs/mocks_test.go b/internal/route/lfs/mocks_test.go
index 3677261c..a1e89f85 100644
--- a/internal/route/lfs/mocks_test.go
+++ b/internal/route/lfs/mocks_test.go
@@ -2295,6 +2295,9 @@ type MockUsersStore struct {
// AuthenticateFunc is an instance of a mock function object controlling
// the behavior of the method Authenticate.
AuthenticateFunc *UsersStoreAuthenticateFunc
+ // ChangeUsernameFunc is an instance of a mock function object
+ // controlling the behavior of the method ChangeUsername.
+ ChangeUsernameFunc *UsersStoreChangeUsernameFunc
// CountFunc is an instance of a mock function object controlling the
// behavior of the method Count.
CountFunc *UsersStoreCountFunc
@@ -2342,6 +2345,11 @@ func NewMockUsersStore() *MockUsersStore {
return
},
},
+ ChangeUsernameFunc: &UsersStoreChangeUsernameFunc{
+ defaultHook: func(context.Context, int64, string) (r0 error) {
+ return
+ },
+ },
CountFunc: &UsersStoreCountFunc{
defaultHook: func(context.Context) (r0 int64) {
return
@@ -2414,6 +2422,11 @@ func NewStrictMockUsersStore() *MockUsersStore {
panic("unexpected invocation of MockUsersStore.Authenticate")
},
},
+ ChangeUsernameFunc: &UsersStoreChangeUsernameFunc{
+ defaultHook: func(context.Context, int64, string) error {
+ panic("unexpected invocation of MockUsersStore.ChangeUsername")
+ },
+ },
CountFunc: &UsersStoreCountFunc{
defaultHook: func(context.Context) int64 {
panic("unexpected invocation of MockUsersStore.Count")
@@ -2484,6 +2497,9 @@ func NewMockUsersStoreFrom(i db.UsersStore) *MockUsersStore {
AuthenticateFunc: &UsersStoreAuthenticateFunc{
defaultHook: i.Authenticate,
},
+ ChangeUsernameFunc: &UsersStoreChangeUsernameFunc{
+ defaultHook: i.ChangeUsername,
+ },
CountFunc: &UsersStoreCountFunc{
defaultHook: i.Count,
},
@@ -2637,6 +2653,114 @@ func (c UsersStoreAuthenticateFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
+// UsersStoreChangeUsernameFunc describes the behavior when the
+// ChangeUsername method of the parent MockUsersStore instance is invoked.
+type UsersStoreChangeUsernameFunc struct {
+ defaultHook func(context.Context, int64, string) error
+ hooks []func(context.Context, int64, string) error
+ history []UsersStoreChangeUsernameFuncCall
+ mutex sync.Mutex
+}
+
+// ChangeUsername delegates to the next hook function in the queue and
+// stores the parameter and result values of this invocation.
+func (m *MockUsersStore) ChangeUsername(v0 context.Context, v1 int64, v2 string) error {
+ r0 := m.ChangeUsernameFunc.nextHook()(v0, v1, v2)
+ m.ChangeUsernameFunc.appendCall(UsersStoreChangeUsernameFuncCall{v0, v1, v2, r0})
+ return r0
+}
+
+// SetDefaultHook sets function that is called when the ChangeUsername
+// method of the parent MockUsersStore instance is invoked and the hook
+// queue is empty.
+func (f *UsersStoreChangeUsernameFunc) SetDefaultHook(hook func(context.Context, int64, string) error) {
+ f.defaultHook = hook
+}
+
+// PushHook adds a function to the end of hook queue. Each invocation of the
+// ChangeUsername method of the parent MockUsersStore instance invokes the
+// hook at the front of the queue and discards it. After the queue is empty,
+// the default hook function is invoked for any future action.
+func (f *UsersStoreChangeUsernameFunc) PushHook(hook func(context.Context, int64, string) error) {
+ f.mutex.Lock()
+ f.hooks = append(f.hooks, hook)
+ f.mutex.Unlock()
+}
+
+// SetDefaultReturn calls SetDefaultHook with a function that returns the
+// given values.
+func (f *UsersStoreChangeUsernameFunc) SetDefaultReturn(r0 error) {
+ f.SetDefaultHook(func(context.Context, int64, string) error {
+ return r0
+ })
+}
+
+// PushReturn calls PushHook with a function that returns the given values.
+func (f *UsersStoreChangeUsernameFunc) PushReturn(r0 error) {
+ f.PushHook(func(context.Context, int64, string) error {
+ return r0
+ })
+}
+
+func (f *UsersStoreChangeUsernameFunc) nextHook() func(context.Context, int64, string) error {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ if len(f.hooks) == 0 {
+ return f.defaultHook
+ }
+
+ hook := f.hooks[0]
+ f.hooks = f.hooks[1:]
+ return hook
+}
+
+func (f *UsersStoreChangeUsernameFunc) appendCall(r0 UsersStoreChangeUsernameFuncCall) {
+ f.mutex.Lock()
+ f.history = append(f.history, r0)
+ f.mutex.Unlock()
+}
+
+// History returns a sequence of UsersStoreChangeUsernameFuncCall objects
+// describing the invocations of this function.
+func (f *UsersStoreChangeUsernameFunc) History() []UsersStoreChangeUsernameFuncCall {
+ f.mutex.Lock()
+ history := make([]UsersStoreChangeUsernameFuncCall, len(f.history))
+ copy(history, f.history)
+ f.mutex.Unlock()
+
+ return history
+}
+
+// UsersStoreChangeUsernameFuncCall is an object that describes an
+// invocation of method ChangeUsername on an instance of MockUsersStore.
+type UsersStoreChangeUsernameFuncCall struct {
+ // Arg0 is the value of the 1st argument passed to this method
+ // invocation.
+ Arg0 context.Context
+ // Arg1 is the value of the 2nd argument passed to this method
+ // invocation.
+ Arg1 int64
+ // Arg2 is the value of the 3rd argument passed to this method
+ // invocation.
+ Arg2 string
+ // Result0 is the value of the 1st result returned from this method
+ // invocation.
+ Result0 error
+}
+
+// Args returns an interface slice containing the arguments of this
+// invocation.
+func (c UsersStoreChangeUsernameFuncCall) Args() []interface{} {
+ return []interface{}{c.Arg0, c.Arg1, c.Arg2}
+}
+
+// Results returns an interface slice containing the results of this
+// invocation.
+func (c UsersStoreChangeUsernameFuncCall) Results() []interface{} {
+ return []interface{}{c.Result0}
+}
+
// UsersStoreCountFunc describes the behavior when the Count method of the
// parent MockUsersStore instance is invoked.
type UsersStoreCountFunc struct {
diff --git a/internal/route/org/setting.go b/internal/route/org/setting.go
index 198012ef..f3e65b9b 100644
--- a/internal/route/org/setting.go
+++ b/internal/route/org/setting.go
@@ -7,6 +7,7 @@ package org
import (
"strings"
+ "github.com/pkg/errors"
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/auth"
@@ -45,13 +46,13 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) {
c.Data["OrgName"] = true
c.RenderWithErr(c.Tr("form.username_been_taken"), SETTINGS_OPTIONS, &f)
return
- } else if err := db.ChangeUserName(org, f.Name); err != nil {
+ } else if err := db.Users.ChangeUsername(c.Req.Context(), org.ID, f.Name); err != nil {
c.Data["OrgName"] = true
switch {
- case db.IsErrNameNotAllowed(err):
+ case db.IsErrNameNotAllowed(errors.Cause(err)):
c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), SETTINGS_OPTIONS, &f)
default:
- c.Error(err, "change user name")
+ c.Error(err, "change organization name")
}
return
}
diff --git a/internal/route/user/setting.go b/internal/route/user/setting.go
index c873aeaf..2924a8f0 100644
--- a/internal/route/user/setting.go
+++ b/internal/route/user/setting.go
@@ -71,13 +71,13 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) {
if c.User.IsLocal() {
// Check if username characters have been changed
if c.User.LowerName != strings.ToLower(f.Name) {
- if err := db.ChangeUserName(c.User, f.Name); err != nil {
+ if err := db.Users.ChangeUsername(c.Req.Context(), c.User.ID, f.Name); err != nil {
c.FormErr("Name")
var msg string
switch {
- case db.IsErrUserAlreadyExist(err):
+ case db.IsErrUserAlreadyExist(errors.Cause(err)):
msg = c.Tr("form.username_been_taken")
- case db.IsErrNameNotAllowed(err):
+ case db.IsErrNameNotAllowed(errors.Cause(err)):
msg = c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value())
default:
c.Error(err, "change user name")