MNT-20500 - Admin console breaks with serialised objects (#538)

* MNT-20500 - Admin console breaks with serialised objects (#291)

* 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

(cherry picked from commit ce62fb1da3)

* 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.

(cherry picked from commit d7ec130756)
This commit is contained in:
evasques
2021-06-17 12:00:17 +01:00
committed by GitHub
parent 0eaeea35f8
commit 4a03e8cc98

View File

@@ -1,34 +1,76 @@
<#assign null><span style="color:red">${msg("nodebrowser.null")?html}</span></#assign> <#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 none><span style="color:red">${msg("nodebrowser.none")?html}</span></#assign>
<#assign collection>${msg("nodebrowser.collection")?html}</#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 dateFormat date>${date?string("dd MMM yyyy HH:mm:ss 'GMT'Z '('zzz')'")}</#macro>
<#macro propValue p> <#macro propValue p>
<#if p.value??> <#attempt>
<#if p.value?is_date> <#if p.value??>
<@dateFormat p.value /> <#if p.value?is_date>
<#elseif p.value?is_boolean> <@dateFormat p.value />
${p.value?string} <#elseif p.value?is_boolean>
<#elseif p.value?is_number> ${p.value?string}
${p.value?c} <#elseif p.value?is_number>
<#elseif p.value?is_string> ${p.value?c}
${p.value?html} <#elseif p.value?is_string>
<#elseif p.value?is_hash> ${p.value?html}
<#assign result = "{"/> <#elseif p.value?is_hash || p.value?is_enumerable>
<#assign first = true /> <@convertToJSON p.value />
<#list p.value?keys as key> </#if>
<#if first = false> <#else>
<#assign result = result + ", "/> ${null}
</#if>
<#recover>
<span style="color:red">${.error}</span>
</#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> </#if>
<#assign result = result + "${key}=${p.value[key]?html}" /> <@compress single_line=true>
<#assign first = false/> {
</#list> <#assign first = true />
<#assign result = result + "}"/> <#list v?keys as key>
${result} <#if first = false>,</#if>
"${key}":
<#if v[key]??>
<@convertToJSON v[key] />
<#else>
${null}
</#if>
<#assign first = false/>
</#list>
}
</@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>
</#if>
<#else>
${null}
</#if> </#if>
<#else>
${null}
</#if>
</#macro> </#macro>
<#macro contentUrl nodeRef prop> <#macro contentUrl nodeRef prop>
${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url} ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}