package service import ( "context" "errors" "strings" "github.com/user-management-system/internal/auth" "github.com/user-management-system/internal/domain" "github.com/user-management-system/internal/repository" ) // UserService 用户服务 type UserService struct { userRepo *repository.UserRepository userRoleRepo *repository.UserRoleRepository roleRepo *repository.RoleRepository passwordHistoryRepo *repository.PasswordHistoryRepository } const passwordHistoryLimit = 5 // 保留最近5条密码历史 // NewUserService 创建用户服务实例 func NewUserService( userRepo *repository.UserRepository, userRoleRepo *repository.UserRoleRepository, roleRepo *repository.RoleRepository, passwordHistoryRepo *repository.PasswordHistoryRepository, ) *UserService { return &UserService{ userRepo: userRepo, userRoleRepo: userRoleRepo, roleRepo: roleRepo, passwordHistoryRepo: passwordHistoryRepo, } } // ChangePassword 修改用户密码(含历史记录检查) func (s *UserService) ChangePassword(ctx context.Context, userID int64, oldPassword, newPassword string) error { if s.userRepo == nil { return errors.New("user repository is not configured") } user, err := s.userRepo.GetByID(ctx, userID) if err != nil { return errors.New("用户不存在") } // 验证旧密码 if strings.TrimSpace(oldPassword) == "" { return errors.New("请输入当前密码") } if !auth.VerifyPassword(user.Password, oldPassword) { return errors.New("当前密码不正确") } // 检查新密码强度 if strings.TrimSpace(newPassword) == "" { return errors.New("新密码不能为空") } if err := validatePasswordStrength(newPassword, 8, false); err != nil { return err } // 检查密码历史 if s.passwordHistoryRepo != nil { histories, err := s.passwordHistoryRepo.GetByUserID(ctx, userID, passwordHistoryLimit) if err == nil && len(histories) > 0 { for _, h := range histories { if auth.VerifyPassword(h.PasswordHash, newPassword) { return errors.New("新密码不能与最近5次密码相同") } } } // 保存新密码到历史记录 newHashedPassword, hashErr := auth.HashPassword(newPassword) if hashErr != nil { return errors.New("密码哈希失败") } go func() { _ = s.passwordHistoryRepo.Create(context.Background(), &domain.PasswordHistory{ UserID: userID, PasswordHash: newHashedPassword, }) _ = s.passwordHistoryRepo.DeleteOldRecords(context.Background(), userID, passwordHistoryLimit) }() } // 更新密码 newHashedPassword, err := auth.HashPassword(newPassword) if err != nil { return errors.New("密码哈希失败") } user.Password = newHashedPassword return s.userRepo.Update(ctx, user) } // GetByID 根据ID获取用户 func (s *UserService) GetByID(ctx context.Context, id int64) (*domain.User, error) { return s.userRepo.GetByID(ctx, id) } // GetByEmail 根据邮箱获取用户 func (s *UserService) GetByEmail(ctx context.Context, email string) (*domain.User, error) { return s.userRepo.GetByEmail(ctx, email) } // Create 创建用户 func (s *UserService) Create(ctx context.Context, user *domain.User) error { return s.userRepo.Create(ctx, user) } // Update 更新用户 func (s *UserService) Update(ctx context.Context, user *domain.User) error { return s.userRepo.Update(ctx, user) } // Delete 删除用户 func (s *UserService) Delete(ctx context.Context, id int64) error { return s.userRepo.Delete(ctx, id) } // List 获取用户列表 func (s *UserService) List(ctx context.Context, offset, limit int) ([]*domain.User, int64, error) { return s.userRepo.List(ctx, offset, limit) } // UpdateStatus 更新用户状态 func (s *UserService) UpdateStatus(ctx context.Context, id int64, status domain.UserStatus) error { return s.userRepo.UpdateStatus(ctx, id, status) }