You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.2 KiB
91 lines
2.2 KiB
package middleware |
|
|
|
import ( |
|
"bytes" |
|
"gofaster/internal/shared/model" |
|
"io" |
|
"strconv" |
|
"strings" |
|
"time" |
|
|
|
"github.com/gin-gonic/gin" |
|
"go.uber.org/zap" |
|
"gorm.io/gorm" |
|
) |
|
|
|
// 从 Gin 上下文中获取用户ID(假设 JWT 中间件已将用户信息存入上下文) |
|
func getUserIdFromContext(c *gin.Context) uint { |
|
if userId, exists := c.Get("userID"); exists { |
|
if uid, ok := userId.(uint); ok { |
|
return uid |
|
} |
|
} |
|
return 0 // 0 表示未登录用户或获取失败 |
|
} |
|
|
|
// 从请求路径解析操作类型(根据 RESTful 路径映射) |
|
func getActionFromPath(path string) string { |
|
// 移除查询参数和版本前缀(如 /api/v1/users -> /users) |
|
cleanPath := strings.Split(path, "?")[0] |
|
segments := strings.Split(cleanPath, "/") |
|
lastSegment := segments[len(segments)-1] |
|
|
|
// 常见 RESTful 操作映射 |
|
switch lastSegment { |
|
case "login": |
|
return "用户登录" |
|
case "logout": |
|
return "用户登出" |
|
case "users": |
|
return "用户管理" |
|
case "roles": |
|
return "角色管理" |
|
case "permissions": |
|
return "权限管理" |
|
default: |
|
// 如果是数字ID(如 /users/123),取上一级路径 |
|
if _, err := strconv.Atoi(lastSegment); err == nil && len(segments) > 1 { |
|
return getActionFromPath(strings.Join(segments[:len(segments)-1], "/")) |
|
} |
|
return "未知操作" |
|
} |
|
} |
|
|
|
func LoggerMiddleware(logger *zap.Logger, db *gorm.DB) gin.HandlerFunc { |
|
return func(c *gin.Context) { |
|
start := time.Now() |
|
path := c.Request.URL.Path |
|
|
|
// 记录请求体 |
|
var requestBody string |
|
if c.Request.Body != nil { |
|
bodyBytes, _ := io.ReadAll(c.Request.Body) |
|
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) |
|
requestBody = string(bodyBytes) |
|
} |
|
|
|
// 处理请求 |
|
c.Next() |
|
|
|
// 记录日志 |
|
latency := time.Since(start).Milliseconds() |
|
actionLog := model.ActionLog{ |
|
UserID: getUserIdFromContext(c), |
|
Action: getActionFromPath(path), |
|
IP: c.ClientIP(), |
|
UserAgent: c.Request.UserAgent(), |
|
Path: path, |
|
Method: c.Request.Method, |
|
Request: requestBody, |
|
Status: c.Writer.Status(), |
|
Latency: latency, |
|
} |
|
|
|
// 异步保存日志 |
|
go func() { |
|
if err := db.Create(&actionLog).Error; err != nil { |
|
logger.Error("保存操作日志失败", zap.Error(err)) |
|
} |
|
}() |
|
} |
|
}
|
|
|