From 5a2ff8b2e5b6f55a20f7ed491f818490eb535ea7 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 1 Apr 2026 01:21:21 -0500 Subject: [PATCH] refac --- backend/open_webui/config.py | 5 +++++ backend/open_webui/routers/automations.py | 20 +++++++++++++++++ backend/open_webui/routers/users.py | 1 + .../admin/Users/Groups/Permissions.svelte | 22 +++++++++++++++++++ .../components/layout/Sidebar/UserMenu.svelte | 3 +++ src/lib/constants/permissions.ts | 3 ++- src/routes/(app)/automations/+page.svelte | 11 +++++++++- 7 files changed, 63 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 9e8e8d27d..f2dcd92a7 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -1435,6 +1435,10 @@ USER_PERMISSIONS_FEATURES_API_KEYS = os.environ.get('USER_PERMISSIONS_FEATURES_A USER_PERMISSIONS_FEATURES_MEMORIES = os.environ.get('USER_PERMISSIONS_FEATURES_MEMORIES', 'True').lower() == 'true' +USER_PERMISSIONS_FEATURES_AUTOMATIONS = ( + os.environ.get('USER_PERMISSIONS_FEATURES_AUTOMATIONS', 'False').lower() == 'true' +) + USER_PERMISSIONS_SETTINGS_INTERFACE = os.environ.get('USER_PERMISSIONS_SETTINGS_INTERFACE', 'True').lower() == 'true' @@ -1504,6 +1508,7 @@ DEFAULT_USER_PERMISSIONS = { 'image_generation': USER_PERMISSIONS_FEATURES_IMAGE_GENERATION, 'code_interpreter': USER_PERMISSIONS_FEATURES_CODE_INTERPRETER, 'memories': USER_PERMISSIONS_FEATURES_MEMORIES, + 'automations': USER_PERMISSIONS_FEATURES_AUTOMATIONS, }, 'settings': { 'interface': USER_PERMISSIONS_SETTINGS_INTERFACE, diff --git a/backend/open_webui/routers/automations.py b/backend/open_webui/routers/automations.py index 41dc761df..6375cb7e4 100644 --- a/backend/open_webui/routers/automations.py +++ b/backend/open_webui/routers/automations.py @@ -21,6 +21,7 @@ from open_webui.utils.automations import ( execute_automation, ) from open_webui.utils.auth import get_verified_user, get_admin_user +from open_webui.utils.access_control import has_permission from open_webui.internal.db import get_session from open_webui.constants import ERROR_MESSAGES @@ -36,6 +37,16 @@ PAGE_ITEM_COUNT = 30 ############################ +def check_automations_permission(request, user): + if user.role != 'admin' and not has_permission( + user.id, 'features.automations', request.app.state.config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.UNAUTHORIZED, + ) + + def check_automation_access(automation, user): if not automation: raise HTTPException( @@ -71,6 +82,7 @@ async def get_automations( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automations = Automations.get_by_user(user.id, db=db) return [enrich_automation(automation, db, tz=user.timezone) for automation in automations] @@ -89,6 +101,7 @@ async def get_automation_items( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) limit = PAGE_ITEM_COUNT page = max(1, page) skip = (page - 1) * limit @@ -123,6 +136,7 @@ async def create_new_automation( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) try: validate_rrule(form_data.data.rrule) except ValueError as e: @@ -159,6 +173,7 @@ async def get_automation_by_id( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automation = Automations.get_by_id(id, db=db) check_automation_access(automation, user) return enrich_automation(automation, db, tz=user.timezone) @@ -177,6 +192,7 @@ async def update_automation_by_id( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automation = Automations.get_by_id(id, db=db) check_automation_access(automation, user) @@ -216,6 +232,7 @@ async def toggle_automation_by_id( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automation = Automations.get_by_id(id, db=db) check_automation_access(automation, user) toggled = Automations.toggle( @@ -236,6 +253,7 @@ async def run_automation_by_id( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automation = Automations.get_by_id(id, db=db) check_automation_access(automation, user) asyncio.create_task(execute_automation(request.app, automation)) @@ -254,6 +272,7 @@ async def delete_automation_by_id( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automation = Automations.get_by_id(id, db=db) check_automation_access(automation, user) AutomationRuns.delete_by_automation(id, db=db) @@ -274,6 +293,7 @@ async def get_automation_runs( user=Depends(get_verified_user), db: Session = Depends(get_session), ): + check_automations_permission(request, user) automation = Automations.get_by_id(id, db=db) check_automation_access(automation, user) return AutomationRuns.get_by_automation(id, skip=skip, limit=limit, db=db) diff --git a/backend/open_webui/routers/users.py b/backend/open_webui/routers/users.py index b26314087..0ccc20185 100644 --- a/backend/open_webui/routers/users.py +++ b/backend/open_webui/routers/users.py @@ -232,6 +232,7 @@ class FeaturesPermissions(BaseModel): image_generation: bool = True code_interpreter: bool = True memories: bool = True + automations: bool = False class SettingsPermissions(BaseModel): diff --git a/src/lib/components/admin/Users/Groups/Permissions.svelte b/src/lib/components/admin/Users/Groups/Permissions.svelte index 9ebae25b7..7bd8fd00e 100644 --- a/src/lib/components/admin/Users/Groups/Permissions.svelte +++ b/src/lib/components/admin/Users/Groups/Permissions.svelte @@ -894,6 +894,28 @@ {/if} + +
+ +
+ {$i18n.t('Automations')} +
+ +
+ {#if defaultPermissions?.features?.automations && !permissions.features.automations} +
+
+ {$i18n.t('This is a default user permission and will remain enabled.')} +
+
+ {/if} +

diff --git a/src/lib/components/layout/Sidebar/UserMenu.svelte b/src/lib/components/layout/Sidebar/UserMenu.svelte index 7e2e25eb6..1dc710eac 100644 --- a/src/lib/components/layout/Sidebar/UserMenu.svelte +++ b/src/lib/components/layout/Sidebar/UserMenu.svelte @@ -9,6 +9,7 @@ import { showSettings, mobile, showSidebar, showShortcuts, user, config } from '$lib/stores'; + import { WEBUI_API_BASE_URL } from '$lib/constants'; import Dropdown from '$lib/components/common/Dropdown.svelte'; @@ -214,6 +215,7 @@
{$i18n.t('Settings')}
+ {#if $user?.role === 'admin' || $user?.permissions?.features?.automations}
{$i18n.t('Automations')}
+ {/if}