diff --git a/src/documents/tests/test_permission_filtering_security.py b/src/documents/tests/test_permission_filtering_security.py index 2d701090b..5349e0402 100644 --- a/src/documents/tests/test_permission_filtering_security.py +++ b/src/documents/tests/test_permission_filtering_security.py @@ -351,3 +351,42 @@ class TestBulkDownloadPermissionChecksRootDocument: format="json", ) assert response.status_code == HTTPStatus.FORBIDDEN + + +@pytest.mark.django_db +class TestTrashRestorePermissionBoundary: + def test_restore_rejects_document_without_delete_permission( + self, + rest_api_client, + ): + owner = User.objects.create_user(username="owner") + requester = User.objects.create_user(username="requester") + rest_api_client.force_authenticate(user=requester) + doc = DocumentFactory(owner=owner) + assign_perm("view_document", requester, doc) # view only, NOT delete + doc.delete() + + response = rest_api_client.post( + "/api/trash/", + {"documents": [doc.pk], "action": "restore"}, + format="json", + ) + assert response.status_code == HTTPStatus.FORBIDDEN + + def test_restore_allows_document_with_explicit_delete_permission( + self, + rest_api_client, + ): + owner = User.objects.create_user(username="owner") + requester = User.objects.create_user(username="requester") + rest_api_client.force_authenticate(user=requester) + doc = DocumentFactory(owner=owner) + assign_perm("delete_document", requester, doc) + doc.delete() + + response = rest_api_client.post( + "/api/trash/", + {"documents": [doc.pk], "action": "restore"}, + format="json", + ) + assert response.status_code == HTTPStatus.OK diff --git a/src/documents/views.py b/src/documents/views.py index e8b9d5e8b..e4157028d 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -5308,9 +5308,15 @@ class TrashView(ListModelMixin, PassUserMixin): if doc_ids is not None else self.filter_queryset(self.get_queryset()).all() ) - for doc in docs: - if not has_perms_owner_aware(request.user, "delete_document", doc): - return HttpResponseForbidden("Insufficient permissions") + permitted_ids = set( + permitted_document_ids( + request.user, + perm="delete_document", + include_deleted=True, + ), + ) + if not all(doc.pk in permitted_ids for doc in docs): + return HttpResponseForbidden("Insufficient permissions") action = serializer.validated_data.get("action") if action == "restore": for doc in Document.deleted_objects.filter(id__in=doc_ids).all():