From 240c91e79d9a3577332c030a4b46059859f787d8 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 16 Nov 2024 01:24:34 -0800 Subject: [PATCH] wip: access control --- .../open_webui/apps/webui/routers/groups.py | 7 +- .../open_webui/apps/webui/routers/users.py | 22 ++- backend/open_webui/main.py | 22 ++- src/lib/apis/users/index.ts | 38 ++++- .../components/admin/Settings/Users.svelte | 6 +- src/lib/components/admin/Users/Groups.svelte | 6 +- .../chat/ModelSelector/Selector.svelte | 33 ++-- src/lib/components/workspace/Models.svelte | 2 +- .../workspace/Models/ModelEditor.svelte | 8 +- .../workspace/common/AccessControl.svelte | 157 +++++++++++++----- 10 files changed, 212 insertions(+), 89 deletions(-) diff --git a/backend/open_webui/apps/webui/routers/groups.py b/backend/open_webui/apps/webui/routers/groups.py index 984cece57..59d7d0052 100644 --- a/backend/open_webui/apps/webui/routers/groups.py +++ b/backend/open_webui/apps/webui/routers/groups.py @@ -22,8 +22,11 @@ router = APIRouter() @router.get("/", response_model=list[GroupResponse]) -async def get_groups(user=Depends(get_admin_user)): - return Groups.get_groups() +async def get_groups(user=Depends(get_verified_user)): + if user.role == "admin": + return Groups.get_groups() + else: + return Groups.get_groups_by_member_id(user.id) ############################ diff --git a/backend/open_webui/apps/webui/routers/users.py b/backend/open_webui/apps/webui/routers/users.py index 3cd7166ad..a4e21a5d7 100644 --- a/backend/open_webui/apps/webui/routers/users.py +++ b/backend/open_webui/apps/webui/routers/users.py @@ -31,11 +31,29 @@ async def get_users(skip: int = 0, limit: int = 50, user=Depends(get_admin_user) return Users.get_users(skip, limit) +############################ +# User Groups +############################ + + +@router.get("/groups") +async def get_user_groups(user=Depends(get_verified_user)): + return Users.get_user_groups(user.id) + + ############################ # User Permissions ############################ +@router.get("/permissions") +async def get_user_permissisions(user=Depends(get_verified_user)): + return Users.get_user_groups(user.id) + + +############################ +# User Default Permissions +############################ class WorkspacePermissions(BaseModel): models: bool knowledge: bool @@ -54,12 +72,12 @@ class UserPermissions(BaseModel): chat: ChatPermissions -@router.get("/permissions") +@router.get("/default/permissions") async def get_user_permissions(request: Request, user=Depends(get_admin_user)): return request.app.state.config.USER_PERMISSIONS -@router.post("/permissions") +@router.post("/default/permissions") async def update_user_permissions( request: Request, form_data: UserPermissions, user=Depends(get_admin_user) ): diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index a0311a6cb..9deb3a5cb 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -967,15 +967,23 @@ async def get_all_models(): custom_model.id == model["id"] or custom_model.id == model["id"].split(":")[0] ): - model["name"] = custom_model.name - model["info"] = custom_model.model_dump() + if custom_model.is_active: + model["name"] = custom_model.name + model["info"] = custom_model.model_dump() - action_ids = [] - if "info" in model and "meta" in model["info"]: - action_ids.extend(model["info"]["meta"].get("actionIds", [])) + action_ids = [] + if "info" in model and "meta" in model["info"]: + action_ids.extend( + model["info"]["meta"].get("actionIds", []) + ) - model["action_ids"] = action_ids - elif custom_model.id not in [model["id"] for model in models]: + model["action_ids"] = action_ids + else: + models.remove(model) + + elif custom_model.is_active and ( + custom_model.id not in [model["id"] for model in models] + ): owned_by = "openai" pipe = None action_ids = [] diff --git a/src/lib/apis/users/index.ts b/src/lib/apis/users/index.ts index 4ae440ed7..5c95c7cdf 100644 --- a/src/lib/apis/users/index.ts +++ b/src/lib/apis/users/index.ts @@ -1,10 +1,11 @@ import { WEBUI_API_BASE_URL } from '$lib/constants'; import { getUserPosition } from '$lib/utils'; -export const getUserPermissions = async (token: string) => { + +export const getUserGroups = async (token: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/users/permissions`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/users/groups`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -28,10 +29,39 @@ export const getUserPermissions = async (token: string) => { return res; }; -export const updateUserPermissions = async (token: string, permissions: object) => { + + +export const getUserDefaultPermissions = async (token: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/users/permissions`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/users/default/permissions`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateUserDefaultPermissions = async (token: string, permissions: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/users/default/permissions`, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/src/lib/components/admin/Settings/Users.svelte b/src/lib/components/admin/Settings/Users.svelte index 20f13bb9d..a0ec10780 100644 --- a/src/lib/components/admin/Settings/Users.svelte +++ b/src/lib/components/admin/Settings/Users.svelte @@ -1,7 +1,7 @@ -
+
{$i18n.t('Visibility')}
-
+
-
- {#if access === 'private'} +
+ {#if privateAccess} - - + +
- {#if access === 'private'} + {#if privateAccess} {$i18n.t('Only select users and groups with permission can access')} - {:else if access === 'public'} + {:else} {$i18n.t('Accessible to all users')} {/if}
@@ -80,37 +100,90 @@
- {#if access === 'private'} + {#if privateAccess} + {@const accessGroups = groups.filter((group) => + accessControl.read.group_ids.includes(group.id) + )}
-
{$i18n.t('People with access')}
+
+
+
+ {$i18n.t('Groups')} +
+
-
-
-
-
- - - +
+ {#if accessGroups.length > 0} + {#each accessGroups as group} +
+
+
+ +
+ +
+ {group.name} +
+
+ +
+ +
+
+ {/each} + {:else} +
+
+ {$i18n.t('No groups with access, add a group to grant access')} +
+
+ {/if} +
+
+ +
+ +
+
+
+
+
-
- +