roosterwijs/backend/core/audit.py
bes-r c845588e5e
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
Add roles modules audit logging and CI
2026-07-04 23:01:06 +02:00

58 lines
1.8 KiB
Python

"""Kleine auditlog-helper voor gevoelige acties."""
import logging
from rest_framework import viewsets
logger = logging.getLogger("roosterwijs.audit")
def audit_log(request, action, target="", extra=None):
"""Log wie wat deed, zonder request bodies of wachtwoorden te loggen."""
user = getattr(request, "user", None)
username = user.get_username() if user and user.is_authenticated else "anonymous"
ip = None
if request is not None:
forwarded = request.META.get("HTTP_X_FORWARDED_FOR", "")
ip = (forwarded.split(",", 1)[0].strip() or request.META.get("REMOTE_ADDR") or None)
logger.info(
"actor=%r action=%s target=%s extra=%s",
username,
action,
target or "-",
extra or {},
)
try:
from plugins.models import AuditEvent
AuditEvent.objects.create(
actor=username,
action=action,
target=target or "",
ip_address=ip,
extra=extra or {},
)
except Exception:
logger.exception("Kon audit-event niet opslaan")
class AuditedModelViewSet(viewsets.ModelViewSet):
"""ModelViewSet die create/update/delete-acties auditbaar maakt."""
audit_name = None
def _audit_target(self, obj):
name = self.audit_name or obj.__class__.__name__
return f"{name}:{getattr(obj, 'pk', '-')}"
def perform_create(self, serializer):
obj = serializer.save()
audit_log(self.request, "create", self._audit_target(obj))
def perform_update(self, serializer):
obj = serializer.save()
audit_log(self.request, "update", self._audit_target(obj))
def perform_destroy(self, instance):
target = self._audit_target(instance)
super().perform_destroy(instance)
audit_log(self.request, "delete", target)