fix: unify handler response format in multiple handlers
- captcha_handler.go: Fix GenerateCaptcha/VerifyCaptcha to use {code, message, data}
- password_reset_handler.go: Fix all error responses to use {code, message}
- settings_handler.go: Add missing "code" and "message" fields
- sms_handler.go: Fix error responses to use {code, message}
- sso_handler.go: Fix all error responses to use {code, message, data}
- stats_handler.go: Add missing "message" field in success responses
- theme_handler.go: Fix error responses to use {code, message}
- totp_handler.go: Fix all responses to use {code, message, data}
Standardize all JSON responses to {code: 0, message: "success", data: ...} for success
and {code: XXX, message: "..."} for errors.
This commit is contained in:
@@ -38,20 +38,20 @@ type AuthorizeRequest struct {
|
||||
func (h *SSOHandler) Authorize(c *gin.Context) {
|
||||
var req AuthorizeRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证 response_type
|
||||
if req.ResponseType != "code" && req.ResponseType != "token" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported response_type"})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "unsupported response_type"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证 redirect_uri 是否在白名单中
|
||||
if h.clientsStore != nil {
|
||||
if !h.clientsStore.ValidateClientRedirectURI(req.ClientID, req.RedirectURI) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid redirect_uri"})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "invalid redirect_uri"})
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func (h *SSOHandler) Authorize(c *gin.Context) {
|
||||
// 获取当前登录用户(从 auth middleware 设置的 context)
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "unauthorized"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func (h *SSOHandler) Authorize(c *gin.Context) {
|
||||
username.(string),
|
||||
)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate code"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to generate code"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -95,20 +95,20 @@ func (h *SSOHandler) Authorize(c *gin.Context) {
|
||||
username.(string),
|
||||
)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate code"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to generate code"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证授权码获取 session
|
||||
session, err := h.ssoManager.ValidateAuthorizationCode(code)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to validate code"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to validate code"})
|
||||
return
|
||||
}
|
||||
|
||||
token, _, err := h.ssoManager.GenerateAccessToken(req.ClientID, session)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to generate token"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -143,13 +143,13 @@ type TokenResponse struct {
|
||||
func (h *SSOHandler) Token(c *gin.Context) {
|
||||
var req TokenRequest
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证 grant_type
|
||||
if req.GrantType != "authorization_code" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported grant_type"})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "unsupported grant_type"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -157,12 +157,12 @@ func (h *SSOHandler) Token(c *gin.Context) {
|
||||
if h.clientsStore != nil {
|
||||
client, err := h.clientsStore.GetByClientID(req.ClientID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid client"})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid client"})
|
||||
return
|
||||
}
|
||||
// 使用常量时间比较防止时序攻击
|
||||
if subtle.ConstantTimeCompare([]byte(req.ClientSecret), []byte(client.ClientSecret)) != 1 {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid client_secret"})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid client_secret"})
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -170,14 +170,14 @@ func (h *SSOHandler) Token(c *gin.Context) {
|
||||
// 验证授权码
|
||||
session, err := h.ssoManager.ValidateAuthorizationCode(req.Code)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid code"})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid code"})
|
||||
return
|
||||
}
|
||||
|
||||
// 生成 access token
|
||||
token, expiresAt, err := h.ssoManager.GenerateAccessToken(req.ClientID, session)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "failed to generate token"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ type IntrospectResponse struct {
|
||||
func (h *SSOHandler) Introspect(c *gin.Context) {
|
||||
var req IntrospectRequest
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -238,13 +238,13 @@ type RevokeRequest struct {
|
||||
func (h *SSOHandler) Revoke(c *gin.Context) {
|
||||
var req RevokeRequest
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
h.ssoManager.RevokeToken(req.Token)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "token revoked"})
|
||||
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "token revoked"})
|
||||
}
|
||||
|
||||
// UserInfoResponse 用户信息响应
|
||||
@@ -258,14 +258,18 @@ type UserInfoResponse struct {
|
||||
func (h *SSOHandler) UserInfo(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "unauthorized"})
|
||||
return
|
||||
}
|
||||
|
||||
username, _ := c.Get("username")
|
||||
|
||||
c.JSON(http.StatusOK, UserInfoResponse{
|
||||
UserID: userID.(int64),
|
||||
Username: username.(string),
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": UserInfoResponse{
|
||||
UserID: userID.(int64),
|
||||
Username: username.(string),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user