feat: enhance audit log functionality with tenant_id handling and optional seed data in initialization script

This commit is contained in:
2026-02-18 12:58:11 -06:00
parent bbd0b7ad90
commit d4b52b32ed
8 changed files with 341 additions and 63 deletions

View File

@@ -1,11 +1,14 @@
"""
Audit Log Events
"""
from sqlalchemy import event, inspect
from sqlalchemy.orm import Session
from .services.service import AuditService
from .utils.serialization import serialize_for_json
from core.context import get_user_context
def register_audit_listeners(models_to_audit):
"""
Register SQLAlchemy listeners for given models
@@ -15,16 +18,23 @@ def register_audit_listeners(models_to_audit):
event.listen(model, "after_update", after_update_listener)
event.listen(model, "after_delete", after_delete_listener)
def _get_current_username():
try:
context = get_user_context()
if context:
# Token usually has 'preferred_username' or 'name' or 'sub'
return context.get("preferred_username") or context.get("email") or context.get("sub") or "System"
return (
context.get("preferred_username")
or context.get("email")
or context.get("sub")
or "System"
)
except:
pass
return "System"
def after_insert_listener(mapper, connection, target):
"""
Listener for INSERT operations
@@ -33,7 +43,8 @@ def after_insert_listener(mapper, connection, target):
record_data = {c.name: getattr(target, c.name) for c in mapper.columns}
username = _get_current_username()
company_id = getattr(target, "company_id", None)
tenant_id = getattr(target, "tenant_id", None)
# Create a session bound to the connection
session = Session(bind=connection)
try:
@@ -44,24 +55,26 @@ def after_insert_listener(mapper, connection, target):
record_data=record_data,
username=username,
record_id=str(getattr(target, "id", "")),
company_id=company_id
company_id=company_id,
tenant_id=tenant_id,
)
except Exception as e:
print(f"Error logging insert: {e}")
finally:
session.close()
def after_update_listener(mapper, connection, target):
"""
Listener for UPDATE operations
"""
table_name = target.__tablename__
state = inspect(target)
changes = {}
old_values = {}
new_values = {}
for attr in state.attrs:
hist = attr.history
if hist.has_changes():
@@ -74,6 +87,8 @@ def after_update_listener(mapper, connection, target):
record_data = {c.name: getattr(target, c.name) for c in mapper.columns}
username = _get_current_username()
company_id = getattr(target, "company_id", None)
tenant_id = getattr(target, "tenant_id", None)
session = Session(bind=connection)
try:
@@ -84,13 +99,16 @@ def after_update_listener(mapper, connection, target):
record_data=record_data,
username=username,
record_id=str(getattr(target, "id", "")),
old_values=old_values,
new_values=new_values
old_values=serialize_for_json(old_values),
new_values=serialize_for_json(new_values),
company_id=company_id,
tenant_id=tenant_id,
)
except Exception as e:
print(f"Error logging update: {e}")
print(f"Error logging update: {e}")
finally:
session.close()
session.close()
def after_delete_listener(mapper, connection, target):
"""
@@ -99,7 +117,9 @@ def after_delete_listener(mapper, connection, target):
table_name = target.__tablename__
record_data = {c.name: getattr(target, c.name) for c in mapper.columns}
username = _get_current_username()
company_id = getattr(target, "company_id", None)
tenant_id = getattr(target, "tenant_id", None)
session = Session(bind=connection)
try:
AuditService.log_crud_operation(
@@ -108,9 +128,11 @@ def after_delete_listener(mapper, connection, target):
operation_type="DELETE",
record_data=record_data,
username=username,
record_id=str(getattr(target, "id", ""))
record_id=str(getattr(target, "id", "")),
company_id=company_id,
tenant_id=tenant_id,
)
except Exception as e:
print(f"Error logging delete: {e}")
print(f"Error logging delete: {e}")
finally:
session.close()
session.close()