Coverage for src/lexigram/admin/rbac/inventory.py: 0%
17 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:18 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:18 +0800
1"""Permission inventory for the RBAC admin UI.
3The form pages render grouped checkboxes from an inventory of
4``resource.action`` strings. Supply the builtin resources set
5(``roles``, ``users``, ``settings``) plus any resources discovered from
6the bundle provider's registered resource classes. The service is
7mutable and registered as a container singleton so discovery can
8populate it at mount time; the controller reads ``options()`` on every
9request, so late registrations appear immediately.
10"""
12from __future__ import annotations
14from collections.abc import Iterable
16_RBAC_RESOURCES: tuple[str, ...] = ("roles", "users", "settings")
17_RBAC_ACTIONS: tuple[str, ...] = (
18 "list",
19 "view",
20 "create",
21 "update",
22 "delete",
23 "export",
24)
27class PermissionInventoryService:
28 """Mutable permission inventory for the RBAC editing pages."""
30 def __init__(self) -> None:
31 """Initialise with the builtin resources only."""
32 self._resources: list[str] = list(_RBAC_RESOURCES)
34 def register_resources(self, names: Iterable[str]) -> None:
35 """Append unknown, non-blank resource names (case normalized).
37 Duplicates and blank entries are ignored.
39 Args:
40 names: Resource names to add to the inventory.
41 """
42 for name in names:
43 key = str(name).strip().lower()
44 if key and key not in self._resources:
45 self._resources.append(key)
47 def resources(self) -> tuple[str, ...]:
48 """Return the current resource names, builtin first."""
49 return tuple(self._resources)
51 def options(self) -> dict[str, list[str]]:
52 """Return grouped permission options for every resource.
54 Returns:
55 Mapping ``{resource: ["resource.action", ...]}`` with all
56 builtin actions per resource.
57 """
58 return {
59 resource: [f"{resource}.{action}" for action in _RBAC_ACTIONS]
60 for resource in self._resources
61 }
64__all__ = [
65 "_RBAC_ACTIONS",
66 "_RBAC_RESOURCES",
67 "PermissionInventoryService",
68]