feat(gateway): 敏感操作审计日志(T4.B)
- store.AuditLog 表(sundynix_audit_log) + AppendAudit/ListAudit - middleware.Audit(db):只审计变更类(POST/PUT/DELETE/PATCH),收尾 best-effort 落库(独立超时 ctx,失败静默不拖垮主流程);挂管理组 + prompt 激活/撤销 + HITL 审批 - GET /api/v1/admin/audit:倒序审计流(limit/offset 翻页) - live:PUT pricing / POST prompts/deactivate 留痕(actor/path/status/ip),GET 不记 - DEPTH_ROADMAP T4.B:overview✅ + audit✅ 打勾 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/sundynix/sundynix-gateway/internal/store"
|
||||
)
|
||||
|
||||
// Audit 记录敏感操作留痕:仅对变更类请求(POST/PUT/DELETE)在收尾时 best-effort 落库。
|
||||
// 挂在受保护/管理组上即可自动覆盖模型/密钥/prompt/审批等变更,无需在每个 handler 里手写。
|
||||
// 写库用独立超时 context(不受请求取消影响),失败静默——审计不能拖垮主流程。
|
||||
func Audit(db *store.Postgres) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Next() // 先跑 handler,拿到最终状态码
|
||||
|
||||
switch c.Request.Method {
|
||||
case "POST", "PUT", "DELETE", "PATCH":
|
||||
default:
|
||||
return // 只审计变更类操作
|
||||
}
|
||||
|
||||
actor, _ := c.Get(CtxUserID)
|
||||
uid, _ := actor.(string)
|
||||
|
||||
entry := &store.AuditLog{
|
||||
Actor: uid,
|
||||
Action: c.Request.Method,
|
||||
Route: c.FullPath(),
|
||||
Path: c.Request.URL.Path,
|
||||
Status: c.Writer.Status(),
|
||||
IP: c.ClientIP(),
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
_ = db.AppendAudit(ctx, entry)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user