diff --git a/backend/open_webui/routers/knowledge.py b/backend/open_webui/routers/knowledge.py index eab00aa19..e60c30cb6 100644 --- a/backend/open_webui/routers/knowledge.py +++ b/backend/open_webui/routers/knowledge.py @@ -511,6 +511,7 @@ class KnowledgeAccessGrantsForm(BaseModel): @router.post("/{id}/access/update", response_model=Optional[KnowledgeFilesResponse]) async def update_knowledge_access_by_id( + request: Request, id: str, form_data: KnowledgeAccessGrantsForm, user=Depends(get_verified_user), @@ -539,6 +540,24 @@ async def update_knowledge_access_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) + # Strip public sharing if user lacks permission + if ( + user.role != "admin" + and has_public_read_access_grant(form_data.access_grants) + and not has_permission( + user.id, + "sharing.public_knowledge", + request.app.state.config.USER_PERMISSIONS, + ) + ): + form_data.access_grants = [ + g for g in form_data.access_grants + if not ( + g.get("principal_type") == "user" + and g.get("principal_id") == "*" + ) + ] + AccessGrants.set_access_grants("knowledge", id, form_data.access_grants, db=db) return KnowledgeFilesResponse( diff --git a/backend/open_webui/routers/models.py b/backend/open_webui/routers/models.py index 7202262bb..666b7ced2 100644 --- a/backend/open_webui/routers/models.py +++ b/backend/open_webui/routers/models.py @@ -15,7 +15,7 @@ from open_webui.models.models import ( ModelAccessResponse, Models, ) -from open_webui.models.access_grants import AccessGrants +from open_webui.models.access_grants import AccessGrants, has_public_read_access_grant from pydantic import BaseModel from open_webui.constants import ERROR_MESSAGES @@ -506,6 +506,7 @@ class ModelAccessGrantsForm(BaseModel): @router.post("/model/access/update", response_model=Optional[ModelModel]) async def update_model_access_by_id( + request: Request, form_data: ModelAccessGrantsForm, user=Depends(get_verified_user), db: Session = Depends(get_session), @@ -533,6 +534,24 @@ async def update_model_access_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) + # Strip public sharing if user lacks permission + if ( + user.role != "admin" + and has_public_read_access_grant(form_data.access_grants) + and not has_permission( + user.id, + "sharing.public_models", + request.app.state.config.USER_PERMISSIONS, + ) + ): + form_data.access_grants = [ + g for g in form_data.access_grants + if not ( + g.get("principal_type") == "user" + and g.get("principal_id") == "*" + ) + ] + AccessGrants.set_access_grants( "model", form_data.id, form_data.access_grants, db=db ) diff --git a/backend/open_webui/routers/notes.py b/backend/open_webui/routers/notes.py index 04841e87c..0c4ca0d2e 100644 --- a/backend/open_webui/routers/notes.py +++ b/backend/open_webui/routers/notes.py @@ -345,6 +345,24 @@ async def update_note_access_by_id( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT() ) + # Strip public sharing if user lacks permission + if ( + user.role != "admin" + and has_public_read_access_grant(form_data.access_grants) + and not has_permission( + user.id, + "sharing.public_notes", + request.app.state.config.USER_PERMISSIONS, + ) + ): + form_data.access_grants = [ + g for g in form_data.access_grants + if not ( + g.get("principal_type") == "user" + and g.get("principal_id") == "*" + ) + ] + AccessGrants.set_access_grants("note", id, form_data.access_grants, db=db) return Notes.get_note_by_id(id, db=db) diff --git a/backend/open_webui/routers/prompts.py b/backend/open_webui/routers/prompts.py index e8d4660f0..8720ba1aa 100644 --- a/backend/open_webui/routers/prompts.py +++ b/backend/open_webui/routers/prompts.py @@ -9,7 +9,7 @@ from open_webui.models.prompts import ( PromptModel, Prompts, ) -from open_webui.models.access_grants import AccessGrants +from open_webui.models.access_grants import AccessGrants, has_public_read_access_grant from open_webui.models.groups import Groups from open_webui.models.prompt_history import ( PromptHistories, @@ -436,6 +436,7 @@ class PromptAccessGrantsForm(BaseModel): @router.post("/id/{prompt_id}/access/update", response_model=Optional[PromptModel]) async def update_prompt_access_by_id( + request: Request, prompt_id: str, form_data: PromptAccessGrantsForm, user=Depends(get_verified_user), @@ -464,6 +465,24 @@ async def update_prompt_access_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) + # Strip public sharing if user lacks permission + if ( + user.role != "admin" + and has_public_read_access_grant(form_data.access_grants) + and not has_permission( + user.id, + "sharing.public_prompts", + request.app.state.config.USER_PERMISSIONS, + ) + ): + form_data.access_grants = [ + g for g in form_data.access_grants + if not ( + g.get("principal_type") == "user" + and g.get("principal_id") == "*" + ) + ] + AccessGrants.set_access_grants("prompt", prompt_id, form_data.access_grants, db=db) return Prompts.get_prompt_by_id(prompt_id, db=db) diff --git a/backend/open_webui/routers/skills.py b/backend/open_webui/routers/skills.py index 367768e61..a9a17f147 100644 --- a/backend/open_webui/routers/skills.py +++ b/backend/open_webui/routers/skills.py @@ -17,7 +17,7 @@ from open_webui.models.skills import ( SkillAccessListResponse, Skills, ) -from open_webui.models.access_grants import AccessGrants +from open_webui.models.access_grants import AccessGrants, has_public_read_access_grant from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.access_control import has_access, has_permission @@ -312,6 +312,7 @@ class SkillAccessGrantsForm(BaseModel): @router.post("/id/{id}/access/update", response_model=Optional[SkillModel]) async def update_skill_access_by_id( + request: Request, id: str, form_data: SkillAccessGrantsForm, user=Depends(get_verified_user), @@ -340,6 +341,24 @@ async def update_skill_access_by_id( detail=ERROR_MESSAGES.UNAUTHORIZED, ) + # Strip public sharing if user lacks permission + if ( + user.role != "admin" + and has_public_read_access_grant(form_data.access_grants) + and not has_permission( + user.id, + "sharing.public_skills", + request.app.state.config.USER_PERMISSIONS, + ) + ): + form_data.access_grants = [ + g for g in form_data.access_grants + if not ( + g.get("principal_type") == "user" + and g.get("principal_id") == "*" + ) + ] + AccessGrants.set_access_grants("skill", id, form_data.access_grants, db=db) return Skills.get_skill_by_id(id, db=db) diff --git a/backend/open_webui/routers/tools.py b/backend/open_webui/routers/tools.py index 057eb509a..81194c2f4 100644 --- a/backend/open_webui/routers/tools.py +++ b/backend/open_webui/routers/tools.py @@ -21,7 +21,7 @@ from open_webui.models.tools import ( ToolAccessResponse, Tools, ) -from open_webui.models.access_grants import AccessGrants +from open_webui.models.access_grants import AccessGrants, has_public_read_access_grant from open_webui.utils.plugin import ( load_tool_module_by_id, replace_imports, @@ -526,6 +526,7 @@ class ToolAccessGrantsForm(BaseModel): @router.post("/id/{id}/access/update", response_model=Optional[ToolModel]) async def update_tool_access_by_id( + request: Request, id: str, form_data: ToolAccessGrantsForm, user=Depends(get_verified_user), @@ -554,6 +555,24 @@ async def update_tool_access_by_id( detail=ERROR_MESSAGES.UNAUTHORIZED, ) + # Strip public sharing if user lacks permission + if ( + user.role != "admin" + and has_public_read_access_grant(form_data.access_grants) + and not has_permission( + user.id, + "sharing.public_tools", + request.app.state.config.USER_PERMISSIONS, + ) + ): + form_data.access_grants = [ + g for g in form_data.access_grants + if not ( + g.get("principal_type") == "user" + and g.get("principal_id") == "*" + ) + ] + AccessGrants.set_access_grants("tool", id, form_data.access_grants, db=db) return Tools.get_tool_by_id(id, db=db) diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte index 50b443033..58bb6203c 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte @@ -837,8 +837,7 @@ bind:accessGrants={knowledge.access_grants} share={$user?.permissions?.sharing?.knowledge || $user?.role === 'admin'} sharePublic={$user?.permissions?.sharing?.public_knowledge || - $user?.role === 'admin' || - knowledge?.write_access} + $user?.role === 'admin'} onChange={async () => { try { await updateKnowledgeAccessGrants(localStorage.token, id, knowledge.access_grants ?? []); diff --git a/src/lib/components/workspace/Models/ModelEditor.svelte b/src/lib/components/workspace/Models/ModelEditor.svelte index 05d17ddaf..80abd6544 100644 --- a/src/lib/components/workspace/Models/ModelEditor.svelte +++ b/src/lib/components/workspace/Models/ModelEditor.svelte @@ -342,7 +342,7 @@ bind:accessGrants accessRoles={preset ? ['read', 'write'] : ['read']} share={$user?.permissions?.sharing?.models || $user?.role === 'admin'} - sharePublic={$user?.permissions?.sharing?.public_models || $user?.role === 'admin' || edit} + sharePublic={$user?.permissions?.sharing?.public_models || $user?.role === 'admin'} onChange={async () => { if (edit && model?.id) { try { diff --git a/src/lib/components/workspace/Prompts/PromptEditor.svelte b/src/lib/components/workspace/Prompts/PromptEditor.svelte index 288d674c0..118575d1f 100644 --- a/src/lib/components/workspace/Prompts/PromptEditor.svelte +++ b/src/lib/components/workspace/Prompts/PromptEditor.svelte @@ -282,7 +282,7 @@ bind:accessGrants accessRoles={['read', 'write']} share={$user?.permissions?.sharing?.prompts || $user?.role === 'admin'} - sharePublic={$user?.permissions?.sharing?.public_prompts || $user?.role === 'admin' || edit} + sharePublic={$user?.permissions?.sharing?.public_prompts || $user?.role === 'admin'} onChange={async () => { if (edit && prompt?.id) { try { diff --git a/src/lib/components/workspace/Skills/SkillEditor.svelte b/src/lib/components/workspace/Skills/SkillEditor.svelte index 1e63ff0c0..2670337b0 100644 --- a/src/lib/components/workspace/Skills/SkillEditor.svelte +++ b/src/lib/components/workspace/Skills/SkillEditor.svelte @@ -113,7 +113,7 @@ bind:accessGrants accessRoles={['read', 'write']} share={$user?.permissions?.sharing?.skills || $user?.role === 'admin'} - sharePublic={$user?.permissions?.sharing?.public_skills || $user?.role === 'admin' || edit} + sharePublic={$user?.permissions?.sharing?.public_skills || $user?.role === 'admin'} onChange={async () => { if (edit && skill?.id) { try { diff --git a/src/lib/components/workspace/Tools/ToolkitEditor.svelte b/src/lib/components/workspace/Tools/ToolkitEditor.svelte index 4822ebbf8..c73d47a79 100644 --- a/src/lib/components/workspace/Tools/ToolkitEditor.svelte +++ b/src/lib/components/workspace/Tools/ToolkitEditor.svelte @@ -192,7 +192,7 @@ class Tools: bind:accessGrants accessRoles={['read', 'write']} share={$user?.permissions?.sharing?.tools || $user?.role === 'admin'} - sharePublic={$user?.permissions?.sharing?.public_tools || $user?.role === 'admin' || edit} + sharePublic={$user?.permissions?.sharing?.public_tools || $user?.role === 'admin'} onChange={async () => { if (edit && id) { try {