diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 4bb1ff8c1..a4cc459e8 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -2137,6 +2137,8 @@ class BulkEditSerializer( raise serializers.ValidationError("pages must be a list") if not all(isinstance(i, int) for i in parameters["pages"]): raise serializers.ValidationError("pages must be a list of integers") + if any(i < 1 for i in parameters["pages"]): + raise serializers.ValidationError("pages must be positive integers") def _validate_parameters_merge(self, parameters) -> None: if "delete_originals" in parameters: diff --git a/src/documents/tests/test_api_bulk_edit.py b/src/documents/tests/test_api_bulk_edit.py index 9c7ba3db8..539cd68d8 100644 --- a/src/documents/tests/test_api_bulk_edit.py +++ b/src/documents/tests/test_api_bulk_edit.py @@ -1843,6 +1843,36 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase): m.assert_called_once() self.assertEqual(m.call_args.kwargs["pages"], [[1], [2, 3, 4], [5]]) + @mock.patch("documents.serialisers.bulk_edit.delete_pages") + def test_bulk_edit_delete_pages_rejects_pages_below_one(self, m) -> None: + """ + GIVEN: + - A legacy delete_pages bulk edit + WHEN: + - API to bulk edit is called with a page number below 1 + THEN: + - API returns HTTP 400 + - delete_pages is not called + """ + self.setup_mock(m, "delete_pages") + + for pages in ([0], [-1], [1, 0]): + with self.subTest(pages=pages): + response = self.client.post( + "/api/documents/bulk_edit/", + json.dumps( + { + "documents": [self.doc2.id], + "method": "delete_pages", + "parameters": {"pages": pages}, + }, + ), + content_type="application/json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn(b"pages must be positive integers", response.content) + m.assert_not_called() + @mock.patch("documents.views.bulk_edit.rotate") def test_rotate_insufficient_permissions(self, m) -> None: self.doc1.owner = User.objects.get(username="temp_admin")