Files
silk/server-go/internal/handler/audit.go
T

107 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}
}