Skip to content

Commit

Permalink
Merge branch 'master' into exclude_form_blocks_conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
luca-bellenghi authored Mar 19, 2024
2 parents ff06cc2 + 40e29c7 commit bd6c64c
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Changelog
------------------

- Do not try to convert strings in internal paths for *form* blocks.
- Handle None values in link integrity blocks adapter.
- Patch in @querystring-search that avoid to search through all the site if there is an absolutePath criteria with non existing UID and b_size==1.
See #99 for more details.
[cekk]


Expand Down
2 changes: 2 additions & 0 deletions src/redturtle/volto/adapters/blocks_linkintegrity.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def retrieveLinks(self):
links |= set(extractLinks(value.raw))
elif isinstance(field, BlocksField):
value = field.get(self.context)
if not value:
continue
if not isinstance(value, dict):
continue
blocks = value.get("blocks", {})
Expand Down
38 changes: 38 additions & 0 deletions src/redturtle/volto/restapi/services/querystringsearch/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def __call__(self):
raise BadRequest(str(err))

query = data.get("query", None)

if self.is_event_search(query=query):
return self.reply_events()

Expand All @@ -50,6 +51,8 @@ def __call__(self):
sort_on = data.get("sort_on", None)
sort_order = data.get("sort_order", None)

query = self.cleanup_query(query=query, b_size=b_size)

# LIMIT PATCH
if not query:
self.request.response.setStatus(400)
Expand Down Expand Up @@ -97,6 +100,41 @@ def __call__(self):
)
return results

def cleanup_query(self, query, b_size):
"""
If b_size == 1 and there is an absolutePath in query that points to a non
existing content, reeturn empty query.
This is the case where absolutePath points to an UID that is not present on the site.
A call with b_size == 1 usually is made in objectbrowser to draw the reference, but with a
wrong UID, Plone by default return all site contents and the first one will be returned.
If you then save the blocks, you'll have that random content as new absolutePath value.
"""
if b_size != 1:
return query
fixed_query = []
for criteria in query:
index = criteria.get("i", "")
operation = criteria.get("o", "")
if (
index == "path"
and operation # noqa
== "plone.app.querystring.operation.string.absolutePath" # noqa
):
criteria_value = criteria.get("v", "").split("::")
value = criteria_value[0]

if "/" not in value:
# It must be a UID
item = api.content.get(UID=value)
if not item:
continue
else:
item = api.content.get(value)
if not item:
continue
fixed_query.append(criteria)
return fixed_query

def get_limit(self, data):
"""
If limit is <= 0 or higher than MAX_LIMIT, set it to MAX_LIMIT
Expand Down
81 changes: 81 additions & 0 deletions src/redturtle/volto/tests/test_querystringsearch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
from plone import api
from plone.app.testing import setRoles
from plone.app.testing import SITE_OWNER_NAME
from plone.app.testing import SITE_OWNER_PASSWORD
from plone.app.testing import TEST_USER_ID
from plone.restapi.testing import RelativeSession
from redturtle.volto.testing import REDTURTLE_VOLTO_API_FUNCTIONAL_TESTING
from transaction import commit

import unittest


class TestQuerystringSearch(unittest.TestCase):
layer = REDTURTLE_VOLTO_API_FUNCTIONAL_TESTING

def setUp(self):
self.app = self.layer["app"]
self.portal = self.layer["portal"]
self.portal_url = self.portal.absolute_url()

setRoles(self.portal, TEST_USER_ID, ["Manager"])

api.content.create(container=self.portal, type="Document", title="First")
api.content.create(container=self.portal, type="Document", title="Second")
commit()

self.api_session = RelativeSession(self.portal_url)
self.api_session.headers.update({"Accept": "application/json"})
self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)

def tearDown(self):
self.api_session.close()

def test_do_not_return_random_item_in_objectbrowser_call_if_absolutePath_is_invalid(
self,
):
"""
objectbrowser calls always ask for an absolutePath adn b_size == 1.
absolutePath is the uid of the referenced object
"""
response = self.api_session.post(
"/@querystring-search",
json={
"query": [
{
"i": "path",
"o": "plone.app.querystring.operation.string.absolutePath",
"v": "xxx::1",
}
],
"b_size": 1,
},
)
result = response.json()
self.assertEqual(response.status_code, 400)
self.assertEqual(result["error"]["message"], "No query supplied")

def test_if_absolutePath_is_invalid_and_is_not_a_objectbrowser_call_do_not_filter_by_path(
self,
):
"""
objectbrowser calls always ask for an absolutePath adn b_size == 1.
absolutePath is the uid of the referenced object.
By default Plone (querystringsearch) set /Plone as query path if absolutePath is invalid
"""
response = self.api_session.post(
"/@querystring-search",
json={
"query": [
{
"i": "path",
"o": "plone.app.querystring.operation.string.absolutePath",
"v": "xxx::1",
}
],
},
)
result = response.json()
self.assertEqual(response.status_code, 200)
self.assertEqual(result["items_total"], 2)

0 comments on commit bd6c64c

Please sign in to comment.