From 5e9be254e2b8f1d0a57a0154ef4825ecbf5c5974 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Sun, 23 Aug 2026 21:59:22 +0200 Subject: [PATCH] feat(c1): permission fields on frontend menu items and page routes + manifest migration for all plugins --- app/plugins/builtins/ai_assistant/plugin.py | 4 ++-- app/plugins/builtins/automation/plugin.py | 9 +++++++++ app/plugins/builtins/calendar/plugin.py | 4 ++-- app/plugins/builtins/dms/plugin.py | 8 ++++---- app/plugins/builtins/kommunikation/plugin.py | 4 ++-- app/plugins/builtins/mail/plugin.py | 6 +++--- app/plugins/builtins/report_generator/plugin.py | 4 ++-- app/plugins/builtins/tasks/plugin.py | 2 ++ app/plugins/builtins/wiki/plugin.py | 4 ++-- app/plugins/manifest.py | 8 ++++++++ 10 files changed, 36 insertions(+), 17 deletions(-) diff --git a/app/plugins/builtins/ai_assistant/plugin.py b/app/plugins/builtins/ai_assistant/plugin.py index f6290d3..94430be 100644 --- a/app/plugins/builtins/ai_assistant/plugin.py +++ b/app/plugins/builtins/ai_assistant/plugin.py @@ -52,10 +52,10 @@ class AIAssistantPlugin(BasePlugin): ], is_core=True, menu_items=[ - FrontendMenuItem(label_key='nav.aiAssistant', label='KI Assistent', path='/ai-assistant', icon='Bot', order=90), + FrontendMenuItem(label_key='nav.aiAssistant', label='KI Assistent', path='/ai-assistant', icon='Bot', order=90, permission='ai:read'), ], page_routes=[ - FrontendPageRoute(path='/ai-assistant', component='@/pages/AIAssistant', protected=True), + FrontendPageRoute(path='/ai-assistant', component='@/pages/AIAssistant', protected=True, permission='ai:read'), ], settings_pages=[ FrontendSettingsPage(path='ai', label_key='settings.ai', label='AI Settings', component='@/pages/AISettings', icon='Bot', order=60), diff --git a/app/plugins/builtins/automation/plugin.py b/app/plugins/builtins/automation/plugin.py index 523da60..fff33d2 100644 --- a/app/plugins/builtins/automation/plugin.py +++ b/app/plugins/builtins/automation/plugin.py @@ -82,6 +82,7 @@ class AutomationPlugin(BasePlugin): path="/workflows", icon="Workflow", order=52, + permission="automation:read", ), FrontendMenuItem( label_key="nav.importExport", @@ -89,6 +90,7 @@ class AutomationPlugin(BasePlugin): path="/import-export", icon="ArrowUpDown", order=53, + permission="import_export:read", ), FrontendMenuItem( label_key="nav.dedupMerge", @@ -96,6 +98,7 @@ class AutomationPlugin(BasePlugin): path="/contacts/dedup", icon="Copy", order=54, + permission="contacts:read", ), FrontendMenuItem( label_key="nav.tags", @@ -103,6 +106,7 @@ class AutomationPlugin(BasePlugin): path="/tags", icon="Tag", order=55, + permission="tags:read", ), FrontendMenuItem( label_key="nav.activity", @@ -110,6 +114,7 @@ class AutomationPlugin(BasePlugin): path="/activity", icon="Activity", order=56, + permission="contacts:read", ), ], page_routes=[ @@ -117,21 +122,25 @@ class AutomationPlugin(BasePlugin): path="/automation", component="@/pages/AutomationDashboard", order=50, + permission="automation:read", ), FrontendPageRoute( path="/agents", component="@/pages/AgentDashboard", order=51, + permission="agents:read", ), FrontendPageRoute( path="/workflows", component="@/pages/Workflows", order=52, + permission="automation:read", ), FrontendPageRoute( path="/import-export", component="@/pages/ImportExport", order=53, + permission="import_export:read", ), ], settings_pages=[ diff --git a/app/plugins/builtins/calendar/plugin.py b/app/plugins/builtins/calendar/plugin.py index 692f89d..5c66209 100644 --- a/app/plugins/builtins/calendar/plugin.py +++ b/app/plugins/builtins/calendar/plugin.py @@ -48,10 +48,10 @@ class CalendarPlugin(BasePlugin): "calendar:admin", ], menu_items=[ - FrontendMenuItem(label_key='nav.calendar', label='Kalender', path='/calendar', icon='Calendar', order=20), + FrontendMenuItem(label_key='nav.calendar', label='Kalender', path='/calendar', icon='Calendar', order=20, permission='calendar:read'), ], page_routes=[ - FrontendPageRoute(path='/calendar', component='@/pages/Calendar', protected=True), + FrontendPageRoute(path='/calendar', component='@/pages/Calendar', protected=True, permission='calendar:read'), ], detail_tabs=[ FrontendDetailTab(entity_type='contact', label_key='tabs.calendar', label='Calendar', component='@/components/contact/ContactCalendarTab', icon='Calendar', order=30, permission='calendar:read'), diff --git a/app/plugins/builtins/dms/plugin.py b/app/plugins/builtins/dms/plugin.py index 90b1419..d699cf3 100644 --- a/app/plugins/builtins/dms/plugin.py +++ b/app/plugins/builtins/dms/plugin.py @@ -38,12 +38,12 @@ class DmsPlugin(BasePlugin): "dms:admin", ], menu_items=[ - FrontendMenuItem(label_key='nav.dms', label='Dateien', path='/dms', icon='FolderOpen', group='Dateien', order=40), - FrontendMenuItem(label_key='nav.dms.trash', label='Papierkorb', path='/dms/trash', icon='Trash2', group='Dateien', order=41), + FrontendMenuItem(label_key='nav.dms', label='Dateien', path='/dms', icon='FolderOpen', group='Dateien', order=40, permission='dms:read'), + FrontendMenuItem(label_key='nav.dms.trash', label='Papierkorb', path='/dms/trash', icon='Trash2', group='Dateien', order=41, permission='dms:read'), ], page_routes=[ - FrontendPageRoute(path='/dms', component='@/pages/Dms', protected=True), - FrontendPageRoute(path='/dms/trash', component='@/pages/DmsTrash', protected=True), + FrontendPageRoute(path='/dms', component='@/pages/Dms', protected=True, permission='dms:read'), + FrontendPageRoute(path='/dms/trash', component='@/pages/DmsTrash', protected=True, permission='dms:read'), ], detail_tabs=[ FrontendDetailTab(entity_type='contact', label_key='tabs.files', label='Dateien', component='@/components/contact/ContactFilesTab', icon='FolderOpen', order=40, permission='dms:read'), diff --git a/app/plugins/builtins/kommunikation/plugin.py b/app/plugins/builtins/kommunikation/plugin.py index ab0a6b9..7dfde5f 100644 --- a/app/plugins/builtins/kommunikation/plugin.py +++ b/app/plugins/builtins/kommunikation/plugin.py @@ -50,10 +50,10 @@ class KommunikationPlugin(BasePlugin): ], is_core=True, menu_items=[ - FrontendMenuItem(label_key='nav.communication', label='Kommunikation', path='/communication', icon='MessageSquare', order=80), + FrontendMenuItem(label_key='nav.communication', label='Kommunikation', path='/communication', icon='MessageSquare', order=80, permission='comm:read'), ], page_routes=[ - FrontendPageRoute(path='/communication', component='@/pages/Communication', protected=True), + FrontendPageRoute(path='/communication', component='@/pages/Communication', protected=True, permission='comm:read'), ], author="LeoCRM Team", min_app_version="1.0.0", diff --git a/app/plugins/builtins/mail/plugin.py b/app/plugins/builtins/mail/plugin.py index c6af338..d28f84a 100644 --- a/app/plugins/builtins/mail/plugin.py +++ b/app/plugins/builtins/mail/plugin.py @@ -141,11 +141,11 @@ class MailPlugin(BasePlugin): migrations=["0001_initial.sql", "0006_flag_type.sql", "0007_sync_queue.sql", "0008_sync_queue_deleted_at.sql", "0009_remove_mail_soft_delete.sql", "0010_add_deleted_at.sql"], permissions=["mail:read", "mail:send", "mail:config", "mail:share", "mail:write", "mail:delete"], menu_items=[ - FrontendMenuItem(label_key='nav.mail', label='E-Mail', path='/mail', icon='Mail', order=30), + FrontendMenuItem(label_key='nav.mail', label='E-Mail', path='/mail', icon='Mail', order=30, permission='mail:read'), ], page_routes=[ - FrontendPageRoute(path='/mail', component='@/pages/Mail', protected=True), - FrontendPageRoute(path='/mail/settings', component='@/pages/MailSettings', protected=True), + FrontendPageRoute(path='/mail', component='@/pages/Mail', protected=True, permission='mail:read'), + FrontendPageRoute(path='/mail/settings', component='@/pages/MailSettings', protected=True, permission='mail:config'), ], settings_pages=[ FrontendSettingsPage(path='mail', label_key='settings.mail', label='Mail', component='@/pages/MailSettings', icon='Mail', order=50), diff --git a/app/plugins/builtins/report_generator/plugin.py b/app/plugins/builtins/report_generator/plugin.py index baf7b90..d681faa 100644 --- a/app/plugins/builtins/report_generator/plugin.py +++ b/app/plugins/builtins/report_generator/plugin.py @@ -27,10 +27,10 @@ class ReportGeneratorPlugin(BasePlugin): migrations=["0001_initial.sql", "0002_reports_folder_id.sql"], permissions=["reports:read", "reports:generate", "reports:manage_templates"], menu_items=[ - FrontendMenuItem(label_key='nav.reports', label='Berichte', path='/reports', icon='BarChart3', order=70), + FrontendMenuItem(label_key='nav.reports', label='Berichte', path='/reports', icon='BarChart3', order=70, permission='reports:read'), ], page_routes=[ - FrontendPageRoute(path='/reports', component='@/pages/Reports', protected=True), + FrontendPageRoute(path='/reports', component='@/pages/Reports', protected=True, permission='reports:read'), ], author="LeoCRM Team", diff --git a/app/plugins/builtins/tasks/plugin.py b/app/plugins/builtins/tasks/plugin.py index 260a6e3..773158a 100644 --- a/app/plugins/builtins/tasks/plugin.py +++ b/app/plugins/builtins/tasks/plugin.py @@ -43,6 +43,7 @@ class TasksPlugin(BasePlugin): path="/tasks", icon="CheckSquare", order=30, + permission="tasks:read", ), ], page_routes=[ @@ -51,6 +52,7 @@ class TasksPlugin(BasePlugin): component="@/pages/Tasks", protected=True, order=30, + permission="tasks:read", ), ], cron_jobs=[ diff --git a/app/plugins/builtins/wiki/plugin.py b/app/plugins/builtins/wiki/plugin.py index 8635100..0278cc0 100644 --- a/app/plugins/builtins/wiki/plugin.py +++ b/app/plugins/builtins/wiki/plugin.py @@ -18,8 +18,8 @@ class WikiPlugin(BasePlugin): PluginRouteDef(path="/api/v1/wiki", module="app.plugins.builtins.wiki.routes", router_attr="router"), ], permissions=["wiki:read", "wiki:write", "wiki:delete", "wiki:admin"], - menu_items=[FrontendMenuItem(label_key="wiki.menu.wiki", label="Wiki", path="/wiki", icon="BookOpen")], - page_routes=[FrontendPageRoute(path="/wiki", component="@/pages/Wiki")], + menu_items=[FrontendMenuItem(label_key="wiki.menu.wiki", label="Wiki", path="/wiki", icon="BookOpen", permission="wiki:read")], + page_routes=[FrontendPageRoute(path="/wiki", component="@/pages/Wiki", permission="wiki:read")], ) async def on_activate(self, db, service_container, event_bus) -> None: diff --git a/app/plugins/manifest.py b/app/plugins/manifest.py index 0661f61..501f92f 100644 --- a/app/plugins/manifest.py +++ b/app/plugins/manifest.py @@ -43,6 +43,10 @@ class FrontendMenuItem(BaseModel): group: str = Field(default="", description="Optional group label_key for tree-style nesting") order: int = Field(default=100, description="Sort order within the sidebar") badge_key: str = Field(default="", description="Optional store key for badge count") + permission: str = Field( + default="", + description="Permission required to see/use this item (empty = any authenticated user)", + ) class FrontendPageRoute(BaseModel): @@ -58,6 +62,10 @@ class FrontendPageRoute(BaseModel): ) protected: bool = Field(default=True, description="Whether the route requires authentication") order: int = Field(default=100, description="Sort order") + permission: str = Field( + default="", + description="Permission required to access this route (empty = any authenticated user)", + ) class FrontendDetailTab(BaseModel):