diff options
author | Joe Chen <jc@unknwon.io> | 2022-11-05 23:33:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-05 23:33:05 +0800 |
commit | 5fb29db2db04bc128af410867f1f602320eb5d66 (patch) | |
tree | 9d0b86702d872f8f5ab7d0691e511c52f38fde34 /internal/route | |
parent | b5d47b969258f3d644ad797b29901eb607f6b94f (diff) |
refactor(db): migrate methods off and delete deprecated methods from `user.go` (#7231)
Diffstat (limited to 'internal/route')
-rw-r--r-- | internal/route/admin/orgs.go | 12 | ||||
-rw-r--r-- | internal/route/admin/users.go | 8 | ||||
-rw-r--r-- | internal/route/api/v1/api.go | 4 | ||||
-rw-r--r-- | internal/route/api/v1/convert/convert.go | 5 | ||||
-rw-r--r-- | internal/route/api/v1/org/org.go | 2 | ||||
-rw-r--r-- | internal/route/api/v1/repo/collaborators.go | 6 | ||||
-rw-r--r-- | internal/route/api/v1/repo/commits.go | 4 | ||||
-rw-r--r-- | internal/route/api/v1/repo/issue.go | 4 | ||||
-rw-r--r-- | internal/route/api/v1/repo/repo.go | 10 | ||||
-rw-r--r-- | internal/route/api/v1/user/email.go | 6 | ||||
-rw-r--r-- | internal/route/api/v1/user/key.go | 2 | ||||
-rw-r--r-- | internal/route/api/v1/user/user.go | 2 | ||||
-rw-r--r-- | internal/route/home.go | 23 | ||||
-rw-r--r-- | internal/route/lfs/mocks_test.go | 243 | ||||
-rw-r--r-- | internal/route/org/members.go | 2 | ||||
-rw-r--r-- | internal/route/org/teams.go | 2 | ||||
-rw-r--r-- | internal/route/repo/pull.go | 4 | ||||
-rw-r--r-- | internal/route/repo/repo.go | 2 | ||||
-rw-r--r-- | internal/route/repo/setting.go | 2 | ||||
-rw-r--r-- | internal/route/repo/webhook.go | 4 | ||||
-rw-r--r-- | internal/route/user/auth.go | 77 | ||||
-rw-r--r-- | internal/route/user/home.go | 8 | ||||
-rw-r--r-- | internal/route/user/setting.go | 6 |
23 files changed, 377 insertions, 61 deletions
diff --git a/internal/route/admin/orgs.go b/internal/route/admin/orgs.go index 06aa74be..922d7f86 100644 --- a/internal/route/admin/orgs.go +++ b/internal/route/admin/orgs.go @@ -5,6 +5,8 @@ package admin import ( + gocontext "context" + "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" @@ -21,9 +23,13 @@ func Organizations(c *context.Context) { c.Data["PageIsAdminOrganizations"] = true route.RenderUserSearch(c, &route.UserSearchOptions{ - Type: db.UserTypeOrganization, - Counter: db.CountOrganizations, - Ranger: db.Organizations, + Type: db.UserTypeOrganization, + Counter: func(gocontext.Context) int64 { + return db.CountOrganizations() + }, + Ranger: func(_ gocontext.Context, page, pageSize int) ([]*db.User, error) { + return db.Organizations(page, pageSize) + }, PageSize: conf.UI.Admin.OrgPagingNum, OrderBy: "id ASC", TplName: ORGS, diff --git a/internal/route/admin/users.go b/internal/route/admin/users.go index c1891fc4..592f3fee 100644 --- a/internal/route/admin/users.go +++ b/internal/route/admin/users.go @@ -33,8 +33,8 @@ func Users(c *context.Context) { route.RenderUserSearch(c, &route.UserSearchOptions{ Type: db.UserTypeIndividual, - Counter: db.CountUsers, - Ranger: db.ListUsers, + Counter: db.Users.Count, + Ranger: db.Users.List, PageSize: conf.UI.Admin.UserPagingNum, OrderBy: "id ASC", TplName: USERS, @@ -119,7 +119,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { } func prepareUserInfo(c *context.Context) *db.User { - u, err := db.GetUserByID(c.ParamsInt64(":userid")) + u, err := db.Users.GetByID(c.Req.Context(), c.ParamsInt64(":userid")) if err != nil { c.Error(err, "get user by ID") return nil @@ -223,7 +223,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { } func DeleteUser(c *context.Context) { - u, err := db.GetUserByID(c.ParamsInt64(":userid")) + u, err := db.Users.GetByID(c.Req.Context(), c.ParamsInt64(":userid")) if err != nil { c.Error(err, "get user by ID") return diff --git a/internal/route/api/v1/api.go b/internal/route/api/v1/api.go index 0a17e657..79d346fe 100644 --- a/internal/route/api/v1/api.go +++ b/internal/route/api/v1/api.go @@ -37,7 +37,7 @@ func repoAssignment() macaron.Handler { if c.IsLogged && c.User.LowerName == strings.ToLower(username) { owner = c.User } else { - owner, err = db.GetUserByName(username) + owner, err = db.Users.GetByUsername(c.Req.Context(), username) if err != nil { c.NotFoundOrError(err, "get user by name") return @@ -91,7 +91,7 @@ func orgAssignment(args ...bool) macaron.Handler { var err error if assignOrg { - c.Org.Organization, err = db.GetUserByName(c.Params(":orgname")) + c.Org.Organization, err = db.Users.GetByUsername(c.Req.Context(), c.Params(":orgname")) if err != nil { c.NotFoundOrError(err, "get organization by name") return diff --git a/internal/route/api/v1/convert/convert.go b/internal/route/api/v1/convert/convert.go index 04d4df33..a91432dd 100644 --- a/internal/route/api/v1/convert/convert.go +++ b/internal/route/api/v1/convert/convert.go @@ -5,6 +5,7 @@ package convert import ( + "context" "fmt" "github.com/unknwon/com" @@ -44,12 +45,12 @@ func ToTag(b *db.Tag, c *git.Commit) *Tag { func ToCommit(c *git.Commit) *api.PayloadCommit { authorUsername := "" - author, err := db.GetUserByEmail(c.Author.Email) + author, err := db.Users.GetByEmail(context.TODO(), c.Author.Email) if err == nil { authorUsername = author.Name } committerUsername := "" - committer, err := db.GetUserByEmail(c.Committer.Email) + committer, err := db.Users.GetByEmail(context.TODO(), c.Committer.Email) if err == nil { committerUsername = committer.Name } diff --git a/internal/route/api/v1/org/org.go b/internal/route/api/v1/org/org.go index cefe5cc6..2f6b4b70 100644 --- a/internal/route/api/v1/org/org.go +++ b/internal/route/api/v1/org/org.go @@ -45,7 +45,7 @@ func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user * func listUserOrgs(c *context.APIContext, u *db.User, all bool) { orgs, err := db.Orgs.List( c.Req.Context(), - db.ListOrgOptions{ + db.ListOrgsOptions{ MemberID: u.ID, IncludePrivateMembers: all, }, diff --git a/internal/route/api/v1/repo/collaborators.go b/internal/route/api/v1/repo/collaborators.go index c9d2ff30..4d813c07 100644 --- a/internal/route/api/v1/repo/collaborators.go +++ b/internal/route/api/v1/repo/collaborators.go @@ -28,7 +28,7 @@ func ListCollaborators(c *context.APIContext) { } func AddCollaborator(c *context.APIContext, form api.AddCollaboratorOption) { - collaborator, err := db.GetUserByName(c.Params(":collaborator")) + collaborator, err := db.Users.GetByUsername(c.Req.Context(), c.Params(":collaborator")) if err != nil { if db.IsErrUserNotExist(err) { c.Status(http.StatusUnprocessableEntity) @@ -54,7 +54,7 @@ func AddCollaborator(c *context.APIContext, form api.AddCollaboratorOption) { } func IsCollaborator(c *context.APIContext) { - collaborator, err := db.GetUserByName(c.Params(":collaborator")) + collaborator, err := db.Users.GetByUsername(c.Req.Context(), c.Params(":collaborator")) if err != nil { if db.IsErrUserNotExist(err) { c.Status(http.StatusUnprocessableEntity) @@ -72,7 +72,7 @@ func IsCollaborator(c *context.APIContext) { } func DeleteCollaborator(c *context.APIContext) { - collaborator, err := db.GetUserByName(c.Params(":collaborator")) + collaborator, err := db.Users.GetByUsername(c.Req.Context(), c.Params(":collaborator")) if err != nil { if db.IsErrUserNotExist(err) { c.Status(http.StatusUnprocessableEntity) diff --git a/internal/route/api/v1/repo/commits.go b/internal/route/api/v1/repo/commits.go index 5b3280a1..8d16c845 100644 --- a/internal/route/api/v1/repo/commits.go +++ b/internal/route/api/v1/repo/commits.go @@ -120,7 +120,7 @@ func GetReferenceSHA(c *context.APIContext) { func gitCommitToAPICommit(commit *git.Commit, c *context.APIContext) (*api.Commit, error) { // Retrieve author and committer information var apiAuthor, apiCommitter *api.User - author, err := db.GetUserByEmail(commit.Author.Email) + author, err := db.Users.GetByEmail(c.Req.Context(), commit.Author.Email) if err != nil && !db.IsErrUserNotExist(err) { return nil, err } else if err == nil { @@ -131,7 +131,7 @@ func gitCommitToAPICommit(commit *git.Commit, c *context.APIContext) (*api.Commi if commit.Committer.Email == commit.Author.Email { apiCommitter = apiAuthor } else { - committer, err := db.GetUserByEmail(commit.Committer.Email) + committer, err := db.Users.GetByEmail(c.Req.Context(), commit.Committer.Email) if err != nil && !db.IsErrUserNotExist(err) { return nil, err } else if err == nil { diff --git a/internal/route/api/v1/repo/issue.go b/internal/route/api/v1/repo/issue.go index 8d54fd35..c663a830 100644 --- a/internal/route/api/v1/repo/issue.go +++ b/internal/route/api/v1/repo/issue.go @@ -83,7 +83,7 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) { if c.Repo.IsWriter() { if len(form.Assignee) > 0 { - assignee, err := db.GetUserByName(form.Assignee) + assignee, err := db.Users.GetByUsername(c.Req.Context(), form.Assignee) if err != nil { if db.IsErrUserNotExist(err) { c.ErrorStatus(http.StatusUnprocessableEntity, fmt.Errorf("assignee does not exist: [name: %s]", form.Assignee)) @@ -145,7 +145,7 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) { if *form.Assignee == "" { issue.AssigneeID = 0 } else { - assignee, err := db.GetUserByName(*form.Assignee) + assignee, err := db.Users.GetByUsername(c.Req.Context(), *form.Assignee) if err != nil { if db.IsErrUserNotExist(err) { c.ErrorStatus(http.StatusUnprocessableEntity, fmt.Errorf("assignee does not exist: [name: %s]", *form.Assignee)) diff --git a/internal/route/api/v1/repo/repo.go b/internal/route/api/v1/repo/repo.go index 81341627..c0e3b612 100644 --- a/internal/route/api/v1/repo/repo.go +++ b/internal/route/api/v1/repo/repo.go @@ -32,7 +32,7 @@ func Search(c *context.APIContext) { if c.User.ID == opts.OwnerID { opts.Private = true } else { - u, err := db.GetUserByID(opts.OwnerID) + u, err := db.Users.GetByID(c.Req.Context(), opts.OwnerID) if err != nil { c.JSON(http.StatusInternalServerError, map[string]interface{}{ "ok": false, @@ -77,7 +77,7 @@ func Search(c *context.APIContext) { } func listUserRepositories(c *context.APIContext, username string) { - user, err := db.GetUserByName(username) + user, err := db.Users.GetByUsername(c.Req.Context(), username) if err != nil { c.NotFoundOrError(err, "get user by name") return @@ -209,7 +209,7 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) { // Not equal means context user is an organization, // or is another user/organization if current user is admin. if f.Uid != ctxUser.ID { - org, err := db.GetUserByID(f.Uid) + org, err := db.Users.GetByID(c.Req.Context(), f.Uid) if err != nil { if db.IsErrUserNotExist(err) { c.ErrorStatus(http.StatusUnprocessableEntity, err) @@ -287,7 +287,7 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) { // FIXME: inject in the handler chain func parseOwnerAndRepo(c *context.APIContext) (*db.User, *db.Repository) { - owner, err := db.GetUserByName(c.Params(":username")) + owner, err := db.Users.GetByUsername(c.Req.Context(), c.Params(":username")) if err != nil { if db.IsErrUserNotExist(err) { c.ErrorStatus(http.StatusUnprocessableEntity, err) @@ -453,7 +453,7 @@ func Releases(c *context.APIContext) { } apiReleases := make([]*api.Release, 0, len(releases)) for _, r := range releases { - publisher, err := db.GetUserByID(r.PublisherID) + publisher, err := db.Users.GetByID(c.Req.Context(), r.PublisherID) if err != nil { c.Error(err, "get release publisher") return diff --git a/internal/route/api/v1/user/email.go b/internal/route/api/v1/user/email.go index 5584803e..cda2a0a4 100644 --- a/internal/route/api/v1/user/email.go +++ b/internal/route/api/v1/user/email.go @@ -38,7 +38,7 @@ func AddEmail(c *context.APIContext, form api.CreateEmailOption) { emails := make([]*db.EmailAddress, len(form.Emails)) for i := range form.Emails { emails[i] = &db.EmailAddress{ - UID: c.User.ID, + UserID: c.User.ID, Email: form.Emails[i], IsActivated: !conf.Auth.RequireEmailConfirmation, } @@ -69,8 +69,8 @@ func DeleteEmail(c *context.APIContext, form api.CreateEmailOption) { emails := make([]*db.EmailAddress, len(form.Emails)) for i := range form.Emails { emails[i] = &db.EmailAddress{ - UID: c.User.ID, - Email: form.Emails[i], + UserID: c.User.ID, + Email: form.Emails[i], } } diff --git a/internal/route/api/v1/user/key.go b/internal/route/api/v1/user/key.go index 344c7ca2..c80e3bf0 100644 --- a/internal/route/api/v1/user/key.go +++ b/internal/route/api/v1/user/key.go @@ -18,7 +18,7 @@ import ( ) func GetUserByParamsName(c *context.APIContext, name string) *db.User { - user, err := db.GetUserByName(c.Params(name)) + user, err := db.Users.GetByUsername(c.Req.Context(), c.Params(name)) if err != nil { c.NotFoundOrError(err, "get user by name") return nil diff --git a/internal/route/api/v1/user/user.go b/internal/route/api/v1/user/user.go index 5852f660..10d82b9a 100644 --- a/internal/route/api/v1/user/user.go +++ b/internal/route/api/v1/user/user.go @@ -55,7 +55,7 @@ func Search(c *context.APIContext) { } func GetInfo(c *context.APIContext) { - u, err := db.GetUserByName(c.Params(":username")) + u, err := db.Users.GetByUsername(c.Req.Context(), c.Params(":username")) if err != nil { c.NotFoundOrError(err, "get user by name") return diff --git a/internal/route/home.go b/internal/route/home.go index 51c7b54b..ec4be9d2 100644 --- a/internal/route/home.go +++ b/internal/route/home.go @@ -5,6 +5,7 @@ package route import ( + gocontext "context" "fmt" "net/http" @@ -84,8 +85,8 @@ func ExploreRepos(c *context.Context) { type UserSearchOptions struct { Type db.UserType - Counter func() int64 - Ranger func(int, int) ([]*db.User, error) + Counter func(ctx gocontext.Context) int64 + Ranger func(ctx gocontext.Context, page, pageSize int) ([]*db.User, error) PageSize int OrderBy string TplName string @@ -105,12 +106,12 @@ func RenderUserSearch(c *context.Context, opts *UserSearchOptions) { keyword := c.Query("q") if keyword == "" { - users, err = opts.Ranger(page, opts.PageSize) + users, err = opts.Ranger(c.Req.Context(), page, opts.PageSize) if err != nil { c.Error(err, "ranger") return } - count = opts.Counter() + count = opts.Counter(c.Req.Context()) } else { users, count, err = db.SearchUserByName(&db.SearchUserOptions{ Keyword: keyword, @@ -139,8 +140,8 @@ func ExploreUsers(c *context.Context) { RenderUserSearch(c, &UserSearchOptions{ Type: db.UserTypeIndividual, - Counter: db.CountUsers, - Ranger: db.ListUsers, + Counter: db.Users.Count, + Ranger: db.Users.List, PageSize: conf.UI.ExplorePagingNum, OrderBy: "updated_unix DESC", TplName: EXPLORE_USERS, @@ -153,9 +154,13 @@ func ExploreOrganizations(c *context.Context) { c.Data["PageIsExploreOrganizations"] = true RenderUserSearch(c, &UserSearchOptions{ - Type: db.UserTypeOrganization, - Counter: db.CountOrganizations, - Ranger: db.Organizations, + Type: db.UserTypeOrganization, + Counter: func(gocontext.Context) int64 { + return db.CountOrganizations() + }, + Ranger: func(_ gocontext.Context, page, pageSize int) ([]*db.User, error) { + return db.Organizations(page, pageSize) + }, PageSize: conf.UI.ExplorePagingNum, OrderBy: "updated_unix DESC", TplName: EXPLORE_ORGANIZATIONS, diff --git a/internal/route/lfs/mocks_test.go b/internal/route/lfs/mocks_test.go index 8a087e0b..3677261c 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 + // CountFunc is an instance of a mock function object controlling the + // behavior of the method Count. + CountFunc *UsersStoreCountFunc // CreateFunc is an instance of a mock function object controlling the // behavior of the method Create. CreateFunc *UsersStoreCreateFunc @@ -2316,6 +2319,9 @@ type MockUsersStore struct { // IsUsernameUsedFunc is an instance of a mock function object // controlling the behavior of the method IsUsernameUsed. IsUsernameUsedFunc *UsersStoreIsUsernameUsedFunc + // ListFunc is an instance of a mock function object controlling the + // behavior of the method List. + ListFunc *UsersStoreListFunc // ListFollowersFunc is an instance of a mock function object // controlling the behavior of the method ListFollowers. ListFollowersFunc *UsersStoreListFollowersFunc @@ -2336,6 +2342,11 @@ func NewMockUsersStore() *MockUsersStore { return }, }, + CountFunc: &UsersStoreCountFunc{ + defaultHook: func(context.Context) (r0 int64) { + return + }, + }, CreateFunc: &UsersStoreCreateFunc{ defaultHook: func(context.Context, string, string, db.CreateUserOptions) (r0 *db.User, r1 error) { return @@ -2371,6 +2382,11 @@ func NewMockUsersStore() *MockUsersStore { return }, }, + ListFunc: &UsersStoreListFunc{ + defaultHook: func(context.Context, int, int) (r0 []*db.User, r1 error) { + return + }, + }, ListFollowersFunc: &UsersStoreListFollowersFunc{ defaultHook: func(context.Context, int64, int, int) (r0 []*db.User, r1 error) { return @@ -2398,6 +2414,11 @@ func NewStrictMockUsersStore() *MockUsersStore { panic("unexpected invocation of MockUsersStore.Authenticate") }, }, + CountFunc: &UsersStoreCountFunc{ + defaultHook: func(context.Context) int64 { + panic("unexpected invocation of MockUsersStore.Count") + }, + }, CreateFunc: &UsersStoreCreateFunc{ defaultHook: func(context.Context, string, string, db.CreateUserOptions) (*db.User, error) { panic("unexpected invocation of MockUsersStore.Create") @@ -2433,6 +2454,11 @@ func NewStrictMockUsersStore() *MockUsersStore { panic("unexpected invocation of MockUsersStore.IsUsernameUsed") }, }, + ListFunc: &UsersStoreListFunc{ + defaultHook: func(context.Context, int, int) ([]*db.User, error) { + panic("unexpected invocation of MockUsersStore.List") + }, + }, ListFollowersFunc: &UsersStoreListFollowersFunc{ defaultHook: func(context.Context, int64, int, int) ([]*db.User, error) { panic("unexpected invocation of MockUsersStore.ListFollowers") @@ -2458,6 +2484,9 @@ func NewMockUsersStoreFrom(i db.UsersStore) *MockUsersStore { AuthenticateFunc: &UsersStoreAuthenticateFunc{ defaultHook: i.Authenticate, }, + CountFunc: &UsersStoreCountFunc{ + defaultHook: i.Count, + }, CreateFunc: &UsersStoreCreateFunc{ defaultHook: i.Create, }, @@ -2479,6 +2508,9 @@ func NewMockUsersStoreFrom(i db.UsersStore) *MockUsersStore { IsUsernameUsedFunc: &UsersStoreIsUsernameUsedFunc{ defaultHook: i.IsUsernameUsed, }, + ListFunc: &UsersStoreListFunc{ + defaultHook: i.List, + }, ListFollowersFunc: &UsersStoreListFollowersFunc{ defaultHook: i.ListFollowers, }, @@ -2605,6 +2637,107 @@ func (c UsersStoreAuthenticateFuncCall) Results() []interface{} { return []interface{}{c.Result0, c.Result1} } +// UsersStoreCountFunc describes the behavior when the Count method of the +// parent MockUsersStore instance is invoked. +type UsersStoreCountFunc struct { + defaultHook func(context.Context) int64 + hooks []func(context.Context) int64 + history []UsersStoreCountFuncCall + mutex sync.Mutex +} + +// Count delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockUsersStore) Count(v0 context.Context) int64 { + r0 := m.CountFunc.nextHook()(v0) + m.CountFunc.appendCall(UsersStoreCountFuncCall{v0, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the Count method of the +// parent MockUsersStore instance is invoked and the hook queue is empty. +func (f *UsersStoreCountFunc) SetDefaultHook(hook func(context.Context) int64) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// Count 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 *UsersStoreCountFunc) PushHook(hook func(context.Context) int64) { + 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 *UsersStoreCountFunc) SetDefaultReturn(r0 int64) { + f.SetDefaultHook(func(context.Context) int64 { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *UsersStoreCountFunc) PushReturn(r0 int64) { + f.PushHook(func(context.Context) int64 { + return r0 + }) +} + +func (f *UsersStoreCountFunc) nextHook() func(context.Context) int64 { + 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 *UsersStoreCountFunc) appendCall(r0 UsersStoreCountFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of UsersStoreCountFuncCall objects describing +// the invocations of this function. +func (f *UsersStoreCountFunc) History() []UsersStoreCountFuncCall { + f.mutex.Lock() + history := make([]UsersStoreCountFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// UsersStoreCountFuncCall is an object that describes an invocation of +// method Count on an instance of MockUsersStore. +type UsersStoreCountFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 int64 +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c UsersStoreCountFuncCall) Args() []interface{} { + return []interface{}{c.Arg0} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c UsersStoreCountFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + // UsersStoreCreateFunc describes the behavior when the Create method of the // parent MockUsersStore instance is invoked. type UsersStoreCreateFunc struct { @@ -3363,6 +3496,116 @@ func (c UsersStoreIsUsernameUsedFuncCall) Results() []interface{} { return []interface{}{c.Result0} } +// UsersStoreListFunc describes the behavior when the List method of the +// parent MockUsersStore instance is invoked. +type UsersStoreListFunc struct { + defaultHook func(context.Context, int, int) ([]*db.User, error) + hooks []func(context.Context, int, int) ([]*db.User, error) + history []UsersStoreListFuncCall + mutex sync.Mutex +} + +// List delegates to the next hook function in the queue and stores the +// parameter and result values of this invocation. +func (m *MockUsersStore) List(v0 context.Context, v1 int, v2 int) ([]*db.User, error) { + r0, r1 := m.ListFunc.nextHook()(v0, v1, v2) + m.ListFunc.appendCall(UsersStoreListFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the List method of the +// parent MockUsersStore instance is invoked and the hook queue is empty. +func (f *UsersStoreListFunc) SetDefaultHook(hook func(context.Context, int, int) ([]*db.User, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// List 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 *UsersStoreListFunc) PushHook(hook func(context.Context, int, int) ([]*db.User, 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 *UsersStoreListFunc) SetDefaultReturn(r0 []*db.User, r1 error) { + f.SetDefaultHook(func(context.Context, int, int) ([]*db.User, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *UsersStoreListFunc) PushReturn(r0 []*db.User, r1 error) { + f.PushHook(func(context.Context, int, int) ([]*db.User, error) { + return r0, r1 + }) +} + +func (f *UsersStoreListFunc) nextHook() func(context.Context, int, int) ([]*db.User, 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 *UsersStoreListFunc) appendCall(r0 UsersStoreListFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of UsersStoreListFuncCall objects describing +// the invocations of this function. +func (f *UsersStoreListFunc) History() []UsersStoreListFuncCall { + f.mutex.Lock() + history := make([]UsersStoreListFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// UsersStoreListFuncCall is an object that describes an invocation of +// method List on an instance of MockUsersStore. +type UsersStoreListFuncCall 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 int + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 int + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 []*db.User + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c UsersStoreListFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c UsersStoreListFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + // UsersStoreListFollowersFunc describes the behavior when the ListFollowers // method of the parent MockUsersStore instance is invoked. type UsersStoreListFollowersFunc struct { diff --git a/internal/route/org/members.go b/internal/route/org/members.go index c4ad3306..c8516b72 100644 --- a/internal/route/org/members.go +++ b/internal/route/org/members.go @@ -97,7 +97,7 @@ func Invitation(c *context.Context) { if c.Req.Method == "POST" { uname := c.Query("uname") - u, err := db.GetUserByName(uname) + u, err := db.Users.GetByUsername(c.Req.Context(), uname) if err != nil { if db.IsErrUserNotExist(err) { c.Flash.Error(c.Tr("form.user_not_exist")) diff --git a/internal/route/org/teams.go b/internal/route/org/teams.go index c681ec9f..7f932f3f 100644 --- a/internal/route/org/teams.go +++ b/internal/route/org/teams.go @@ -71,7 +71,7 @@ func TeamsAction(c *context.Context) { } uname := c.Query("uname") var u *db.User - u, err = db.GetUserByName(uname) + u, err = db.Users.GetByUsername(c.Req.Context(), uname) if err != nil { if db.IsErrUserNotExist(err) { c.Flash.Error(c.Tr("form.user_not_exist")) diff --git a/internal/route/repo/pull.go b/internal/route/repo/pull.go index c203266c..2429ff8b 100644 --- a/internal/route/repo/pull.go +++ b/internal/route/repo/pull.go @@ -71,7 +71,7 @@ func parseBaseRepository(c *context.Context) *db.Repository { orgs, err := db.Orgs.List( c.Req.Context(), - db.ListOrgOptions{ + db.ListOrgsOptions{ MemberID: c.User.ID, IncludePrivateMembers: true, }, @@ -466,7 +466,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi headBranch = headInfos[0] } else if len(headInfos) == 2 { - headUser, err = db.GetUserByName(headInfos[0]) + headUser, err = db.Users.GetByUsername(c.Req.Context(), headInfos[0]) if err != nil { c.NotFoundOrError(err, "get user by name") return nil, nil, nil, nil, "", "" diff --git a/internal/route/repo/repo.go b/internal/route/repo/repo.go index 943540c8..b9f9f988 100644 --- a/internal/route/repo/repo.go +++ b/internal/route/repo/repo.go @@ -47,7 +47,7 @@ func checkContextUser(c *context.Context, uid int64) *db.User { return c.User } - org, err := db.GetUserByID(uid) + org, err := db.Users.GetByID(c.Req.Context(), uid) if db.IsErrUserNotExist(err) { return c.User } diff --git a/internal/route/repo/setting.go b/internal/route/repo/setting.go index bc7c62bc..cd87769a 100644 --- a/internal/route/repo/setting.go +++ b/internal/route/repo/setting.go @@ -380,7 +380,7 @@ func SettingsCollaborationPost(c *context.Context) { return } - u, err := db.GetUserByName(name) + u, err := db.Users.GetByUsername(c.Req.Context(), name) if err != nil { if db.IsErrUserNotExist(err) { c.Flash.Error(c.Tr("form.user_not_exist")) diff --git a/internal/route/repo/webhook.go b/internal/route/repo/webhook.go index f52e80c0..615137bc 100644 --- a/internal/route/repo/webhook.go +++ b/internal/route/repo/webhook.go @@ -493,7 +493,7 @@ func TestWebhook(c *context.Context) { committer = c.Repo.Commit.Committer // Try to match email with a real user. - author, err := db.GetUserByEmail(c.Repo.Commit.Author.Email) + author, err := db.Users.GetByEmail(c.Req.Context(), c.Repo.Commit.Author.Email) if err == nil { authorUsername = author.Name } else if !db.IsErrUserNotExist(err) { @@ -501,7 +501,7 @@ func TestWebhook(c *context.Context) { return } - user, err := db.GetUserByEmail(c.Repo.Commit.Committer.Email) + user, err := db.Users.GetByEmail(c.Req.Context(), c.Repo.Commit.Committer.Email) if err == nil { committerUsername = user.Name } else if !db.IsErrUserNotExist(err) { diff --git a/internal/route/user/auth.go b/internal/route/user/auth.go index 17229a40..86cf1f2e 100644 --- a/internal/route/user/auth.go +++ b/internal/route/user/auth.go @@ -5,12 +5,15 @@ package user import ( + gocontext "context" + "encoding/hex" "fmt" "net/http" "net/url" "github.com/go-macaron/captcha" "github.com/pkg/errors" + "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/auth" @@ -54,7 +57,7 @@ func AutoLogin(c *context.Context) (bool, error) { } }() - u, err := db.GetUserByName(uname) + u, err := db.Users.GetByUsername(c.Req.Context(), uname) if err != nil { if !db.IsErrUserNotExist(err) { return false, fmt.Errorf("get user by name: %v", err) @@ -229,7 +232,7 @@ func LoginTwoFactorPost(c *context.Context) { return } - u, err := db.GetUserByID(userID) + u, err := db.Users.GetByID(c.Req.Context(), userID) if err != nil { c.Error(err, "get user by ID") return @@ -275,7 +278,7 @@ func LoginTwoFactorRecoveryCodePost(c *context.Context) { return } - u, err := db.GetUserByID(userID) + u, err := db.Users.GetByID(c.Req.Context(), userID) if err != nil { c.Error(err, "get user by ID") return @@ -360,8 +363,11 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { } log.Trace("Account created: %s", user.Name) + // FIXME: Count has pretty bad performance implication in large instances, we + // should have a dedicate method to check whether the "user" table is empty. + // // Auto-set admin for the only user. - if db.CountUsers() == 1 { + if db.Users.Count(c.Req.Context()) == 1 { user.IsAdmin = true user.IsActive = true if err := db.UpdateUser(user); err != nil { @@ -387,6 +393,61 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { c.RedirectSubpath("/user/login") } +// parseUserFromCode returns user by username encoded in code. +// It returns nil if code or username is invalid. +func parseUserFromCode(code string) (user *db.User) { + if len(code) <= tool.TIME_LIMIT_CODE_LENGTH { + return nil + } + + // Use tail hex username to query user + hexStr := code[tool.TIME_LIMIT_CODE_LENGTH:] + if b, err := hex.DecodeString(hexStr); err == nil { + if user, err = db.Users.GetByUsername(gocontext.TODO(), string(b)); user != nil { + return user + } else if !db.IsErrUserNotExist(err) { + log.Error("Failed to get user by name %q: %v", string(b), err) + } + } + + return nil +} + +// verify active code when active account +func verifyUserActiveCode(code string) (user *db.User) { + minutes := conf.Auth.ActivateCodeLives + + if user = parseUserFromCode(code); user != nil { + // time limit code + prefix := code[:tool.TIME_LIMIT_CODE_LENGTH] + data := com.ToStr(user.ID) + user.Email + user.LowerName + user.Password + user.Rands + + if tool.VerifyTimeLimitCode(data, minutes, prefix) { + return user + } + } + return nil +} + +// verify active code when active account +func verifyActiveEmailCode(code, email string) *db.EmailAddress { + minutes := conf.Auth.ActivateCodeLives + + if user := parseUserFromCode(code); user != nil { + // time limit code + prefix := code[:tool.TIME_LIMIT_CODE_LENGTH] + data := com.ToStr(user.ID) + email + user.LowerName + user.Password + user.Rands + + if tool.VerifyTimeLimitCode(data, minutes, prefix) { + emailAddress, err := db.EmailAddresses.GetByEmail(gocontext.TODO(), email) + if err == nil { + return emailAddress + } + } + } + return nil +} + func Activate(c *context.Context) { code := c.Query("code") if code == "" { @@ -415,7 +476,7 @@ func Activate(c *context.Context) { } // Verify code. - if user := db.VerifyUserActiveCode(code); user != nil { + if user := verifyUserActiveCode(code); user != nil { user.IsActive = true var err error if user.Rands, err = userutil.RandomSalt(); err != nil { @@ -444,7 +505,7 @@ func ActivateEmail(c *context.Context) { emailAddr := c.Query("email") // Verify code. - if email := db.VerifyActiveEmailCode(code, emailAddr); email != nil { + if email := verifyActiveEmailCode(code, emailAddr); email != nil { if err := email.Activate(); err != nil { c.Error(err, "activate email") } @@ -481,7 +542,7 @@ func ForgotPasswdPost(c *context.Context) { emailAddr := c.Query("email") c.Data["Email"] = emailAddr - u, err := db.GetUserByEmail(emailAddr) + u, err := db.Users.GetByEmail(c.Req.Context(), emailAddr) if err != nil { if db.IsErrUserNotExist(err) { c.Data["Hours"] = conf.Auth.ActivateCodeLives / 60 @@ -539,7 +600,7 @@ func ResetPasswdPost(c *context.Context) { } c.Data["Code"] = code - if u := db.VerifyUserActiveCode(code); u != nil { + if u := verifyUserActiveCode(code); u != nil { // Validate password length. passwd := c.Query("password") if len(passwd) < 6 { diff --git a/internal/route/user/home.go b/internal/route/user/home.go index 04b5eb65..f9f1b7b1 100644 --- a/internal/route/user/home.go +++ b/internal/route/user/home.go @@ -31,7 +31,7 @@ func getDashboardContextUser(c *context.Context) *db.User { orgName := c.Params(":org") if len(orgName) > 0 { // Organization. - org, err := db.GetUserByName(orgName) + org, err := db.Users.GetByUsername(c.Req.Context(), orgName) if err != nil { c.NotFoundOrError(err, "get user by name") return nil @@ -42,7 +42,7 @@ func getDashboardContextUser(c *context.Context) *db.User { orgs, err := db.Orgs.List( c.Req.Context(), - db.ListOrgOptions{ + db.ListOrgsOptions{ MemberID: c.User.ID, IncludePrivateMembers: true, }, @@ -81,7 +81,7 @@ func retrieveFeeds(c *context.Context, ctxUser *db.User, userID int64, isProfile // Cache results to reduce queries. _, ok := unameAvatars[act.ActUserName] if !ok { - u, err := db.GetUserByName(act.ActUserName) + u, err := db.Users.GetByUsername(c.Req.Context(), act.ActUserName) if err != nil { if db.IsErrUserNotExist(err) { continue @@ -444,7 +444,7 @@ func showOrgProfile(c *context.Context) { } func Email2User(c *context.Context) { - u, err := db.GetUserByEmail(c.Query("email")) + u, err := db.Users.GetByEmail(c.Req.Context(), c.Query("email")) if err != nil { c.NotFoundOrError(err, "get user by email") return diff --git a/internal/route/user/setting.go b/internal/route/user/setting.go index 6d781cbe..c873aeaf 100644 --- a/internal/route/user/setting.go +++ b/internal/route/user/setting.go @@ -256,7 +256,7 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) { } emailAddr := &db.EmailAddress{ - UID: c.User.ID, + UserID: c.User.ID, Email: f.Email, IsActivated: !conf.Auth.RequireEmailConfirmation, } @@ -286,8 +286,8 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) { func DeleteEmail(c *context.Context) { if err := db.DeleteEmailAddress(&db.EmailAddress{ - ID: c.QueryInt64("id"), - UID: c.User.ID, + ID: c.QueryInt64("id"), + UserID: c.User.ID, }); err != nil { c.Errorf(err, "delete email address") return |