fix: enhance query filtering by including workspace_id in various model lookups#6516
Merged
Conversation
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 |
There was a problem hiding this comment.
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_idscoping 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 deletesDocumentTagrows for the originally providedtag_ids. BecauseDocumentTag.tagusesDO_NOTHING, this can leave danglingdocument_tagrows referencing tags that were deleted by key but not included intag_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 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: enhance query filtering by including workspace_id in various model lookups