Commit 145f8437 authored by Mickaël Desfrênes's avatar Mickaël Desfrênes
Browse files

prevent cross-project resource bleeding through replace_file

parent 26a913fd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2381,6 +2381,8 @@ def replace_file(user: User, from_resource_id: int, to_resource_id: int) -> bool
        )
        if not to_resource_instance.file:
            raise ServiceException(NOT_A_FILE)
        if from_resource_instance.ptr_project_id != to_resource_instance.ptr_project_id:
            raise ServiceException(PROJECT_MISMATCH)
        acl = UserAccess(user, to_resource_instance.ptr_project)
        acl.check_read(from_resource_instance)
        acl.check_update(to_resource_instance)
+29 −0
Original line number Diff line number Diff line
@@ -1116,6 +1116,35 @@ class ServiceTestCase(TestCase):
            models.Resource.objects.filter(deleted_at__isnull=True).count() == 1
        )

    def test_replace_file_rejects_resources_from_different_projects(self):
        from resources.helpers import handle_local_file

        other_project = models.Project.objects.create(
            label="other project", description="other project"
        )
        source_id = handle_local_file(
            Path(os.path.dirname(__file__), "test_assets", "cat_1.png"),
            other_project,
        )
        destination_id = handle_local_file(
            Path(os.path.dirname(__file__), "test_assets", "cat_2.png"),
            self.test_project,
        )
        source = models.File.objects.get(pk=source_id)
        destination = models.File.objects.get(pk=destination_id)
        source_hash = source.hash
        destination_hash = destination.hash

        with self.assertRaises(ServiceException) as context:
            methods.replace_file(self.test_user, source_id, destination_id)

        self.assertEqual(context.exception.message, methods.PROJECT_MISMATCH)
        self.assertTrue(models.File.objects.filter(pk=source_id).exists())
        self.assertEqual(models.File.objects.get(pk=source_id).hash, source_hash)
        self.assertEqual(
            models.File.objects.get(pk=destination_id).hash, destination_hash
        )

    def test_download_metas_xls_filters_metadatas_and_metadatasets(self):
        collection = models.Collection.objects.create(
            title="xlsx target",