diff --git a/backend/open_webui/models/chats.py b/backend/open_webui/models/chats.py index 1e5c60c5b4..901e115961 100644 --- a/backend/open_webui/models/chats.py +++ b/backend/open_webui/models/chats.py @@ -1793,6 +1793,13 @@ class ChatTable: result = await session.execute(stmt) return [meta for meta in result.scalars().all() if isinstance(meta, dict)] + async def get_owner_ids_by_chat_ids(self, chat_ids: list[str], db: AsyncSession | None = None) -> dict[str, str]: + if not chat_ids: + return {} + async with get_async_db_context(db) as session: + result = await session.execute(select(Chat.id, Chat.user_id).filter(Chat.id.in_(chat_ids))) + return dict(result.all()) + async def get_chats_by_model_id( self, model_id: str, diff --git a/backend/open_webui/socket/main.py b/backend/open_webui/socket/main.py index a535fb0f51..c8d4641745 100644 --- a/backend/open_webui/socket/main.py +++ b/backend/open_webui/socket/main.py @@ -622,12 +622,23 @@ async def refresh_chat_access(chat_id=None): access = {} chat_ids = set() for batch in get_session_pool_batches(): + chat_owner_ids: dict[str, str] = {} + if not chat_id: + # Owners keep access; role changes and deletion disconnect them separately. + open_chat_ids: set[str] = set() + for _, session in batch: + if not session: + continue + open_chat_ids.update(session.get('chat_ids') or []) + chat_owner_ids = await Chats.get_owner_ids_by_chat_ids(list(open_chat_ids)) for sid, session in batch: if not session: continue for cid in session.get('chat_ids') or []: if chat_id and cid != chat_id: continue + if chat_owner_ids.get(cid) == session['id']: + continue key = (cid, session['id']) if key not in access: user = await Users.get_user_by_id(session['id'])