From 7be750bcbb40da91912a0a66b7ab791effdcc3b6 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 20 Nov 2025 19:12:56 -0500 Subject: [PATCH] feat/enh: group share setting --- backend/open_webui/models/groups.py | 1 + backend/open_webui/routers/groups.py | 28 ++++++++++++----- src/lib/apis/groups/index.ts | 9 ++++-- .../admin/Users/Groups/EditGroupModal.svelte | 7 +++-- .../admin/Users/Groups/General.svelte | 31 ++++++++++++++++++- .../admin/Users/Groups/GroupItem.svelte | 4 +-- .../workspace/common/AccessControl.svelte | 2 +- 7 files changed, 65 insertions(+), 17 deletions(-) diff --git a/backend/open_webui/models/groups.py b/backend/open_webui/models/groups.py index faf2769a8a..1d96f5cfaa 100644 --- a/backend/open_webui/models/groups.py +++ b/backend/open_webui/models/groups.py @@ -101,6 +101,7 @@ class GroupForm(BaseModel): name: str description: str permissions: Optional[dict] = None + data: Optional[dict] = None class UserIdsForm(BaseModel): diff --git a/backend/open_webui/routers/groups.py b/backend/open_webui/routers/groups.py index 331c831153..2b531b462b 100755 --- a/backend/open_webui/routers/groups.py +++ b/backend/open_webui/routers/groups.py @@ -31,20 +31,32 @@ router = APIRouter() @router.get("/", response_model=list[GroupResponse]) -async def get_groups(user=Depends(get_verified_user)): +async def get_groups(share: Optional[bool] = None, user=Depends(get_verified_user)): if user.role == "admin": groups = Groups.get_groups() else: groups = Groups.get_groups_by_member_id(user.id) - return [ - GroupResponse( - **group.model_dump(), - member_count=Groups.get_group_member_count_by_id(group.id), + group_list = [] + + for group in groups: + if share is not None: + # Check if the group has data and a config with share key + if ( + group.data + and "share" in group.data.get("config", {}) + and group.data["config"]["share"] != share + ): + continue + + group_list.append( + GroupResponse( + **group.model_dump(), + member_count=Groups.get_group_member_count_by_id(group.id), + ) ) - for group in groups - if group - ] + + return group_list ############################ diff --git a/src/lib/apis/groups/index.ts b/src/lib/apis/groups/index.ts index 51b49bf4d9..a74c61b83d 100644 --- a/src/lib/apis/groups/index.ts +++ b/src/lib/apis/groups/index.ts @@ -31,10 +31,15 @@ export const createNewGroup = async (token: string, group: object) => { return res; }; -export const getGroups = async (token: string = '') => { +export const getGroups = async (token: string = '', share?: boolean) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/groups/`, { + const searchParams = new URLSearchParams(); + if (share !== undefined) { + searchParams.append('share', String(share)); + } + + const res = await fetch(`${WEBUI_API_BASE_URL}/groups/?${searchParams.toString()}`, { method: 'GET', headers: { Accept: 'application/json', diff --git a/src/lib/components/admin/Users/Groups/EditGroupModal.svelte b/src/lib/components/admin/Users/Groups/EditGroupModal.svelte index c90b834197..ef97294c96 100644 --- a/src/lib/components/admin/Users/Groups/EditGroupModal.svelte +++ b/src/lib/components/admin/Users/Groups/EditGroupModal.svelte @@ -34,7 +34,7 @@ export let name = ''; export let description = ''; - export let config = {}; + export let data = {}; export let permissions = { workspace: { @@ -98,6 +98,7 @@ const group = { name, description, + data, permissions }; @@ -112,7 +113,7 @@ name = group.name; description = group.description; permissions = group?.permissions ?? {}; - config = group?.data?.config ?? {}; + data = group?.data ?? {}; userCount = group?.member_count ?? 0; } @@ -246,7 +247,7 @@ { showDeleteConfirmDialog = true; diff --git a/src/lib/components/admin/Users/Groups/General.svelte b/src/lib/components/admin/Users/Groups/General.svelte index 727c1d9f16..ad365a994b 100644 --- a/src/lib/components/admin/Users/Groups/General.svelte +++ b/src/lib/components/admin/Users/Groups/General.svelte @@ -2,13 +2,14 @@ import { getContext } from 'svelte'; import Textarea from '$lib/components/common/Textarea.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte'; + import Switch from '$lib/components/common/Switch.svelte'; const i18n = getContext('i18n'); export let name = ''; export let color = ''; export let description = ''; - export let config = {}; + export let data = {}; export let edit = false; export let onDelete: Function = () => {}; @@ -64,6 +65,34 @@ +
+ +
+
{$i18n.t('Setting')}
+ +
+
+
+ {$i18n.t('Allow Group Sharing')} +
+ +
+ { + if (data?.config?.share) { + data.config.share = e.detail; + } else { + data.config = { ...(data?.config ?? {}), share: e.detail }; + } + }} + /> +
+
+
+
+ {#if edit}
{$i18n.t('Actions')}
diff --git a/src/lib/components/admin/Users/Groups/GroupItem.svelte b/src/lib/components/admin/Users/Groups/GroupItem.svelte index 47481655cb..8d4a761529 100644 --- a/src/lib/components/admin/Users/Groups/GroupItem.svelte +++ b/src/lib/components/admin/Users/Groups/GroupItem.svelte @@ -10,7 +10,7 @@ import Pencil from '$lib/components/icons/Pencil.svelte'; import User from '$lib/components/icons/User.svelte'; import UserCircleSolid from '$lib/components/icons/UserCircleSolid.svelte'; - import GroupModal from './EditGroupModal.svelte'; + import EditGroupModal from './EditGroupModal.svelte'; export let group = { name: 'Admins', @@ -54,7 +54,7 @@ }); - { - groups = await getGroups(localStorage.token); + groups = await getGroups(localStorage.token, true); if (accessControl === null) { initPublicAccess();