80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
import time
|
|
import uuid
|
|
|
|
from django.conf import settings
|
|
from django.utils.deprecation import MiddlewareMixin
|
|
|
|
from .models import APIInteractionLog
|
|
|
|
|
|
class AuditAPIMiddleware(MiddlewareMixin):
|
|
def process_request(self, request):
|
|
request.request_id = str(uuid.uuid4())
|
|
request._audit_start_time = time.time()
|
|
|
|
def process_response(self, request, response):
|
|
config = getattr(settings, "INFRASYNTH_AUDIT", {})
|
|
if not config.get("ENABLE_API_LOGGING", True):
|
|
return response
|
|
|
|
path = request.path
|
|
if path.startswith("/admin/"):
|
|
return response
|
|
|
|
if hasattr(request, "_audit_start_time"):
|
|
duration_ms = int((time.time() - request._audit_start_time) * 1000)
|
|
else:
|
|
duration_ms = 0
|
|
|
|
max_body = config.get("MAX_BODY_SIZE_BYTES", 5000)
|
|
request_body = None
|
|
response_body = None
|
|
sensitive_keys = config.get("SENSITIVE_KEYS", [])
|
|
|
|
try:
|
|
raw_body = getattr(request, "body", b"")
|
|
if raw_body and len(raw_body) <= max_body:
|
|
body = raw_body.decode("utf-8", errors="replace")
|
|
if not any(k in body.lower() for k in sensitive_keys):
|
|
import json
|
|
|
|
try:
|
|
request_body = json.loads(body)
|
|
except (json.JSONDecodeError, ValueError):
|
|
request_body = {"_truncated": True}
|
|
except Exception:
|
|
pass
|
|
|
|
try:
|
|
if hasattr(response, "data") and response.data:
|
|
import json as _json
|
|
|
|
try:
|
|
raw = _json.dumps(response.data)
|
|
if len(raw) <= max_body:
|
|
response_body = response.data
|
|
except (TypeError, ValueError):
|
|
pass
|
|
except Exception:
|
|
pass
|
|
|
|
actor = getattr(request, "user", None)
|
|
if actor and not actor.is_authenticated:
|
|
actor = None
|
|
if actor is not None and not hasattr(actor, "_meta"):
|
|
actor = None
|
|
|
|
APIInteractionLog.objects.create(
|
|
method=request.method,
|
|
path=path,
|
|
status_code=response.status_code,
|
|
request_body=request_body,
|
|
response_body=response_body,
|
|
ip_address=request.META.get("REMOTE_ADDR"),
|
|
actor=actor,
|
|
duration_ms=duration_ms,
|
|
request_id=getattr(request, "request_id", ""),
|
|
user_agent=request.META.get("HTTP_USER_AGENT", ""),
|
|
)
|
|
|
|
return response
|