Merge branch 'feature/reportes_facturas' into development
This commit is contained in:
28
backend/core/celery_app.py
Normal file
28
backend/core/celery_app.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
from celery import Celery
|
||||
|
||||
|
||||
valkey_url = os.getenv("VALKEY_URL", "redis://valkey:6379/0")
|
||||
|
||||
celery_app = Celery(
|
||||
"anexo76_tasks",
|
||||
broker=valkey_url,
|
||||
backend=valkey_url,
|
||||
include=[
|
||||
"api.v1.modules.a76.reports.importacion.facturas.task",
|
||||
"api.v1.modules.a76.reports.importacion.consolidados.task"
|
||||
] # Ruta al módulo donde están las tareas
|
||||
)
|
||||
|
||||
# Configuraciones adicionales
|
||||
celery_app.conf.update(
|
||||
task_track_started=True,
|
||||
task_serializer="json",
|
||||
accept_content=["json"],
|
||||
result_serializer="json",
|
||||
timezone="America/Mexico_City",
|
||||
enable_utc=True,
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
celery_app.start()
|
||||
@@ -1,29 +1,15 @@
|
||||
"""
|
||||
Middleware personalizado para Anexo76
|
||||
- Validación de licencias
|
||||
- Gestión de multi-tenancy
|
||||
- Logging de requests
|
||||
"""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from typing import Callable
|
||||
|
||||
from fastapi import HTTPException, Request
|
||||
from fastapi import HTTPException, Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
from .config import settings
|
||||
from .database import CoreSessionLocal
|
||||
from .security import get_tenant_from_token, verify_token
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TenantMiddleware(BaseHTTPMiddleware):
|
||||
"""
|
||||
Middleware para identificar y validar el tenant en cada request
|
||||
"""
|
||||
|
||||
async def dispatch(self, request: Request, call_next: Callable):
|
||||
# Rutas públicas que no requieren tenant
|
||||
# Permitir acceso sin autenticación a rutas de documentación y salud
|
||||
@@ -37,53 +23,35 @@ class TenantMiddleware(BaseHTTPMiddleware):
|
||||
]
|
||||
|
||||
path = request.url.path
|
||||
# Permitir cualquier subruta de docs/redoc/openapi.json (por ejemplo, /api/docs, /api/docs/, /api/docs/oauth2-redirect)
|
||||
if any(
|
||||
path == prefix or path.startswith(prefix + "/") for prefix in doc_prefixes
|
||||
):
|
||||
|
||||
# 3. Bypass para rutas públicas y docs
|
||||
if any(path == prefix or path.startswith(prefix + "/") for prefix in doc_prefixes):
|
||||
return await call_next(request)
|
||||
# Permitir rutas públicas exactas o con prefijo
|
||||
if any(
|
||||
path == prefix or (prefix != "/" and path.startswith(prefix))
|
||||
for prefix in public_prefixes
|
||||
):
|
||||
|
||||
if any(path == prefix or (prefix != "/" and path.startswith(prefix)) for prefix in public_prefixes):
|
||||
return await call_next(request)
|
||||
|
||||
# Extraer token y obtener tenant
|
||||
# 4. Validación estricta de Token (solo para lo que no es público ni OPTIONS)
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
if not auth_header or not auth_header.startswith("Bearer "):
|
||||
raise HTTPException(
|
||||
status_code=401, detail="Missing or invalid authorization header"
|
||||
status_code=401,
|
||||
detail="Missing or invalid authorization header"
|
||||
)
|
||||
|
||||
token = auth_header.split(" ")[1]
|
||||
|
||||
try:
|
||||
user_info = verify_token(token)
|
||||
tenant_id = get_tenant_from_token(user_info)
|
||||
|
||||
# ⚠️ NOTA: tenant_id puede ser None para usuarios SSO que aún no tienen tenant asignado
|
||||
# En ese caso, el endpoint específico deberá manejarlo
|
||||
if not tenant_id:
|
||||
logger.warning(
|
||||
f"⚠️ Token sin tenant_id para usuario: {user_info.get('sub', 'unknown')}"
|
||||
)
|
||||
# No lanzamos error aquí, dejamos que el endpoint decida qué hacer
|
||||
|
||||
# Agregar tenant_id al state del request (puede ser None)
|
||||
|
||||
request.state.tenant_id = tenant_id
|
||||
request.state.user_info = user_info
|
||||
|
||||
except HTTPException:
|
||||
# Re-lanzar HTTPException directamente
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Tenant validation error: {str(e)}")
|
||||
raise HTTPException(status_code=401, detail="Invalid authentication")
|
||||
|
||||
response = await call_next(request)
|
||||
return response
|
||||
# 5. Continuar con la petición real
|
||||
return await call_next(request)
|
||||
|
||||
|
||||
class LicenseValidationMiddleware(BaseHTTPMiddleware):
|
||||
|
||||
Reference in New Issue
Block a user