feat(backend): unified response helpers, refresh token, security hardening
- new resp package (OK/Page/Fail/BadRequest/.../InternalErr): unified error
envelope {detail, code?}, sanitized 500s (full error logged server-side,
generic message to client - stops DB error leakage), pagination envelope
{items,total,page,page_size}; migrate 200+ inline c.JSON error sites
- refresh token: 7d rotation tokens (SHA-256 hashed at rest), public
POST /auth/refresh with single-use rotation, POST /auth/logout revokes
all user refresh tokens (endpoint previously missing - frontend 404)
- security: gh-ost command line password masked in task status payload;
Instance.MarshalJSON guarantees encrypted passwords never leave the API
(removes reliance on per-handler manual masking); production (DEBUG=false)
with default JWT secret now auto-generates and persists a random secret
- safe.Go recover wrapper for background goroutines (instance probe,
gh-ost async)
- delete dead service layer (zero callers)
- fix pre-existing go vet unkeyed bson.E literals
This commit is contained in:
1 parent
d5b8b8116c
commit
16f1f7d65f
26 files changed
+916
-963
No files matched your search
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"sql-platform/internal/handler/resp"
|
||||
"sql-platform/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -63,11 +64,11 @@ func CreateNotification(c *gin.Context) {
|
||||
IsEnabled bool `json:"is_enabled"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": "参数错误"})
|
||||
resp.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if input.Name == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": "名称不能为空"})
|
||||
resp.BadRequest(c, "名称不能为空")
|
||||
return
|
||||
}
|
||||
cfgBytes, _ := json.Marshal(input.Config)
|
||||
@@ -79,7 +80,7 @@ func CreateNotification(c *gin.Context) {
|
||||
IsEnabled: &enabled,
|
||||
}
|
||||
if err := model.DB.Create(&ch).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"detail": "创建失败"})
|
||||
resp.InternalMsg(c, "创建失败")
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, toChannelResponse(ch))
|
||||
@@ -90,12 +91,12 @@ func UpdateNotification(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var ch model.NotificationChannel
|
||||
if err := model.DB.First(&ch, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"detail": "通知渠道不存在"})
|
||||
resp.NotFound(c, "通知渠道不存在")
|
||||
return
|
||||
}
|
||||
var input map[string]interface{}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": "参数错误"})
|
||||
resp.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if name, ok := input["name"].(string); ok {
|
||||
@@ -127,7 +128,7 @@ func TestNotificationSend(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var ch model.NotificationChannel
|
||||
if err := model.DB.First(&ch, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"detail": "通知渠道不存在"})
|
||||
resp.NotFound(c, "通知渠道不存在")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -135,7 +136,7 @@ func TestNotificationSend(c *gin.Context) {
|
||||
_ = json.Unmarshal([]byte(ch.Config), &cfg)
|
||||
webhookURL, _ := cfg["webhook_url"].(string)
|
||||
if webhookURL == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": "Webhook URL 未配置"})
|
||||
resp.BadRequest(c, "Webhook URL 未配置")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -150,12 +151,12 @@ func TestNotificationSend(c *gin.Context) {
|
||||
secret, _ := cfg["secret"].(string)
|
||||
sendErr = sendDingtalkWebhook(webhookURL, secret, title, body)
|
||||
default:
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": "不支持的通知类型: " + ch.ChannelType})
|
||||
resp.BadRequest(c, "不支持的通知类型: "+ch.ChannelType)
|
||||
return
|
||||
}
|
||||
|
||||
if sendErr != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"detail": "发送失败: " + sendErr.Error()})
|
||||
resp.InternalErr(c, sendErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "测试消息已发送"})
|
||||
|
||||
Reference in new issue
Block a user