// Package service 业务逻辑层 // 包含所有核心业务逻辑 package service import ( "errors" "time" "context" "github.com/LoveLosita/smartflow/backend/auth" "github.com/LoveLosita/smartflow/backend/dao" "github.com/LoveLosita/smartflow/backend/model" "github.com/LoveLosita/smartflow/backend/respond" "github.com/LoveLosita/smartflow/backend/utils" "gorm.io/gorm" ) type UserService struct { userRepo *dao.UserDAO cacheRepo *dao.CacheDAO } func NewUserService(userRepo *dao.UserDAO, cacheRepo *dao.CacheDAO) *UserService { return &UserService{ userRepo: userRepo, // 把传进来的 DAO 揣进口袋里 cacheRepo: cacheRepo, } } func (sv *UserService) UserRegister(ctx context.Context, user model.UserRegisterRequest) (*model.UserRegisterResponse, error) { //检查是否有空字段 if user.Username == "" || user.Password == "" || user.PhoneNumber == "" { return nil, respond.MissingParam } // 检查字段长度是否超过90% if len(user.Username) > 45 || len(user.Password) > 229 || len(user.PhoneNumber) > 18 { return nil, respond.ParamTooLong } //检查用户名是否已存在 result, err := sv.userRepo.IfUsernameExists(user.Username) if err != nil { return nil, err } if result { return nil, respond.InvalidName } hashedPwd, err := utils.HashPassword(user.Password) //调用utils层的方法 if err != nil { return nil, err } user.Password = hashedPwd //将user的密码字段改为加密后的密码 newUser, err := sv.userRepo.Create(user.Username, user.PhoneNumber, user.Password) if err != nil { return nil, err } //返回注册成功的用户ID return &model.UserRegisterResponse{ID: newUser.ID}, nil } func (sv *UserService) UserLogin(ctx context.Context, req *model.UserLoginRequest) (*model.Tokens, error) { var tokens model.Tokens hashedPwd, err := sv.userRepo.GetUserHashedPasswordByName(req.Username) //调用dao层的方法 if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, respond.WrongName } return nil, err } result, err := utils.CompareHashPwdAndPwd(hashedPwd, req.Password) //比较密码是否匹配 if err != nil { //其他错误 return &tokens, err } else if !result { //密码不匹配 return nil, respond.WrongPwd } id, err := sv.userRepo.GetUserIDByName(req.Username) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, respond.WrongName } return nil, err } tokens.AccessToken, tokens.RefreshToken, err = auth.GenerateTokens(id) //生成jwt key if err != nil { //其他错误 return nil, err } return &tokens, nil } func (sv *UserService) RefreshTokenHandler(ctx context.Context, refreshToken string) (*model.Tokens, error) { // 1. 验证刷新令牌 (这里已经包含了 Redis 黑名单检查) token, err := auth.ValidateRefreshToken(refreshToken, sv.cacheRepo) if err != nil { return nil, err } // 2. 改动点:直接断言为你定义的结构体 model.MyCustomClaims if claims, ok := token.Claims.(*model.MyCustomClaims); ok { // 3. 这里的 userID 已经是 int 了,不再需要 (float64) 转换 newAccessToken, newRefreshToken, err := auth.GenerateTokens(claims.UserID) if err != nil { return nil, err } // 返回新的双 Token return &model.Tokens{ AccessToken: newAccessToken, RefreshToken: newRefreshToken, }, nil } return nil, respond.InvalidClaims } func (sv *UserService) UserLogout(ctx context.Context, jti string, expireTime time.Time) error { //1.直接把 jti 扔进黑名单 expiration := time.Until(expireTime) err := sv.cacheRepo.SetBlacklist(jti, expiration) if err != nil { return err } return nil }