feat: add opt support to account, refactor validation api
This commit is contained in:
parent
431dec55f9
commit
96758a5559
|
@ -11,6 +11,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidOTPCode = errors.New("Invalid OTP code")
|
||||||
|
)
|
||||||
|
|
||||||
type AccountServiceParams struct {
|
type AccountServiceParams struct {
|
||||||
fx.In
|
fx.In
|
||||||
Db *gorm.DB
|
Db *gorm.DB
|
||||||
|
@ -107,7 +111,7 @@ func (s AccountServiceDefault) AddPubkeyToAccount(user models.User, pubkey strin
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (s AccountServiceDefault) LoginPassword(email string, password string, ip string) (string, *models.User, error) {
|
func (s AccountServiceDefault) LoginPassword(email string, password string, ip string) (string, *models.User, error) {
|
||||||
valid, user, err := s.ValidLogin(email, password)
|
valid, user, err := s.ValidLoginByEmail(email, password)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
|
@ -126,7 +130,33 @@ func (s AccountServiceDefault) LoginPassword(email string, password string, ip s
|
||||||
return token, user, nil
|
return token, user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s AccountServiceDefault) ValidLogin(email string, password string) (bool, *models.User, error) {
|
func (s AccountServiceDefault) LoginOTP(userId uint, code string) (string, error) {
|
||||||
|
valid, err := s.OTPVerify(userId, code)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
return "", ErrInvalidOTPCode
|
||||||
|
}
|
||||||
|
|
||||||
|
var user models.User
|
||||||
|
user.ID = userId
|
||||||
|
|
||||||
|
token, err := JWTGenerateToken(s.config.GetString("core.domain"), s.identity, user.ID, JWTPurposeLogin)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) ValidLoginByUserObj(user *models.User, password string) bool {
|
||||||
|
return s.validPassword(user, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) ValidLoginByEmail(email string, password string) (bool, *models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
result := s.db.Model(&models.User{}).Where(&models.User{Email: email}).First(&user)
|
result := s.db.Model(&models.User{}).Where(&models.User{Email: email}).First(&user)
|
||||||
|
@ -135,14 +165,35 @@ func (s AccountServiceDefault) ValidLogin(email string, password string) (bool,
|
||||||
return false, nil, result.Error
|
return false, nil, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password))
|
valid := s.ValidLoginByUserObj(&user, password)
|
||||||
if err != nil {
|
|
||||||
return false, nil, err
|
if !valid {
|
||||||
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil, nil
|
return true, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) ValidLoginByUserID(id uint, password string) (bool, *models.User, error) {
|
||||||
|
var user models.User
|
||||||
|
|
||||||
|
user.ID = id
|
||||||
|
|
||||||
|
result := s.db.Model(&user).Where(&user).First(&user)
|
||||||
|
|
||||||
|
if result.RowsAffected == 0 || result.Error != nil {
|
||||||
|
return false, nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
valid := s.ValidLoginByUserObj(&user, password)
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, &user, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s AccountServiceDefault) LoginPubkey(pubkey string) (string, error) {
|
func (s AccountServiceDefault) LoginPubkey(pubkey string) (string, error) {
|
||||||
var model models.PublicKey
|
var model models.PublicKey
|
||||||
|
|
||||||
|
@ -252,8 +303,62 @@ func (s AccountServiceDefault) PinByID(uploadId uint, accountID uint) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) OTPGenerate(userId uint) (string, error) {
|
||||||
|
exists, user, err := s.AccountExists(userId)
|
||||||
|
|
||||||
|
if !exists || err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
otp, err := TOTPGenerate(user.Email, s.config.GetString("core.domain"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.updateAccountInfo(user.ID, models.User{OTPSecret: otp})
|
||||||
|
return otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) OTPVerify(userId uint, code string) (bool, error) {
|
||||||
|
exists, user, err := s.AccountExists(userId)
|
||||||
|
|
||||||
|
if !exists || err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
valid := TOTPValidate(user.OTPSecret, code)
|
||||||
|
if !valid {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) OTPEnable(userId uint, code string) error {
|
||||||
|
verify, err := s.OTPVerify(userId, code)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !verify {
|
||||||
|
return ErrInvalidOTPCode
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.updateAccountInfo(userId, models.User{OTPEnabled: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) OTPDisable(userId uint) error {
|
||||||
|
return s.updateAccountInfo(userId, models.User{OTPEnabled: false, OTPSecret: ""})
|
||||||
|
}
|
||||||
|
|
||||||
func (s AccountServiceDefault) doLogin(user *models.User, ip string) (string, error) {
|
func (s AccountServiceDefault) doLogin(user *models.User, ip string) (string, error) {
|
||||||
token, err := JWTGenerateToken(s.config.GetString("core.domain"), s.identity, user.ID, JWTPurposeLogin)
|
purpose := JWTPurposeLogin
|
||||||
|
|
||||||
|
if user.OTPEnabled {
|
||||||
|
purpose = JWTPurpose2FA
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := JWTGenerateToken(s.config.GetString("core.domain"), s.identity, user.ID, purpose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -295,3 +400,9 @@ func (s AccountServiceDefault) exists(model interface{}, conditions map[string]i
|
||||||
|
|
||||||
return exists, model, result.Error
|
return exists, model, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s AccountServiceDefault) validPassword(user *models.User, password string) bool {
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password))
|
||||||
|
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue