38 lines
1.5 KiB
Python
38 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable
|
|
|
|
from govoplan_access.backend.permissions.evaluator import expand_scopes, scopes_grant
|
|
from govoplan_core.core.modules import PermissionDefinition
|
|
|
|
|
|
class PermissionRegistry:
|
|
def __init__(self, permissions: Iterable[PermissionDefinition] = ()) -> None:
|
|
self._catalog: dict[str, PermissionDefinition] = {}
|
|
for permission in permissions:
|
|
self.register(permission)
|
|
|
|
@property
|
|
def catalog(self) -> dict[str, PermissionDefinition]:
|
|
return dict(self._catalog)
|
|
|
|
def register(self, permission: PermissionDefinition) -> None:
|
|
if permission.scope in self._catalog:
|
|
raise ValueError(f"Duplicate permission scope: {permission.scope}")
|
|
self._catalog[permission.scope] = permission
|
|
|
|
def has(self, scope: str) -> bool:
|
|
return scope in self._catalog
|
|
|
|
def grants(self, scopes: Iterable[str], required: str) -> bool:
|
|
return scopes_grant(scopes, required, catalog=self._catalog)
|
|
|
|
def expand(self, scopes: Iterable[str], *, include_unknown: bool = False) -> list[str]:
|
|
return expand_scopes(scopes, catalog=self._catalog, include_unknown=include_unknown)
|
|
|
|
def validate_known(self, scopes: Iterable[str]) -> list[str]:
|
|
unknown = sorted(scope for scope in scopes if scope not in self._catalog and not scope.endswith(":*") and scope not in {"*", "tenant:*", "system:*"})
|
|
if unknown:
|
|
raise ValueError("Unknown permission scope(s): " + ", ".join(unknown))
|
|
return sorted(set(scopes))
|