refac
This commit is contained in:
@@ -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_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'
|
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,
|
'image_generation': USER_PERMISSIONS_FEATURES_IMAGE_GENERATION,
|
||||||
'code_interpreter': USER_PERMISSIONS_FEATURES_CODE_INTERPRETER,
|
'code_interpreter': USER_PERMISSIONS_FEATURES_CODE_INTERPRETER,
|
||||||
'memories': USER_PERMISSIONS_FEATURES_MEMORIES,
|
'memories': USER_PERMISSIONS_FEATURES_MEMORIES,
|
||||||
|
'automations': USER_PERMISSIONS_FEATURES_AUTOMATIONS,
|
||||||
},
|
},
|
||||||
'settings': {
|
'settings': {
|
||||||
'interface': USER_PERMISSIONS_SETTINGS_INTERFACE,
|
'interface': USER_PERMISSIONS_SETTINGS_INTERFACE,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from open_webui.utils.automations import (
|
|||||||
execute_automation,
|
execute_automation,
|
||||||
)
|
)
|
||||||
from open_webui.utils.auth import get_verified_user, get_admin_user
|
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.internal.db import get_session
|
||||||
from open_webui.constants import ERROR_MESSAGES
|
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):
|
def check_automation_access(automation, user):
|
||||||
if not automation:
|
if not automation:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
@@ -71,6 +82,7 @@ async def get_automations(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automations = Automations.get_by_user(user.id, db=db)
|
automations = Automations.get_by_user(user.id, db=db)
|
||||||
return [enrich_automation(automation, db, tz=user.timezone) for automation in automations]
|
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),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
limit = PAGE_ITEM_COUNT
|
limit = PAGE_ITEM_COUNT
|
||||||
page = max(1, page)
|
page = max(1, page)
|
||||||
skip = (page - 1) * limit
|
skip = (page - 1) * limit
|
||||||
@@ -123,6 +136,7 @@ async def create_new_automation(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
try:
|
try:
|
||||||
validate_rrule(form_data.data.rrule)
|
validate_rrule(form_data.data.rrule)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
@@ -159,6 +173,7 @@ async def get_automation_by_id(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automation = Automations.get_by_id(id, db=db)
|
automation = Automations.get_by_id(id, db=db)
|
||||||
check_automation_access(automation, user)
|
check_automation_access(automation, user)
|
||||||
return enrich_automation(automation, db, tz=user.timezone)
|
return enrich_automation(automation, db, tz=user.timezone)
|
||||||
@@ -177,6 +192,7 @@ async def update_automation_by_id(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automation = Automations.get_by_id(id, db=db)
|
automation = Automations.get_by_id(id, db=db)
|
||||||
check_automation_access(automation, user)
|
check_automation_access(automation, user)
|
||||||
|
|
||||||
@@ -216,6 +232,7 @@ async def toggle_automation_by_id(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automation = Automations.get_by_id(id, db=db)
|
automation = Automations.get_by_id(id, db=db)
|
||||||
check_automation_access(automation, user)
|
check_automation_access(automation, user)
|
||||||
toggled = Automations.toggle(
|
toggled = Automations.toggle(
|
||||||
@@ -236,6 +253,7 @@ async def run_automation_by_id(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automation = Automations.get_by_id(id, db=db)
|
automation = Automations.get_by_id(id, db=db)
|
||||||
check_automation_access(automation, user)
|
check_automation_access(automation, user)
|
||||||
asyncio.create_task(execute_automation(request.app, automation))
|
asyncio.create_task(execute_automation(request.app, automation))
|
||||||
@@ -254,6 +272,7 @@ async def delete_automation_by_id(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automation = Automations.get_by_id(id, db=db)
|
automation = Automations.get_by_id(id, db=db)
|
||||||
check_automation_access(automation, user)
|
check_automation_access(automation, user)
|
||||||
AutomationRuns.delete_by_automation(id, db=db)
|
AutomationRuns.delete_by_automation(id, db=db)
|
||||||
@@ -274,6 +293,7 @@ async def get_automation_runs(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
check_automations_permission(request, user)
|
||||||
automation = Automations.get_by_id(id, db=db)
|
automation = Automations.get_by_id(id, db=db)
|
||||||
check_automation_access(automation, user)
|
check_automation_access(automation, user)
|
||||||
return AutomationRuns.get_by_automation(id, skip=skip, limit=limit, db=db)
|
return AutomationRuns.get_by_automation(id, skip=skip, limit=limit, db=db)
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ class FeaturesPermissions(BaseModel):
|
|||||||
image_generation: bool = True
|
image_generation: bool = True
|
||||||
code_interpreter: bool = True
|
code_interpreter: bool = True
|
||||||
memories: bool = True
|
memories: bool = True
|
||||||
|
automations: bool = False
|
||||||
|
|
||||||
|
|
||||||
class SettingsPermissions(BaseModel):
|
class SettingsPermissions(BaseModel):
|
||||||
|
|||||||
@@ -894,6 +894,28 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col w-full">
|
||||||
|
<Tooltip
|
||||||
|
className="flex w-full justify-between my-1"
|
||||||
|
content={$i18n.t(
|
||||||
|
'Warning: Enabling this will allow users to run scheduled prompts automatically.'
|
||||||
|
)}
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
<div class=" self-center text-xs font-medium">
|
||||||
|
{$i18n.t('Automations')}
|
||||||
|
</div>
|
||||||
|
<Switch bind:state={permissions.features.automations} />
|
||||||
|
</Tooltip>
|
||||||
|
{#if defaultPermissions?.features?.automations && !permissions.features.automations}
|
||||||
|
<div>
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
{$i18n.t('This is a default user permission and will remain enabled.')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class=" border-gray-100/30 dark:border-gray-850/30" />
|
<hr class=" border-gray-100/30 dark:border-gray-850/30" />
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import { showSettings, mobile, showSidebar, showShortcuts, user, config } from '$lib/stores';
|
import { showSettings, mobile, showSidebar, showShortcuts, user, config } from '$lib/stores';
|
||||||
|
|
||||||
|
|
||||||
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
||||||
|
|
||||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||||
@@ -214,6 +215,7 @@
|
|||||||
<div class=" self-center truncate">{$i18n.t('Settings')}</div>
|
<div class=" self-center truncate">{$i18n.t('Settings')}</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{#if $user?.role === 'admin' || $user?.permissions?.features?.automations}
|
||||||
<a
|
<a
|
||||||
href="/automations"
|
href="/automations"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
@@ -247,6 +249,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="self-center truncate">{$i18n.t('Automations')}</div>
|
<div class="self-center truncate">{$i18n.t('Automations')}</div>
|
||||||
</a>
|
</a>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ export const DEFAULT_PERMISSIONS = {
|
|||||||
web_search: true,
|
web_search: true,
|
||||||
image_generation: true,
|
image_generation: true,
|
||||||
code_interpreter: true,
|
code_interpreter: true,
|
||||||
memories: true
|
memories: true,
|
||||||
|
automations: false
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
interface: true
|
interface: true
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
import { onMount, onDestroy, getContext } from 'svelte';
|
import { onMount, onDestroy, getContext } from 'svelte';
|
||||||
|
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { WEBUI_NAME, mobile, showSidebar } from '$lib/stores';
|
import { goto } from '$app/navigation';
|
||||||
|
import { WEBUI_NAME, mobile, showSidebar, user, config } from '$lib/stores';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getAutomationItems,
|
getAutomationItems,
|
||||||
@@ -165,6 +166,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
if (
|
||||||
|
$user?.role !== 'admin' &&
|
||||||
|
!($user?.permissions?.features?.automations ?? false)
|
||||||
|
) {
|
||||||
|
goto('/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user