2024-01-06 17:56:32 +00:00
|
|
|
package services
|
|
|
|
|
|
|
|
import (
|
2024-03-12 15:23:16 +00:00
|
|
|
"fmt"
|
2024-04-20 11:04:33 +00:00
|
|
|
"github.com/samber/lo"
|
2024-03-12 15:23:16 +00:00
|
|
|
|
2024-04-13 05:48:19 +00:00
|
|
|
"git.solsynth.dev/hydrogen/passport/pkg/database"
|
|
|
|
"git.solsynth.dev/hydrogen/passport/pkg/models"
|
2024-01-29 08:11:59 +00:00
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/spf13/viper"
|
2024-01-06 17:56:32 +00:00
|
|
|
)
|
|
|
|
|
2024-01-29 08:11:59 +00:00
|
|
|
const EmailPasswordTemplate = `Dear %s,
|
|
|
|
|
|
|
|
We hope this message finds you well.
|
|
|
|
As part of our ongoing commitment to ensuring the security of your account, we require you to complete the login process by entering the verification code below:
|
|
|
|
|
|
|
|
Your Login Verification Code: %s
|
|
|
|
|
|
|
|
Please use the provided code within the next 2 hours to complete your login.
|
|
|
|
If you did not request this code, please update your information, maybe your username or email has been leak.
|
|
|
|
|
|
|
|
Thank you for your cooperation in helping us maintain the security of your account.
|
|
|
|
|
|
|
|
Best regards,
|
|
|
|
%s`
|
|
|
|
|
2024-04-20 11:04:33 +00:00
|
|
|
func GetPasswordFactor(userId uint) (models.AuthFactor, error) {
|
|
|
|
var factor models.AuthFactor
|
|
|
|
err := database.C.Where(models.AuthFactor{
|
|
|
|
Type: models.PasswordAuthFactor,
|
|
|
|
AccountID: userId,
|
|
|
|
}).First(&factor).Error
|
|
|
|
|
|
|
|
return factor, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetFactor(id uint) (models.AuthFactor, error) {
|
2024-01-06 17:56:32 +00:00
|
|
|
var factor models.AuthFactor
|
|
|
|
err := database.C.Where(models.AuthFactor{
|
|
|
|
BaseModel: models.BaseModel{ID: id},
|
|
|
|
}).First(&factor).Error
|
|
|
|
|
|
|
|
return factor, err
|
|
|
|
}
|
|
|
|
|
2024-04-20 11:04:33 +00:00
|
|
|
func ListUserFactor(userId uint) ([]models.AuthFactor, error) {
|
2024-01-06 17:56:32 +00:00
|
|
|
var factors []models.AuthFactor
|
|
|
|
err := database.C.Where(models.AuthFactor{
|
2024-04-20 11:04:33 +00:00
|
|
|
AccountID: userId,
|
2024-01-06 17:56:32 +00:00
|
|
|
}).Find(&factors).Error
|
|
|
|
|
|
|
|
return factors, err
|
|
|
|
}
|
2024-01-29 08:11:59 +00:00
|
|
|
|
|
|
|
func GetFactorCode(factor models.AuthFactor) (bool, error) {
|
|
|
|
switch factor.Type {
|
|
|
|
case models.EmailPasswordFactor:
|
|
|
|
var user models.Account
|
|
|
|
if err := database.C.Where(&models.Account{
|
|
|
|
BaseModel: models.BaseModel{ID: factor.AccountID},
|
|
|
|
}).Preload("Contacts").First(&user).Error; err != nil {
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
|
2024-03-12 15:23:16 +00:00
|
|
|
factor.Secret = uuid.NewString()[:6]
|
2024-01-29 08:11:59 +00:00
|
|
|
if err := database.C.Save(&factor).Error; err != nil {
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
|
|
|
|
subject := fmt.Sprintf("[%s] Login verification code", viper.GetString("name"))
|
|
|
|
content := fmt.Sprintf(EmailPasswordTemplate, user.Name, factor.Secret, viper.GetString("maintainer"))
|
|
|
|
if err := SendMail(user.GetPrimaryEmail().Content, subject, content); err != nil {
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
}
|
2024-04-20 11:04:33 +00:00
|
|
|
|
|
|
|
func CheckFactor(factor models.AuthFactor, code string) error {
|
|
|
|
switch factor.Type {
|
|
|
|
case models.PasswordAuthFactor:
|
|
|
|
return lo.Ternary(
|
|
|
|
VerifyPassword(code, factor.Secret),
|
|
|
|
nil,
|
|
|
|
fmt.Errorf("invalid password"),
|
|
|
|
)
|
|
|
|
case models.EmailPasswordFactor:
|
|
|
|
return lo.Ternary(
|
|
|
|
code == factor.Secret,
|
|
|
|
nil,
|
|
|
|
fmt.Errorf("invalid verification code"),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|