2025-12-03 10:58:39 +08:00
|
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
apperrors "carrotskin/internal/errors"
|
|
|
|
|
|
"carrotskin/internal/model"
|
|
|
|
|
|
"carrotskin/internal/repository"
|
|
|
|
|
|
"carrotskin/pkg/auth"
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// yggdrasilAuthService Yggdrasil认证服务实现
|
|
|
|
|
|
// 负责认证和密码管理
|
|
|
|
|
|
type yggdrasilAuthService struct {
|
|
|
|
|
|
db *gorm.DB
|
|
|
|
|
|
userRepo repository.UserRepository
|
|
|
|
|
|
yggdrasilRepo repository.YggdrasilRepository
|
|
|
|
|
|
logger *zap.Logger
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewYggdrasilAuthService 创建Yggdrasil认证服务实例(内部使用)
|
|
|
|
|
|
func NewYggdrasilAuthService(
|
|
|
|
|
|
db *gorm.DB,
|
|
|
|
|
|
userRepo repository.UserRepository,
|
|
|
|
|
|
yggdrasilRepo repository.YggdrasilRepository,
|
|
|
|
|
|
logger *zap.Logger,
|
|
|
|
|
|
) *yggdrasilAuthService {
|
|
|
|
|
|
return &yggdrasilAuthService{
|
|
|
|
|
|
db: db,
|
|
|
|
|
|
userRepo: userRepo,
|
|
|
|
|
|
yggdrasilRepo: yggdrasilRepo,
|
|
|
|
|
|
logger: logger,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *yggdrasilAuthService) GetUserIDByEmail(ctx context.Context, email string) (int64, error) {
|
2025-12-03 15:27:12 +08:00
|
|
|
|
user, err := s.userRepo.FindByEmail(ctx, email)
|
2025-12-03 10:58:39 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return 0, apperrors.ErrUserNotFound
|
|
|
|
|
|
}
|
|
|
|
|
|
return user.ID, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *yggdrasilAuthService) VerifyPassword(ctx context.Context, password string, userID int64) error {
|
2025-12-03 15:27:12 +08:00
|
|
|
|
passwordStore, err := s.yggdrasilRepo.GetPasswordByID(ctx, userID)
|
2025-12-03 10:58:39 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return apperrors.ErrPasswordNotSet
|
|
|
|
|
|
}
|
|
|
|
|
|
// 使用 bcrypt 验证密码
|
|
|
|
|
|
if !auth.CheckPassword(passwordStore, password) {
|
|
|
|
|
|
return apperrors.ErrPasswordMismatch
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *yggdrasilAuthService) ResetYggdrasilPassword(ctx context.Context, userID int64) (string, error) {
|
|
|
|
|
|
// 生成新的16位随机密码(明文,返回给用户)
|
|
|
|
|
|
plainPassword := model.GenerateRandomPassword(16)
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 bcrypt 加密密码后存储
|
|
|
|
|
|
hashedPassword, err := auth.HashPassword(plainPassword)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return "", fmt.Errorf("密码加密失败: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查Yggdrasil记录是否存在
|
2025-12-03 15:27:12 +08:00
|
|
|
|
_, err = s.yggdrasilRepo.GetPasswordByID(ctx, userID)
|
2025-12-03 10:58:39 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
// 如果不存在,创建新记录
|
|
|
|
|
|
yggdrasil := model.Yggdrasil{
|
|
|
|
|
|
ID: userID,
|
|
|
|
|
|
Password: hashedPassword,
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := s.db.Create(&yggdrasil).Error; err != nil {
|
|
|
|
|
|
return "", fmt.Errorf("创建Yggdrasil密码失败: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
return plainPassword, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果存在,更新密码(存储加密后的密码)
|
2025-12-03 15:27:12 +08:00
|
|
|
|
if err := s.yggdrasilRepo.ResetPassword(ctx, userID, hashedPassword); err != nil {
|
2025-12-03 10:58:39 +08:00
|
|
|
|
return "", fmt.Errorf("重置Yggdrasil密码失败: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 返回明文密码给用户
|
|
|
|
|
|
return plainPassword, nil
|
|
|
|
|
|
}
|