refactor: fix architecture violations with provider patterns and dependency inversion
Major changes: - Add AuditProvider protocol for cross-module audit logging - Move customer order operations to orders module (dependency inversion) - Add customer order metrics via MetricsProvider pattern - Fix missing db parameter in get_admin_context() calls - Move ProductMedia relationship to catalog module (proper ownership) - Add marketplace breakdown stats to marketplace_widgets New files: - contracts/audit.py - AuditProviderProtocol - core/services/audit_aggregator.py - Aggregates audit providers - monitoring/services/audit_provider.py - Monitoring audit implementation - orders/services/customer_order_service.py - Customer order operations - orders/routes/api/vendor_customer_orders.py - Customer order endpoints - catalog/services/product_media_service.py - Product media service - Architecture documentation for patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,13 @@ def _get_admin_router():
|
||||
return admin_router
|
||||
|
||||
|
||||
def _get_audit_provider():
|
||||
"""Lazy import of audit provider to avoid circular imports."""
|
||||
from app.modules.monitoring.services.audit_provider import audit_provider
|
||||
|
||||
return audit_provider
|
||||
|
||||
|
||||
# Monitoring module definition
|
||||
monitoring_module = ModuleDefinition(
|
||||
code="monitoring",
|
||||
@@ -112,6 +119,10 @@ monitoring_module = ModuleDefinition(
|
||||
is_core=False,
|
||||
is_internal=True, # Internal module - admin-only, not customer-facing
|
||||
# =========================================================================
|
||||
# Audit Provider
|
||||
# =========================================================================
|
||||
audit_provider=_get_audit_provider,
|
||||
# =========================================================================
|
||||
# Self-Contained Module Configuration
|
||||
# =========================================================================
|
||||
is_self_contained=True,
|
||||
|
||||
78
app/modules/monitoring/services/audit_provider.py
Normal file
78
app/modules/monitoring/services/audit_provider.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# app/modules/monitoring/services/audit_provider.py
|
||||
"""
|
||||
Audit provider implementation for the monitoring module.
|
||||
|
||||
Provides database-backed audit logging using the AdminAuditLog model.
|
||||
This wraps the existing admin_audit_service functionality in the
|
||||
AuditProviderProtocol interface.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.modules.contracts.audit import AuditEvent, AuditProviderProtocol
|
||||
from app.modules.tenancy.models import AdminAuditLog
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DatabaseAuditProvider:
|
||||
"""
|
||||
Database-backed audit provider.
|
||||
|
||||
Logs admin actions to the AdminAuditLog table.
|
||||
This is the default audit backend for the platform.
|
||||
"""
|
||||
|
||||
@property
|
||||
def audit_backend(self) -> str:
|
||||
return "database"
|
||||
|
||||
def log_action(self, db: Session, event: AuditEvent) -> bool:
|
||||
"""
|
||||
Log an audit event to the database.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
event: The audit event to log
|
||||
|
||||
Returns:
|
||||
True if logged successfully, False otherwise
|
||||
"""
|
||||
try:
|
||||
audit_log = AdminAuditLog(
|
||||
admin_user_id=event.admin_user_id,
|
||||
action=event.action,
|
||||
target_type=event.target_type,
|
||||
target_id=str(event.target_id),
|
||||
details=event.details or {},
|
||||
ip_address=event.ip_address,
|
||||
user_agent=event.user_agent,
|
||||
request_id=event.request_id,
|
||||
)
|
||||
|
||||
db.add(audit_log)
|
||||
db.flush()
|
||||
|
||||
logger.debug(
|
||||
f"Admin action logged: {event.action} on {event.target_type}:"
|
||||
f"{event.target_id} by admin {event.admin_user_id}"
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to log admin action: {str(e)}")
|
||||
# Don't raise exception - audit logging should not break operations
|
||||
return False
|
||||
|
||||
|
||||
# Singleton instance
|
||||
audit_provider = DatabaseAuditProvider()
|
||||
|
||||
__all__ = ["DatabaseAuditProvider", "audit_provider"]
|
||||
Reference in New Issue
Block a user