From b8c9215a21a4e36e450d403edd65a41f5065cd1d Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 5 Sep 2026 10:39:52 -0700 Subject: [PATCH] Thread the user through for bulk edit all --- src/documents/filters.py | 12 ++++++- src/documents/tests/test_api_bulk_edit.py | 38 +++++++++++++++++++++++ src/documents/views.py | 1 + 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/documents/filters.py b/src/documents/filters.py index dc0838e44..6abadabc0 100644 --- a/src/documents/filters.py +++ b/src/documents/filters.py @@ -796,6 +796,10 @@ class CustomFieldQueryFilter(Filter): class DocumentFilterSet(FilterSet): has_duplicates = BooleanFilter(method="filter_has_duplicates") + def __init__(self, *args: Any, user: Any = None, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self._user = user + is_tagged = BooleanFilter( label="Is tagged", field_name="tags", @@ -859,10 +863,16 @@ class DocumentFilterSet(FilterSet): if value is None: return queryset + user = ( + self._user + if self._user is not None + else getattr(self.request, "user", None) + ) + visible_root_documents = Document.global_objects.filter( root_document__isnull=True, pk__in=permitted_document_ids( - getattr(self.request, "user", None), + user, include_deleted=True, ), ).exclude(pk=OuterRef("pk")) diff --git a/src/documents/tests/test_api_bulk_edit.py b/src/documents/tests/test_api_bulk_edit.py index cf447501c..2f34b2425 100644 --- a/src/documents/tests/test_api_bulk_edit.py +++ b/src/documents/tests/test_api_bulk_edit.py @@ -717,6 +717,44 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase): self.assertEqual(args[0], [self.doc2.id]) self.assertEqual(kwargs["storage_path"], self.sp1.id) + @mock.patch("documents.serialisers.bulk_edit.set_storage_path") + def test_api_bulk_edit_with_all_true_resolves_owned_duplicates(self, m) -> None: + self.setup_mock(m, "set_storage_path") + user = User.objects.create_user(username="duplicate-owner") + user.user_permissions.add( + Permission.objects.get(codename="change_document"), + ) + first_duplicate = Document.objects.create( + checksum="owned-duplicate", + title="First duplicate", + owner=user, + ) + second_duplicate = Document.objects.create( + checksum="owned-duplicate", + title="Second duplicate", + owner=user, + ) + self.client.force_authenticate(user=user) + + response = self.client.post( + "/api/documents/bulk_edit/", + json.dumps( + { + "all": True, + "filters": {"has_duplicates": True}, + "method": "set_storage_path", + "parameters": {"storage_path": self.sp1.id}, + }, + ), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + m.assert_called_once() + args, kwargs = m.call_args + self.assertCountEqual(args[0], [first_duplicate.id, second_duplicate.id]) + self.assertEqual(kwargs["storage_path"], self.sp1.id) + @mock.patch("documents.search.get_backend") @mock.patch("documents.serialisers.bulk_edit.set_storage_path") def test_api_bulk_edit_with_all_true_resolves_documents_from_search_filters( diff --git a/src/documents/views.py b/src/documents/views.py index 4d0a16c4a..dca788cb2 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -2815,6 +2815,7 @@ class DocumentSelectionMixin: filtered_documents = DocumentFilterSet( data=orm_filters, queryset=permitted_documents, + user=user, ).qs.distinct() # tantivy-filtered docs (if search params provided) search_filtered_ids = self._get_search_document_ids(