package middleware import ( "bytes" "io" "strings" "time" "kra/internal/service" "kra/internal/service/dto" "github.com/gin-gonic/gin" ) func OperationAudit(service *service.AuditService) gin.HandlerFunc { return func(c *gin.Context) { if isBootstrapPath(c.Request.URL.Path) || c.Request.Method == "GET" || c.Request.Method == "HEAD" || c.Request.Method == "OPTIONS" { c.Next() return } path := c.Request.URL.Path if strings.Contains(path, "sysOperationRecord") || strings.Contains(path, "sysLoginLog") || strings.Contains(path, "dataAccessLog") { c.Next() return } var requestBody []byte if c.Request.Body != nil { requestBody, _ = io.ReadAll(io.LimitReader(c.Request.Body, 32769)) c.Request.Body = io.NopCloser(bytes.NewReader(requestBody)) } writer := &captureWriter{ResponseWriter: c.Writer} c.Writer = writer started := time.Now() c.Next() userID := uint(0) if claims := Claims(c); claims != nil { userID = claims.ID } requestID, _ := c.Get("request_id") status, errorMessage := c.Writer.Status(), "" if status >= 400 { errorMessage = writer.body.String() } _ = service.RecordOperationRequest(c.Request.Context(), &dto.OperationRecordRequest{IP: c.ClientIP(), Method: c.Request.Method, Path: path, Status: status, LatencyMS: time.Since(started).Milliseconds(), Agent: c.Request.UserAgent(), ErrorMessage: errorMessage, Body: redactJSON(requestBody), Response: redactJSON(writer.body.Bytes()), UserID: userID, RequestID: stringValue(requestID), TraceID: c.GetHeader("traceparent"), DeviceID: c.GetHeader("X-Device-Id")}) } }