Source code for loom.core.authz.product
"""The product's authorization declaration, published through the ``loom.authz`` entry point."""
from __future__ import annotations
from collections.abc import Mapping
from importlib.metadata import entry_points
from typing import Protocol, runtime_checkable
from loom.core.authz._roles import Permission, RoleCatalog
ENTRY_POINT_GROUP = "loom.authz"
[docs]
@runtime_checkable
class AuthzProduct(Protocol):
"""What loom needs from a product to decide, delegate and elevate."""
@property
def catalog(self) -> RoleCatalog: ...
@property
def delegate(self) -> Permission: ...
@property
def elevations(self) -> Mapping[str, Permission]: ...
_registered: AuthzProduct | None = None
[docs]
def register_authz_product(product: AuthzProduct) -> None:
"""Install ``product`` for this process, ahead of any entry point."""
global _registered
_registered = product
[docs]
def clear_authz_product() -> None:
"""Forget the registered product; for tests."""
global _registered
_registered = None
[docs]
def load_authz_product() -> AuthzProduct | None:
"""Return the registered product, else the one the ``loom.authz`` entry point names."""
if _registered is not None:
return _registered
entry = next(iter(entry_points(group=ENTRY_POINT_GROUP)), None)
if entry is None:
return None
loaded: object = entry.load()
product = loaded() if callable(loaded) else loaded
if not isinstance(product, AuthzProduct):
raise TypeError(f"entry point {entry.name!r} does not provide an AuthzProduct")
return product