From f85159c9b6522eb3b8411cda31887ae26c77c41e Mon Sep 17 00:00:00 2001 From: leo <260626284+cameledev@users.noreply.github.com> Date: Wed, 10 Jun 2026 14:34:52 +0200 Subject: [PATCH] wip --- CHANGELOG.md | 4 +++ src/backend/core/external_api/viewsets.py | 25 +++++++++-------- src/backend/meet/settings.py | 34 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1617fb1..6314f9bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to ## [Unreleased] +### Added + +- ✨(backend) add structured audit logging + ## [1.19.0] - 2026-06-04 ### Added diff --git a/src/backend/core/external_api/viewsets.py b/src/backend/core/external_api/viewsets.py index 07ecf4f8..da5f42dd 100644 --- a/src/backend/core/external_api/viewsets.py +++ b/src/backend/core/external_api/viewsets.py @@ -1,7 +1,5 @@ """External API endpoints""" -from logging import getLogger - from django.conf import settings from django.contrib.auth.hashers import check_password from django.core.exceptions import ValidationError @@ -21,6 +19,7 @@ from rest_framework import ( from core import api, models from core.api.feature_flag import FeatureFlag +from core.audit_meet import getLogger from core.services.jwt_token import JwtTokenService from ..services.provisional_user_service import ( @@ -30,7 +29,7 @@ from ..services.provisional_user_service import ( ) from . import authentication, permissions, serializers -logger = getLogger(__name__) +audit_logger = getLogger(__name__) class ApplicationViewSet(viewsets.ViewSet): @@ -86,10 +85,11 @@ class ApplicationViewSet(viewsets.ViewSet): ) if not application.can_delegate_email(email): - logger.warning( - "Application %s denied delegation for %s", - application.client_id, - email, + audit_logger.warning( + "Application denied delegation", + request=request, + application_client_id=application.client_id, + email=email, ) return drf_response.Response( { @@ -195,9 +195,10 @@ class RoomViewSet( ) # Log for auditing - logger.info( - "Room created via application: room_id=%s, user_id=%s, client_id=%s", - room.id, - self.request.user.id, - getattr(self.request.auth, "client_id", "unknown"), + audit_logger.info( + "room_created_via_application", + request=self.request, + # Extra + room=room, + client_id=getattr(self.request.auth, "client_id", "unknown"), ) diff --git a/src/backend/meet/settings.py b/src/backend/meet/settings.py index 4f7d696a..5d917449 100755 --- a/src/backend/meet/settings.py +++ b/src/backend/meet/settings.py @@ -1025,12 +1025,22 @@ class Base(Configuration): "format": "{asctime} {name} {levelname} {message}", "style": "{", }, + "audit_json": { + "()": "core.audit.AuditJsonFormatter", + }, }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "simple", }, + # Audit events go to stdout on their own handler so they stay + # distinguishable from regular application logs. + "audit_console": { + "class": "logging.StreamHandler", + "stream": "ext://sys.stdout", + "formatter": "audit_json", + }, }, # Override root logger to send it to console "root": { @@ -1049,6 +1059,15 @@ class Base(Configuration): ), "propagate": False, }, + "audit": { + "handlers": ["audit_console"], + "level": values.Value( + "INFO", + environ_name="LOGGING_LEVEL_LOGGERS_AUDIT", + environ_prefix=None, + ), + "propagate": False, + }, }, } @@ -1158,16 +1177,31 @@ class Test(Base): { "version": 1, "disable_existing_loggers": False, + "formatters": { + "audit_json": { + "()": "core.audit.AuditJsonFormatter", + }, + }, "handlers": { "console": { "class": "logging.StreamHandler", }, + "audit_console": { + "class": "logging.StreamHandler", + "stream": "ext://sys.stdout", + "formatter": "audit_json", + }, }, "loggers": { "meet": { "handlers": ["console"], "level": "DEBUG", }, + "audit": { + "handlers": ["audit_console"], + "level": "INFO", + "propagate": False, + }, }, } )