Volver a la wiki

Utilidad require_org: resolver organización con fallo cerrado

Definición

require_org(request: HttpRequest) → Organization

Utility en core.utils.organization que resuelve la organización del request o lanza HttpError(403, "Forbidden: no organization in context").

Ubicación: core/utils/organization.py
Módulo exportador: core.utils (promovido desde local en monitoring/api/common.py)
Re-exporta: monitoring/api/common.py (backward compat)

Propósito

Reemplazar el antipatrón heredado:

org = request.user.organization or Organization.objects.first()  # ✗ INSEGURO

Por un flujo explícito fail-closed:

org = require_org(request)  # ✓ 403 si no hay org

Caso de uso: endpoints que REQUIEREN contexto de organización (escritura, operaciones sensibles).

Implementación

def require_org(request):
    """Resolve the request's organization or raise HttpError(403) — fail closed.
    
    Replaces the legacy ``user.organization or Organization.objects.first()``
    fallback (T5): a principal without an org must NEVER fall through to the
    first tenant in the DB (cross-tenant read/write).
    """
    from ninja.errors import HttpError
    
    org = get_current_org(request)
    if org is None:
        raise HttpError(403, "Forbidden: no organization in context")
    return org

Depende de:

Call-sites (antes de T5)

require_org era local en:

En T5 (2026-06-11):

Arquitectura

Request sin auth / sin org
    ↓
call require_org(request)
    ↓
    ├─ get_current_org(request) retorna None
    └─ → HttpError(403) ← fail-closed, no intenta Organization.objects.first()

Request con auth + org
    ↓
call require_org(request)
    ↓
    ├─ get_current_org(request) retorna Organization
    └─ → org ← ok, procede

Tests

tests/api/test_t5_org_fallback.py::TestRequireOrgHelper:

def test_require_org_raises_without_org(self, rf, orgless_admin):
    """Lanza HttpError(403) si user.organization es None."""
    from core.utils import require_org
    request = rf.get("/")
    request.user = orgless_admin
    with pytest.raises(HttpError):
        require_org(request)

def test_require_org_returns_org(self, rf, admin_user, organization):
    """Retorna org si user.organization existe."""
    from core.utils import require_org
    request = rf.get("/")
    request.user = admin_user
    assert require_org(request) == organization

Estado

Véase también

Subir