chore: 初始化仓库基线(AGENTS.md、git 规范、敏感文件排除)
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"silk-server-go/internal/middleware"
|
||||
"silk-server-go/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// RegisterAuditRoutes 注册审计日志路由
|
||||
func RegisterAuditRoutes(rg *gin.RouterGroup, db *gorm.DB) {
|
||||
perm := middleware.RequirePermission(db, "audit:read")
|
||||
rg.GET("/audit-logs", perm, listAuditLogs(db))
|
||||
rg.POST("/audit-logs", perm, createAuditLog(db))
|
||||
}
|
||||
|
||||
// listAuditLogs 审计日志列表(query: limit,默认100,上限500)
|
||||
func listAuditLogs(db *gorm.DB) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
limit := 100
|
||||
if l := c.Query("limit"); l != "" {
|
||||
if n, err := strconv.Atoi(l); err == nil && n > 0 {
|
||||
limit = n
|
||||
}
|
||||
}
|
||||
if limit > 500 {
|
||||
limit = 500
|
||||
}
|
||||
|
||||
var logs []model.AuditLog
|
||||
db.Order("created_at DESC").Limit(limit).Find(&logs)
|
||||
c.JSON(http.StatusOK, logs)
|
||||
}
|
||||
}
|
||||
|
||||
// createAuditLog 手动写入审计日志,自动补充 userId/username/IP/UA
|
||||
func createAuditLog(db *gorm.DB) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var body struct {
|
||||
Action string `json:"action"`
|
||||
Resource *string `json:"resource"`
|
||||
TargetID *string `json:"targetId"`
|
||||
Description *string `json:"description"`
|
||||
Metadata json.RawMessage `json:"metadata"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if body.Action == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "action 不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
// 从 context 获取当前用户信息
|
||||
var userID, username *string
|
||||
if user, ok := c.Get("user"); ok {
|
||||
if userMap, ok := user.(map[string]interface{}); ok {
|
||||
if sub, ok := userMap["sub"].(string); ok {
|
||||
s := sub
|
||||
userID = &s
|
||||
}
|
||||
if uname, ok := userMap["username"].(string); ok {
|
||||
s := uname
|
||||
username = &s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip := c.ClientIP()
|
||||
ua := c.GetHeader("User-Agent")
|
||||
|
||||
log := model.AuditLog{
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
Action: body.Action,
|
||||
Resource: body.Resource,
|
||||
TargetID: body.TargetID,
|
||||
Description: body.Description,
|
||||
IPAddress: &ip,
|
||||
UserAgent: &ua,
|
||||
Metadata: body.Metadata,
|
||||
}
|
||||
if err := db.Create(&log).Error; err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "写入审计日志失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, log)
|
||||
}
|
||||
}
|
||||
|
||||
// recordAudit 记录审计日志(供其他 handler 调用)
|
||||
func recordAudit(db *gorm.DB, log *model.AuditLog) {
|
||||
if log == nil || log.Action == "" {
|
||||
return
|
||||
}
|
||||
if err := db.Create(log).Error; err != nil {
|
||||
slog.Warn("记录审计日志失败", "error", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user