diff --git a/backend/open_webui/models/knowledge.py b/backend/open_webui/models/knowledge.py index 544eec9284..3163a24f49 100644 --- a/backend/open_webui/models/knowledge.py +++ b/backend/open_webui/models/knowledge.py @@ -479,20 +479,16 @@ class KnowledgeTable: user_groups = await Groups.get_groups_by_member_id(user_id, db=db) user_group_ids = {group.id for group in user_groups} - result = [] - for knowledge_base in knowledge_bases: - if knowledge_base.user_id == user_id: - result.append(knowledge_base) - elif await AccessGrants.has_access( - user_id=user_id, - resource_type='knowledge', - resource_id=knowledge_base.id, - permission=permission, - user_group_ids=user_group_ids, - db=db, - ): - result.append(knowledge_base) - return result + # One grants query for all non-owned knowledge bases instead of one each + accessible_ids = await AccessGrants.get_accessible_resource_ids( + user_id=user_id, + resource_type='knowledge', + resource_ids=[kb.id for kb in knowledge_bases if kb.user_id != user_id], + permission=permission, + user_group_ids=user_group_ids, + db=db, + ) + return [kb for kb in knowledge_bases if kb.user_id == user_id or kb.id in accessible_ids] async def get_knowledge_by_id(self, id: str, db: Optional[AsyncSession] = None) -> Optional[KnowledgeModel]: try: diff --git a/backend/open_webui/models/tools.py b/backend/open_webui/models/tools.py index a6468f1876..2873b7c9ac 100644 --- a/backend/open_webui/models/tools.py +++ b/backend/open_webui/models/tools.py @@ -43,7 +43,8 @@ class ToolModel(BaseModel): id: str user_id: str name: str - content: str + # None when listed with defer_content=True (source skipped for listings) + content: str | None = None specs: list[dict] meta: ToolMeta access_grants: list[AccessGrantModel] = Field(default_factory=list) @@ -171,11 +172,18 @@ class ToolsTable: async def get_tools(self, defer_content: bool = False, db: AsyncSession | None = None) -> list[ToolUserModel]: async with get_async_db_context(db) as db: - stmt = select(Tool).order_by(Tool.updated_at.desc()) if defer_content: - stmt = stmt - result = await db.execute(stmt) - all_tools = result.scalars().all() + # Skip Tool.content (plugin source, potentially large) via a + # column select; Row attributes satisfy from_attributes. + result = await db.execute( + select( + Tool.id, Tool.user_id, Tool.name, Tool.specs, Tool.meta, Tool.updated_at, Tool.created_at + ).order_by(Tool.updated_at.desc()) + ) + all_tools = result.all() + else: + result = await db.execute(select(Tool).order_by(Tool.updated_at.desc())) + all_tools = result.scalars().all() user_ids = list(set(tool.user_id for tool in all_tools)) tool_ids = [tool.id for tool in all_tools] @@ -214,20 +222,16 @@ class ToolsTable: user_groups = await Groups.get_groups_by_member_id(user_id, db=db) user_group_ids = {group.id for group in user_groups} - result = [] - for tool in tools: - if tool.user_id == user_id: - result.append(tool) - elif await AccessGrants.has_access( - user_id=user_id, - resource_type='tool', - resource_id=tool.id, - permission=permission, - user_group_ids=user_group_ids, - db=db, - ): - result.append(tool) - return result + # One grants query for all non-owned tools instead of one per tool + accessible_ids = await AccessGrants.get_accessible_resource_ids( + user_id=user_id, + resource_type='tool', + resource_ids=[tool.id for tool in tools if tool.user_id != user_id], + permission=permission, + user_group_ids=user_group_ids, + db=db, + ) + return [tool for tool in tools if tool.user_id == user_id or tool.id in accessible_ids] async def get_tool_valves_by_id(self, id: str, db: AsyncSession | None = None) -> dict | None: try: