mirror of https://github.com/gogs/gogs.git
refactor(db): migrate methods off `user.go` (#7230)
parent
fd798b4197
commit
b5d47b9692
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!")
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue