package auth import ( "backend/config" "backend/internal/dto" authservice "backend/internal/service/auth" "backend/utils" "net/http" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // AuthController 认证控制器 // Logan.Li type AuthController struct { authService *authservice.AuthService db *gorm.DB } // NewAuthController 创建控制器实例 // Logan.Li func NewAuthController(db *gorm.DB, cfg *config.Config) *AuthController { return &AuthController{ authService: authservice.NewAuthService(db, cfg), db: db, } } // buildLoginResponse 把 service 结果组装成响应体(登录与刷新同构) // Logan.Li func buildLoginResponse(result *authservice.LoginResult) dto.LoginResponse { return dto.LoginResponse{ Token: result.AccessToken, ExpiresIn: utils.AccessTokenTTLSeconds(), RefreshToken: result.RefreshToken, RefreshExpiresAt: result.RefreshExpiresAt.Format("2006-01-02T15:04:05Z07:00"), UserInfo: dto.UserInfoResponse{ ID: result.User.ID, Username: result.User.Username, Email: result.User.Email, Avatar: result.User.Avatar, Role: result.User.Role, }, } } // Login 管理员登录(成功/失败均记审计) // Logan.Li func (ctrl *AuthController) Login(c *gin.Context) { var req struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "请求参数错误: " + err.Error()}) return } result, err := ctrl.authService.Login(dto.LoginRequest{Username: req.Username, Password: req.Password}, c.ClientIP(), c.Request.UserAgent()) if err != nil { utils.LogAuthAction(ctrl.db, c, "login", req.Username, err.Error(), "failure") c.JSON(http.StatusOK, gin.H{"code": 1, "message": utils.InternalMsg(err)}) return } utils.LogAuthAction(ctrl.db, c, "login", req.Username, "登录成功", "success") c.JSON(http.StatusOK, gin.H{"code": 0, "message": "登录成功", "data": buildLoginResponse(result)}) } // Refresh 用刷新令牌换取新的访问令牌(一次性轮换,重放会撤销全部会话) // Logan.Li func (ctrl *AuthController) Refresh(c *gin.Context) { var req dto.RefreshRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "请求参数错误: " + err.Error()}) return } result, err := ctrl.authService.Refresh(req.RefreshToken, c.ClientIP(), c.Request.UserAgent()) if err != nil { utils.LogAuthAction(ctrl.db, c, "refresh", "-", err.Error(), "failure") c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": utils.InternalMsg(err)}) return } c.JSON(http.StatusOK, gin.H{"code": 0, "message": "刷新成功", "data": buildLoginResponse(result)}) } // Logout 登出:撤销刷新令牌(幂等,未带令牌也返回成功) // Logan.Li func (ctrl *AuthController) Logout(c *gin.Context) { var req dto.LogoutRequest _ = c.ShouldBindJSON(&req) // 允许空 body:前端丢了本地令牌也要能登出 // Logan.Li ctrl.authService.Revoke(req.RefreshToken) utils.LogAuthAction(ctrl.db, c, "logout", "-", "退出登录", "success") c.JSON(http.StatusOK, gin.H{"code": 0, "message": "已退出登录"}) } // Me 获取当前登录用户信息 // Logan.Li func (ctrl *AuthController) Me(c *gin.Context) { userID, _ := c.Get("user_id") userInfo, err := ctrl.authService.GetCurrentUser(userID.(uint)) if err != nil { c.JSON(http.StatusOK, gin.H{"code": 1, "message": utils.InternalMsg(err)}) return } c.JSON(http.StatusOK, gin.H{"code": 0, "data": userInfo}) } // ChangePassword 修改当前用户密码 // Logan.Li func (ctrl *AuthController) ChangePassword(c *gin.Context) { userID, _ := c.Get("user_id") var req struct { OldPassword string `json:"old_password" binding:"required"` NewPassword string `json:"new_password" binding:"required,min=6"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "请求参数错误: " + err.Error()}) return } if err := ctrl.authService.ChangePassword(userID.(uint), dto.ChangePasswordRequest{ OldPassword: req.OldPassword, NewPassword: req.NewPassword, }); err != nil { c.JSON(http.StatusOK, gin.H{"code": 1, "message": utils.InternalMsg(err)}) return } c.JSON(http.StatusOK, gin.H{"code": 0, "message": "密码修改成功"}) }