package interfaces import ( "mengstack/internal/kernel/response" "mengstack/internal/modules/auth/application" "mengstack/internal/modules/auth/domain" "github.com/gin-gonic/gin" ) type Handler struct { svc *application.Service } func NewHandler(svc *application.Service) *Handler { return &Handler{svc: svc} } // Register godoc // @Summary 用户注册 // @Description 使用邮箱、用户名和密码注册新用户,返回 JWT token // @Tags Auth // @Accept json // @Produce json // @Param request body domain.RegisterRequest true "注册信息" // @Success 200 {object} response.Response{data=domain.TokenPair} // @Failure 400 {object} response.Response // @Failure 409 {object} response.Response // @Router /auth/register [post] func (h *Handler) Register(c *gin.Context) { var req domain.RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { response.Fail(c, response.NewBadRequest("invalid request body")) return } tokens, err := h.svc.Register(c.Request.Context(), req) if err != nil { response.HandleError(c, err) return } response.Success(c, tokens) } // Login godoc // @Summary 用户登录 // @Description 使用邮箱和密码登录,返回 JWT token // @Tags Auth // @Accept json // @Produce json // @Param request body domain.LoginRequest true "登录信息" // @Success 200 {object} response.Response{data=domain.TokenPair} // @Failure 400 {object} response.Response // @Failure 401 {object} response.Response // @Router /auth/login [post] func (h *Handler) Login(c *gin.Context) { var req domain.LoginRequest if err := c.ShouldBindJSON(&req); err != nil { response.Fail(c, response.NewBadRequest("invalid request body")) return } tokens, err := h.svc.Login(c.Request.Context(), req) if err != nil { response.HandleError(c, err) return } response.Success(c, tokens) } // RefreshToken godoc // @Summary 刷新 Token // @Description 使用 refresh_token 获取新的 token 对 // @Tags Auth // @Accept json // @Produce json // @Param request body object true "{ \"refresh_token\": \"...\" }" // @Success 200 {object} response.Response{data=domain.TokenPair} // @Failure 400 {object} response.Response // @Failure 401 {object} response.Response // @Router /auth/refresh [post] func (h *Handler) RefreshToken(c *gin.Context) { var req struct { RefreshToken string `json:"refresh_token" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { response.Fail(c, response.NewBadRequest("invalid request body")) return } tokens, err := h.svc.RefreshToken(c.Request.Context(), req.RefreshToken) if err != nil { response.HandleError(c, err) return } response.Success(c, tokens) } // ChangePassword godoc // @Summary 修改密码 // @Description 使用旧密码验证后设置新密码 // @Tags Auth // @Accept json // @Produce json // @Param request body domain.ChangePasswordRequest true "密码修改请求" // @Success 200 {object} response.Response // @Failure 400 {object} response.Response // @Failure 401 {object} response.Response // @Security Bearer // @Security TenantID // @Router /password [post] func (h *Handler) ChangePassword(c *gin.Context) { userID := c.GetUint("user_id") var req domain.ChangePasswordRequest if err := c.ShouldBindJSON(&req); err != nil { response.Fail(c, response.NewBadRequest("invalid request body")) return } if err := h.svc.ChangePassword(c.Request.Context(), userID, req); err != nil { response.HandleError(c, err) return } response.Success(c, nil) } // GetProfile godoc // @Summary 获取当前用户信息 // @Description 返回当前认证用户的个人资料 // @Tags Auth // @Produce json // @Success 200 {object} response.Response{data=domain.UserDTO} // @Failure 401 {object} response.Response // @Failure 404 {object} response.Response // @Security Bearer // @Security TenantID // @Router /profile [get] func (h *Handler) GetProfile(c *gin.Context) { userID := c.GetUint("user_id") dto, err := h.svc.GetProfile(c.Request.Context(), userID) if err != nil { response.HandleError(c, err) return } response.Success(c, dto) } // Ping godoc // @Summary 健康探测 // @Description 返回 pong,用于验证认证和多租户中间件是否正常 // @Tags System // @Produce json // @Success 200 {object} response.Response // @Security Bearer // @Security TenantID // @Router /ping [get] func (h *Handler) Ping(c *gin.Context) { response.Success(c, gin.H{"message": "pong"}) }