diff --git a/aiohttp_admin/backends/abc.py b/aiohttp_admin/backends/abc.py index d83cce79..0f9ee01f 100644 --- a/aiohttp_admin/backends/abc.py +++ b/aiohttp_admin/backends/abc.py @@ -13,7 +13,7 @@ from aiohttp_security import check_permission, permits from pydantic import Json -from ..security import check, permissions_as_dict +from ..security import check from ..types import ComponentState, InputState, fk, resources_key if sys.version_info >= (3, 10): @@ -435,8 +435,8 @@ def _process_list_query(self, query: _ListQuery, request: web.Request) -> None: query["filter"] = merged_filter # Add filters from advanced permissions. - # The permissions will be cached on the request from a previous permissions check. - permissions = permissions_as_dict(request["aiohttpadmin_permissions"]) + # The parsed permissions are cached on the request from a previous check. + permissions = request["aiohttpadmin_permissions"] filters = permissions.get(f"admin.{self.name}.view", permissions.get(f"admin.{self.name}.*", {})) for k, v in filters.items(): diff --git a/aiohttp_admin/security.py b/aiohttp_admin/security.py index 5355a088..23edb5ab 100644 --- a/aiohttp_admin/security.py +++ b/aiohttp_admin/security.py @@ -94,16 +94,20 @@ async def permits( except (TypeError, ValueError): raise TypeError("Context must be `(request, record)` or `(request, None)`") - permissions: Optional[Collection[str]] = request.get("aiohttpadmin_permissions") + permissions = request.get("aiohttpadmin_permissions") if permissions is None: + raw: Collection[str] if self._identity_callback is None: - permissions = (Permissions.all,) + raw = (Permissions.all,) else: user = await self._identity_callback(identity) - permissions = user["permissions"] - # Cache permissions per request to avoid potentially dozens of DB calls. + raw = user["permissions"] + # Cache the parsed permissions per request to avoid both repeat DB calls + # and re-parsing the permission strings on every check (permits() runs + # O(records * fields) times per request). + permissions = permissions_as_dict(raw) request["aiohttpadmin_permissions"] = permissions - return has_permission(permission, permissions_as_dict(permissions), record) + return has_permission(permission, permissions, record) class TokenIdentityPolicy(SessionIdentityPolicy):