fix(d3): ARCH-055/056/057 — errors.py error.user_agent statt nicht existierendem userAgent (AttributeError zur Laufzeit); roles.py SYSTEM_PERMISSIONS aus CORE_PERMISSIONS abgeleitet (47 statt 36 Permissions, Drift behoben, category→system für Frontend-Gruppierung); registry._plugins→öffentliche API list_discovered()+get_plugin()

This commit is contained in:
Agent Zero
2026-08-24 08:28:35 +02:00
parent 56e401969e
commit 0768cfb29a
2 changed files with 16 additions and 41 deletions
+2 -2
View File
@@ -114,7 +114,7 @@ async def report_error(error: ErrorReport, request: Request) -> Response:
"error_stack": error.stack, "error_stack": error.stack,
"error_context": sanitized_context, "error_context": sanitized_context,
"error_url": error.url, "error_url": error.url,
"error_user_agent": error.userAgent, "error_user_agent": error.user_agent,
"client_ip": client_ip, "client_ip": client_ip,
}, },
) )
@@ -128,7 +128,7 @@ async def report_error(error: ErrorReport, request: Request) -> Response:
"message": error.message, "message": error.message,
"stack": error.stack, "stack": error.stack,
"url": error.url, "url": error.url,
"userAgent": error.userAgent, "userAgent": error.user_agent,
"timestamp": error.timestamp, "timestamp": error.timestamp,
"context": sanitized_context, "context": sanitized_context,
} }
+14 -39
View File
@@ -12,7 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.core.audit import log_audit from app.core.audit import log_audit
from app.core.auth import get_redis from app.core.auth import get_redis
from app.core.db import get_db 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.core.permissions import invalidate_all_user_permissions
from app.deps import require_permission from app.deps import require_permission
from app.models.plugin import Plugin as PluginModel 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"]) 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]] = [ SYSTEM_PERMISSIONS: list[dict[str, str]] = [
# Plugin permissions are loaded dynamically from the permission registry. {
{"key": "users:read", "label": "Users: Read", "category": "system"}, "key": perm["key"],
{"key": "users:write", "label": "Users: Write", "category": "system"}, "label": perm["label"],
{"key": "users:delete", "label": "Users: Delete", "category": "system"}, "category": "system",
{"key": "roles:read", "label": "Roles: Read", "category": "system"}, }
{"key": "roles:write", "label": "Roles: Write", "category": "system"}, for perm in CORE_PERMISSIONS
{"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"},
] ]
@@ -87,9 +59,12 @@ async def list_permissions(
# Collect permissions from active plugins' manifests # Collect permissions from active plugins' manifests
seen_keys: set[str] = set() seen_keys: set[str] = set()
for name, plugin in registry._plugins.items(): for name in registry.list_discovered():
if name not in active_records: if name not in active_records:
continue continue
plugin = registry.get_plugin(name)
if plugin is None:
continue
for perm in plugin.manifest.permissions: for perm in plugin.manifest.permissions:
if perm in seen_keys: if perm in seen_keys:
continue continue