From 52248a35a0d3f43245f9805ff3fd6188b384ce2c Mon Sep 17 00:00:00 2001 From: Nicolas ROCHE Date: Tue, 24 Jan 2023 17:00:00 +0100 Subject: [PATCH] cmis: add setting to reload object after folder creation (#73794) --- passerelle/apps/cmis/models.py | 5 +++ tests/test_cmis.py | 76 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/passerelle/apps/cmis/models.py b/passerelle/apps/cmis/models.py index d4b61b27..ff59b07d 100644 --- a/passerelle/apps/cmis/models.py +++ b/passerelle/apps/cmis/models.py @@ -31,6 +31,7 @@ from cmislib.exceptions import ( PermissionDeniedException, UpdateConflictException, ) +from django.conf import settings from django.db import models from django.http import HttpResponse from django.utils.functional import cached_property @@ -262,6 +263,10 @@ class CMISGateway: except ObjectNotFoundException: self._logger.debug("'%s' not found" % basepath) folder = folder.createFolder(path_part) + if getattr(settings, 'CMIS_RELOAD_FOLDER_OBJET_ON_CREATE', False) is True: + # reload object from server to make sure internal references are correct, + # as some misconfigured servers would fail otherwise. + folder = self.get_object(folder.getObjectId()) self._logger.debug("create folder '%s'" % basepath) return folder diff --git a/tests/test_cmis.py b/tests/test_cmis.py index 03420e64..5b23acc6 100644 --- a/tests/test_cmis.py +++ b/tests/test_cmis.py @@ -329,6 +329,29 @@ def test_get_or_create_folder_one_level_creation(monkeypatch): root_folder.createFolder.assert_called_once_with('whatever') +def test_get_or_create_folder_one_level_creation_reloading_object(settings, monkeypatch): + settings.CMIS_RELOAD_FOLDER_OBJET_ON_CREATE = True + whatever_folder = Mock() + whatever_folder.getObjectId.return_value = '123' + root_folder = Mock() + root_folder.createFolder.return_value = whatever_folder + default_repository = Mock( + rootFolder=root_folder, + **{ + 'getObjectByPath.side_effect': ObjectNotFoundException(), + 'getObject.return_value': 'folder', + }, + ) + cmis_client_cls = Mock(return_value=Mock(spec=CmisClient, defaultRepository=default_repository)) + import passerelle.apps.cmis.models + + monkeypatch.setattr(passerelle.apps.cmis.models, 'CmisClient', cmis_client_cls) + gateway = passerelle.apps.cmis.models.CMISGateway('cmis-url', 'user', 'password', Mock()) + assert gateway._get_or_create_folder('/whatever') == 'folder' + default_repository.getObjectByPath.assert_has_calls([call('/whatever'), call('/whatever')]) + root_folder.createFolder.assert_called_once_with('whatever') + + def test_get_or_create_folder_two_level_creation(monkeypatch): whatever_folder = Mock() whatever_folder.createFolder.return_value = 'folder' @@ -349,6 +372,32 @@ def test_get_or_create_folder_two_level_creation(monkeypatch): whatever_folder.createFolder.assert_called_once_with('man') +def test_get_or_create_folder_two_level_creation_reloading_object(settings, monkeypatch): + settings.CMIS_RELOAD_FOLDER_OBJET_ON_CREATE = True + man_folder = Mock() + man_folder.getObjectId.return_value = '456' + whatever_folder_reloaded = Mock() + whatever_folder_reloaded.createFolder.return_value = man_folder + whatever_folder = Mock() + whatever_folder.getObjectId.return_value = '123' + root_folder = Mock() + root_folder.createFolder.return_value = whatever_folder + default_repository = Mock(rootFolder=root_folder) + default_repository.getObjectByPath.side_effect = ObjectNotFoundException() + default_repository.getObject.side_effect = [whatever_folder_reloaded, 'folder'] + cmis_client_cls = Mock(return_value=Mock(spec=CmisClient, defaultRepository=default_repository)) + import passerelle.apps.cmis.models + + monkeypatch.setattr(passerelle.apps.cmis.models, 'CmisClient', cmis_client_cls) + gateway = passerelle.apps.cmis.models.CMISGateway('cmis_url', 'user', 'password', Mock()) + assert gateway._get_or_create_folder('/whatever/man') == 'folder' + default_repository.getObjectByPath.assert_has_calls( + [call('/whatever/man'), call('/whatever'), call('/whatever/man')] + ) + root_folder.createFolder.assert_called_once_with('whatever') + whatever_folder_reloaded.createFolder.assert_called_once_with('man') + + def test_get_or_create_folder_with_some_existing_and_some_not(monkeypatch): whatever_folder = Mock() whatever_folder.createFolder.return_value = 'folder' @@ -374,6 +423,33 @@ def test_get_or_create_folder_with_some_existing_and_some_not(monkeypatch): whatever_folder.createFolder.assert_called_once_with('man') +def test_get_or_create_folder_with_some_existing_and_some_not_reloading_object(settings, monkeypatch): + settings.CMIS_RELOAD_FOLDER_OBJET_ON_CREATE = True + whatever_folder = Mock() + whatever_folder.getObjectId.return_value = '123' + + def getObjectByPath(path): + if path == '/whatever': + return whatever_folder + elif path == '/whatever/man': + raise ObjectNotFoundException() + else: + raise Exception("I should not be called with: %s" % path) + + root_folder = Mock() + default_repository = Mock(rootFolder=root_folder) + default_repository.getObjectByPath.side_effect = getObjectByPath + default_repository.getObject.return_value = 'folder' + cmis_client_cls = Mock(return_value=Mock(spec=CmisClient, defaultRepository=default_repository)) + import passerelle.apps.cmis.models + + monkeypatch.setattr(passerelle.apps.cmis.models, 'CmisClient', cmis_client_cls) + gateway = passerelle.apps.cmis.models.CMISGateway('cmis_url', 'user', 'password', Mock()) + assert gateway._get_or_create_folder('/whatever/man') == 'folder' + root_folder.createFolder.assert_not_called() + whatever_folder.createFolder.assert_called_once_with('man') + + def test_create_doc(): from passerelle.apps.cmis.models import CMISGateway -- 2.39.2