code.gitea.io/gitea@v1.21.7/services/auth/source/db/authenticate.go (about)

     1  // Copyright 2021 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package db
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	user_model "code.gitea.io/gitea/models/user"
    11  	"code.gitea.io/gitea/modules/setting"
    12  	"code.gitea.io/gitea/modules/util"
    13  )
    14  
    15  // ErrUserPasswordNotSet represents a "ErrUserPasswordNotSet" kind of error.
    16  type ErrUserPasswordNotSet struct {
    17  	UID  int64
    18  	Name string
    19  }
    20  
    21  func (err ErrUserPasswordNotSet) Error() string {
    22  	return fmt.Sprintf("user's password isn't set [uid: %d, name: %s]", err.UID, err.Name)
    23  }
    24  
    25  // Unwrap unwraps this error as a ErrInvalidArgument error
    26  func (err ErrUserPasswordNotSet) Unwrap() error {
    27  	return util.ErrInvalidArgument
    28  }
    29  
    30  // ErrUserPasswordInvalid represents a "ErrUserPasswordInvalid" kind of error.
    31  type ErrUserPasswordInvalid struct {
    32  	UID  int64
    33  	Name string
    34  }
    35  
    36  func (err ErrUserPasswordInvalid) Error() string {
    37  	return fmt.Sprintf("user's password is invalid [uid: %d, name: %s]", err.UID, err.Name)
    38  }
    39  
    40  // Unwrap unwraps this error as a ErrInvalidArgument error
    41  func (err ErrUserPasswordInvalid) Unwrap() error {
    42  	return util.ErrInvalidArgument
    43  }
    44  
    45  // Authenticate authenticates the provided user against the DB
    46  func Authenticate(ctx context.Context, user *user_model.User, login, password string) (*user_model.User, error) {
    47  	if user == nil {
    48  		return nil, user_model.ErrUserNotExist{Name: login}
    49  	}
    50  
    51  	if !user.IsPasswordSet() {
    52  		return nil, ErrUserPasswordNotSet{UID: user.ID, Name: user.Name}
    53  	} else if !user.ValidatePassword(password) {
    54  		return nil, ErrUserPasswordInvalid{UID: user.ID, Name: user.Name}
    55  	}
    56  
    57  	// Update password hash if server password hash algorithm have changed
    58  	// Or update the password when the salt length doesn't match the current
    59  	// recommended salt length, this in order to migrate user's salts to a more secure salt.
    60  	if user.PasswdHashAlgo != setting.PasswordHashAlgo || len(user.Salt) != user_model.SaltByteLength*2 {
    61  		if err := user.SetPassword(password); err != nil {
    62  			return nil, err
    63  		}
    64  		if err := user_model.UpdateUserCols(ctx, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
    65  			return nil, err
    66  		}
    67  	}
    68  
    69  	// WARN: DON'T check user.IsActive, that will be checked on reqSign so that
    70  	// user could be hinted to resend confirm email.
    71  	if user.ProhibitLogin {
    72  		return nil, user_model.ErrUserProhibitLogin{
    73  			UID:  user.ID,
    74  			Name: user.Name,
    75  		}
    76  	}
    77  
    78  	// attempting to login as a non-user account
    79  	if user.Type != user_model.UserTypeIndividual {
    80  		return nil, user_model.ErrUserProhibitLogin{
    81  			UID:  user.ID,
    82  			Name: user.Name,
    83  		}
    84  	}
    85  
    86  	return user, nil
    87  }