diff --git a/app/routes/errors.py b/app/routes/errors.py index 6dfde66..49fb251 100644 --- a/app/routes/errors.py +++ b/app/routes/errors.py @@ -114,7 +114,7 @@ async def report_error(error: ErrorReport, request: Request) -> Response: "error_stack": error.stack, "error_context": sanitized_context, "error_url": error.url, - "error_user_agent": error.userAgent, + "error_user_agent": error.user_agent, "client_ip": client_ip, }, ) @@ -128,7 +128,7 @@ async def report_error(error: ErrorReport, request: Request) -> Response: "message": error.message, "stack": error.stack, "url": error.url, - "userAgent": error.userAgent, + "userAgent": error.user_agent, "timestamp": error.timestamp, "context": sanitized_context, } diff --git a/app/routes/roles.py b/app/routes/roles.py index 1135d81..84c5ece 100644 --- a/app/routes/roles.py +++ b/app/routes/roles.py @@ -12,7 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from app.core.audit import log_audit from app.core.auth import get_redis from app.core.db import get_db -from app.core.permission_registry import get_permission_registry +from app.core.permission_registry import CORE_PERMISSIONS, get_permission_registry from app.core.permissions import invalidate_all_user_permissions from app.deps import require_permission from app.models.plugin import Plugin as PluginModel @@ -24,44 +24,16 @@ from app.services.role_service import role_service router = APIRouter(prefix="/api/v1/roles", tags=["roles"]) +# Derived from CORE_PERMISSIONS so changes in permission_registry are reflected +# automatically. ``category`` is remapped to "system" because the frontend groups +# permissions by that value (SettingsGroups.tsx). SYSTEM_PERMISSIONS: list[dict[str, str]] = [ - # Plugin permissions are loaded dynamically from the permission registry. - {"key": "users:read", "label": "Users: Read", "category": "system"}, - {"key": "users:write", "label": "Users: Write", "category": "system"}, - {"key": "users:delete", "label": "Users: Delete", "category": "system"}, - {"key": "roles:read", "label": "Roles: Read", "category": "system"}, - {"key": "roles:write", "label": "Roles: Write", "category": "system"}, - {"key": "roles:delete", "label": "Roles: Delete", "category": "system"}, - {"key": "groups:read", "label": "Groups: Read", "category": "system"}, - {"key": "groups:write", "label": "Groups: Write", "category": "system"}, - {"key": "groups:delete", "label": "Groups: Delete", "category": "system"}, - {"key": "audit:read", "label": "Audit Log: Read", "category": "system"}, - {"key": "settings:read", "label": "Settings: Read", "category": "system"}, - {"key": "settings:write", "label": "Settings: Write", "category": "system"}, - {"key": "plugins:read", "label": "Plugins: Read", "category": "system"}, - {"key": "plugins:install", "label": "Plugins: Install", "category": "system"}, - {"key": "plugins:configure", "label": "Plugins: Configure", "category": "system"}, - {"key": "tenants:read", "label": "Tenants: Read", "category": "system"}, - {"key": "tenants:write", "label": "Tenants: Write", "category": "system"}, - {"key": "tenants:delete", "label": "Tenants: Delete", "category": "system"}, - {"key": "notifications:read", "label": "Notifications: Read", "category": "system"}, - {"key": "notifications:write", "label": "Notifications: Write", "category": "system"}, - {"key": "attachments:read", "label": "Attachments: Read", "category": "system"}, - {"key": "attachments:write", "label": "Attachments: Write", "category": "system"}, - {"key": "attachments:delete", "label": "Attachments: Delete", "category": "system"}, - {"key": "workflows:read", "label": "Workflows: Read", "category": "system"}, - {"key": "workflows:write", "label": "Workflows: Write", "category": "system"}, - {"key": "sequences:read", "label": "Sequences: Read", "category": "system"}, - {"key": "sequences:write", "label": "Sequences: Write", "category": "system"}, - {"key": "addresses:read", "label": "Addresses: Read", "category": "system"}, - {"key": "addresses:write", "label": "Addresses: Write", "category": "system"}, - {"key": "addresses:delete", "label": "Addresses: Delete", "category": "system"}, - {"key": "taxes:read", "label": "Taxes: Read", "category": "system"}, - {"key": "taxes:write", "label": "Taxes: Write", "category": "system"}, - {"key": "currencies:read", "label": "Currencies: Read", "category": "system"}, - {"key": "currencies:write", "label": "Currencies: Write", "category": "system"}, - {"key": "import_export:read", "label": "Import/Export: Read", "category": "system"}, - {"key": "import_export:write", "label": "Import/Export: Write", "category": "system"}, + { + "key": perm["key"], + "label": perm["label"], + "category": "system", + } + for perm in CORE_PERMISSIONS ] @@ -87,9 +59,12 @@ async def list_permissions( # Collect permissions from active plugins' manifests seen_keys: set[str] = set() - for name, plugin in registry._plugins.items(): + for name in registry.list_discovered(): if name not in active_records: continue + plugin = registry.get_plugin(name) + if plugin is None: + continue for perm in plugin.manifest.permissions: if perm in seen_keys: continue