Enforce tenant isolation on verified audit firm domains

This commit is contained in:
A R R R Associates
2026-07-10 15:04:54 +05:30
parent 18cfb0b8a7
commit 2e87013563
3 changed files with 127 additions and 15 deletions
+42 -15
View File
@@ -59,6 +59,19 @@ def _normalise_session_int(value):
return None
_TENANT_BOUND_DOMAIN_TYPES = {"audit_firm_domain", "audit_firm_subdomain"}
def _is_trusted_tenant_bound_domain(request: Request) -> bool:
return (
bool(getattr(request.state, "domain_resolved", False))
and bool(getattr(request.state, "domain_is_verified", False))
and (getattr(request.state, "domain_status", None) or "").strip().lower() == "active"
and (getattr(request.state, "domain_type", None) or "").strip() in _TENANT_BOUND_DOMAIN_TYPES
and _normalise_session_int(getattr(request.state, "domain_tenant_id", None)) is not None
)
class ContextResolveMiddleware(BaseHTTPMiddleware):
def __init__(self, app: ASGIApp) -> None:
super().__init__(app)
@@ -101,22 +114,35 @@ class ContextResolveMiddleware(BaseHTTPMiddleware):
session_tenant_code = (session.get("active_tenant_code") or session.get("tenant_code") or "").strip() or None
session_branch_code = (session.get("active_branch_code") or session.get("branch_code") or "").strip() or None
domain_tenant_id = _normalise_session_int(getattr(request.state, "domain_tenant_id", None))
domain_branch_id = _normalise_session_int(getattr(request.state, "domain_branch_id", None))
domain_tenant_code = getattr(request.state, "domain_tenant_code", None)
domain_branch_code = getattr(request.state, "domain_branch_code", None)
tenant_bound_domain = _is_trusted_tenant_bound_domain(request)
tenant_code = (
session_tenant_code
or domain_tenant_code
or (request.headers.get(_TENANT_HEADER) if trust_headers else None)
or self.s.DEFAULT_TENANT_CODE
)
branch_code = (
session_branch_code
or domain_branch_code
or (request.headers.get(_BRANCH_HEADER) if trust_headers else None)
or self.s.DEFAULT_BRANCH_CODE
)
# On a verified active audit-firm hostname, the domain mapping is the
# authoritative tenant/branch context. Session selection must never
# escape to another tenant while the user remains on that hostname.
if tenant_bound_domain:
active_tenant_id = domain_tenant_id
active_branch_id = domain_branch_id if domain_branch_id is not None else session_branch_id
tenant_code = domain_tenant_code or self.s.DEFAULT_TENANT_CODE
branch_code = domain_branch_code or session_branch_code or self.s.DEFAULT_BRANCH_CODE
else:
active_tenant_id = session_tenant_id
active_branch_id = session_branch_id
tenant_code = (
session_tenant_code
or domain_tenant_code
or (request.headers.get(_TENANT_HEADER) if trust_headers else None)
or self.s.DEFAULT_TENANT_CODE
)
branch_code = (
session_branch_code
or domain_branch_code
or (request.headers.get(_BRANCH_HEADER) if trust_headers else None)
or self.s.DEFAULT_BRANCH_CODE
)
year_code = (
session.get("active_financial_year")
@@ -124,8 +150,9 @@ class ContextResolveMiddleware(BaseHTTPMiddleware):
or self.s.DEFAULT_YEAR_CODE
)
request.state.active_tenant_id = session_tenant_id
request.state.active_branch_id = session_branch_id
request.state.active_tenant_id = active_tenant_id
request.state.active_branch_id = active_branch_id
request.state.tenant_bound_domain = tenant_bound_domain
request.state.tenant_code = tenant_code
request.state.branch_code = branch_code
request.state.year_code = year_code