package app import ( "errors" "time" "git.echol.cn/loser/st/server/global" "git.echol.cn/loser/st/server/model/app" "git.echol.cn/loser/st/server/model/app/request" "git.echol.cn/loser/st/server/model/app/response" "git.echol.cn/loser/st/server/utils" "github.com/google/uuid" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) type AuthService struct{} // Register 用户注册 func (s *AuthService) Register(req *request.RegisterRequest) error { // 检查用户名是否已存在 var count int64 err := global.GVA_DB.Model(&app.AppUser{}).Where("username = ?", req.Username).Count(&count).Error if err != nil { return err } if count > 0 { return errors.New("用户名已存在") } // 检查邮箱是否已存在 if req.Email != "" { err = global.GVA_DB.Model(&app.AppUser{}).Where("email = ?", req.Email).Count(&count).Error if err != nil { return err } if count > 0 { return errors.New("邮箱已被使用") } } // 密码加密 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { return errors.New("密码加密失败") } // 创建用户 user := app.AppUser{ UUID: uuid.New().String(), Username: req.Username, Password: string(hashedPassword), NickName: req.NickName, Email: req.Email, Phone: req.Phone, Status: "active", Enable: true, } if user.NickName == "" { user.NickName = req.Username } return global.GVA_DB.Create(&user).Error } // Login 用户登录 func (s *AuthService) Login(req *request.LoginRequest, ip string) (*response.LoginResponse, error) { // 查询用户 var user app.AppUser err := global.GVA_DB.Where("username = ?", req.Username).First(&user).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("用户名或密码错误") } return nil, err } // 检查用户状态 if !user.Enable { return nil, errors.New("账户已被禁用") } if user.Status != "active" { return nil, errors.New("账户状态异常") } // 验证密码 err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)) if err != nil { return nil, errors.New("用户名或密码错误") } // 生成 Token token, expiresAt, err := utils.CreateAppToken(user.ID, user.Username) if err != nil { return nil, errors.New("Token 生成失败") } // 生成刷新 Token refreshToken, refreshExpiresAt, err := utils.CreateAppRefreshToken(user.ID, user.Username) if err != nil { return nil, errors.New("刷新 Token 生成失败") } // 更新最后登录信息 now := time.Now() global.GVA_DB.Model(&user).Updates(map[string]interface{}{ "last_login_at": now, "last_login_ip": ip, }) // 保存会话信息(可选) session := app.AppUserSession{ UserID: user.ID, SessionToken: token, RefreshToken: refreshToken, ExpiresAt: time.Unix(expiresAt, 0), RefreshExpiresAt: func() *time.Time { t := time.Unix(refreshExpiresAt, 0); return &t }(), IPAddress: ip, } global.GVA_DB.Create(&session) return &response.LoginResponse{ User: response.ToAppUserResponse(&user), Token: token, RefreshToken: refreshToken, ExpiresAt: expiresAt, }, nil } // RefreshToken 刷新 Token func (s *AuthService) RefreshToken(req *request.RefreshTokenRequest) (*response.LoginResponse, error) { // 解析刷新 Token claims, err := utils.ParseAppToken(req.RefreshToken) if err != nil { return nil, errors.New("刷新 Token 无效") } // 查询用户 var user app.AppUser err = global.GVA_DB.Where("id = ?", claims.UserID).First(&user).Error if err != nil { return nil, errors.New("用户不存在") } // 检查用户状态 if !user.Enable { return nil, errors.New("账户已被禁用") } // 生成新的 Token token, expiresAt, err := utils.CreateAppToken(user.ID, user.Username) if err != nil { return nil, errors.New("Token 生成失败") } // 生成新的刷新 Token refreshToken, _, err := utils.CreateAppRefreshToken(user.ID, user.Username) if err != nil { return nil, errors.New("刷新 Token 生成失败") } return &response.LoginResponse{ User: response.ToAppUserResponse(&user), Token: token, RefreshToken: refreshToken, ExpiresAt: expiresAt, }, nil } // Logout 用户登出 func (s *AuthService) Logout(userID uint, token string) error { // 删除会话记录 return global.GVA_DB.Where("user_id = ? AND session_token = ?", userID, token). Delete(&app.AppUserSession{}).Error } // GetUserInfo 获取用户信息 func (s *AuthService) GetUserInfo(userID uint) (*response.AppUserResponse, error) { var user app.AppUser err := global.GVA_DB.Where("id = ?", userID).First(&user).Error if err != nil { return nil, err } resp := response.ToAppUserResponse(&user) return &resp, nil } // UpdateProfile 更新用户信息 func (s *AuthService) UpdateProfile(userID uint, req *request.UpdateProfileRequest) error { updates := make(map[string]interface{}) if req.NickName != "" { updates["nick_name"] = req.NickName } if req.Email != "" { // 检查邮箱是否已被其他用户使用 var count int64 err := global.GVA_DB.Model(&app.AppUser{}). Where("email = ? AND id != ?", req.Email, userID). Count(&count).Error if err != nil { return err } if count > 0 { return errors.New("邮箱已被使用") } updates["email"] = req.Email } if req.Phone != "" { updates["phone"] = req.Phone } if req.Avatar != "" { updates["avatar"] = req.Avatar } if req.Preferences != "" { updates["preferences"] = req.Preferences } if req.AISettings != "" { updates["ai_settings"] = req.AISettings } if len(updates) == 0 { return nil } return global.GVA_DB.Model(&app.AppUser{}).Where("id = ?", userID).Updates(updates).Error } // ChangePassword 修改密码 func (s *AuthService) ChangePassword(userID uint, req *request.ChangePasswordRequest) error { // 查询用户 var user app.AppUser err := global.GVA_DB.Where("id = ?", userID).First(&user).Error if err != nil { return err } // 验证旧密码 err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword)) if err != nil { return errors.New("原密码错误") } // 加密新密码 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost) if err != nil { return errors.New("密码加密失败") } // 更新密码 return global.GVA_DB.Model(&user).Update("password", string(hashedPassword)).Error }