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} + +