From 0768cfb29ae872d6f6c6fb004b084ae6b6cb50e3 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Mon, 24 Aug 2026 08:28:35 +0200 Subject: [PATCH] =?UTF-8?q?fix(d3):=20ARCH-055/056/057=20=E2=80=94=20error?= =?UTF-8?q?s.py=20error.user=5Fagent=20statt=20nicht=20existierendem=20use?= =?UTF-8?q?rAgent=20(AttributeError=20zur=20Laufzeit);=20roles.py=20SYSTEM?= =?UTF-8?q?=5FPERMISSIONS=20aus=20CORE=5FPERMISSIONS=20abgeleitet=20(47=20?= =?UTF-8?q?statt=2036=20Permissions,=20Drift=20behoben,=20category?= =?UTF-8?q?=E2=86=92system=20f=C3=BCr=20Frontend-Gruppierung);=20registry.?= =?UTF-8?q?=5Fplugins=E2=86=92=C3=B6ffentliche=20API=20list=5Fdiscovered()?= =?UTF-8?q?+get=5Fplugin()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/routes/errors.py | 4 ++-- app/routes/roles.py | 53 ++++++++++++-------------------------------- 2 files changed, 16 insertions(+), 41 deletions(-) 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