♻️(backend) split audit registrations from the action catalogue

core/auditing.py both declared the actions that emitters import and
registered the models and authentication classes: it made it impossible
for authentication class to emit an audit event without an import cycle.

Keep the actions and transit_code_target in core/auditing.py and move the
model and authentication method registrations to core/audit_registry.py, the
module the audit app now autodiscovers.
This commit is contained in:
briquet
2026-10-19 13:18:56 +02:00
parent 2aa2a4ed46
commit 90206f8673
5 changed files with 96 additions and 84 deletions
+5 -2
View File
@@ -383,6 +383,9 @@ APPLICATION_TOKEN_ISSUE = audit.Action(
ROOM_CREATE = audit.Action("room.create")
```
`core/auditing.py` imports nothing but the audit facility, so that any module can import it, authentication classes
included. Models and authentication classes are registered apart, in `core/audit_registry.py`.
### Auditing a DRF view
A DRF view only declares the actions it audits: everything else is derived from the response. CRUD actions are mapped
@@ -466,8 +469,8 @@ on. A registered field that cannot be read is left out of the target, and the ev
### Registering models and authentication methods
The project describes itself to the audit facility in code, in `core/auditing.py`. Once the audit app is ready, it
imports the `auditing` module of every installed app.
The project describes itself to the audit facility in code, in `core/audit_registry.py`. Once the audit app is ready,
it imports the `audit_registry` module of every installed app.
**`audit.register(Model, ...)`** tells the audit log how to handle a model:
+3 -3
View File
@@ -16,11 +16,11 @@ class AuditConfig(AppConfig):
def ready(self):
"""Connect the login, failed login and logout receivers.
Then import the ``auditing`` module of every installed app, where the
project registers its models and authentication classes.
Then import the ``audit_registry`` module of every installed app, where
the project registers its models and authentication classes.
"""
connect_auth_signals()
autodiscover_modules("auditing")
autodiscover_modules("audit_registry")
class AuditedAdminConfig(AdminConfig):
+1 -1
View File
@@ -1,6 +1,6 @@
"""Declare what audit events may say about models and authentication classes.
The project registers them from an ``auditing`` module in one of its apps,
The project registers them from an ``audit_registry`` module in one of its apps,
imported once the audit app is ready::
audit.register(
+82
View File
@@ -0,0 +1,82 @@
"""How Meet describes itself to the audit facility: its models and authentication classes.
Imported by the audit app once it is ready, see ``core.audit.apps``. The actions
Meet audits are declared in ``core.auditing``.
"""
from django.contrib.auth.models import Group
from lasuite.oidc_resource_server.authentication import ResourceServerAuthentication
from core import audit, models
from core.audit import EventCategory
from core.authentication.backends import OIDCAuthenticationBackend
from core.authentication.livekit import LiveKitTokenAuthentication
from core.authentication.user_token import UserAccessJWTAuthentication
from core.external_api.authentication import (
AddonsJWTAuthentication,
ApplicationJWTAuthentication,
)
from core.recording.event.authentication import HeaderBasedAuthentication
from core.roomkit.authentication import ServerToServerAuthentication
# Models
audit.register(
models.User,
category=EventCategory.IAM,
admin_values=(
"is_active",
"is_staff",
"is_superuser",
"is_device",
"groups",
"user_permissions",
),
)
audit.register(Group, category=EventCategory.IAM, admin_values=("name", "permissions"))
audit.register(
models.Application,
category=EventCategory.IAM,
entity_type="application",
fields=("client_id", "name", "is_active", "scopes"),
admin_values=("name", "is_active", "scopes"),
)
audit.register(
models.ApplicationDomain, category=EventCategory.IAM, admin_values=("domain",)
)
audit.register(
models.ResourceAccess,
category=EventCategory.IAM,
fields=("resource_id", "user_id", "role"),
admin_values=("role",),
user_target="user",
)
audit.register(
models.RecordingAccess,
category=EventCategory.IAM,
admin_values=("role",),
user_target="user",
)
audit.register(
models.Room,
fields=("slug", "name", "access_level"),
admin_values=("name", "slug", "access_level", "configuration"),
)
audit.register(
models.Recording,
fields=("room_id", "status", "mode", "requested_mode", "is_transcribed"),
admin_values=("status", "mode"),
)
audit.register(models.File, admin_values=("title", "upload_state"))
# Authentication classes and login backends -> ``lasuite.auth.method``
audit.register_auth_method(OIDCAuthenticationBackend, "oidc")
audit.register_auth_method(ApplicationJWTAuthentication, "application_jwt")
audit.register_auth_method(AddonsJWTAuthentication, "addons_jwt")
audit.register_auth_method(ResourceServerAuthentication, "resource_server")
audit.register_auth_method(LiveKitTokenAuthentication, "livekit_token")
audit.register_auth_method(UserAccessJWTAuthentication, "user_access_jwt")
audit.register_auth_method(HeaderBasedAuthentication, "shared_secret")
audit.register_auth_method(ServerToServerAuthentication, "shared_secret")
+5 -78
View File
@@ -1,23 +1,12 @@
"""What Meet audits, and what its audit events may say.
"""The catalogue of what Meet audits: its actions and the targets that are not models.
Imported by the audit app once it is ready, see ``core.audit.apps``.
It imports nothing but the audit facility and leaf helpers, so that any module can
import it, authentication classes included. Models and authentication classes
are registered in ``core.audit_registry``.
"""
from django.contrib.auth.models import Group
from lasuite.oidc_resource_server.authentication import ResourceServerAuthentication
from core import audit, models
from core import audit
from core.audit import EventCategory, EventType
from core.authentication.backends import OIDCAuthenticationBackend
from core.authentication.livekit import LiveKitTokenAuthentication
from core.authentication.user_token import UserAccessJWTAuthentication
from core.external_api.authentication import (
AddonsJWTAuthentication,
ApplicationJWTAuthentication,
)
from core.recording.event.authentication import HeaderBasedAuthentication
from core.roomkit.authentication import ServerToServerAuthentication
from core.services.transit_code import TransitCodeService
# Actions
@@ -57,68 +46,6 @@ RECORDING_SUMMARY_REPORT = audit.Action(
"recording.summary.report", types=(EventType.END,)
)
# Models
audit.register(
models.User,
category=EventCategory.IAM,
admin_values=(
"is_active",
"is_staff",
"is_superuser",
"is_device",
"groups",
"user_permissions",
),
)
audit.register(Group, category=EventCategory.IAM, admin_values=("name", "permissions"))
audit.register(
models.Application,
category=EventCategory.IAM,
entity_type="application",
fields=("client_id", "name", "is_active", "scopes"),
admin_values=("name", "is_active", "scopes"),
)
audit.register(
models.ApplicationDomain, category=EventCategory.IAM, admin_values=("domain",)
)
audit.register(
models.ResourceAccess,
category=EventCategory.IAM,
fields=("resource_id", "user_id", "role"),
admin_values=("role",),
user_target="user",
)
audit.register(
models.RecordingAccess,
category=EventCategory.IAM,
admin_values=("role",),
user_target="user",
)
audit.register(
models.Room,
fields=("slug", "name", "access_level"),
admin_values=("name", "slug", "access_level", "configuration"),
)
audit.register(
models.Recording,
fields=("room_id", "status", "mode", "requested_mode", "is_transcribed"),
admin_values=("status", "mode"),
)
audit.register(models.File, admin_values=("title", "upload_state"))
# Authentication classes and login backends -> ``lasuite.auth.method``
audit.register_auth_method(OIDCAuthenticationBackend, "oidc")
audit.register_auth_method(ApplicationJWTAuthentication, "application_jwt")
audit.register_auth_method(AddonsJWTAuthentication, "addons_jwt")
audit.register_auth_method(ResourceServerAuthentication, "resource_server")
audit.register_auth_method(LiveKitTokenAuthentication, "livekit_token")
audit.register_auth_method(UserAccessJWTAuthentication, "user_access_jwt")
audit.register_auth_method(HeaderBasedAuthentication, "shared_secret")
audit.register_auth_method(ServerToServerAuthentication, "shared_secret")
# Targets that are not models