package auth import ( "net/http" "github.com/gin-gonic/gin" "hyapp-admin-server/internal/config" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/repository" "hyapp-admin-server/internal/response" authcore "hyapp-admin-server/internal/service" ) const refreshCookieName = "hyapp_admin_refresh" type Handler struct { service *AuthFlowService audit shared.OperationLogger cfg config.Config } func New(store *repository.Store, auth *authcore.AuthService, audit shared.OperationLogger, cfg config.Config) *Handler { return &Handler{service: NewService(store, auth, cfg), audit: audit, cfg: cfg} } func (h *Handler) Login(c *gin.Context) { var req loginRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "用户名和密码不能为空") return } result, err := h.service.Login(LoginInput{ Username: req.Username, Password: req.Password, IP: c.ClientIP(), UserAgent: c.Request.UserAgent(), }) if err != nil { response.Unauthorized(c, "用户名或密码错误") return } h.setRefreshCookie(c, result.RefreshToken, int(h.cfg.RefreshTokenTTL.Seconds())) response.OK(c, gin.H{ "accessToken": result.AccessToken, "expiresAtMs": result.ExpiresAtMS, "user": shared.UserDTO(result.User), "permissions": result.Permissions, }) } func (h *Handler) Logout(c *gin.Context) { if token, err := c.Cookie(refreshCookieName); err == nil && token != "" { _ = h.service.Logout(token) } h.setRefreshCookie(c, "", -1) response.OK(c, gin.H{"loggedOut": true}) } func (h *Handler) Refresh(c *gin.Context) { token, err := c.Cookie(refreshCookieName) if err != nil || token == "" { response.Unauthorized(c, "刷新会话不存在") return } result, err := h.service.Refresh(token) if err != nil { response.Unauthorized(c, "刷新会话已失效") return } response.OK(c, gin.H{ "accessToken": result.AccessToken, "expiresAtMs": result.ExpiresAtMS, "user": shared.UserDTO(result.User), "permissions": result.Permissions, }) } func (h *Handler) Me(c *gin.Context) { user, permissions, err := h.service.Me(shared.ActorFromContext(c)) if err != nil { response.Unauthorized(c, "用户不存在") return } response.OK(c, gin.H{ "user": shared.UserDTO(*user), "permissions": permissions, }) } func (h *Handler) ChangePassword(c *gin.Context) { var req changePasswordRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "旧密码和新密码不能为空") return } if err := h.service.ChangePassword(shared.ActorFromContext(c), req.OldPassword, req.NewPassword); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "change-password", "admin_users", "success", "用户修改自己的密码") response.OK(c, gin.H{"changed": true}) } func (h *Handler) setRefreshCookie(c *gin.Context, token string, maxAge int) { c.SetSameSite(http.SameSiteLaxMode) c.SetCookie(refreshCookieName, token, maxAge, "/api/v1/auth", "", h.cfg.RefreshCookieSecure, true) }