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.
This commit is contained in:
evasques
2021-06-16 15:41:34 +01:00
committed by GitHub
parent 2fbfa123e5
commit d7ec130756
2 changed files with 111 additions and 61 deletions

View File

@@ -1,6 +1,8 @@
<#macro dateFormat date>${date?string("dd MMM yyyy HH:mm:ss 'GMT'Z '('zzz')'")}</#macro>
<#escape x as jsonUtils.encodeJSONString(x)>
<#assign maxDepth=1000 />
<#macro printPropertyValue p>
<#attempt>
<#if p.value??>
<#if p.value?is_date>
"<@dateFormat p.value />"
@@ -10,19 +12,64 @@
${p.value?c}
<#elseif p.value?is_string>
"${p.value}"
<#elseif p.value?is_hash>
<#assign result = "{"/>
<#assign first = true />
<#list p.value?keys as key>
<#if first = false>
<#assign result = result + ", "/>
<#elseif p.value?is_hash || p.value?is_enumerable>
<#assign val>
<@convertToJSON p.value />
</#assign>
"${val}"
</#if>
<#else>
null
</#if>
<#recover>
"${.error}"
</#attempt>
</#macro>
<#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">
</#if>
<@compress single_line=true>
{
<#assign first = true />
<#list v?keys as key>
<#if first = false>,</#if>
"${key}":
<#if v[key]??>
<@convertToJSON v[key] />
<#else>
null
</#if>
<#assign result = result + "${key} = ${p.value[key]}" />
<#assign first = false/>
</#list>
<#assign result = result + "}"/>
<#-- output the result -->
"${result}"
}
</@compress>
<#elseif v?is_enumerable>
<#if v?size gt maxDepth>
<#stop "Max depth of object achieved" >
</#if>
<#assign first = true />
<@compress single_line=true>
[
<#list v as item>
<#if first = false>,</#if>
<@convertToJSON item />
<#assign first = false/>
</#list>
]
</@compress>
<#else>
${v}
</#if>
<#else>
null
@@ -70,7 +117,8 @@
"isContent": ${val.content?string},
"isNodeRef": ${val.nodeRef?string},
"isNullValue": ${val.nullValue?string}
}<#if val_has_next>,</#if>
}
<#if val_has_next>,</#if>
</#list>
],
"type": {

View File

@@ -1,7 +1,7 @@
<#assign null><span style="color:red">${msg("nodebrowser.null")?html}</span></#assign>
<#assign none><span style="color:red">${msg("nodebrowser.none")?html}</span></#assign>
<#assign collection>${msg("nodebrowser.collection")?html}</#assign>
<#assign maxDepth=1000 />
<#macro dateFormat date>${date?string("dd MMM yyyy HH:mm:ss 'GMT'Z '('zzz')'")}</#macro>
<#macro propValue p>
<#attempt>
@@ -25,7 +25,6 @@
</#attempt>
</#macro>
<#macro convertToJSON v>
<#attempt>
<#if v??>
<#if v?is_date>
<@dateFormat v />
@@ -36,6 +35,9 @@
<#elseif v?is_string>
"${v?string}"
<#elseif v?is_hash>
<#if v?keys?size gt maxDepth >
<#stop "Max depth of object achieved">
</#if>
<@compress single_line=true>
{
<#assign first = true />
@@ -52,6 +54,9 @@
}
</@compress>
<#elseif v?is_enumerable>
<#if v?size gt maxDepth>
<#stop "Max depth of object achieved" >
</#if>
<#assign first = true />
<@compress single_line=true>
[
@@ -66,9 +71,6 @@
<#else>
${null}
</#if>
<#recover>
<span style="color:red">${.error}</span>
</#attempt>
</#macro>
<#macro contentUrl nodeRef prop>
${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}