""" Audit Schemas - ServiceManagerWeb Schemas Pydantic para endpoints de auditoría """ from pydantic import BaseModel, Field, UUID4 from typing import Optional, Dict, Any from datetime import datetime class AuditLogBase(BaseModel): """Schema base para audit logs.""" action: str = Field(..., description="Acción realizada (ej: ticket.create)") resource_type: str = Field(..., description="Tipo de recurso (ticket, user, etc.)") resource_id: Optional[UUID4] = Field(None, description="ID del recurso afectado") extra_metadata: Optional[Dict[str, Any]] = Field(None, description="Metadata adicional", alias="metadata") class AuditLogResponse(AuditLogBase): """ Schema de respuesta para audit logs. Incluye toda la información del log con datos del usuario. """ id: UUID4 tenant_id: UUID4 user_id: Optional[UUID4] # Información del usuario (si existe) user_email: Optional[str] = None user_name: Optional[str] = None user_role: Optional[str] = None # Contexto de la acción ip_address: Optional[str] user_agent: Optional[str] correlation_id: Optional[UUID4] # Cambios realizados old_values: Optional[Dict[str, Any]] new_values: Optional[Dict[str, Any]] # Timestamp created_at: datetime # Display friendly action_display: str = Field(description="Acción en formato amigable") class Config: from_attributes = True class AuditLogFilters(BaseModel): """ Filtros para consulta de audit logs. Permite filtrar por múltiples criterios. """ # Paginación page: int = Field(default=1, ge=1, description="Número de página") per_page: int = Field(default=50, ge=1, le=100, description="Elementos por página") # Filtros user_id: Optional[UUID4] = Field(None, description="Filtrar por usuario") action: Optional[str] = Field(None, description="Filtrar por acción específica") resource_type: Optional[str] = Field(None, description="Filtrar por tipo de recurso") resource_id: Optional[UUID4] = Field(None, description="Filtrar por ID de recurso") # Rango de fechas date_from: Optional[datetime] = Field(None, description="Fecha inicio (ISO 8601)") date_to: Optional[datetime] = Field(None, description="Fecha fin (ISO 8601)") # Búsqueda search: Optional[str] = Field(None, description="Búsqueda en acciones o recursos") class AuditLogStats(BaseModel): """ Estadísticas de auditoría. Resumen de actividad del sistema. """ total_actions: int = Field(description="Total de acciones registradas") actions_today: int = Field(description="Acciones en las últimas 24 horas") actions_this_week: int = Field(description="Acciones en los últimos 7 días") critical_actions_today: int = Field(description="Acciones críticas hoy (delete, cambios sensibles)") # Top acciones top_actions: Dict[str, int] = Field(description="Acciones más frecuentes") # Top usuarios top_users: Dict[str, int] = Field(description="Usuarios más activos") # Actividad por tipo de recurso by_resource_type: Dict[str, int] = Field(description="Acciones por tipo de recurso") class AuditLogListResponse(BaseModel): """ Respuesta paginada de audit logs. """ logs: list[AuditLogResponse] total: int = Field(description="Total de registros") page: int = Field(description="Página actual") per_page: int = Field(description="Registros por página") total_pages: int = Field(description="Total de páginas") class Config: from_attributes = True