67 lines
1.8 KiB
Go
67 lines
1.8 KiB
Go
package audit
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type ActorResolver func(*gin.Context) (id string, name string)
|
|
|
|
func Middleware(sourceService string, resolveActor ActorResolver) gin.HandlerFunc {
|
|
sourceService = strings.TrimSpace(sourceService)
|
|
return func(ctx *gin.Context) {
|
|
if ctx.Request.Method == "GET" || ctx.Request.Method == "HEAD" || ctx.Request.Method == "OPTIONS" {
|
|
ctx.Next()
|
|
return
|
|
}
|
|
|
|
var body []byte
|
|
if ctx.Request.Body != nil {
|
|
body, _ = io.ReadAll(ctx.Request.Body)
|
|
ctx.Request.Body = io.NopCloser(bytes.NewBuffer(body))
|
|
}
|
|
ctx.Next()
|
|
|
|
actorID, actorName := "", ""
|
|
if resolveActor != nil {
|
|
actorID, actorName = resolveActor(ctx)
|
|
}
|
|
if actorID == "" {
|
|
actorID = firstNonEmpty(ctx.GetHeader("X-User-Id"), ctx.GetHeader("X-Actor-Id"), "unknown")
|
|
}
|
|
if actorName == "" {
|
|
actorName = firstNonEmpty(ctx.GetHeader("X-User-Name"), ctx.GetHeader("X-Actor-Name"))
|
|
}
|
|
result := "success"
|
|
if len(ctx.Errors) > 0 || ctx.Writer.Status() >= 400 {
|
|
result = "failed"
|
|
}
|
|
_, _ = SaveRecord(Record{
|
|
TraceID: firstNonEmpty(ctx.GetHeader("X-Trace-Id"), ctx.GetHeader("Request-Id")),
|
|
SourceService: sourceService,
|
|
ActorID: actorID,
|
|
ActorName: actorName,
|
|
Action: ctx.Request.Method + " " + ctx.FullPath(),
|
|
ObjectType: routeObjectType(ctx.FullPath()),
|
|
ObjectID: firstNonEmpty(ctx.Param("id"), ctx.Query("id"), ctx.FullPath()),
|
|
RequestMethod: ctx.Request.Method,
|
|
RequestPath: ctx.FullPath(),
|
|
ClientIP: ctx.ClientIP(),
|
|
AfterJSON: string(body),
|
|
Result: result,
|
|
})
|
|
}
|
|
}
|
|
|
|
func routeObjectType(path string) string {
|
|
path = strings.Trim(path, "/")
|
|
if path == "" {
|
|
return "unknown"
|
|
}
|
|
parts := strings.Split(path, "/")
|
|
return parts[len(parts)-1]
|
|
}
|