From d7ec1307567600c9475775b76fe14871b3b72a59 Mon Sep 17 00:00:00 2001 From: evasques Date: Wed, 16 Jun 2021 15:41:34 +0100 Subject: [PATCH] MNT-20500 - Admin console breaks with serialised objects (#536) * In node browser: ** Added macro convertToJSON to recursively parse hashes and enumerables ** Added attempt/recover in macros to handle errors and not break the page ** Changed the output of serialized objects to JSON format * In both admin console and node browser: ** Adjusted consistency of the ouput when an error occurs ** Validate the depth of each hash. When we find a hash with over 1000 elements, we throw an error instead of displaying the object. Used the stop tag to effectively force an abort of the template processing preventing performance or security issues regarding very large objects. --- .../node-browser/node-browser.get.json.ftl | 84 ++++++++++++++---- .../admin-nodebrowser.get.html.ftl | 88 ++++++++++--------- 2 files changed, 111 insertions(+), 61 deletions(-) diff --git a/amps/share-services/src/main/resources/alfresco/templates/webscripts/org/alfresco/slingshot/node-browser/node-browser.get.json.ftl b/amps/share-services/src/main/resources/alfresco/templates/webscripts/org/alfresco/slingshot/node-browser/node-browser.get.json.ftl index 46b2343f69..b1eb8cbf49 100644 --- a/amps/share-services/src/main/resources/alfresco/templates/webscripts/org/alfresco/slingshot/node-browser/node-browser.get.json.ftl +++ b/amps/share-services/src/main/resources/alfresco/templates/webscripts/org/alfresco/slingshot/node-browser/node-browser.get.json.ftl @@ -1,28 +1,75 @@ <#macro dateFormat date>${date?string("dd MMM yyyy HH:mm:ss 'GMT'Z '('zzz')'")} <#escape x as jsonUtils.encodeJSONString(x)> +<#assign maxDepth=1000 /> <#macro printPropertyValue p> - <#if p.value??> - <#if p.value?is_date> + <#attempt> + <#if p.value??> + <#if p.value?is_date> "<@dateFormat p.value />" - <#elseif p.value?is_boolean> + <#elseif p.value?is_boolean> ${p.value?string} - <#elseif p.value?is_number> + <#elseif p.value?is_number> ${p.value?c} - <#elseif p.value?is_string> + <#elseif p.value?is_string> "${p.value}" - <#elseif p.value?is_hash> - <#assign result = "{"/> + <#elseif p.value?is_hash || p.value?is_enumerable> + <#assign val> + <@convertToJSON p.value /> + + "${val}" + + <#else> + null + + <#recover> + "${.error}" + + +<#macro convertToJSON v> + <#if v??> + <#if v?is_date> + "<@dateFormat v />" + <#elseif v?is_boolean> + ${v?string} + <#elseif v?is_number> + ${v?c} + <#elseif v?is_string> + "${v?string}" + <#elseif v?is_hash> + <#if v?keys?size gt maxDepth > + <#stop "Max depth of object achieved"> + + <@compress single_line=true> + { + <#assign first = true /> + <#list v?keys as key> + <#if first = false>, + "${key}": + <#if v[key]??> + <@convertToJSON v[key] /> + <#else> + null + + <#assign first = false/> + + } + + <#elseif v?is_enumerable> + <#if v?size gt maxDepth> + <#stop "Max depth of object achieved" > + <#assign first = true /> - <#list p.value?keys as key> - <#if first = false> - <#assign result = result + ", "/> - - <#assign result = result + "${key} = ${p.value[key]}" /> - <#assign first = false/> - - <#assign result = result + "}"/> - <#-- output the result --> - "${result}" + <@compress single_line=true> + [ + <#list v as item> + <#if first = false>, + <@convertToJSON item /> + <#assign first = false/> + + ] + + <#else> + ${v} <#else> null @@ -70,7 +117,8 @@ "isContent": ${val.content?string}, "isNodeRef": ${val.nodeRef?string}, "isNullValue": ${val.nullValue?string} - }<#if val_has_next>, + } + <#if val_has_next>, ], "type": { diff --git a/remote-api/src/main/resources/alfresco/templates/webscripts/org/alfresco/repository/admin/support-tools/admin-nodebrowser.get.html.ftl b/remote-api/src/main/resources/alfresco/templates/webscripts/org/alfresco/repository/admin/support-tools/admin-nodebrowser.get.html.ftl index eceb98b36d..4c5b7cd0c5 100644 --- a/remote-api/src/main/resources/alfresco/templates/webscripts/org/alfresco/repository/admin/support-tools/admin-nodebrowser.get.html.ftl +++ b/remote-api/src/main/resources/alfresco/templates/webscripts/org/alfresco/repository/admin/support-tools/admin-nodebrowser.get.html.ftl @@ -1,7 +1,7 @@ <#assign null>${msg("nodebrowser.null")?html} <#assign none>${msg("nodebrowser.none")?html} <#assign collection>${msg("nodebrowser.collection")?html} - +<#assign maxDepth=1000 /> <#macro dateFormat date>${date?string("dd MMM yyyy HH:mm:ss 'GMT'Z '('zzz')'")} <#macro propValue p> <#attempt> @@ -25,50 +25,52 @@ <#macro convertToJSON v> - <#attempt> - <#if v??> - <#if v?is_date> - <@dateFormat v /> - <#elseif v?is_boolean> - ${v?string} - <#elseif v?is_number> - ${v?c} - <#elseif v?is_string> - "${v?string}" - <#elseif v?is_hash> - <@compress single_line=true> - { - <#assign first = true /> - <#list v?keys as key> - <#if first = false>, - "${key}": - <#if v[key]??> - <@convertToJSON v[key] /> - <#else> - ${null} - - <#assign first = false/> - - } - - <#elseif v?is_enumerable> - <#assign first = true /> - <@compress single_line=true> - [ - <#list v as item> - <#if first = false>, - <@convertToJSON item /> - <#assign first = false/> - - ] - + <#if v??> + <#if v?is_date> + <@dateFormat v /> + <#elseif v?is_boolean> + ${v?string} + <#elseif v?is_number> + ${v?c} + <#elseif v?is_string> + "${v?string}" + <#elseif v?is_hash> + <#if v?keys?size gt maxDepth > + <#stop "Max depth of object achieved"> - <#else> - ${null} + <@compress single_line=true> + { + <#assign first = true /> + <#list v?keys as key> + <#if first = false>, + "${key}": + <#if v[key]??> + <@convertToJSON v[key] /> + <#else> + ${null} + + <#assign first = false/> + + } + + <#elseif v?is_enumerable> + <#if v?size gt maxDepth> + <#stop "Max depth of object achieved" > + + <#assign first = true /> + <@compress single_line=true> + [ + <#list v as item> + <#if first = false>, + <@convertToJSON item /> + <#assign first = false/> + + ] + - <#recover> - ${.error} - + <#else> + ${null} + <#macro contentUrl nodeRef prop> ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}