package handler import ( "net/http" "fashionapi/internal/dto" "fashionapi/internal/middleware" "fashionapi/internal/pkg/response" "fashionapi/internal/service" "github.com/gin-gonic/gin" ) // AuthHandler 账号体系接口(JWT 无状态)。 type AuthHandler struct { auth service.AuthService } // NewAuthHandler 创建账号 handler。 func NewAuthHandler(auth service.AuthService) *AuthHandler { return &AuthHandler{auth: auth} } // Me 当前登录用户,需 Authorization: Bearer 。 // // GET /api/auth/me // 成功:200 { user } func (h *AuthHandler) Me(c *gin.Context) { userID, ok := middleware.UserIDFrom(c) if !ok { response.Error(c, http.StatusUnauthorized, "unauthorized") return } user, err := h.auth.Me(c.Request.Context(), userID) if err != nil { fail(c, err) return } c.JSON(http.StatusOK, gin.H{"user": user}) } // Login 账号登录,校验账号密码后签发 access + refresh 双令牌。 // // POST /api/auth/login // body: { account, password } // 成功:200 { access_token, refresh_token, expires_in, user } func (h *AuthHandler) Login(c *gin.Context) { var req dto.LoginRequest if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, http.StatusBadRequest, "invalid request") return } access, refresh, expiresIn, user, err := h.auth.Login(c.Request.Context(), req.Account, req.Password) if err != nil { fail(c, err) return } c.JSON(http.StatusOK, dto.LoginResponse{ AccessToken: access, RefreshToken: refresh, ExpiresIn: expiresIn, User: *user, }) } // Refresh 用 refresh token 换取新的 access token。 // // POST /api/auth/refresh // body: { refresh_token } // 成功:200 { access_token, expires_in } func (h *AuthHandler) Refresh(c *gin.Context) { var req dto.RefreshRequest if err := c.ShouldBindJSON(&req); err != nil || req.RefreshToken == "" { response.Error(c, http.StatusBadRequest, "invalid request") return } access, expiresIn, err := h.auth.Refresh(c.Request.Context(), req.RefreshToken) if err != nil { fail(c, err) return } c.JSON(http.StatusOK, dto.RefreshResponse{AccessToken: access, ExpiresIn: expiresIn}) } // Logout 吊销当前 refresh token(单设备登出)。 // // POST /api/auth/logout // body: { refresh_token } // 成功:200 { ok: true } func (h *AuthHandler) Logout(c *gin.Context) { var req dto.RefreshRequest _ = c.ShouldBindJSON(&req) if req.RefreshToken == "" { response.Error(c, http.StatusBadRequest, "invalid request") return } if err := h.auth.Logout(c.Request.Context(), req.RefreshToken); err != nil { fail(c, err) return } response.Data(c, http.StatusOK, gin.H{"ok": true}) } // LogoutAll 吊销当前用户全部 refresh token(踢下线 / 全设备登出)。 // // POST /api/auth/logout-all // body: { refresh_token } // 成功:200 { revoked: <受影响行数> } func (h *AuthHandler) LogoutAll(c *gin.Context) { var req dto.RefreshRequest if err := c.ShouldBindJSON(&req); err != nil || req.RefreshToken == "" { response.Error(c, http.StatusBadRequest, "invalid request") return } n, err := h.auth.RevokeAllByRefresh(c.Request.Context(), req.RefreshToken) if err != nil { fail(c, err) return } response.Data(c, http.StatusOK, gin.H{"revoked": n}) }