From 1f059fe7307eb7cda6c9d3af5423ed6c67da3aa6 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Mon, 5 Jan 2026 01:36:13 +0100 Subject: [PATCH] feat: Prompts Atomic PR of #20243 (#20368) * feat: Add read-only access support for Prompts - Backend: Add write_access field to PromptAccessResponse - Backend: Update /prompts/list to return prompts with write_access - Frontend: Display Read Only badge in Prompts list - Frontend: Disable inputs and save button when no write access * feat: Add read-only visual indicators for Prompts workspace * fix: Return write_access from getPromptByCommand endpoint - Backend returns write_access directly in response - Frontend extracts write_access from getPromptByCommand response - Remove inefficient getPromptList call in edit page * fix: Align Read Only badge to right in Prompts.svelte - Title and command stay on left - Badge pushed to right by justify-between * fix: Use PromptAccessResponse in get_prompt_by_command endpoint fix: Use PromptAccessResponse in get_prompt_by_command endpoint - Return PromptAccessResponse Pydantic model instead of raw dict - Properly type the response with response_model --- backend/open_webui/models/prompts.py | 4 + backend/open_webui/routers/prompts.py | 33 ++++++--- src/lib/components/workspace/Prompts.svelte | 14 +++- .../workspace/Prompts/PromptEditor.svelte | 74 +++++++++++-------- .../(app)/workspace/prompts/edit/+page.svelte | 5 +- 5 files changed, 85 insertions(+), 45 deletions(-) diff --git a/backend/open_webui/models/prompts.py b/backend/open_webui/models/prompts.py index eefb74de5..89c49ccc8 100644 --- a/backend/open_webui/models/prompts.py +++ b/backend/open_webui/models/prompts.py @@ -64,6 +64,10 @@ class PromptUserResponse(PromptModel): user: Optional[UserResponse] = None +class PromptAccessResponse(PromptUserResponse): + write_access: Optional[bool] = False + + class PromptForm(BaseModel): command: str title: str diff --git a/backend/open_webui/routers/prompts.py b/backend/open_webui/routers/prompts.py index 70f9f71e5..645cfe83a 100644 --- a/backend/open_webui/routers/prompts.py +++ b/backend/open_webui/routers/prompts.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, Depends, HTTPException, status, Request from open_webui.models.prompts import ( PromptForm, PromptUserResponse, + PromptAccessResponse, PromptModel, Prompts, ) @@ -31,14 +32,24 @@ async def get_prompts(user=Depends(get_verified_user), db: Session = Depends(get return prompts -@router.get("/list", response_model=list[PromptUserResponse]) +@router.get("/list", response_model=list[PromptAccessResponse]) async def get_prompt_list(user=Depends(get_verified_user), db: Session = Depends(get_session)): if user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL: prompts = Prompts.get_prompts(db=db) else: - prompts = Prompts.get_prompts_by_user_id(user.id, "write", db=db) + prompts = Prompts.get_prompts_by_user_id(user.id, "read", db=db) - return prompts + return [ + PromptAccessResponse( + **prompt.model_dump(), + write_access=( + (user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL) + or user.id == prompt.user_id + or has_access(user.id, "write", prompt.access_control, db=db) + ), + ) + for prompt in prompts + ] ############################ @@ -87,7 +98,7 @@ async def create_new_prompt( ############################ -@router.get("/command/{command}", response_model=Optional[PromptModel]) +@router.get("/command/{command}", response_model=Optional[PromptAccessResponse]) async def get_prompt_by_command(command: str, user=Depends(get_verified_user), db: Session = Depends(get_session)): prompt = Prompts.get_prompt_by_command(f"/{command}", db=db) @@ -97,15 +108,17 @@ async def get_prompt_by_command(command: str, user=Depends(get_verified_user), d or prompt.user_id == user.id or has_access(user.id, "read", prompt.access_control, db=db) ): - return prompt - else: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + return PromptAccessResponse( + **prompt.model_dump(), + write_access=( + (user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL) + or user.id == prompt.user_id + or has_access(user.id, "write", prompt.access_control, db=db) + ), ) else: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, + status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.NOT_FOUND, ) diff --git a/src/lib/components/workspace/Prompts.svelte b/src/lib/components/workspace/Prompts.svelte index 446c29f7e..c95dd1dba 100644 --- a/src/lib/components/workspace/Prompts.svelte +++ b/src/lib/components/workspace/Prompts.svelte @@ -26,6 +26,7 @@ import XMark from '../icons/XMark.svelte'; import GarbageBin from '../icons/GarbageBin.svelte'; import ViewSelector from './common/ViewSelector.svelte'; + import Badge from '$lib/components/common/Badge.svelte'; let shiftKey = false; @@ -327,11 +328,16 @@ href={`/workspace/prompts/edit?command=${encodeURIComponent(prompt.command)}`} >