Skip to content

Commit

Permalink
Register IObjectPrimaryFieldTarget for Link objects (#1847)
Browse files Browse the repository at this point in the history
* Register IObjectPrimaryFieldTarget for Link objects to render target url for anonymous users

* add changelog

* Update news/1847.feat

Co-authored-by: David Glick <[email protected]>

* rename changelog file

---------

Co-authored-by: David Glick <[email protected]>
  • Loading branch information
cekk and davisagli authored Nov 26, 2024
1 parent a5b547e commit 447a87c
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions news/1847.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
When a Link content item is linked by UID, resolve its URL as the linked target URL for anonymous users. @cekk
2 changes: 2 additions & 0 deletions src/plone/restapi/serializer/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<adapter factory=".dxcontent.SerializeToJson" />
<adapter factory=".dxcontent.SerializeFolderToJson" />
<adapter factory=".dxcontent.DexterityObjectPrimaryFieldTarget" />
<adapter factory=".dxcontent.LinkObjectPrimaryFieldTarget" />


<configure zcml:condition="installed plone.app.contenttypes">
<adapter factory=".collection.SerializeCollectionToJson" />
Expand Down
25 changes: 25 additions & 0 deletions src/plone/restapi/serializer/dxcontent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from AccessControl import getSecurityManager
from Acquisition import aq_inner
from Acquisition import aq_parent
from plone.app.contenttypes.interfaces import ILink
from plone.autoform.interfaces import READ_PERMISSIONS_KEY
from plone.dexterity.interfaces import IDexterityContainer
from plone.dexterity.interfaces import IDexterityContent
Expand Down Expand Up @@ -266,3 +267,27 @@ def check_permission(self, permission_name, obj):
sm.checkPermission(permission.title, obj)
)
return self.permission_cache[permission_name]


@adapter(ILink, Interface)
@implementer(IObjectPrimaryFieldTarget)
class LinkObjectPrimaryFieldTarget:
def __init__(self, context, request):
self.context = context
self.request = request

self.permission_cache = {}

def __call__(self):
"""
If user can edit Link object, do not return remoteUrl
"""
pm = getToolByName(self.context, "portal_membership")
if bool(pm.isAnonymousUser()):
for schema in iterSchemata(self.context):
for name, field in getFields(schema).items():
if name == "remoteUrl":
serializer = queryMultiAdapter(
(field, self.context, self.request), IFieldSerializer
)
return serializer()
37 changes: 37 additions & 0 deletions src/plone/restapi/tests/test_dxcontent_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
from plone.namedfile.file import NamedFile
from plone.registry.interfaces import IRegistry
from plone.restapi.interfaces import IExpandableElement
from plone.restapi.interfaces import IObjectPrimaryFieldTarget
from plone.restapi.interfaces import ISerializeToJson
from plone.restapi.testing import PLONE_RESTAPI_DX_INTEGRATION_TESTING
from plone.restapi.tests.test_expansion import ExpandableElementFoo
from plone.restapi.serializer.utils import get_portal_type_title
from plone.uuid.interfaces import IMutableUUID
from plone.uuid.interfaces import IUUID
from Products.CMFCore.utils import getToolByName
from zope.component import getGlobalSiteManager
from zope.component import getMultiAdapter
Expand Down Expand Up @@ -756,3 +758,38 @@ def test_primary_field_target_with_edit_permissions(self):
serializer = getMultiAdapter((self.portal.doc1, self.request), ISerializeToJson)
data = serializer()
self.assertNotIn("targetUrl", data)

def test_primary_field_target_for_link_objects_for_auth_return_none(self):
self.portal.invokeFactory(
"Document",
id="linked",
)
self.portal.invokeFactory(
"Link",
id="link",
remoteUrl=f"../resolveuid/{IUUID(self.portal.linked)}",
)
wftool = getToolByName(self.portal, "portal_workflow")
wftool.doActionFor(self.portal.linked, "publish")
adapter = getMultiAdapter(
(self.portal.link, self.request), IObjectPrimaryFieldTarget
)
self.assertEqual(adapter(), None)

def test_primary_field_target_for_link_objects_for_anonymous(self):
self.portal.invokeFactory(
"Document",
id="linked",
)
self.portal.invokeFactory(
"Link",
id="link",
remoteUrl=f"../resolveuid/{IUUID(self.portal.linked)}",
)
wftool = getToolByName(self.portal, "portal_workflow")
wftool.doActionFor(self.portal.linked, "publish")
logout()
adapter = getMultiAdapter(
(self.portal.link, self.request), IObjectPrimaryFieldTarget
)
self.assertEqual(adapter(), self.portal.linked.absolute_url())

0 comments on commit 447a87c

Please sign in to comment.