Browse Source

Merge pull request #8470 from tarmst/add-read-write-toggle-to-access-control

feat: Add toggle to read/write perms on access control
Timothy Jaeryang Baek 3 months ago
parent
commit
f6a54c96bc

+ 2 - 2
backend/open_webui/routers/knowledge.py

@@ -213,8 +213,8 @@ async def update_knowledge_by_id(
             status_code=status.HTTP_400_BAD_REQUEST,
             detail=ERROR_MESSAGES.NOT_FOUND,
         )
-
-    if knowledge.user_id != user.id and user.role != "admin":
+    # Is the user the original creator, in a group with write access, or an admin
+    if knowledge.user_id != user.id and not has_access(user.id, "write", knowledge.access_control) and user.role != "admin":
         raise HTTPException(
             status_code=status.HTTP_400_BAD_REQUEST,
             detail=ERROR_MESSAGES.ACCESS_PROHIBITED,

+ 3 - 2
backend/open_webui/routers/prompts.py

@@ -111,8 +111,9 @@ async def update_prompt_by_command(
             status_code=status.HTTP_401_UNAUTHORIZED,
             detail=ERROR_MESSAGES.NOT_FOUND,
         )
-
-    if prompt.user_id != user.id and user.role != "admin":
+    
+    # Is the user the original creator, in a group with write access, or an admin
+    if prompt.user_id != user.id and not has_access(user.id, "write", prompt.access_control) and user.role != "admin":
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED,
             detail=ERROR_MESSAGES.ACCESS_PROHIBITED,

+ 2 - 1
backend/open_webui/routers/tools.py

@@ -165,7 +165,8 @@ async def update_tools_by_id(
             detail=ERROR_MESSAGES.NOT_FOUND,
         )
 
-    if tools.user_id != user.id and user.role != "admin":
+    # Is the user the original creator, in a group with write access, or an admin
+    if tools.user_id != user.id and not has_access(user.id, "write", tools.access_control) and user.role != "admin":
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED,
             detail=ERROR_MESSAGES.UNAUTHORIZED,

+ 7 - 1
src/lib/components/workspace/Models.svelte

@@ -21,6 +21,7 @@
 	} from '$lib/apis/models';
 
 	import { getModels } from '$lib/apis';
+	import { getGroups } from '$lib/apis/groups';
 
 	import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte';
 	import ModelMenu from './Models/ModelMenu.svelte';
@@ -47,6 +48,8 @@
 
 	let showModelDeleteConfirm = false;
 
+	let group_ids = [];
+
 	$: if (models) {
 		filteredModels = models.filter(
 			(m) => searchValue === '' || m.name.toLowerCase().includes(searchValue.toLowerCase())
@@ -151,6 +154,9 @@
 
 	onMount(async () => {
 		models = await getWorkspaceModels(localStorage.token);
+		let groups = await getGroups(localStorage.token);
+		group_ids = groups.map(group => group.id);
+		
 
 		loaded = true;
 
@@ -308,7 +314,7 @@
 								</button>
 							</Tooltip>
 						{:else}
-							{#if $user?.role === 'admin' || model.user_id === $user?.id}
+							{#if $user?.role === 'admin' || model.user_id === $user?.id || model.access_control.write.group_ids.some(wg => group_ids.includes(wg))} 
 								<a
 									class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 									type="button"

+ 25 - 1
src/lib/components/workspace/common/AccessControl.svelte

@@ -8,6 +8,7 @@
 	import Plus from '$lib/components/icons/Plus.svelte';
 	import UserCircleSolid from '$lib/components/icons/UserCircleSolid.svelte';
 	import XMark from '$lib/components/icons/XMark.svelte';
+	import Badge from '$lib/components/common/Badge.svelte';
 
 	export let onChange: Function = () => {};
 
@@ -91,6 +92,9 @@
 							accessControl = {
 								read: {
 									group_ids: []
+								},
+								write: {
+									group_ids: []
 								}
 							};
 						}
@@ -110,7 +114,6 @@
 			</div>
 		</div>
 	</div>
-
 	{#if accessControl !== null}
 		{@const accessGroups = groups.filter((group) =>
 			accessControl.read.group_ids.includes(group.id)
@@ -138,6 +141,27 @@
 								</div>
 
 								<div class="w-full flex justify-end">
+									<button
+										class=" translate-y-0.5"
+										type="button"
+										on:click={() => {
+											if (accessControl.write.group_ids.includes(group.id)) {
+												accessControl.write.group_ids = accessControl.write.group_ids.filter(
+													(group_id) => group_id !== group.id)
+											} else {
+												accessControl.write.group_ids = [
+												...accessControl.write.group_ids,
+												group.id
+												];
+											}
+										}}
+									>
+									<Badge	
+										type={accessControl.write.group_ids.includes(group.id) ? 'info' : 'success'}
+										content={$i18n.t(accessControl.write.group_ids.includes(group.id) ? "Write" : "Read")}
+									/>
+									</button>
+
 									<button
 										class=" rounded-full p-1 hover:bg-gray-100 dark:hover:bg-gray-850 transition"
 										type="button"