aboutsummaryrefslogtreecommitdiff
path: root/internal/db/users.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/db/users.go')
-rw-r--r--internal/db/users.go94
1 files changed, 51 insertions, 43 deletions
diff --git a/internal/db/users.go b/internal/db/users.go
index 5c8f2d38..cac22c44 100644
--- a/internal/db/users.go
+++ b/internal/db/users.go
@@ -23,8 +23,8 @@ import (
//
// NOTE: All methods are sorted in alphabetical order.
type UsersStore interface {
- // Authenticate validates username and password via given login source ID.
- // It returns ErrUserNotExist when the user was not found.
+ // Authenticate validates username and password via given login source ID. It
+ // returns ErrUserNotExist when the user was not found.
//
// When the "loginSourceID" is negative, it aborts the process and returns
// ErrUserNotExist if the user was not found in the database.
@@ -34,23 +34,25 @@ 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(username, password string, loginSourceID int64) (*User, error)
- // 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.
- Create(username, email string, opts CreateUserOpts) (*User, error)
- // GetByEmail returns the user (not organization) with given email.
- // It ignores records with unverified emails and returns ErrUserNotExist when not found.
- GetByEmail(email string) (*User, error)
- // GetByID returns the user with given ID. It returns ErrUserNotExist when not found.
- GetByID(id int64) (*User, error)
- // GetByUsername returns the user with given username. It returns ErrUserNotExist when not found.
- GetByUsername(username string) (*User, error)
+ Authenticate(ctx context.Context, username, password string, loginSourceID int64) (*User, error)
+ // 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.
+ Create(ctx context.Context, username, email string, opts CreateUserOpts) (*User, error)
+ // GetByEmail returns the user (not organization) with given email. It ignores
+ // records with unverified emails and returns ErrUserNotExist when not found.
+ GetByEmail(ctx context.Context, email string) (*User, error)
+ // GetByID returns the user with given ID. It returns ErrUserNotExist when not
+ // found.
+ GetByID(ctx context.Context, id int64) (*User, error)
+ // GetByUsername returns the user with given username. It returns
+ // ErrUserNotExist when not found.
+ GetByUsername(ctx context.Context, username string) (*User, error)
}
var Users UsersStore
-// NOTE: This is a GORM create hook.
+// BeforeCreate implements the GORM create hook.
func (u *User) BeforeCreate(tx *gorm.DB) error {
if u.CreatedUnix == 0 {
u.CreatedUnix = tx.NowFunc().Unix()
@@ -59,7 +61,7 @@ func (u *User) BeforeCreate(tx *gorm.DB) error {
return nil
}
-// NOTE: This is a GORM query hook.
+// AfterFind implements the GORM query hook.
func (u *User) AfterFind(_ *gorm.DB) error {
u.Created = time.Unix(u.CreatedUnix, 0).Local()
u.Updated = time.Unix(u.UpdatedUnix, 0).Local()
@@ -80,16 +82,14 @@ func (err ErrLoginSourceMismatch) Error() string {
return fmt.Sprintf("login source mismatch: %v", err.args)
}
-func (db *users) Authenticate(login, password string, loginSourceID int64) (*User, error) {
- ctx := context.TODO()
-
+func (db *users) Authenticate(ctx context.Context, login, password string, loginSourceID int64) (*User, error) {
login = strings.ToLower(login)
- var query *gorm.DB
+ query := db.WithContext(ctx)
if strings.Contains(login, "@") {
- query = db.Where("email = ?", login)
+ query = query.Where("email = ?", login)
} else {
- query = db.Where("lower_name = ?", login)
+ query = query.Where("lower_name = ?", login)
}
user := new(User)
@@ -153,15 +153,17 @@ func (db *users) Authenticate(login, password string, loginSourceID int64) (*Use
return nil, fmt.Errorf("invalid pattern for attribute 'username' [%s]: must be valid alpha or numeric or dash(-_) or dot characters", extAccount.Name)
}
- return Users.Create(extAccount.Name, extAccount.Email, CreateUserOpts{
- FullName: extAccount.FullName,
- LoginSource: authSourceID,
- LoginName: extAccount.Login,
- Location: extAccount.Location,
- Website: extAccount.Website,
- Activated: true,
- Admin: extAccount.Admin,
- })
+ return db.Create(ctx, extAccount.Name, extAccount.Email,
+ CreateUserOpts{
+ FullName: extAccount.FullName,
+ LoginSource: authSourceID,
+ LoginName: extAccount.Login,
+ Location: extAccount.Location,
+ Website: extAccount.Website,
+ Activated: true,
+ Admin: extAccount.Admin,
+ },
+ )
}
type CreateUserOpts struct {
@@ -209,20 +211,20 @@ func (err ErrEmailAlreadyUsed) Error() string {
return fmt.Sprintf("email has been used: %v", err.args)
}
-func (db *users) Create(username, email string, opts CreateUserOpts) (*User, error) {
+func (db *users) Create(ctx context.Context, username, email string, opts CreateUserOpts) (*User, error) {
err := isUsernameAllowed(username)
if err != nil {
return nil, err
}
- _, err = db.GetByUsername(username)
+ _, err = db.GetByUsername(ctx, username)
if err == nil {
return nil, ErrUserAlreadyExist{args: errutil.Args{"name": username}}
} else if !IsErrUserNotExist(err) {
return nil, err
}
- _, err = db.GetByEmail(email)
+ _, err = db.GetByEmail(ctx, email)
if err == nil {
return nil, ErrEmailAlreadyUsed{args: errutil.Args{"email": email}}
} else if !IsErrUserNotExist(err) {
@@ -256,7 +258,7 @@ func (db *users) Create(username, email string, opts CreateUserOpts) (*User, err
}
user.EncodePassword()
- return user, db.DB.Create(user).Error
+ return user, db.WithContext(ctx).Create(user).Error
}
var _ errutil.NotFound = (*ErrUserNotExist)(nil)
@@ -278,7 +280,7 @@ func (ErrUserNotExist) NotFound() bool {
return true
}
-func (db *users) GetByEmail(email string) (*User, error) {
+func (db *users) GetByEmail(ctx context.Context, email string) (*User, error) {
email = strings.ToLower(email)
if email == "" {
@@ -287,7 +289,10 @@ func (db *users) GetByEmail(email string) (*User, error) {
// First try to find the user by primary email
user := new(User)
- err := db.Where("email = ? AND type = ? AND is_active = ?", email, UserIndividual, true).First(user).Error
+ err := db.WithContext(ctx).
+ Where("email = ? AND type = ? AND is_active = ?", email, UserIndividual, true).
+ First(user).
+ Error
if err == nil {
return user, nil
} else if err != gorm.ErrRecordNotFound {
@@ -296,7 +301,10 @@ func (db *users) GetByEmail(email string) (*User, error) {
// Otherwise, check activated email addresses
emailAddress := new(EmailAddress)
- err = db.Where("email = ? AND is_activated = ?", email, true).First(emailAddress).Error
+ err = db.WithContext(ctx).
+ Where("email = ? AND is_activated = ?", email, true).
+ First(emailAddress).
+ Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrUserNotExist{args: errutil.Args{"email": email}}
@@ -304,12 +312,12 @@ func (db *users) GetByEmail(email string) (*User, error) {
return nil, err
}
- return db.GetByID(emailAddress.UID)
+ return db.GetByID(ctx, emailAddress.UID)
}
-func (db *users) GetByID(id int64) (*User, error) {
+func (db *users) GetByID(ctx context.Context, id int64) (*User, error) {
user := new(User)
- err := db.Where("id = ?", id).First(user).Error
+ err := db.WithContext(ctx).Where("id = ?", id).First(user).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrUserNotExist{args: errutil.Args{"userID": id}}
@@ -319,9 +327,9 @@ func (db *users) GetByID(id int64) (*User, error) {
return user, nil
}
-func (db *users) GetByUsername(username string) (*User, error) {
+func (db *users) GetByUsername(ctx context.Context, username string) (*User, error) {
user := new(User)
- err := db.Where("lower_name = ?", strings.ToLower(username)).First(user).Error
+ err := db.WithContext(ctx).Where("lower_name = ?", strings.ToLower(username)).First(user).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrUserNotExist{args: errutil.Args{"name": username}}