// Package service 提供业务逻辑层 package service import ( "errors" "seeyon-filesystem/config" "seeyon-filesystem/dto" "seeyon-filesystem/model" "seeyon-filesystem/repository" "seeyon-filesystem/utils" "gorm.io/gorm" ) // AuthService 认证服务 type AuthService struct { userRepo *repository.UserRepository } // NewAuthService 创建认证服务实例 func NewAuthService() *AuthService { return &AuthService{ userRepo: repository.NewUserRepository(), } } // Login 用户登录(用户名+密码) func (s *AuthService) Login(req *dto.LoginRequest) (*dto.LoginResponse, error) { // 查找用户 user, err := s.userRepo.FindByUsername(req.Username) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("用户名或密码错误") } return nil, err } // 检查用户状态 if user.Status != 1 { return nil, errors.New("账号已被禁用") } // 验证密码 if !utils.CheckPassword(req.Password, user.Password) { return nil, errors.New("用户名或密码错误") } // 生成JWT Token token, err := utils.GenerateToken( user.ID, user.Username, user.Role, config.AppConfig.JWT.Secret, config.AppConfig.JWT.Expiration, ) if err != nil { return nil, errors.New("生成Token失败") } return &dto.LoginResponse{ Token: token, Username: user.Username, Nickname: user.Nickname, Role: user.Role, MustChangePwd: user.MustChangePwd == 1, }, nil } // validateAppLogin 校验 appId 登录 func (s *AuthService) validateAppLogin(appID string, userID uint64) error { // 1. appId 是否存在且启用 var app model.App if err := config.DB.Where("app_id = ? AND status = 1", appID).First(&app).Error; err != nil { return errors.New("应用ID无效或已禁用") } // 2. 用户是否已绑定该应用 var count int64 config.DB.Model(&model.AppUser{}).Where("app_id = ? AND user_id = ?", app.ID, userID).Count(&count) if count == 0 { return errors.New("用户未授权此应用") } return nil } // AppLogin 应用登录(用户名+appId) func (s *AuthService) AppLogin(req *dto.AppLoginRequest) (*dto.LoginResponse, error) { // 查找用户 user, err := s.userRepo.FindByUsername(req.Username) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("用户名或密码错误") } return nil, err } // 检查用户状态 if user.Status != 1 { return nil, errors.New("账号已被禁用") } // 校验 appId if err := s.validateAppLogin(req.AppID, user.ID); err != nil { return nil, err } // 生成JWT Token token, err := utils.GenerateToken( user.ID, user.Username, user.Role, config.AppConfig.JWT.Secret, config.AppConfig.JWT.Expiration, ) if err != nil { return nil, errors.New("生成Token失败") } return &dto.LoginResponse{ Token: token, Username: user.Username, Nickname: user.Nickname, Role: user.Role, MustChangePwd: user.MustChangePwd == 1, }, nil } // Register 用户注册 func (s *AuthService) Register(req *dto.RegisterRequest) error { existing, _ := s.userRepo.FindByUsername(req.Username) if existing != nil { return errors.New("用户名已存在") } hashedPassword, err := utils.HashPassword(req.Password) if err != nil { return errors.New("密码加密失败") } user := &model.User{ Username: req.Username, Password: hashedPassword, Email: req.Email, Nickname: req.Nickname, Role: "user", Status: 1, } if err := s.userRepo.Create(user); err != nil { return err } // 分配默认角色(user), 使存储策略分配生效 var role model.Role if config.DB.Where("name = ?", "user").First(&role).Error == nil { config.DB.Create(&model.UserRole{UserID: user.ID, RoleID: role.ID}) } return nil } // ChangePassword 修改密码 func (s *AuthService) ChangePassword(userID uint64, req *dto.ChangePasswordRequest) error { user, err := s.userRepo.FindByID(userID) if err != nil { return errors.New("用户不存在") } // 验证旧密码 if !utils.CheckPassword(req.OldPassword, user.Password) { return errors.New("当前密码错误") } // 新密码不能和旧密码相同 if req.OldPassword == req.NewPassword { return errors.New("新密码不能与当前密码相同") } // 加密新密码 hashedPassword, err := utils.HashPassword(req.NewPassword) if err != nil { return errors.New("密码加密失败") } user.Password = hashedPassword user.MustChangePwd = 0 // 清除强制改密码标记 return s.userRepo.Update(user) }