fix(security): improve tenant ID resolution and error handling for hub_admin access

This commit is contained in:
2026-05-20 10:46:31 -05:00
parent 64d81c83f9
commit 7920f190e3
3 changed files with 56 additions and 19 deletions

View File

@@ -721,7 +721,6 @@ async def get_all_movements(
logger.warning(f"Email sending failed: {str(email_error)} - continuing with report generation")
return movements
return movements
except ValueError as e:
logger.warning(f"Validation error fetching all movements: {str(e)}")
raise HTTPException(
@@ -761,11 +760,18 @@ def generate_invoice_report_async(
# validate_access_to_resource returns the integer tenant_id from DB
tenant_id = validate_access_to_resource(db, company_id, current_user, ["report.process"])
# Guardia explícita: tenant_id debe ser un entero positivo antes del dispatch a Celery.
# Un valor inválido aquí generaría un reporte sin filtro de tenant o un crash en la tarea.
if not isinstance(tenant_id, int) or tenant_id <= 0:
raise HTTPException(
status_code=400,
detail="No se pudo determinar el tenant para esta empresa. Verifica que la empresa exista.",
)
# Serialize filters to dict for Celery
filter_data = filters.model_dump()
user_email = current_user.get('email')
# tenant_id ya validado por validate_access_to_resource
task = track_and_dispatch(
db=db,
task=generate_invoice_movements_async,

View File

@@ -580,7 +580,7 @@ class UserService:
con ``X-Tenant-Override``; activos desde users-with-info del Hub si hay token;
inactivos y fallback de conteos en BD local.
"""
max_users_allowed = 0
max_users_allowed: Optional[int] = None # None = sin cuota (hub_admin ilimitado)
hub_max_ok = False
active_users = 0
active_from_hub = False
@@ -600,8 +600,8 @@ class UserService:
lic_body = lic_resp.json()
if lic_body.get("valid"):
raw_max = lic_body.get("max_users")
# max_users=null → hub_admin sin cuota; usamos 0 como sentinel
max_users_allowed = int(raw_max) if raw_max is not None else 0
# max_users=null → hub_admin sin cuota; None indica ilimitado
max_users_allowed = int(raw_max) if raw_max is not None else None
hub_max_ok = True
users_resp = client.get(
@@ -647,9 +647,14 @@ class UserService:
)
total_users = active_users + inactive_users
users_available = max(0, max_users_allowed - active_users)
# Cuando max_users_allowed es None la cuota es ilimitada (hub_admin)
users_available = (
max(0, max_users_allowed - active_users)
if max_users_allowed is not None
else None
)
usage_percentage = (
(active_users / max_users_allowed * 100) if max_users_allowed > 0 else 0
(active_users / max_users_allowed * 100) if max_users_allowed else 0.0
)
return {