Subir todos los cambios recientes a la rama principal

This commit is contained in:
arielit3
2026-01-16 13:39:55 -07:00
parent de5b6feef4
commit 99427cd48c
38 changed files with 15383 additions and 66 deletions

View File

@@ -8,10 +8,20 @@ from fastapi import Request, HTTPException, status
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import Response
import structlog
from contextlib import asynccontextmanager
from sqlalchemy.sql import text
logger = structlog.get_logger(__name__)
# Correct the usage of async for by wrapping it in an async function
@asynccontextmanager
async def get_db_context():
from app.core.database import get_db
async for db in get_db():
yield db
class TenantMiddleware(BaseHTTPMiddleware):
"""
Middleware para extraer y validar información del tenant.
@@ -34,33 +44,56 @@ class TenantMiddleware(BaseHTTPMiddleware):
"""Process request and add tenant information."""
# Skip tenant validation for excluded paths
if request.url.path in self.EXCLUDED_PATHS or request.url.path.startswith("/docs"):
if request.url.path in self.EXCLUDED_PATHS or any(request.url.path.startswith(path) for path in self.EXCLUDED_PATHS):
return await call_next(request)
# Extract tenant from header
tenant_id = request.headers.get("X-Tenant-ID")
tenant_slug = request.headers.get("X-Tenant-Slug")
# For now, we'll be more permissive in development
# In production, tenant should be strictly required
# Revertir cambios para requerir encabezados de tenant
if not tenant_id and not tenant_slug:
logger.warning(
"Request without tenant information",
path=request.url.path,
method=request.method
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Tenant information required (X-Tenant-ID or X-Tenant-Slug header)"
)
# For now, continue without tenant for development
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail="Tenant information required (X-Tenant-ID or X-Tenant-Slug header)"
# )
# Store tenant info in request state
request.state.tenant_id = tenant_id
request.state.tenant_slug = tenant_slug
# TODO: Validate tenant exists and is active
# This would involve a database query which we'll implement later
# Validate tenant exists and is active
if tenant_id or tenant_slug:
from app.core.database import get_db
from app.models.tenant import Tenant
# Update the middleware to use the new context manager
async with get_db_context() as db:
tenant = await db.execute(
text(
"""
SELECT * FROM tenants
WHERE id = :tenant_id OR slug = :tenant_slug AND status = 'active'
"""
),
{"tenant_id": tenant_id, "tenant_slug": tenant_slug}
)
tenant = tenant.fetchone()
if not tenant:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Tenant not found or inactive"
)
# Store validated tenant info
request.state.tenant = tenant
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Tenant information required (X-Tenant-ID or X-Tenant-Slug header)"
)
logger.debug(
"Tenant middleware processed",