mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-12 04:15:25 +00:00
enh/feat: toggle folders & user perm
This commit is contained in:
parent
04b337323a
commit
457af65df6
9 changed files with 61 additions and 9 deletions
|
|
@ -1447,6 +1447,10 @@ USER_PERMISSIONS_FEATURES_CODE_INTERPRETER = (
|
||||||
== "true"
|
== "true"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
USER_PERMISSIONS_FEATURES_FOLDERS = (
|
||||||
|
os.environ.get("USER_PERMISSIONS_FEATURES_FOLDERS", "True").lower() == "true"
|
||||||
|
)
|
||||||
|
|
||||||
USER_PERMISSIONS_FEATURES_NOTES = (
|
USER_PERMISSIONS_FEATURES_NOTES = (
|
||||||
os.environ.get("USER_PERMISSIONS_FEATURES_NOTES", "True").lower() == "true"
|
os.environ.get("USER_PERMISSIONS_FEATURES_NOTES", "True").lower() == "true"
|
||||||
)
|
)
|
||||||
|
|
@ -1503,12 +1507,15 @@ DEFAULT_USER_PERMISSIONS = {
|
||||||
"temporary_enforced": USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED,
|
"temporary_enforced": USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED,
|
||||||
},
|
},
|
||||||
"features": {
|
"features": {
|
||||||
|
# General features
|
||||||
"api_keys": USER_PERMISSIONS_FEATURES_API_KEYS,
|
"api_keys": USER_PERMISSIONS_FEATURES_API_KEYS,
|
||||||
|
"folders": USER_PERMISSIONS_FEATURES_FOLDERS,
|
||||||
|
"notes": USER_PERMISSIONS_FEATURES_NOTES,
|
||||||
"direct_tool_servers": USER_PERMISSIONS_FEATURES_DIRECT_TOOL_SERVERS,
|
"direct_tool_servers": USER_PERMISSIONS_FEATURES_DIRECT_TOOL_SERVERS,
|
||||||
|
# Chat features
|
||||||
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
|
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
|
||||||
"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,
|
||||||
"notes": USER_PERMISSIONS_FEATURES_NOTES,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1518,6 +1525,12 @@ USER_PERMISSIONS = PersistentConfig(
|
||||||
DEFAULT_USER_PERMISSIONS,
|
DEFAULT_USER_PERMISSIONS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ENABLE_FOLDERS = PersistentConfig(
|
||||||
|
"ENABLE_FOLDERS",
|
||||||
|
"folders.enable",
|
||||||
|
os.environ.get("ENABLE_FOLDERS", "True").lower() == "true",
|
||||||
|
)
|
||||||
|
|
||||||
ENABLE_CHANNELS = PersistentConfig(
|
ENABLE_CHANNELS = PersistentConfig(
|
||||||
"ENABLE_CHANNELS",
|
"ENABLE_CHANNELS",
|
||||||
"channels.enable",
|
"channels.enable",
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,7 @@ from open_webui.config import (
|
||||||
ENABLE_API_KEYS,
|
ENABLE_API_KEYS,
|
||||||
ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS,
|
ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS,
|
||||||
API_KEYS_ALLOWED_ENDPOINTS,
|
API_KEYS_ALLOWED_ENDPOINTS,
|
||||||
|
ENABLE_FOLDERS,
|
||||||
ENABLE_CHANNELS,
|
ENABLE_CHANNELS,
|
||||||
ENABLE_NOTES,
|
ENABLE_NOTES,
|
||||||
ENABLE_COMMUNITY_SHARING,
|
ENABLE_COMMUNITY_SHARING,
|
||||||
|
|
@ -767,6 +768,7 @@ app.state.config.WEBHOOK_URL = WEBHOOK_URL
|
||||||
app.state.config.BANNERS = WEBUI_BANNERS
|
app.state.config.BANNERS = WEBUI_BANNERS
|
||||||
|
|
||||||
|
|
||||||
|
app.state.config.ENABLE_FOLDERS = ENABLE_FOLDERS
|
||||||
app.state.config.ENABLE_CHANNELS = ENABLE_CHANNELS
|
app.state.config.ENABLE_CHANNELS = ENABLE_CHANNELS
|
||||||
app.state.config.ENABLE_NOTES = ENABLE_NOTES
|
app.state.config.ENABLE_NOTES = ENABLE_NOTES
|
||||||
app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
|
app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
|
||||||
|
|
@ -1842,6 +1844,7 @@ async def get_app_config(request: Request):
|
||||||
**(
|
**(
|
||||||
{
|
{
|
||||||
"enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
"enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
||||||
|
"enable_folders": app.state.config.ENABLE_FOLDERS,
|
||||||
"enable_channels": app.state.config.ENABLE_CHANNELS,
|
"enable_channels": app.state.config.ENABLE_CHANNELS,
|
||||||
"enable_notes": app.state.config.ENABLE_NOTES,
|
"enable_notes": app.state.config.ENABLE_NOTES,
|
||||||
"enable_web_search": app.state.config.ENABLE_WEB_SEARCH,
|
"enable_web_search": app.state.config.ENABLE_WEB_SEARCH,
|
||||||
|
|
|
||||||
|
|
@ -900,6 +900,7 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)):
|
||||||
"JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN,
|
"JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN,
|
||||||
"ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING,
|
"ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING,
|
||||||
"ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING,
|
"ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING,
|
||||||
|
"ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS,
|
||||||
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
||||||
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
||||||
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
||||||
|
|
@ -921,6 +922,7 @@ class AdminConfig(BaseModel):
|
||||||
JWT_EXPIRES_IN: str
|
JWT_EXPIRES_IN: str
|
||||||
ENABLE_COMMUNITY_SHARING: bool
|
ENABLE_COMMUNITY_SHARING: bool
|
||||||
ENABLE_MESSAGE_RATING: bool
|
ENABLE_MESSAGE_RATING: bool
|
||||||
|
ENABLE_FOLDERS: bool
|
||||||
ENABLE_CHANNELS: bool
|
ENABLE_CHANNELS: bool
|
||||||
ENABLE_NOTES: bool
|
ENABLE_NOTES: bool
|
||||||
ENABLE_USER_WEBHOOKS: bool
|
ENABLE_USER_WEBHOOKS: bool
|
||||||
|
|
@ -945,6 +947,7 @@ async def update_admin_config(
|
||||||
form_data.API_KEYS_ALLOWED_ENDPOINTS
|
form_data.API_KEYS_ALLOWED_ENDPOINTS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
request.app.state.config.ENABLE_FOLDERS = form_data.ENABLE_FOLDERS
|
||||||
request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS
|
request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS
|
||||||
request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES
|
request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES
|
||||||
|
|
||||||
|
|
@ -987,6 +990,7 @@ async def update_admin_config(
|
||||||
"JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN,
|
"JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN,
|
||||||
"ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING,
|
"ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING,
|
||||||
"ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING,
|
"ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING,
|
||||||
|
"ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS,
|
||||||
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
||||||
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
||||||
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,23 @@ router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", response_model=list[FolderNameIdResponse])
|
@router.get("/", response_model=list[FolderNameIdResponse])
|
||||||
async def get_folders(user=Depends(get_verified_user)):
|
async def get_folders(request: Request, user=Depends(get_verified_user)):
|
||||||
|
if request.app.state.config.ENABLE_FOLDERS is False:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
|
if user.role != "admin" and not has_permission(
|
||||||
|
user.id,
|
||||||
|
"features.folders",
|
||||||
|
request.app.state.config.USER_PERMISSIONS,
|
||||||
|
):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
folders = Folders.get_folders_by_user_id(user.id)
|
folders = Folders.get_folders_by_user_id(user.id)
|
||||||
|
|
||||||
# Verify folder data integrity
|
# Verify folder data integrity
|
||||||
|
|
|
||||||
|
|
@ -219,11 +219,13 @@ class ChatPermissions(BaseModel):
|
||||||
|
|
||||||
class FeaturesPermissions(BaseModel):
|
class FeaturesPermissions(BaseModel):
|
||||||
api_keys: bool = False
|
api_keys: bool = False
|
||||||
|
folders: bool = True
|
||||||
|
notes: bool = True
|
||||||
direct_tool_servers: bool = False
|
direct_tool_servers: bool = False
|
||||||
|
|
||||||
web_search: bool = True
|
web_search: bool = True
|
||||||
image_generation: bool = True
|
image_generation: bool = True
|
||||||
code_interpreter: bool = True
|
code_interpreter: bool = True
|
||||||
notes: bool = True
|
|
||||||
|
|
||||||
|
|
||||||
class UserPermissions(BaseModel):
|
class UserPermissions(BaseModel):
|
||||||
|
|
|
||||||
|
|
@ -676,6 +676,14 @@
|
||||||
<Switch bind:state={adminConfig.ENABLE_MESSAGE_RATING} />
|
<Switch bind:state={adminConfig.ENABLE_MESSAGE_RATING} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2.5 flex w-full items-center justify-between pr-2">
|
||||||
|
<div class=" self-center text-xs font-medium">
|
||||||
|
{$i18n.t('Folders')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Switch bind:state={adminConfig.ENABLE_FOLDERS} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-2.5 flex w-full items-center justify-between pr-2">
|
<div class="mb-2.5 flex w-full items-center justify-between pr-2">
|
||||||
<div class=" self-center text-xs font-medium">
|
<div class=" self-center text-xs font-medium">
|
||||||
{$i18n.t('Notes')} ({$i18n.t('Beta')})
|
{$i18n.t('Notes')} ({$i18n.t('Beta')})
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,12 @@
|
||||||
},
|
},
|
||||||
features: {
|
features: {
|
||||||
api_keys: false,
|
api_keys: false,
|
||||||
|
folders: true,
|
||||||
|
notes: true,
|
||||||
direct_tool_servers: false,
|
direct_tool_servers: false,
|
||||||
web_search: true,
|
web_search: true,
|
||||||
image_generation: true,
|
image_generation: true,
|
||||||
code_interpreter: true,
|
code_interpreter: true
|
||||||
notes: true
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,12 @@
|
||||||
},
|
},
|
||||||
features: {
|
features: {
|
||||||
api_keys: false,
|
api_keys: false,
|
||||||
|
folders: true,
|
||||||
|
notes: true,
|
||||||
direct_tool_servers: false,
|
direct_tool_servers: false,
|
||||||
web_search: true,
|
web_search: true,
|
||||||
image_generation: true,
|
image_generation: true,
|
||||||
code_interpreter: true,
|
code_interpreter: true
|
||||||
notes: true
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
import Note from '../icons/Note.svelte';
|
import Note from '../icons/Note.svelte';
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
import HotkeyHint from '../common/HotkeyHint.svelte';
|
import HotkeyHint from '../common/HotkeyHint.svelte';
|
||||||
|
import { key } from 'vega';
|
||||||
|
|
||||||
const BREAKPOINT = 768;
|
const BREAKPOINT = 768;
|
||||||
|
|
||||||
|
|
@ -90,8 +91,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const initFolders = async () => {
|
const initFolders = async () => {
|
||||||
|
if ($config?.features?.enable_folders === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const folderList = await getFolders(localStorage.token).catch((error) => {
|
const folderList = await getFolders(localStorage.token).catch((error) => {
|
||||||
toast.error(`${error}`);
|
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
_folders.set(folderList.sort((a, b) => b.updated_at - a.updated_at));
|
_folders.set(folderList.sort((a, b) => b.updated_at - a.updated_at));
|
||||||
|
|
@ -932,7 +936,7 @@
|
||||||
</Folder>
|
</Folder>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if folders}
|
{#if $config?.features?.enable_folders && ($user?.role === 'admin' || ($user?.permissions?.features?.folders ?? true)) && Object.keys(folders).length > 0}
|
||||||
<Folder
|
<Folder
|
||||||
id="sidebar-folders"
|
id="sidebar-folders"
|
||||||
className="px-2 mt-0.5"
|
className="px-2 mt-0.5"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue