From cca6e0f0fb2e5c60cb34625af19f7415d7ba151e Mon Sep 17 00:00:00 2001 From: Roel Bruggink Date: Mon, 2 Oct 2023 14:44:53 +0200 Subject: [PATCH] Treat sub-items like items in @linkintegrity endpoint --- CHANGES.rst | 1 - news/1714.bugfix | 1 + .../restapi/services/linkintegrity/get.py | 30 +++--- .../http-examples/linkintegrity_get.resp | 15 +-- .../tests/test_services_linkintegrity.py | 95 ++++++++++++------- 5 files changed, 77 insertions(+), 65 deletions(-) create mode 100644 news/1714.bugfix diff --git a/CHANGES.rst b/CHANGES.rst index a4e60a71a8..d3391faa8c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,7 +19,6 @@ Breaking changes: - Change the @linkintegrity endpoint to add `items_total`, the number of contained items which would be deleted. @davisagli, @danalvrz, @pgrunewald (#1636) - The default branch was renamed from `master` to `main`. @tisto, @davisagli (#1695) - Drop support for Python 3.7. Set python_requires to >= 3.8 @tisto (#1709) -- Expose the sources + their target instead of just some sources in "breaches" attribute in @linkintegrity endpoint response. [jaroel] New features: diff --git a/news/1714.bugfix b/news/1714.bugfix new file mode 100644 index 0000000000..77864ea940 --- /dev/null +++ b/news/1714.bugfix @@ -0,0 +1 @@ +Treat sub-items like items in @linkintegrity endpoint. [jaroel] \ No newline at end of file diff --git a/src/plone/restapi/services/linkintegrity/get.py b/src/plone/restapi/services/linkintegrity/get.py index 275216a994..9114b33742 100644 --- a/src/plone/restapi/services/linkintegrity/get.py +++ b/src/plone/restapi/services/linkintegrity/get.py @@ -34,25 +34,19 @@ def reply(self): item = uuidToObject(uid) item_path = "/".join(item.getPhysicalPath()) links_info = item.restrictedTraverse("@@delete_confirmation_info") + breaches = links_info.get_breaches() data = getMultiAdapter((item, self.request), ISerializeToJsonSummary)() - data["breaches"] = [ - { - "target": { - "@id": result["target"]["url"], - "uid": result["target"]["uid"], - "title": result["target"]["title"], - }, - "sources": [ - { - "@id": source["url"], - "uid": source["uid"], - "title": source["title"], - } - for source in result["sources"] - ], - } - for result in links_info.get_breaches() - ] + data["breaches"] = [] + for breach in breaches: + if breach["target"]["uid"] != uid: + uids.append(breach["target"]["uid"]) + continue + for source in breach.get("sources", []): + # remove unwanted data + source["@id"] = source["url"] + del source["url"] + del source["accessible"] + data["breaches"].append(source) # subtract one because we don't want to count item_path itself data["items_total"] = len(catalog(path=item_path)) - 1 result.append(data) diff --git a/src/plone/restapi/tests/http-examples/linkintegrity_get.resp b/src/plone/restapi/tests/http-examples/linkintegrity_get.resp index 9391a6d901..338c0815c4 100644 --- a/src/plone/restapi/tests/http-examples/linkintegrity_get.resp +++ b/src/plone/restapi/tests/http-examples/linkintegrity_get.resp @@ -7,18 +7,9 @@ Content-Type: application/json "@type": "Document", "breaches": [ { - "sources": [ - { - "@id": "http://localhost:55001/plone/doc-1", - "title": "First document", - "uid": "SomeUUID000000000000000000000001" - } - ], - "target": { - "@id": "http://localhost:55001/plone/doc-2", - "title": "Second document", - "uid": "SomeUUID000000000000000000000002" - } + "@id": "http://localhost:55001/plone/doc-1", + "title": "First document", + "uid": "SomeUUID000000000000000000000001" } ], "description": "", diff --git a/src/plone/restapi/tests/test_services_linkintegrity.py b/src/plone/restapi/tests/test_services_linkintegrity.py index a530c94f23..83393ce5e3 100644 --- a/src/plone/restapi/tests/test_services_linkintegrity.py +++ b/src/plone/restapi/tests/test_services_linkintegrity.py @@ -68,17 +68,15 @@ def test_return_right_breaches_for_reference_field(self): response = self.api_session.get( "/@linkintegrity", params={"uids": [self.doc2.UID()]} ) - result = response.json() self.assertEqual(response.status_code, 200) - self.assertEqual(result[0]["@id"], self.doc2.absolute_url()) self.assertEqual(len(result), 1) + self.assertEqual(result[0]["@id"], self.doc2.absolute_url()) breaches = result[0]["breaches"] - self.assertEqual(breaches[0]["sources"][0]["uid"], IUUID(self.doc1)) - self.assertEqual(breaches[0]["sources"][0]["@id"], self.doc1.absolute_url()) self.assertEqual(len(breaches), 1) - self.assertEqual(len(breaches[0]["sources"]), 1) + self.assertEqual(breaches[0]["uid"], IUUID(self.doc1)) + self.assertEqual(breaches[0]["@id"], self.doc1.absolute_url()) def test_do_not_return_breaches_if_check_is_disabled(self): registry = getUtility(IRegistry) @@ -139,14 +137,13 @@ def test_return_right_breaches_for_blocks(self): result = response.json() self.assertEqual(response.status_code, 200) - self.assertEqual(result[0]["@id"], self.doc2.absolute_url()) self.assertEqual(len(result), 1) + self.assertEqual(result[0]["@id"], self.doc2.absolute_url()) breaches = result[0]["breaches"] - self.assertEqual(breaches[0]["sources"][0]["uid"], IUUID(doc_with_rel)) - self.assertEqual(breaches[0]["sources"][0]["@id"], doc_with_rel.absolute_url()) self.assertEqual(len(breaches), 1) - self.assertEqual(len(breaches[0]["sources"]), 1) + self.assertEqual(breaches[0]["uid"], IUUID(doc_with_rel)) + self.assertEqual(breaches[0]["@id"], doc_with_rel.absolute_url()) def test_return_breaches_for_contents_in_subfolders(self): # create a folder structure @@ -188,14 +185,13 @@ def test_return_breaches_for_contents_in_subfolders(self): result = response.json() self.assertEqual(response.status_code, 200) - self.assertEqual(result[0]["@id"], self.doc2.absolute_url()) self.assertEqual(len(result), 1) + self.assertEqual(result[0]["@id"], self.doc2.absolute_url()) breaches = result[0]["breaches"] - self.assertEqual(breaches[0]["sources"][0]["uid"], IUUID(doc_in_folder)) - self.assertEqual(breaches[0]["sources"][0]["@id"], doc_in_folder.absolute_url()) self.assertEqual(len(breaches), 1) - self.assertEqual(len(breaches[0]["sources"]), 1) + self.assertEqual(breaches[0]["uid"], IUUID(doc_in_folder)) + self.assertEqual(breaches[0]["@id"], doc_in_folder.absolute_url()) def test_return_items_total_in_subfolders(self): # create a folder structure @@ -235,7 +231,8 @@ def test_tree_breaches_no_duplicates(self): source_a = createContentInContainer( self.portal, "Document", - id="source_a", + id="source-a", + title="Source A", blocks={ "block-uuid1": { "@type": "text", @@ -277,7 +274,8 @@ def test_tree_breaches_no_duplicates(self): source_b = createContentInContainer( self.portal, "Document", - id="source_b", + id="source-b", + title="Source B", blocks={ "block-uuid3": { "@type": "text", @@ -302,7 +300,8 @@ def test_tree_breaches_no_duplicates(self): source_c = createContentInContainer( self.portal, "Document", - id="source_c", + id="source-c", + title="Source C", blocks={ "block-uuid4": { "@type": "text", @@ -330,23 +329,51 @@ def test_tree_breaches_no_duplicates(self): "/@linkintegrity", params={"uids": [target_parent_uid]} ) - result = response.json() - self.assertEqual(response.status_code, 200) - self.assertEqual(len(result), 1) - self.assertEqual(result[0]["@id"], target_parent.absolute_url()) - - breaches = result[0]["breaches"] - self.assertEqual(breaches[0]["target"]["uid"], target_parent_uid) + results = response.json() self.assertEqual( - [source["uid"] for source in breaches[0]["sources"]], - [IUUID(source_a), IUUID(source_b)], - ) - self.assertEqual(breaches[1]["target"]["uid"], target_child_uid) - self.assertEqual( - [source["uid"] for source in breaches[1]["sources"]], - [IUUID(source_a), IUUID(source_c)], + [ + { + "@id": target_parent.absolute_url(), + "@type": "Folder", + "breaches": [ + { + "@id": source_a.absolute_url(), + "title": "Source A", + "uid": IUUID(source_a), + }, + { + "@id": source_b.absolute_url(), + "title": "Source B", + "uid": IUUID(source_b), + }, + ], + "description": "", + "items_total": 1, + "review_state": "private", + "title": "", + "type_title": "Folder", + }, + { + "@id": target_child.absolute_url(), + "@type": "Document", + "breaches": [ + { + "@id": source_a.absolute_url(), + "title": "Source A", + "uid": IUUID(source_a), + }, + { + "@id": source_c.absolute_url(), + "title": "Source C", + "uid": IUUID(source_c), + }, + ], + "description": "", + "items_total": 0, + "review_state": "private", + "title": "", + "type_title": "Page", + }, + ], + results, ) - # target parent + target child - # p.a.linkintegrity > 4.0.2 deduplicates breaches, so if you see 3 - # instead of 2, that's why. - self.assertEqual(len(breaches), 2)