Version:0.0.1.dev.260202
feat: build core architecture & implement user auth modules 🚀 feat: 搭建核心架构并实现用户认证模块 🚀 Framework Migration: Switched from Hertz to Gin, providing a more idiomatic and lightweight web foundation. ⚡ 框架迁移:从 Hertz 切换至 Gin,构建了更符合 Go 惯例且轻量级的 Web 基础。⚡ Architectural Overhaul: Refactored the 3-layer architecture from global-variable-based calls to Explicit Dependency Injection (DI) via New... factory functions. This significantly improves testability and decoupling. 🏗️ 架构重构:将三层架构从基于“全局变量”的调用重构为通过 New... 工厂函数实现的显式依赖注入 (DI)。这大幅提升了代码的可测试性与解耦程度。🏗️ User Auth: Completed and tested Register, Login, and Token Refresh APIs with robust error handling and Bcrypt password hashing. 🔐 用户认证:完成了注册、登录与 Token 刷新接口并通过测试,包含健壮的错误处理与 Bcrypt 密码哈希加密。🔐 Config Management: Integrated Viper for centralized, environment-aware configuration management. ⚙️ 配置管理:集成了 Viper,实现了中心化且具备环境感知能力的配置管理。⚙️ DevOps & Docs: Added docker-compose.yml for seamless MySQL 8.0 & environment setup. 🐳 Updated README.md with corrections for mistakes in image quoting and formats. 📝 运维与文档: 新增 docker-compose.yml,实现 MySQL 8.0 环境的一键启动。🐳 更新 README.md,修改了一些图片引用和格式上小错误。📝
This commit is contained in:
109
backend/service/user.go
Normal file
109
backend/service/user.go
Normal file
@@ -0,0 +1,109 @@
|
||||
// Package service 业务逻辑层
|
||||
// 包含所有核心业务逻辑
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/smartflow/backend/auth"
|
||||
"github.com/smartflow/backend/dao"
|
||||
"github.com/smartflow/backend/model"
|
||||
"github.com/smartflow/backend/respond"
|
||||
"github.com/smartflow/backend/utils"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UserService struct {
|
||||
// 伸出手:准备接住 DAO
|
||||
repo *dao.UserDAO
|
||||
}
|
||||
|
||||
// NewUserService:组装 Service 的“工厂”
|
||||
func NewUserService(repo *dao.UserDAO) *UserService {
|
||||
return &UserService{
|
||||
repo: repo, // 把传进来的 DAO 揣进口袋里
|
||||
}
|
||||
}
|
||||
|
||||
func (sv *UserService) UserRegister(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.repo.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.repo.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(req *model.UserLoginRequest) (*model.Tokens, error) {
|
||||
var tokens model.Tokens
|
||||
hashedPwd, err := sv.repo.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.repo.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(refreshToken string) (*model.Tokens, error) {
|
||||
// 验证刷新令牌
|
||||
token, err := auth.ValidateRefreshToken(refreshToken)
|
||||
if err != nil || !token.Valid { // 刷新令牌无效
|
||||
return nil, respond.InvalidRefreshToken
|
||||
}
|
||||
|
||||
// 生成新的访问令牌和刷新令牌
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok {
|
||||
userID := int(claims["user_id"].(float64))
|
||||
newAccessToken, newRefreshToken, err := auth.GenerateTokens(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回新的访问令牌和刷新令牌
|
||||
return &model.Tokens{AccessToken: newAccessToken, RefreshToken: newRefreshToken}, nil
|
||||
} else {
|
||||
return nil, respond.InvalidClaims
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user