Skip to content

fix: enhance query filtering by including workspace_id in various model lookups#6516

Merged
liuruibin merged 1 commit into
v2from
pr@v2@fix_email_ss
Jul 27, 2026
Merged

fix: enhance query filtering by including workspace_id in various model lookups#6516
liuruibin merged 1 commit into
v2from
pr@v2@fix_email_ss

Conversation

@shaohuzhang1

Copy link
Copy Markdown
Contributor

fix: enhance query filtering by including workspace_id in various model lookups

Copilot AI review requested due to automatic review settings July 27, 2026 05:33
@shaohuzhang1

Copy link
Copy Markdown
Contributor Author

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens multi-tenant scoping by adding workspace_id (and application_id for chat) constraints to a set of lookups and batch operations, reducing the chance of cross-workspace/app access via ID-only queries.

Changes:

  • Add workspace_id-scoped filtering for batch deletes and CRUD operations across several serializers (applications, triggers, tools, models, folders, knowledge entities).
  • Add application_id scoping to chat-record voting and historical chat record retrieval to prevent cross-application access.
  • Introduce/expand permission decorators on several user/file endpoints.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
apps/users/views/user.py Adds has_permissions to workspace user list/member endpoints.
apps/trigger/serializers/trigger.py Restricts batch delete to triggers within the provided workspace_id.
apps/tools/serializers/tool.py Scopes tool edit/delete/update to workspace_id; adds app-store URL validation.
apps/oss/views/file.py Adds permission decorator to file deletion endpoint.
apps/models_provider/serializers/model_serializer.py Scopes model pause/delete/edit operations by workspace_id.
apps/knowledge/serializers/termbase.py Scopes termbase delete/export/one by knowledge_id.
apps/knowledge/serializers/tag.py Scopes tag edit/delete/batch-delete to knowledge_id.
apps/knowledge/serializers/problem.py Scopes problem delete/one by knowledge_id.
apps/knowledge/serializers/knowledge_workflow.py Adds validation to ensure knowledge/actions belong to the specified workspace/knowledge.
apps/folders/serializers/folder.py Adds workspace scoping to folder existence checks and lookups.
apps/chat/views/chat_record.py Passes application_id into vote serializer.
apps/chat/serializers/chat_record.py Requires application_id and scopes vote lookup via chat__application_id.
apps/application/serializers/application.py Restricts application batch delete list to the provided workspace_id.
apps/application/serializers/application_chat_record.py Scopes chat-record reads/list/page by chat__application_id.
Comments suppressed due to low confidence (1)

apps/knowledge/serializers/tag.py:193

  • BatchDelete.batch_delete() deletes all tags in the knowledge base that share the same keys, but it only deletes DocumentTag rows for the originally provided tag_ids. Because DocumentTag.tag uses DO_NOTHING, this can leave dangling document_tag rows referencing tags that were deleted by key but not included in tag_ids.
            # 获取要删除的标签的key
            tags_to_delete = QuerySet(Tag).filter(id__in=tag_ids, knowledge_id=self.data.get('knowledge_id'))
            keys_to_delete = set(tags_to_delete.values_list('key', flat=True))

            # 删除具有相同key的所有标签

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/oss/views/file.py
Comment on lines 68 to 71
@log(menu='file', operate='Delete file')
@has_permissions(RoleConstants.ADMIN, RoleConstants.WORKSPACE_MANAGE, RoleConstants.USER)
def delete(self, request: Request, file_id: str):
return result.success(FileSerializer.Operate(data={'id': file_id}).delete())
Comment on lines 62 to 67
chat_record_details_model = QuerySet(ChatRecord).get(id=self.data.get('chat_record_id'),
chat_id=self.data.get('chat_id'))
chat_id=self.data.get('chat_id'),
chat__application_id=self.data.get('application_id'))
if chat_record_details_model is None:
raise AppApiException(500, gettext("Non-existent conversation chat_record_id"))
vote_status = instance.get("vote_status")
Comment on lines 163 to 166
else:
# 仅删除当前标签
QuerySet(Tag).filter(id=self.data.get('tag_id')).delete()
QuerySet(Tag).filter(id=self.data.get('tag_id'), knowledge_id=self.data.get('knowledge_id')).delete()
QuerySet(DocumentTag).filter(tag_id=self.data.get('tag_id')).delete()
Comment on lines 193 to 196
current_id = self.data.get('id')
current_node = Folder.objects.get(id=current_id)
current_node = Folder.objects.get(id=current_id, workspace_id=self.data.get('workspace_id'))
if current_node is None:
raise serializers.ValidationError(_('Folder does not exist'))
Comment on lines 172 to 178
def pause_download(self, with_valid=True):
if with_valid:
self.is_valid(raise_exception=True)
QuerySet(Model).filter(id=self.data.get("id")).update(status=Status.PAUSE_DOWNLOAD)
QuerySet(Model).filter(
id=self.data.get("id"), workspace_id=self.data.get("workspace_id")
).update(status=Status.PAUSE_DOWNLOAD)
return True
Comment on lines 210 to 216
def edit(self, instance: Dict, user_id: str, with_valid=True):
if with_valid:
super().is_valid(raise_exception=True)
model = QuerySet(Model).filter(id=self.data.get("id")).first()
self.is_valid(raise_exception=True)
model = QuerySet(Model).filter(
id=self.data.get("id"), workspace_id=self.data.get("workspace_id")
).first()

Comment on lines 184 to 187
model_id = self.data.get("id")
model = Model.objects.filter(id=model_id).first()
model = Model.objects.filter(id=model_id, workspace_id=self.data.get("workspace_id")).first()
if model is None:
return True
@liuruibin
liuruibin merged commit cf37f0e into v2 Jul 27, 2026
12 of 15 checks passed
@liuruibin
liuruibin deleted the pr@v2@fix_email_ss branch July 27, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants