65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
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)
|
|
}
|