diff --git a/src/documents/tests/test_permission_filtering_security.py b/src/documents/tests/test_permission_filtering_security.py index 172bfb197..305566f97 100644 --- a/src/documents/tests/test_permission_filtering_security.py +++ b/src/documents/tests/test_permission_filtering_security.py @@ -1,5 +1,6 @@ from __future__ import annotations +from http import HTTPStatus from unittest.mock import patch import pytest @@ -314,3 +315,39 @@ class TestBulkEditChangePermissionBoundary: format="json", ) assert response.status_code == 403 + + +@pytest.mark.django_db +class TestBulkDownloadPermissionChecksRootDocument: + def test_permission_checked_on_root_not_on_version( + self, + rest_api_client, + paperless_dirs, + _media_settings, + ): + owner = User.objects.create_user(username="owner") + requester = User.objects.create_user(username="requester") + rest_api_client.force_authenticate(user=requester) + root = DocumentFactory(owner=owner) + # a version of root that the requester has NOT been individually granted + version = DocumentFactory(owner=owner, root_document=root, version_index=1) + version.source_path.write_bytes(b"%PDF-1.4 test") + assign_perm("view_document", requester, root) # granted on ROOT only + + response = rest_api_client.post( + "/api/documents/bulk_download/", + {"documents": [version.pk]}, + format="json", + ) + assert ( + response.status_code == HTTPStatus.OK + ) # visible because root is permitted + + stranger = User.objects.create_user(username="mallory") + rest_api_client.force_authenticate(user=stranger) + response = rest_api_client.post( + "/api/documents/bulk_download/", + {"documents": [version.pk]}, + format="json", + ) + assert response.status_code == HTTPStatus.FORBIDDEN diff --git a/src/documents/views.py b/src/documents/views.py index 333b04049..e8b9d5e8b 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -3837,9 +3837,10 @@ class BulkDownloadView(DocumentSelectionMixin, GenericAPIView[Any]): content = serializer.validated_data.get("content") follow_filename_format = serializer.validated_data.get("follow_formatting") + permitted_ids = set(permitted_document_ids(request.user)) for document in documents: root_doc = get_root_document(document) - if not has_perms_owner_aware(request.user, "view_document", root_doc): + if root_doc.pk not in permitted_ids: return HttpResponseForbidden("Insufficient permissions") versioned_documents.append( get_latest_version_for_root(