Improve teh securty of teh DB

This commit is contained in:
Urtzi Alfaro
2025-10-19 19:22:37 +02:00
parent 62971c07d7
commit 05da20357d
87 changed files with 7998 additions and 932 deletions

View File

@@ -9,6 +9,9 @@ from datetime import datetime, timezone
from typing import List, Optional, Dict, Any
import uuid
from decimal import Decimal
import structlog
logger = structlog.get_logger()
class AlertSeverity:
@@ -35,11 +38,12 @@ async def create_demo_alert(
title: str,
message: str,
service: str,
rabbitmq_client,
metadata: Dict[str, Any] = None,
created_at: Optional[datetime] = None
):
"""
Create and persist a demo alert
Create and persist a demo alert, then publish to RabbitMQ
Args:
db: Database session
@@ -49,18 +53,24 @@ async def create_demo_alert(
title: Alert title (in Spanish)
message: Alert message (in Spanish)
service: Service name that generated the alert
rabbitmq_client: RabbitMQ client for publishing alerts
metadata: Additional alert-specific data
created_at: When the alert was created (defaults to now)
Returns:
Created Alert instance (dict for cross-service compatibility)
"""
from shared.config.rabbitmq_config import get_routing_key
alert_id = uuid.uuid4()
alert_created_at = created_at or datetime.now(timezone.utc)
# Import here to avoid circular dependencies
try:
from app.models.alerts import Alert
alert = Alert(
id=uuid.uuid4(),
id=alert_id,
tenant_id=tenant_id,
item_type="alert",
alert_type=alert_type,
@@ -70,33 +80,84 @@ async def create_demo_alert(
title=title,
message=message,
alert_metadata=metadata or {},
created_at=created_at or datetime.now(timezone.utc)
created_at=alert_created_at
)
db.add(alert)
return alert
await db.flush()
except ImportError:
# If Alert model not available, return dict representation
# This allows the function to work across services
alert_dict = {
"id": uuid.uuid4(),
"tenant_id": tenant_id,
"item_type": "alert",
"alert_type": alert_type,
"severity": severity,
"status": AlertStatus.ACTIVE,
"service": service,
"title": title,
"message": message,
"alert_metadata": metadata or {},
"created_at": created_at or datetime.now(timezone.utc)
}
return alert_dict
# If Alert model not available, skip DB insert
logger.warning("Alert model not available, skipping DB insert", service=service)
# Publish alert to RabbitMQ for processing by Alert Processor
if rabbitmq_client:
try:
alert_message = {
'id': str(alert_id),
'tenant_id': str(tenant_id),
'item_type': 'alert',
'type': alert_type,
'severity': severity,
'service': service,
'title': title,
'message': message,
'metadata': metadata or {},
'timestamp': alert_created_at.isoformat()
}
routing_key = get_routing_key('alert', severity, service)
published = await rabbitmq_client.publish_event(
exchange_name='alerts.exchange',
routing_key=routing_key,
event_data=alert_message
)
if published:
logger.info(
"Demo alert published to RabbitMQ",
alert_id=str(alert_id),
alert_type=alert_type,
severity=severity,
service=service,
routing_key=routing_key
)
else:
logger.warning(
"Failed to publish demo alert to RabbitMQ",
alert_id=str(alert_id),
alert_type=alert_type
)
except Exception as e:
logger.error(
"Error publishing demo alert to RabbitMQ",
alert_id=str(alert_id),
error=str(e),
exc_info=True
)
else:
logger.warning("No RabbitMQ client provided, alert will not be streamed", alert_id=str(alert_id))
# Return alert dict for compatibility
return {
"id": str(alert_id),
"tenant_id": str(tenant_id),
"item_type": "alert",
"alert_type": alert_type,
"severity": severity,
"status": AlertStatus.ACTIVE,
"service": service,
"title": title,
"message": message,
"alert_metadata": metadata or {},
"created_at": alert_created_at
}
async def generate_inventory_alerts(
db,
tenant_id: uuid.UUID,
session_created_at: datetime
session_created_at: datetime,
rabbitmq_client=None
) -> int:
"""
Generate inventory-related alerts for demo session
@@ -111,6 +172,7 @@ async def generate_inventory_alerts(
db: Database session
tenant_id: Virtual tenant UUID
session_created_at: When the demo session was created
rabbitmq_client: RabbitMQ client for publishing alerts
Returns:
Number of alerts created
@@ -156,6 +218,7 @@ async def generate_inventory_alerts(
f"Cantidad: {stock.current_quantity:.2f} {ingredient.unit_of_measure.value}. "
f"Acción requerida: Retirar inmediatamente del inventario y registrar como pérdida.",
service="inventory",
rabbitmq_client=rabbitmq_client,
metadata={
"stock_id": str(stock.id),
"ingredient_id": str(ingredient.id),
@@ -181,6 +244,7 @@ async def generate_inventory_alerts(
f"Cantidad: {stock.current_quantity:.2f} {ingredient.unit_of_measure.value}. "
f"Recomendación: Planificar uso prioritario en producción inmediata.",
service="inventory",
rabbitmq_client=rabbitmq_client,
metadata={
"stock_id": str(stock.id),
"ingredient_id": str(ingredient.id),
@@ -207,6 +271,7 @@ async def generate_inventory_alerts(
f"Faltante: {shortage:.2f} {ingredient.unit_of_measure.value}. "
f"Se recomienda realizar pedido de {ingredient.reorder_quantity:.2f} {ingredient.unit_of_measure.value}.",
service="inventory",
rabbitmq_client=rabbitmq_client,
metadata={
"stock_id": str(stock.id),
"ingredient_id": str(ingredient.id),
@@ -233,6 +298,7 @@ async def generate_inventory_alerts(
f"Exceso: {excess:.2f} {ingredient.unit_of_measure.value}. "
f"Considerar reducir cantidad en próximos pedidos o buscar uso alternativo.",
service="inventory",
rabbitmq_client=rabbitmq_client,
metadata={
"stock_id": str(stock.id),
"ingredient_id": str(ingredient.id),
@@ -250,7 +316,8 @@ async def generate_inventory_alerts(
async def generate_equipment_alerts(
db,
tenant_id: uuid.UUID,
session_created_at: datetime
session_created_at: datetime,
rabbitmq_client=None
) -> int:
"""
Generate equipment-related alerts for demo session
@@ -264,6 +331,7 @@ async def generate_equipment_alerts(
db: Database session
tenant_id: Virtual tenant UUID
session_created_at: When the demo session was created
rabbitmq_client: RabbitMQ client for publishing alerts
Returns:
Number of alerts created
@@ -295,6 +363,7 @@ async def generate_equipment_alerts(
f"Último mantenimiento: {equipment.last_maintenance_date.strftime('%d/%m/%Y') if equipment.last_maintenance_date else 'No registrado'}. "
f"Programar mantenimiento preventivo lo antes posible.",
service="production",
rabbitmq_client=rabbitmq_client,
metadata={
"equipment_id": str(equipment.id),
"equipment_name": equipment.name,
@@ -316,6 +385,7 @@ async def generate_equipment_alerts(
message=f"El equipo {equipment.name} está actualmente en mantenimiento y no disponible para producción. "
f"Ajustar planificación de producción según capacidad reducida.",
service="production",
rabbitmq_client=rabbitmq_client,
metadata={
"equipment_id": str(equipment.id),
"equipment_name": equipment.name,
@@ -335,6 +405,7 @@ async def generate_equipment_alerts(
f"Contactar con servicio técnico inmediatamente. "
f"Revisar planificación de producción y reasignar lotes a otros equipos.",
service="production",
rabbitmq_client=rabbitmq_client,
metadata={
"equipment_id": str(equipment.id),
"equipment_name": equipment.name,
@@ -354,6 +425,7 @@ async def generate_equipment_alerts(
f"Eficiencia actual: {equipment.efficiency_percentage:.1f}%. "
f"Monitorear de cerca y considerar inspección preventiva.",
service="production",
rabbitmq_client=rabbitmq_client,
metadata={
"equipment_id": str(equipment.id),
"equipment_name": equipment.name,
@@ -375,6 +447,7 @@ async def generate_equipment_alerts(
f"Eficiencia objetivo: e 85%. "
f"Revisar causas: limpieza, calibración, desgaste de componentes.",
service="production",
rabbitmq_client=rabbitmq_client,
metadata={
"equipment_id": str(equipment.id),
"equipment_name": equipment.name,
@@ -390,7 +463,8 @@ async def generate_equipment_alerts(
async def generate_order_alerts(
db,
tenant_id: uuid.UUID,
session_created_at: datetime
session_created_at: datetime,
rabbitmq_client=None
) -> int:
"""
Generate order-related alerts for demo session
@@ -404,6 +478,7 @@ async def generate_order_alerts(
db: Database session
tenant_id: Virtual tenant UUID
session_created_at: When the demo session was created
rabbitmq_client: RabbitMQ client for publishing alerts
Returns:
Number of alerts created
@@ -443,6 +518,7 @@ async def generate_order_alerts(
f"Estado actual: {order.status}. "
f"Verificar que esté en producción.",
service="orders",
rabbitmq_client=rabbitmq_client,
metadata={
"order_id": str(order.id),
"order_number": order.order_number,
@@ -465,6 +541,7 @@ async def generate_order_alerts(
f"Fecha de entrega prevista: {order.requested_delivery_date.strftime('%d/%m/%Y')}. "
f"Contactar al cliente y renegociar fecha de entrega.",
service="orders",
rabbitmq_client=rabbitmq_client,
metadata={
"order_id": str(order.id),
"order_number": order.order_number,
@@ -487,6 +564,7 @@ async def generate_order_alerts(
f"Monto: ¬{float(order.total_amount):.2f}. "
f"Revisar disponibilidad de ingredientes y confirmar producción.",
service="orders",
rabbitmq_client=rabbitmq_client,
metadata={
"order_id": str(order.id),
"order_number": order.order_number,