diff options
author | Joe Chen <jc@unknwon.io> | 2022-11-05 18:56:48 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-05 18:56:48 +0800 |
commit | b5d47b969258f3d644ad797b29901eb607f6b94f (patch) | |
tree | 790d2f06c0fc1dc0442c3869edf7fcd2dd6a8e42 /internal | |
parent | fd798b4197dc53df872d20f5d10edb8d73c32386 (diff) |
refactor(db): migrate methods off `user.go` (#7230)
Diffstat (limited to 'internal')
-rw-r--r-- | internal/cmd/admin.go | 23 | ||||
-rw-r--r-- | internal/context/auth.go | 25 | ||||
-rw-r--r-- | internal/db/org_team.go | 4 | ||||
-rw-r--r-- | internal/db/repo.go | 10 | ||||
-rw-r--r-- | internal/db/user.go | 110 | ||||
-rw-r--r-- | internal/db/users.go | 141 | ||||
-rw-r--r-- | internal/db/users_test.go | 40 | ||||
-rw-r--r-- | internal/route/admin/users.go | 25 | ||||
-rw-r--r-- | internal/route/api/v1/admin/user.go | 40 | ||||
-rw-r--r-- | internal/route/install.go | 30 | ||||
-rw-r--r-- | internal/route/user/auth.go | 36 |
11 files changed, 273 insertions, 211 deletions
diff --git a/internal/cmd/admin.go b/internal/cmd/admin.go index 79820233..54a4a254 100644 --- a/internal/cmd/admin.go +++ b/internal/cmd/admin.go @@ -5,6 +5,7 @@ package cmd import ( + "context" "fmt" "reflect" "runtime" @@ -151,17 +152,21 @@ func runCreateUser(c *cli.Context) error { return errors.Wrap(err, "set engine") } - if err := db.CreateUser(&db.User{ - Name: c.String("name"), - Email: c.String("email"), - Password: c.String("password"), - IsActive: true, - IsAdmin: c.Bool("admin"), - }); err != nil { - return fmt.Errorf("CreateUser: %v", err) + user, err := db.Users.Create( + context.Background(), + c.String("name"), + c.String("email"), + db.CreateUserOptions{ + Password: c.String("password"), + Activated: true, + Admin: c.Bool("admin"), + }, + ) + if err != nil { + return errors.Wrap(err, "create user") } - fmt.Printf("New user '%s' has been successfully created!\n", c.String("name")) + fmt.Printf("New user %q has been successfully created!\n", user.Name) return nil } diff --git a/internal/context/auth.go b/internal/context/auth.go index 775a3dd8..73a362c6 100644 --- a/internal/context/auth.go +++ b/internal/context/auth.go @@ -175,7 +175,7 @@ func authenticatedUser(ctx *macaron.Context, sess session.Store) (_ *db.User, is if conf.Auth.EnableReverseProxyAuthentication { webAuthUser := ctx.Req.Header.Get(conf.Auth.ReverseProxyAuthenticationHeader) if len(webAuthUser) > 0 { - u, err := db.GetUserByName(webAuthUser) + user, err := db.GetUserByName(webAuthUser) if err != nil { if !db.IsErrUserNotExist(err) { log.Error("Failed to get user by name: %v", err) @@ -184,22 +184,21 @@ func authenticatedUser(ctx *macaron.Context, sess session.Store) (_ *db.User, is // Check if enabled auto-registration. if conf.Auth.EnableReverseProxyAutoRegistration { - u := &db.User{ - Name: webAuthUser, - Email: gouuid.NewV4().String() + "@localhost", - Password: webAuthUser, - IsActive: true, - } - if err = db.CreateUser(u); err != nil { - // FIXME: should I create a system notice? - log.Error("Failed to create user: %v", err) + user, err = db.Users.Create( + ctx.Req.Context(), + webAuthUser, + gouuid.NewV4().String()+"@localhost", + db.CreateUserOptions{ + Activated: true, + }, + ) + if err != nil { + log.Error("Failed to create user %q: %v", webAuthUser, err) return nil, false, false - } else { - return u, false, false } } } - return u, false, false + return user, false, false } } diff --git a/internal/db/org_team.go b/internal/db/org_team.go index 6bdf4253..cfc4c08c 100644 --- a/internal/db/org_team.go +++ b/internal/db/org_team.go @@ -245,7 +245,9 @@ func (t *Team) RemoveRepository(repoID int64) error { return sess.Commit() } -var reservedTeamNames = []string{"new"} +var reservedTeamNames = map[string]struct{}{ + "new": {}, +} // IsUsableTeamName return an error if given name is a reserved name or pattern. func IsUsableTeamName(name string) error { diff --git a/internal/db/repo.go b/internal/db/repo.go index bb2cd52e..81a6cd00 100644 --- a/internal/db/repo.go +++ b/internal/db/repo.go @@ -1081,8 +1081,14 @@ func initRepository(e Engine, repoPath string, doer *User, repo *Repository, opt } var ( - reservedRepoNames = []string{".", ".."} - reservedRepoPatterns = []string{"*.git", "*.wiki"} + reservedRepoNames = map[string]struct{}{ + ".": {}, + "..": {}, + } + reservedRepoPatterns = []string{ + "*.git", + "*.wiki", + } ) // isRepoNameAllowed return an error if given name is a reserved name or pattern for repositories. diff --git a/internal/db/user.go b/internal/db/user.go index 4e5e4c1f..e15c9410 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -13,7 +13,6 @@ import ( "path/filepath" "strings" "time" - "unicode/utf8" "github.com/unknwon/com" log "unknwon.dev/clog/v2" @@ -59,115 +58,6 @@ func (u *User) getOrganizationCount(e Engine) (int64, error) { return e.Where("uid=?", u.ID).Count(new(OrgUser)) } -var ( - reservedUsernames = []string{"-", "explore", "create", "assets", "css", "img", "js", "less", "plugins", "debug", "raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin", "new", ".", ".."} - reservedUserPatterns = []string{"*.keys"} -) - -type ErrNameNotAllowed struct { - args errutil.Args -} - -func IsErrNameNotAllowed(err error) bool { - _, ok := err.(ErrNameNotAllowed) - return ok -} - -func (err ErrNameNotAllowed) Value() string { - val, ok := err.args["name"].(string) - if ok { - return val - } - - val, ok = err.args["pattern"].(string) - if ok { - return val - } - - return "<value not found>" -} - -func (err ErrNameNotAllowed) Error() string { - return fmt.Sprintf("name is not allowed: %v", err.args) -} - -// isNameAllowed checks if name is reserved or pattern of name is not allowed -// based on given reserved names and patterns. -// Names are exact match, patterns can be prefix or suffix match with placeholder '*'. -func isNameAllowed(names, patterns []string, name string) error { - name = strings.TrimSpace(strings.ToLower(name)) - if utf8.RuneCountInString(name) == 0 { - return ErrNameNotAllowed{args: errutil.Args{"reason": "empty name"}} - } - - for i := range names { - if name == names[i] { - return ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "name": name}} - } - } - - for _, pat := range patterns { - if pat[0] == '*' && strings.HasSuffix(name, pat[1:]) || - (pat[len(pat)-1] == '*' && strings.HasPrefix(name, pat[:len(pat)-1])) { - return ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "pattern": pat}} - } - } - - return nil -} - -// isUsernameAllowed return an error if given name is a reserved name or pattern for users. -func isUsernameAllowed(name string) error { - return isNameAllowed(reservedUsernames, reservedUserPatterns, name) -} - -// CreateUser creates record of a new user. -// -// Deprecated: Use Users.Create instead. -func CreateUser(u *User) (err error) { - if err = isUsernameAllowed(u.Name); err != nil { - return err - } - - if Users.IsUsernameUsed(context.TODO(), u.Name) { - return ErrUserAlreadyExist{args: errutil.Args{"name": u.Name}} - } - - u.Email = strings.ToLower(u.Email) - isExist, err := IsEmailUsed(u.Email) - if err != nil { - return err - } else if isExist { - return ErrEmailAlreadyUsed{args: errutil.Args{"email": u.Email}} - } - - u.LowerName = strings.ToLower(u.Name) - u.AvatarEmail = u.Email - u.Avatar = tool.HashEmail(u.AvatarEmail) - if u.Rands, err = userutil.RandomSalt(); err != nil { - return err - } - if u.Salt, err = userutil.RandomSalt(); err != nil { - return err - } - u.Password = userutil.EncodePassword(u.Password, u.Salt) - u.MaxRepoCreation = -1 - - sess := x.NewSession() - defer sess.Close() - if err = sess.Begin(); err != nil { - return err - } - - if _, err = sess.Insert(u); err != nil { - return err - } else if err = os.MkdirAll(UserPath(u.Name), os.ModePerm); err != nil { - return err - } - - return sess.Commit() -} - func countUsers(e Engine) int64 { count, _ := e.Where("type=0").Count(new(User)) return count diff --git a/internal/db/users.go b/internal/db/users.go index f87dc28d..37494638 100644 --- a/internal/db/users.go +++ b/internal/db/users.go @@ -10,6 +10,7 @@ import ( "os" "strings" "time" + "unicode/utf8" "github.com/go-macaron/binding" api "github.com/gogs/go-gogs-client" @@ -234,12 +235,20 @@ func (db *users) Create(ctx context.Context, username, email string, opts Create } if db.IsUsernameUsed(ctx, username) { - return nil, ErrUserAlreadyExist{args: errutil.Args{"name": username}} + return nil, ErrUserAlreadyExist{ + args: errutil.Args{ + "name": username, + }, + } } _, err = db.GetByEmail(ctx, email) if err == nil { - return nil, ErrEmailAlreadyUsed{args: errutil.Args{"email": email}} + return nil, ErrEmailAlreadyUsed{ + args: errutil.Args{ + "email": email, + }, + } } else if !IsErrUserNotExist(err) { return nil, err } @@ -257,7 +266,7 @@ func (db *users) Create(ctx context.Context, username, email string, opts Create MaxRepoCreation: -1, IsActive: opts.Activated, IsAdmin: opts.Admin, - Avatar: cryptoutil.MD5(email), + Avatar: cryptoutil.MD5(email), // Gravatar URL uses the MD5 hash of the email, see https://en.gravatar.com/site/implement/hash/ AvatarEmail: email, } @@ -579,16 +588,6 @@ func (u *User) DisplayName() string { return u.Name } -// NewGhostUser creates and returns a fake user for people who has deleted their -// accounts. -func NewGhostUser() *User { - return &User{ - ID: -1, - Name: "Ghost", - LowerName: "ghost", - } -} - // HomeURLPath returns the URL path to the user or organization home page. // // TODO(unknwon): This is also used in templates, which should be fixed by @@ -693,3 +692,119 @@ func (u *User) GetOrganizationCount() (int64, error) { func (u *User) ShortName(length int) string { return strutil.Ellipsis(u.Name, length) } + +// NewGhostUser creates and returns a fake user for people who has deleted their +// accounts. +// +// TODO: Once migrated to unknwon.dev/i18n, pass in the `i18n.Locale` to +// translate the text to local language. +func NewGhostUser() *User { + return &User{ + ID: -1, + Name: "Ghost", + LowerName: "ghost", + } +} + +var ( + reservedUsernames = map[string]struct{}{ + "-": {}, + "explore": {}, + "create": {}, + "assets": {}, + "css": {}, + "img": {}, + "js": {}, + "less": {}, + "plugins": {}, + "debug": {}, + "raw": {}, + "install": {}, + "api": {}, + "avatar": {}, + "user": {}, + "org": {}, + "help": {}, + "stars": {}, + "issues": {}, + "pulls": {}, + "commits": {}, + "repo": {}, + "template": {}, + "admin": {}, + "new": {}, + ".": {}, + "..": {}, + } + reservedUsernamePatterns = []string{"*.keys"} +) + +type ErrNameNotAllowed struct { + args errutil.Args +} + +func IsErrNameNotAllowed(err error) bool { + _, ok := err.(ErrNameNotAllowed) + return ok +} + +func (err ErrNameNotAllowed) Value() string { + val, ok := err.args["name"].(string) + if ok { + return val + } + + val, ok = err.args["pattern"].(string) + if ok { + return val + } + + return "<value not found>" +} + +func (err ErrNameNotAllowed) Error() string { + return fmt.Sprintf("name is not allowed: %v", err.args) +} + +// isNameAllowed checks if the name is reserved or pattern of the name is not +// allowed based on given reserved names and patterns. Names are exact match, +// patterns can be prefix or suffix match with the wildcard ("*"). +func isNameAllowed(names map[string]struct{}, patterns []string, name string) error { + name = strings.TrimSpace(strings.ToLower(name)) + if utf8.RuneCountInString(name) == 0 { + return ErrNameNotAllowed{ + args: errutil.Args{ + "reason": "empty name", + }, + } + } + + if _, ok := names[name]; ok { + return ErrNameNotAllowed{ + args: errutil.Args{ + "reason": "reserved", + "name": name, + }, + } + } + + for _, pattern := range patterns { + if pattern[0] == '*' && strings.HasSuffix(name, pattern[1:]) || + (pattern[len(pattern)-1] == '*' && strings.HasPrefix(name, pattern[:len(pattern)-1])) { + return ErrNameNotAllowed{ + args: errutil.Args{ + "reason": "reserved", + "pattern": pattern, + }, + } + } + } + + return nil +} + +// isUsernameAllowed returns ErrNameNotAllowed if the given name or pattern of +// the name is not allowed as a username. +func isUsernameAllowed(name string) error { + return isNameAllowed(reservedUsernames, reservedUsernamePatterns, name) +} diff --git a/internal/db/users_test.go b/internal/db/users_test.go index 9c940f6b..2479702a 100644 --- a/internal/db/users_test.go +++ b/internal/db/users_test.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "os" + "strings" "testing" "time" @@ -211,7 +212,10 @@ func usersAuthenticate(t *testing.T, db *users) { func usersCreate(t *testing.T, db *users) { ctx := context.Background() - alice, err := db.Create(ctx, "alice", "alice@example.com", + alice, err := db.Create( + ctx, + "alice", + "alice@example.com", CreateUserOptions{ Activated: true, }, @@ -220,19 +224,32 @@ func usersCreate(t *testing.T, db *users) { t.Run("name not allowed", func(t *testing.T) { _, err := db.Create(ctx, "-", "", CreateUserOptions{}) - wantErr := ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "name": "-"}} + wantErr := ErrNameNotAllowed{ + args: errutil.Args{ + "reason": "reserved", + "name": "-", + }, + } assert.Equal(t, wantErr, err) }) t.Run("name already exists", func(t *testing.T) { _, err := db.Create(ctx, alice.Name, "", CreateUserOptions{}) - wantErr := ErrUserAlreadyExist{args: errutil.Args{"name": alice.Name}} + wantErr := ErrUserAlreadyExist{ + args: errutil.Args{ + "name": alice.Name, + }, + } assert.Equal(t, wantErr, err) }) t.Run("email already exists", func(t *testing.T) { _, err := db.Create(ctx, "bob", alice.Email, CreateUserOptions{}) - wantErr := ErrEmailAlreadyUsed{args: errutil.Args{"email": alice.Email}} + wantErr := ErrEmailAlreadyUsed{ + args: errutil.Args{ + "email": alice.Email, + }, + } assert.Equal(t, wantErr, err) }) @@ -495,3 +512,18 @@ func usersUseCustomAvatar(t *testing.T, db *users) { require.NoError(t, err) assert.True(t, alice.UseCustomAvatar) } + +func TestIsUsernameAllowed(t *testing.T) { + for name := range reservedUsernames { + t.Run(name, func(t *testing.T) { + assert.True(t, IsErrNameNotAllowed(isUsernameAllowed(name))) + }) + } + + for _, pattern := range reservedUsernamePatterns { + t.Run(pattern, func(t *testing.T) { + username := strings.ReplaceAll(pattern, "*", "alice") + assert.True(t, IsErrNameNotAllowed(isUsernameAllowed(username))) + }) + } +} diff --git a/internal/route/admin/users.go b/internal/route/admin/users.go index ebdaf460..c1891fc4 100644 --- a/internal/route/admin/users.go +++ b/internal/route/admin/users.go @@ -5,6 +5,7 @@ package admin import ( + "strconv" "strings" "github.com/unknwon/com" @@ -77,22 +78,20 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { return } - u := &db.User{ - Name: f.UserName, - Email: f.Email, - Password: f.Password, - IsActive: true, + createUserOpts := db.CreateUserOptions{ + Password: f.Password, + Activated: true, } - if len(f.LoginType) > 0 { fields := strings.Split(f.LoginType, "-") if len(fields) == 2 { - u.LoginSource = com.StrTo(fields[1]).MustInt64() - u.LoginName = f.LoginName + createUserOpts.LoginSource, _ = strconv.ParseInt(fields[1], 10, 64) + createUserOpts.LoginName = f.LoginName } } - if err := db.CreateUser(u); err != nil { + user, err := db.Users.Create(c.Req.Context(), f.UserName, f.Email, createUserOpts) + if err != nil { switch { case db.IsErrUserAlreadyExist(err): c.Data["Err_UserName"] = true @@ -108,15 +107,15 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { } return } - log.Trace("Account created by admin (%s): %s", c.User.Name, u.Name) + log.Trace("Account %q created by admin %q", user.Name, c.User.Name) // Send email notification. if f.SendNotify && conf.Email.Enabled { - email.SendRegisterNotifyMail(c.Context, db.NewMailerUser(u)) + email.SendRegisterNotifyMail(c.Context, db.NewMailerUser(user)) } - c.Flash.Success(c.Tr("admin.users.new_success", u.Name)) - c.Redirect(conf.Server.Subpath + "/admin/users/" + com.ToStr(u.ID)) + c.Flash.Success(c.Tr("admin.users.new_success", user.Name)) + c.Redirect(conf.Server.Subpath + "/admin/users/" + strconv.FormatInt(user.ID, 10)) } func prepareUserInfo(c *context.Context) *db.User { diff --git a/internal/route/api/v1/admin/user.go b/internal/route/api/v1/admin/user.go index caca77d5..c7c207af 100644 --- a/internal/route/api/v1/admin/user.go +++ b/internal/route/api/v1/admin/user.go @@ -18,12 +18,12 @@ import ( "gogs.io/gogs/internal/userutil" ) -func parseLoginSource(c *context.APIContext, u *db.User, sourceID int64, loginName string) { +func parseLoginSource(c *context.APIContext, sourceID int64) { if sourceID == 0 { return } - source, err := db.LoginSources.GetByID(c.Req.Context(), sourceID) + _, err := db.LoginSources.GetByID(c.Req.Context(), sourceID) if err != nil { if db.IsErrLoginSourceNotExist(err) { c.ErrorStatus(http.StatusUnprocessableEntity, err) @@ -32,26 +32,27 @@ func parseLoginSource(c *context.APIContext, u *db.User, sourceID int64, loginNa } return } - - u.LoginSource = source.ID - u.LoginName = loginName } func CreateUser(c *context.APIContext, form api.CreateUserOption) { - u := &db.User{ - Name: form.Username, - FullName: form.FullName, - Email: form.Email, - Password: form.Password, - IsActive: true, - } - - parseLoginSource(c, u, form.SourceID, form.LoginName) + parseLoginSource(c, form.SourceID) if c.Written() { return } - if err := db.CreateUser(u); err != nil { + user, err := db.Users.Create( + c.Req.Context(), + form.Username, + form.Email, + db.CreateUserOptions{ + FullName: form.FullName, + Password: form.Password, + LoginSource: form.SourceID, + LoginName: form.LoginName, + Activated: true, + }, + ) + if err != nil { if db.IsErrUserAlreadyExist(err) || db.IsErrEmailAlreadyUsed(err) || db.IsErrNameNotAllowed(err) { @@ -61,14 +62,14 @@ func CreateUser(c *context.APIContext, form api.CreateUserOption) { } return } - log.Trace("Account created by admin %q: %s", c.User.Name, u.Name) + log.Trace("Account %q created by admin %q", user.Name, c.User.Name) // Send email notification. if form.SendNotify && conf.Email.Enabled { - email.SendRegisterNotifyMail(c.Context.Context, db.NewMailerUser(u)) + email.SendRegisterNotifyMail(c.Context.Context, db.NewMailerUser(user)) } - c.JSON(http.StatusCreated, u.APIFormat()) + c.JSON(http.StatusCreated, user.APIFormat()) } func EditUser(c *context.APIContext, form api.EditUserOption) { @@ -77,7 +78,7 @@ func EditUser(c *context.APIContext, form api.EditUserOption) { return } - parseLoginSource(c, u, form.SourceID, form.LoginName) + parseLoginSource(c, form.SourceID) if c.Written() { return } @@ -92,6 +93,7 @@ func EditUser(c *context.APIContext, form api.EditUserOption) { u.Password = userutil.EncodePassword(u.Password, u.Salt) } + u.LoginSource = form.SourceID u.LoginName = form.LoginName u.FullName = form.FullName u.Email = form.Email diff --git a/internal/route/install.go b/internal/route/install.go index 2e0e05b9..34a7cffc 100644 --- a/internal/route/install.go +++ b/internal/route/install.go @@ -387,27 +387,35 @@ func InstallPost(c *context.Context, f form.Install) { // Create admin account if len(f.AdminName) > 0 { - u := &db.User{ - Name: f.AdminName, - Email: f.AdminEmail, - Password: f.AdminPasswd, - IsAdmin: true, - IsActive: true, - } - if err := db.CreateUser(u); err != nil { + user, err := db.Users.Create( + c.Req.Context(), + f.AdminName, + f.AdminEmail, + db.CreateUserOptions{ + Password: f.AdminPasswd, + Activated: true, + Admin: true, + }, + ) + if err != nil { if !db.IsErrUserAlreadyExist(err) { conf.Security.InstallLock = false c.FormErr("AdminName", "AdminEmail") c.RenderWithErr(c.Tr("install.invalid_admin_setting", err), INSTALL, &f) return } + log.Info("Admin account already exist") - u, _ = db.GetUserByName(u.Name) + user, err = db.Users.GetByUsername(c.Req.Context(), f.AdminName) + if err != nil { + c.Error(err, "get user by name") + return + } } // Auto-login for admin - _ = c.Session.Set("uid", u.ID) - _ = c.Session.Set("uname", u.Name) + _ = c.Session.Set("uid", user.ID) + _ = c.Session.Set("uname", user.Name) } log.Info("First-time run install finished!") diff --git a/internal/route/user/auth.go b/internal/route/user/auth.go index 74c1a98f..17229a40 100644 --- a/internal/route/user/auth.go +++ b/internal/route/user/auth.go @@ -6,6 +6,7 @@ package user import ( "fmt" + "net/http" "net/url" "github.com/go-macaron/captcha" @@ -311,7 +312,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { c.Data["EnableCaptcha"] = conf.Auth.EnableRegistrationCaptcha if conf.Auth.DisableRegistration { - c.Status(403) + c.Status(http.StatusForbidden) return } @@ -332,13 +333,16 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { return } - u := &db.User{ - Name: f.UserName, - Email: f.Email, - Password: f.Password, - IsActive: !conf.Auth.RequireEmailConfirmation, - } - if err := db.CreateUser(u); err != nil { + user, err := db.Users.Create( + c.Req.Context(), + f.UserName, + f.Email, + db.CreateUserOptions{ + Password: f.Password, + Activated: !conf.Auth.RequireEmailConfirmation, + }, + ) + if err != nil { switch { case db.IsErrUserAlreadyExist(err): c.FormErr("UserName") @@ -354,27 +358,27 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { } return } - log.Trace("Account created: %s", u.Name) + log.Trace("Account created: %s", user.Name) // Auto-set admin for the only user. if db.CountUsers() == 1 { - u.IsAdmin = true - u.IsActive = true - if err := db.UpdateUser(u); err != nil { + user.IsAdmin = true + user.IsActive = true + if err := db.UpdateUser(user); err != nil { c.Error(err, "update user") return } } // Send confirmation email. - if conf.Auth.RequireEmailConfirmation && u.ID > 1 { - email.SendActivateAccountMail(c.Context, db.NewMailerUser(u)) + if conf.Auth.RequireEmailConfirmation && user.ID > 1 { + email.SendActivateAccountMail(c.Context, db.NewMailerUser(user)) c.Data["IsSendRegisterMail"] = true - c.Data["Email"] = u.Email + c.Data["Email"] = user.Email c.Data["Hours"] = conf.Auth.ActivateCodeLives / 60 c.Success(ACTIVATE) - if err := c.Cache.Put(userutil.MailResendCacheKey(u.ID), 1, 180); err != nil { + if err := c.Cache.Put(userutil.MailResendCacheKey(user.ID), 1, 180); err != nil { log.Error("Failed to put cache key 'mail resend': %v", err) } return |