access.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. from __future__ import annotations
  2. from collections.abc import Iterable
  3. from dataclasses import dataclass
  4. from sqlalchemy import text
  5. from app.core.system.permissions import permissions_for_roles
  6. @dataclass(frozen=True)
  7. class KnowledgeAccessContext:
  8. subject_id: str
  9. roles: frozenset[str]
  10. permissions: frozenset[str]
  11. business_domain_uids: frozenset[str]
  12. correlation_id: str
  13. global_access: bool = False
  14. def permits_domain(self, business_domain_uid: str | None) -> bool:
  15. return self.global_access or (
  16. business_domain_uid is not None
  17. and business_domain_uid in self.business_domain_uids
  18. )
  19. def build_access_context(
  20. session,
  21. *,
  22. identity: dict,
  23. requested_business_domains: Iterable[str] | None,
  24. correlation_id: str,
  25. ) -> KnowledgeAccessContext:
  26. roles = frozenset(str(role) for role in identity.get("roles", ()))
  27. global_access = "admin" in roles
  28. grants: frozenset[str]
  29. if global_access:
  30. grants = frozenset()
  31. else:
  32. rows = (
  33. session.execute(
  34. text(
  35. """
  36. SELECT CAST(business_domain_uid AS text)
  37. FROM public.user_business_domain_grants
  38. WHERE user_id = CAST(:user_id AS uuid)
  39. AND grant_type IN ('read', 'manage')
  40. """
  41. ),
  42. {"user_id": identity["id"]},
  43. )
  44. .scalars()
  45. .all()
  46. )
  47. grants = frozenset(str(value) for value in rows)
  48. if requested_business_domains is not None:
  49. requested = frozenset(str(value) for value in requested_business_domains)
  50. grants = requested if global_access else grants & requested
  51. global_access = False
  52. return KnowledgeAccessContext(
  53. subject_id=str(identity["id"]),
  54. roles=roles,
  55. permissions=permissions_for_roles(roles),
  56. business_domain_uids=grants,
  57. correlation_id=correlation_id,
  58. global_access=global_access,
  59. )