255 lines
6.4 KiB
Go
255 lines
6.4 KiB
Go
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
|
|
}
|