diff --git a/backend/open_webui/retrieval/utils.py b/backend/open_webui/retrieval/utils.py index 98e15d38e8..13f75175ea 100644 --- a/backend/open_webui/retrieval/utils.py +++ b/backend/open_webui/retrieval/utils.py @@ -47,6 +47,7 @@ from open_webui.retrieval.external import retrieve_external_knowledge from open_webui.retrieval.vector.factory import VECTOR_DB_CLIENT from open_webui.retrieval.vector.main import GetResult, SearchResult from open_webui.retrieval.web.utils import get_web_loader +from open_webui.utils.access_control.chats import has_chat_read_access from open_webui.utils.access_control.files import get_owner_accessible_folder_files, has_access_to_file from open_webui.utils.access_control.folders import has_folder_access from open_webui.utils.headers import include_user_info_headers @@ -1417,7 +1418,7 @@ async def get_sources_from_items( # Chat Attached chat = await Chats.get_chat_by_id(item.get('id')) - if chat and (user.role == 'admin' or chat.user_id == user.id): + if chat and await has_chat_read_access(user.id, user.role, chat): messages_map = chat.chat.get('history', {}).get('messages', {}) message_id = chat.chat.get('history', {}).get('currentId') diff --git a/backend/open_webui/utils/access_control/chats.py b/backend/open_webui/utils/access_control/chats.py new file mode 100644 index 0000000000..c082e59b14 --- /dev/null +++ b/backend/open_webui/utils/access_control/chats.py @@ -0,0 +1,31 @@ +from typing import Optional + +from open_webui.models.access_grants import AccessGrants +from open_webui.models.chats import ChatModel +from open_webui.models.folders import Folders +from open_webui.utils.access_control.folders import has_folder_access +from sqlalchemy.ext.asyncio import AsyncSession + + +async def has_chat_read_access( + user_id: str, user_role: str, chat: ChatModel, db: Optional[AsyncSession] = None +) -> bool: + """Check if a user can read a chat via ownership, admin role, an explicit share grant, or a shared folder.""" + if user_role == 'admin' or chat.user_id == user_id: + return True + + if await AccessGrants.has_access( + user_id=user_id, + resource_type='shared_chat', + resource_id=chat.id, + permission='read', + db=db, + ): + return True + + if chat.folder_id: + folder = await Folders.get_folder_by_id(chat.folder_id, db=db) + if folder and await has_folder_access(user_id, folder, 'read', db): + return True + + return False