import db import json from fastapi import Request from typing import Optional, Any class AuditService: async def log( self, user_id: int, action: str, target_type: Optional[str] = None, target_id: Optional[int] = None, details: Optional[Any] = None, request: Optional[Request] = None ): ip_address = None if request: # Try to get real IP if behind proxy ip_address = request.headers.get("X-Forwarded-For", request.client.host if request.client else None) details_str = None if details: if isinstance(details, (dict, list)): # Convert details to JSON string, handling Decimals and other types def decimal_default(obj): try: from decimal import Decimal if isinstance(obj, Decimal): return float(obj) except: pass return str(obj) details_str = json.dumps(details, ensure_ascii=False, default=decimal_default) else: details_str = str(details) query = """ INSERT INTO audit_logs (user_id, action, target_type, target_id, details, ip_address) VALUES (%s, %s, %s, %s, %s, %s) """ db.execute_commit(query, (user_id, action, target_type, target_id, details_str, ip_address)) audit_service = AuditService()