This is an automated email from the ASF dual-hosted git repository. ppawar pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/branch-2.0 by this push: new 30e5613ae ATLAS-4805: (UI)Text editor improvements and code clean up 30e5613ae is described below commit 30e5613ae6e2b0f623a4c88c899a84edd2b5cf4b Author: Farhan Khan <farhan.k...@freestoneinfotech.com> AuthorDate: Tue Oct 31 16:26:54 2023 +0530 ATLAS-4805: (UI)Text editor improvements and code clean up Signed-off-by: Prasad Pawar <prasad.pa...@cloudera.com> --- dashboardv2/public/css/scss/trumbowyg.scss | 2 ++ dashboardv2/public/js/utils/Helper.js | 5 +++++ dashboardv2/public/js/utils/Utils.js | 13 ++++++++++--- .../business_metadata/BusinessMetadataDetailLayoutView.js | 3 ++- .../business_metadata/BusinessMetadataTableLayoutView.js | 2 +- .../public/js/views/tag/TagAttributeDetailLayoutView.js | 6 ++++-- dashboardv3/public/css/scss/trumbowyg.scss | 2 ++ dashboardv3/public/js/utils/Helper.js | 5 +++++ dashboardv3/public/js/utils/Utils.js | 13 ++++++++++--- .../business_metadata/BusinessMetadataDetailLayoutView.js | 3 ++- .../business_metadata/BusinessMetadataTableLayoutView.js | 2 +- .../public/js/views/tag/TagAttributeDetailLayoutView.js | 6 ++++-- 12 files changed, 48 insertions(+), 14 deletions(-) diff --git a/dashboardv2/public/css/scss/trumbowyg.scss b/dashboardv2/public/css/scss/trumbowyg.scss index a5463eadd..88a7a9775 100644 --- a/dashboardv2/public/css/scss/trumbowyg.scss +++ b/dashboardv2/public/css/scss/trumbowyg.scss @@ -289,6 +289,8 @@ $slow-transition-duration: 300ms !default; } .trumbowyg-dropdown { + top: auto !important; + bottom: 0px; max-width: 300px; max-height: 250px; overflow-y: auto; diff --git a/dashboardv2/public/js/utils/Helper.js b/dashboardv2/public/js/utils/Helper.js index 8efeeb9c5..86a7aac49 100644 --- a/dashboardv2/public/js/utils/Helper.js +++ b/dashboardv2/public/js/utils/Helper.js @@ -134,6 +134,11 @@ define(['require', $('.trumbowyg').css('border', '1px solid #8fa5b1'); } }); + $('body').on('change', '.trumbowyg-modal-box input[name="url"], .trumbowyg-modal-box input[name="text"]', function(e) { + var inputValue = e.target.value; + var sanitizedValue = Utils.sanitizeHtmlContent({ data: inputValue }); + e.target.value = sanitizedValue; + }); $('body').on('keyup input', '.modal-body', function(e) { var target = e.target, isGlossary = (e.target.dataset.id === "searchTerm" || e.target.dataset.id === "searchCategory") ? true : false; // assign term/category modal diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js index 25ce3190e..b4e02971e 100644 --- a/dashboardv2/public/js/utils/Utils.js +++ b/dashboardv2/public/js/utils/Utils.js @@ -1296,18 +1296,25 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', $parent.css('border', '1px solid #8fa5b1'); }).on('tbwchange', function(e) { options.callback ? options.callback(e) : null; + e.target.value = Utils.sanitizeHtmlContent({ data: e.target.value }); }).on('tbwmodalopen', function(e) { $('input[name="title"], input[name="target"]').parent().css('display', 'none'); }); } Utils.sanitizeHtmlContent = function(options) { - var editorContent, cleanedContent; + var editorContent, cleanedContent, + config = { + ALLOWED_TAGS: ['b', 'em', 'strong', 'u', 'a', 'ul', 'ol', 'li', 'p', 'strike', 'h1', 'h2', 'h3', 'h4'], + ALLOWED_ATTR: ['href'], + FORBID_TAGS: ['script', 'img', 'iframe', 'svg', 'title'], + FORBID_ATTR: ['onmouseover', 'onload', 'onclick', 'onerror'] + }; editorContent = options.selector ? $(options.selector).trumbowyg('html') : options.data; if (options && editorContent) { - cleanedContent = DOMPurify.sanitize(editorContent, { FORBID_TAGS: ['img', 'script', 'iframe', 'embed', 'svg', 'meta'], ALLOWED_ATTR: ['target', 'href'] }); + cleanedContent = DOMPurify.sanitize(editorContent, config); } - return cleanedContent; + return cleanedContent || ""; } //-----------------------------------------END---------------------// diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js index b3d1ff337..f08fb3424 100644 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js +++ b/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js @@ -58,8 +58,9 @@ define(['require', }, renderDetail: function() { this.ui.title.html('<span>' + this.model.get('name') + '</span>'); + var sanitizedDescription = Utils.sanitizeHtmlContent({data: this.model.get("description")}); if (this.model.get('description')) { - this.isTextTypeChecked ? this.ui.description.text(this.model.get('description')) : this.ui.description.html(this.model.get('description')); + this.isTextTypeChecked ? this.ui.description.text(sanitizedDescription) : this.ui.description.html(sanitizedDescription); } }, onDestroy: function() { diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js index ccff1fdaf..c02236843 100644 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js +++ b/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js @@ -301,7 +301,7 @@ define(['require', if (description.length > 50) { description = description.substr(0, 50) + "..."; } - return description; + return Utils.sanitizeHtmlContent({data: description}); } }) }, diff --git a/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js b/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js index 3b26f0e0e..14f1b8c3e 100644 --- a/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js +++ b/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js @@ -57,7 +57,7 @@ define(['require', events["click " + this.ui.editButton] = 'onEditButton'; events["change " + this.ui.textType] = function(e) { this.isTextTypeChecked = !this.isTextTypeChecked; - this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description")); + this.isTextTypeChecked ? this.ui.description.text(this.sanitizedDescription) : this.ui.description.html(this.sanitizedDescription); }; return events; }, @@ -68,6 +68,7 @@ define(['require', initialize: function(options) { _.extend(this, _.pick(options, 'tag', 'collection', 'enumDefCollection')); this.isTextTypeChecked = false; + this.sanitizedDescription = ""; }, bindEvents: function() { this.listenTo(this.collection, 'reset', function() { @@ -127,7 +128,8 @@ define(['require', } this.ui.title.html('<span>' + (Utils.getName(this.model.toJSON())) + '</span>'); if (this.model.get("description")) { - this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description")); + this.sanitizedDescription = Utils.sanitizeHtmlContent({data: this.model.get("description")}); + this.isTextTypeChecked ? this.ui.description.text(this.sanitizedDescription) : this.ui.description.html(this.sanitizedDescription); } if (attributeDefs) { if (!_.isArray(attributeDefs)) { diff --git a/dashboardv3/public/css/scss/trumbowyg.scss b/dashboardv3/public/css/scss/trumbowyg.scss index a5463eadd..88a7a9775 100644 --- a/dashboardv3/public/css/scss/trumbowyg.scss +++ b/dashboardv3/public/css/scss/trumbowyg.scss @@ -289,6 +289,8 @@ $slow-transition-duration: 300ms !default; } .trumbowyg-dropdown { + top: auto !important; + bottom: 0px; max-width: 300px; max-height: 250px; overflow-y: auto; diff --git a/dashboardv3/public/js/utils/Helper.js b/dashboardv3/public/js/utils/Helper.js index 71101a74f..c942ac534 100644 --- a/dashboardv3/public/js/utils/Helper.js +++ b/dashboardv3/public/js/utils/Helper.js @@ -140,6 +140,11 @@ define(['require', $('.trumbowyg').css('border', '1px solid #8fa5b1'); } }); + $('body').on('change', '.trumbowyg-modal-box input[name="url"], .trumbowyg-modal-box input[name="text"]', function(e) { + var inputValue = e.target.value; + var sanitizedValue = Utils.sanitizeHtmlContent({ data: inputValue }); + e.target.value = sanitizedValue; + }); $('body').on('keyup input', '.modal-body', function(e) { var target = e.target, isGlossary = (e.target.dataset.id === "searchTerm" || e.target.dataset.id === "searchCategory") ? true : false; // assign term/category modal diff --git a/dashboardv3/public/js/utils/Utils.js b/dashboardv3/public/js/utils/Utils.js index f60d4be5b..dcd737c01 100644 --- a/dashboardv3/public/js/utils/Utils.js +++ b/dashboardv3/public/js/utils/Utils.js @@ -1311,18 +1311,25 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', $parent.css('border', '1px solid #8fa5b1'); }).on('tbwchange', function(e) { options.callback ? options.callback(e) : null; + e.target.value = Utils.sanitizeHtmlContent({ data: e.target.value }); }).on('tbwmodalopen', function(e) { $('input[name="title"], input[name="target"]').parent().css('display', 'none'); }); } Utils.sanitizeHtmlContent = function(options) { - var editorContent, cleanedContent; + var editorContent, cleanedContent, + config = { + ALLOWED_TAGS: ['b', 'em', 'strong', 'u', 'a', 'ul', 'ol', 'li', 'p', 'strike', 'h1', 'h2', 'h3', 'h4'], + ALLOWED_ATTR: ['href'], + FORBID_TAGS: ['script', 'img', 'iframe', 'svg', 'title'], + FORBID_ATTR: ['onmouseover', 'onload', 'onclick', 'onerror', 'src'] + }; editorContent = options.selector ? $(options.selector).trumbowyg('html') : options.data; if (options && editorContent) { - cleanedContent = DOMPurify.sanitize(editorContent, { FORBID_TAGS: ['img', 'script', 'iframe', 'embed', 'svg', 'meta'], ALLOWED_ATTR: ['target', 'href'] }); + cleanedContent = DOMPurify.sanitize(editorContent, config); } - return cleanedContent; + return cleanedContent || ""; } //-----------------------------------------END---------------------// diff --git a/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js b/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js index 0921d4371..b7d12d665 100644 --- a/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js +++ b/dashboardv3/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js @@ -61,8 +61,9 @@ define(['require', }, renderDetail: function() { this.ui.title.html('<span>' + this.model.get('name') + '</span>'); + var sanitizedDescription = Utils.sanitizeHtmlContent({data: this.model.get("description")}); if (this.model.get('description')) { - this.isTextTypeChecked ? this.ui.description.text(this.model.get('description')) : this.ui.description.html(this.model.get('description')); + this.isTextTypeChecked ? this.ui.description.text(sanitizedDescription) : this.ui.description.html(sanitizedDescription); } } }); diff --git a/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js b/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js index 2e8d7c10c..274630656 100644 --- a/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js +++ b/dashboardv3/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js @@ -301,7 +301,7 @@ define(['require', if (description.length > 50) { description = description.substr(0, 50) + "..."; } - return description; + return Utils.sanitizeHtmlContent({data: description}); } }) }, diff --git a/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js b/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js index 2a22d3212..95d706281 100644 --- a/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js +++ b/dashboardv3/public/js/views/tag/TagAttributeDetailLayoutView.js @@ -61,7 +61,7 @@ define(['require', }; events["change " + this.ui.textType] = function(e) { this.isTextTypeChecked = !this.isTextTypeChecked; - this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description")); + this.isTextTypeChecked ? this.ui.description.text(this.sanitizedDescription) : this.ui.description.html(this.sanitizedDescription); }; return events; }, @@ -72,6 +72,7 @@ define(['require', initialize: function(options) { _.extend(this, _.pick(options, 'tag', 'collection', 'enumDefCollection')); this.isTextTypeChecked = false; + this.sanitizedDescription = ""; }, bindEvents: function() { this.listenTo(this.collection, 'reset', function() { @@ -131,7 +132,8 @@ define(['require', } this.ui.title.html('<span>' + (Utils.getName(this.model.toJSON())) + '</span>'); if (this.model.get("description")) { - this.isTextTypeChecked ? this.ui.description.text(this.model.get("description")) : this.ui.description.html(this.model.get("description")); + this.sanitizedDescription = Utils.sanitizeHtmlContent({data: this.model.get("description")}); + this.isTextTypeChecked ? this.ui.description.text(this.sanitizedDescription) : this.ui.description.html(this.sanitizedDescription); } if (attributeDefs) { if (!_.isArray(attributeDefs)) {