package middleware import ( "RenewCMS/api/pkg/claims" "RenewCMS/internal/domain/audit" "RenewCMS/internal/infrastructure/useCases" "net/http" ) func AuditContext(getUser *useCases.GetUserUseCase, trustedProxies []string) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := audit.Origin{ Actor: auditActor(getUser, r), Source: auditSource(r), IP: clientIP(r, trustedProxies), UserAgent: truncatedUserAgent(r), } next.ServeHTTP(w, r.WithContext(audit.WithOrigin(r.Context(), origin))) }) } } func auditActor(getUser *useCases.GetUserUseCase, r *http.Request) audit.Actor { if id, ok := apiKeyIdFrom(r); ok { return audit.APIKeyActor(id, apiKeyNameFrom(r)) } userId, ok := claims.UserId(r) if !ok { return audit.AnonymousActor("") } current, err := getUser.GetUser(userId) if err != nil { return audit.AnonymousActor("") } tokenVersion, ok := claims.TokenVersion(r) if !ok || tokenVersion != current.TokenVersion { return audit.AnonymousActor("") } return audit.UserActor(current) } func auditSource(r *http.Request) audit.Source { if _, ok := apiKeyIdFrom(r); ok { return audit.SourceAPIKey } return audit.SourceWeb } func clientIP(r *http.Request, trustedProxies []string) string { realIP := r.Header.Get("X-Real-IP") if realIP != "" && isTrustedProxy(r.RemoteAddr, trustedProxies) { return realIP } return hostOf(r.RemoteAddr) } func truncatedUserAgent(r *http.Request) string { runes := []rune(r.Header.Get("User-Agent")) if len(runes) > audit.MaxUserAgentLength { runes = runes[:audit.MaxUserAgentLength] } return string(runes) }