| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- from __future__ import annotations
- from collections.abc import Iterable
- from dataclasses import dataclass
- from sqlalchemy import text
- from app.core.system.permissions import permissions_for_roles
- @dataclass(frozen=True)
- class KnowledgeAccessContext:
- subject_id: str
- roles: frozenset[str]
- permissions: frozenset[str]
- business_domain_uids: frozenset[str]
- correlation_id: str
- global_access: bool = False
- def permits_domain(self, business_domain_uid: str | None) -> bool:
- return self.global_access or (
- business_domain_uid is not None
- and business_domain_uid in self.business_domain_uids
- )
- def build_access_context(
- session,
- *,
- identity: dict,
- requested_business_domains: Iterable[str] | None,
- correlation_id: str,
- ) -> KnowledgeAccessContext:
- roles = frozenset(str(role) for role in identity.get("roles", ()))
- global_access = "admin" in roles
- grants: frozenset[str]
- if global_access:
- grants = frozenset()
- else:
- rows = (
- session.execute(
- text(
- """
- SELECT CAST(business_domain_uid AS text)
- FROM public.user_business_domain_grants
- WHERE user_id = CAST(:user_id AS uuid)
- AND grant_type IN ('read', 'manage')
- """
- ),
- {"user_id": identity["id"]},
- )
- .scalars()
- .all()
- )
- grants = frozenset(str(value) for value in rows)
- if requested_business_domains is not None:
- requested = frozenset(str(value) for value in requested_business_domains)
- grants = requested if global_access else grants & requested
- global_access = False
- return KnowledgeAccessContext(
- subject_id=str(identity["id"]),
- roles=roles,
- permissions=permissions_for_roles(roles),
- business_domain_uids=grants,
- correlation_id=correlation_id,
- global_access=global_access,
- )
|