Files
pig-farm-controller/internal/app/controller/user/user_controller.go
2025-09-12 17:43:42 +08:00

148 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package user
import (
"net/http"
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// Controller 用户控制器
type Controller struct {
userRepo repository.UserRepository
logger *logs.Logger
tokenService token.TokenService // 注入 token 服务
}
// NewController 创建用户控制器实例
func NewController(userRepo repository.UserRepository, logger *logs.Logger, tokenService token.TokenService) *Controller {
return &Controller{
userRepo: userRepo,
logger: logger,
tokenService: tokenService,
}
}
// CreateUserRequest 定义创建用户请求的结构体
type CreateUserRequest struct {
Username string `json:"username" binding:"required" example:"newuser"`
Password string `json:"password" binding:"required,min=6" example:"password123"`
}
// LoginRequest 定义登录请求的结构体
type LoginRequest struct {
Username string `json:"username" binding:"required" example:"testuser"`
Password string `json:"password" binding:"required" example:"password123"`
}
// CreateUserResponse 定义创建用户成功响应的结构体
type CreateUserResponse struct {
Username string `json:"username" example:"newuser"`
ID uint `json:"id" example:"1"`
}
// LoginResponse 定义登录成功响应的结构体
type LoginResponse struct {
Username string `json:"username" example:"testuser"`
ID uint `json:"id" example:"1"`
Token string `json:"token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."`
}
// CreateUser godoc
// @Summary 创建新用户
// @Description 根据用户名和密码创建一个新的系统用户。
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param user body CreateUserRequest true "用户信息"
// @Success 200 {object} controller.Response{data=user.CreateUserResponse} "业务码为201代表创建成功"
// @Failure 200 {object} controller.Response "业务失败具体错误码和信息见响应体例如400, 409, 500"
// @Router /users [post]
func (c *Controller) CreateUser(ctx *gin.Context) {
var req CreateUserRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
c.logger.Errorf("创建用户: 参数绑定失败: %v", err)
controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
user := &models.User{
Username: req.Username,
Password: req.Password, // 密码会在 BeforeSave 钩子中哈希
}
if err := c.userRepo.Create(user); err != nil {
c.logger.Errorf("创建用户: 创建用户失败: %v", err)
// 尝试查询用户,以判断是否是用户名重复导致的错误
_, findErr := c.userRepo.FindByUsername(req.Username)
if findErr == nil { // 如果能找到用户,说明是用户名重复
controller.SendErrorResponse(ctx, http.StatusConflict, "用户名已存在")
return
}
// 其他创建失败的情况
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "创建用户失败")
return
}
controller.SendResponse(ctx, http.StatusCreated, "用户创建成功", CreateUserResponse{
Username: user.Username,
ID: user.ID,
})
}
// Login godoc
// @Summary 用户登录
// @Description 用户使用用户名和密码登录,成功后返回 JWT 令牌。
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param credentials body LoginRequest true "登录凭证"
// @Success 200 {object} controller.Response{data=user.LoginResponse} "业务码为200代表登录成功"
// @Failure 200 {object} controller.Response "业务失败具体错误码和信息见响应体例如400, 401, 500"
// @Router /users/login [post]
func (c *Controller) Login(ctx *gin.Context) {
var req LoginRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
c.logger.Errorf("登录: 参数绑定失败: %v", err)
controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
return
}
user, err := c.userRepo.FindByUsername(req.Username)
if err != nil {
if err == gorm.ErrRecordNotFound {
controller.SendErrorResponse(ctx, http.StatusUnauthorized, "用户名或密码不正确")
return
}
c.logger.Errorf("登录: 查询用户失败: %v", err)
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败")
return
}
if !user.CheckPassword(req.Password) {
controller.SendErrorResponse(ctx, http.StatusUnauthorized, "用户名或密码不正确")
return
}
// 登录成功,生成 JWT token
tokenString, err := c.tokenService.GenerateToken(user.ID)
if err != nil {
c.logger.Errorf("登录: 生成令牌失败: %v", err)
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败,无法生成认证信息")
return
}
controller.SendResponse(ctx, http.StatusOK, "登录成功", LoginResponse{
Username: user.Username,
ID: user.ID,
Token: tokenString,
})
}