From a571899353937b7e3609eaab728116107caf567a Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Tue, 17 Dec 2024 06:12:14 +0100 Subject: [PATCH] Handle aliases in path2uid (#1848) * Handle aliases in path2uid * add changelog * make sure it found the correct page * adjust changelog --------- Co-authored-by: David Glick --- news/1848.bugfix | 1 + src/plone/restapi/deserializer/utils.py | 11 +++++++++++ .../restapi/tests/test_blocks_deserializer.py | 14 ++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 news/1848.bugfix diff --git a/news/1848.bugfix b/news/1848.bugfix new file mode 100644 index 0000000000..c9816615af --- /dev/null +++ b/news/1848.bugfix @@ -0,0 +1 @@ +Fix resolving paths in deserializer if the target was moved in the same request. @cekk diff --git a/src/plone/restapi/deserializer/utils.py b/src/plone/restapi/deserializer/utils.py index 67d67d5556..c6b687fa2f 100644 --- a/src/plone/restapi/deserializer/utils.py +++ b/src/plone/restapi/deserializer/utils.py @@ -2,6 +2,9 @@ from plone.uuid.interfaces import IUUID from plone.uuid.interfaces import IUUIDAware from zope.component import getMultiAdapter +from plone.app.redirector.interfaces import IRedirectionStorage +from zope.component import getUtility + import re PATH_RE = re.compile(r"^(.*?)((?=/@@|#).*)?$") @@ -35,6 +38,14 @@ def path2uid(context, link): suffix = match.group(2) or "" obj = portal.unrestrictedTraverse(path, None) + if obj is None: + # last try: maybe the object or some parent has been renamed. + # if yes, there should be a reference into redirection storage + storage = getUtility(IRedirectionStorage) + alias_path = storage.get(path) + if alias_path: + path = alias_path + obj = portal.unrestrictedTraverse(path, None) if obj is None or obj == portal: return link segments = path.split("/") diff --git a/src/plone/restapi/tests/test_blocks_deserializer.py b/src/plone/restapi/tests/test_blocks_deserializer.py index 874e5446e8..dcaf3bf2c8 100644 --- a/src/plone/restapi/tests/test_blocks_deserializer.py +++ b/src/plone/restapi/tests/test_blocks_deserializer.py @@ -1,3 +1,4 @@ +from plone import api from plone.dexterity.interfaces import IDexterityFTI from plone.dexterity.interfaces import IDexterityItem from plone.restapi.behaviors import IBlocks @@ -724,3 +725,16 @@ def test_deserialize_url_with_image_scales(self): res = self.deserialize(blocks=blocks) self.assertTrue(res.blocks["123"]["url"].startswith("../resolveuid/")) self.assertNotIn("image_scales", res.blocks["123"]) + + def test_deserializer_resolve_path_also_if_it_is_an_alias(self): + + self.portal.invokeFactory( + "Document", + id="doc", + ) + api.content.move(source=self.portal.doc, id="renamed-doc") + blocks = {"abc": {"href": "%s/doc" % self.portal.absolute_url()}} + + res = self.deserialize(blocks=blocks) + link = res.blocks["abc"]["href"] + self.assertEqual(link, f"../resolveuid/{self.portal['renamed-doc'].UID()}")