From 224a841171ae4de1f67a12efe631aa8836b08e7e Mon Sep 17 00:00:00 2001 From: jfavellar90 Date: Mon, 24 Aug 2020 10:29:53 -0500 Subject: [PATCH 1/8] backport of security patch from PR 24258 upstream --- .../certificates/views/certificate_editor.js | 7 +- .../certificates/views/certificate_preview.js | 14 +- .../certificates/views/signatory_details.js | 15 +- .../js/certificates/views/signatory_editor.js | 27 +-- .../js/maintenance/force_publish_course.js | 6 +- .../js/models/settings/course_details.js | 28 ++- .../models/settings/course_grading_policy.js | 27 ++- cms/static/js/views/abstract_editor.js | 1 + cms/static/js/views/asset.js | 23 +-- cms/static/js/views/course_info_handout.js | 179 +++++++++--------- .../templates/cors_csrf/xdomain_proxy.html | 11 +- .../learner_profile/js/views/badge_view.js | 7 +- .../js/views/section_two_tab.js | 10 +- .../js/views/share_modal_view.js | 7 +- .../ace_common/edx_ace/common/base_body.html | 20 +- .../course_about_sidebar_header.html | 5 +- 16 files changed, 213 insertions(+), 174 deletions(-) diff --git a/cms/static/js/certificates/views/certificate_editor.js b/cms/static/js/certificates/views/certificate_editor.js index e08ac582b46..fa19bd2de25 100644 --- a/cms/static/js/certificates/views/certificate_editor.js +++ b/cms/static/js/certificates/views/certificate_editor.js @@ -8,10 +8,11 @@ define([ 'js/views/list_item_editor', 'js/certificates/models/signatory', 'js/certificates/views/signatory_editor', - 'text!templates/certificate-editor.underscore' + 'text!templates/certificate-editor.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], function($, _, Backbone, gettext, - ListItemEditorView, SignatoryModel, SignatoryEditorView, certificateEditorTemplate) { + ListItemEditorView, SignatoryModel, SignatoryEditorView, certificateEditorTemplate, HtmlUtils) { 'use strict'; // If signatories limit is required to specific value then we can change it. @@ -75,7 +76,7 @@ function($, _, Backbone, gettext, isEditingAllCollections: true, eventAgg: self.eventAgg }); - self.$('div.signatory-edit-list').append($(signatory_view.render())); + self.$('div.signatory-edit-list').append(HtmlUtils.HTML((signatory_view.render())).toString()); }); this.disableAddSignatoryButton(); return this; diff --git a/cms/static/js/certificates/views/certificate_preview.js b/cms/static/js/certificates/views/certificate_preview.js index d07f3d1fdca..5300f784c9f 100644 --- a/cms/static/js/certificates/views/certificate_preview.js +++ b/cms/static/js/certificates/views/certificate_preview.js @@ -8,9 +8,10 @@ define([ 'js/views/baseview', 'common/js/components/utils/view_utils', 'common/js/components/views/feedback_notification', - 'text!templates/certificate-web-preview.underscore' + 'text!templates/certificate-web-preview.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], -function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPreviewTemplate) { +function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPreviewTemplate, HtmlUtils) { 'use strict'; var CertificateWebPreview = BaseView.extend({ el: $('.preview-certificate'), @@ -27,7 +28,7 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie }, render: function() { - this.$el.html(_.template(certificateWebPreviewTemplate)({ + HtmlUtils.setHtml(this.$el, HtmlUtils.template(certificateWebPreviewTemplate)({ course_modes: this.course_modes, certificate_web_view_url: this.certificate_web_view_url, is_active: this.is_active @@ -36,13 +37,8 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie }, toggleCertificateActivation: function() { - var msg = 'Activating'; - if (this.is_active) { - msg = 'Deactivating'; - } - var notification = new NotificationView.Mini({ - title: gettext(msg) + title: gettext(this.is_active ? 'Deactivating' : 'Activating') }); $.ajax({ diff --git a/cms/static/js/certificates/views/signatory_details.js b/cms/static/js/certificates/views/signatory_details.js index 9d6543e2793..9286b282599 100644 --- a/cms/static/js/certificates/views/signatory_details.js +++ b/cms/static/js/certificates/views/signatory_details.js @@ -11,10 +11,11 @@ define([ 'js/views/baseview', 'js/certificates/views/signatory_editor', 'text!templates/signatory-details.underscore', - 'text!templates/signatory-actions.underscore' + 'text!templates/signatory-actions.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, SignatoryEditorView, - signatoryDetailsTemplate, signatoryActionsTemplate) { + signatoryDetailsTemplate, signatoryActionsTemplate, HtmlUtils) { 'use strict'; var SignatoryDetailsView = BaseView.extend({ tagName: 'div', @@ -52,20 +53,20 @@ function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Signa editSignatory: function(event) { // Retrieve the edit view for this model if (event && event.preventDefault) { event.preventDefault(); } - this.$el.html(this.edit_view.render()); - $(_.template(signatoryActionsTemplate)()).appendTo(this.el); + this.$el.html(HtmlUtils.HTML(this.edit_view.render()).toString()); + this.$el.append(HtmlUtils.template(signatoryActionsTemplate)().toString()); this.edit_view.delegateEvents(); this.delegateEvents(); }, saveSignatoryData: function(event) { // Persist the data for this model - if (event && event.preventDefault) { event.preventDefault(); } var certificate = this.model.get('certificate'); + var self = this; + if (event && event.preventDefault) { event.preventDefault(); } if (!certificate.isValid()) { return; } - var self = this; ViewUtils.runOperationShowingMessage( gettext('Saving'), function() { @@ -94,7 +95,7 @@ function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Signa var attributes = $.extend({}, this.model.attributes, { signatory_number: this.model.collection.indexOf(this.model) + 1 }); - return $(this.el).html(_.template(signatoryDetailsTemplate)(attributes)); + return HtmlUtils.setHtml(this.$el, HtmlUtils.template(signatoryDetailsTemplate)(attributes)); } }); return SignatoryDetailsView; diff --git a/cms/static/js/certificates/views/signatory_editor.js b/cms/static/js/certificates/views/signatory_editor.js index 21d53f7f20b..9c70e68a443 100644 --- a/cms/static/js/certificates/views/signatory_editor.js +++ b/cms/static/js/certificates/views/signatory_editor.js @@ -11,11 +11,12 @@ define([ 'common/js/components/views/feedback_notification', 'js/models/uploads', 'js/views/uploads', - 'text!templates/signatory-editor.underscore' + 'text!templates/signatory-editor.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], function($, _, Backbone, gettext, TemplateUtils, ViewUtils, PromptView, NotificationView, FileUploadModel, FileUploadDialog, - signatoryEditorTemplate) { + signatoryEditorTemplate, HtmlUtils) { 'use strict'; var SignatoryEditorView = Backbone.View.extend({ tagName: 'div', @@ -78,7 +79,7 @@ function($, _, Backbone, gettext, is_editing_all_collections: this.isEditingAllCollections, total_saved_signatories: this.getTotalSignatoriesOnServer() }); - return $(this.el).html(_.template(signatoryEditorTemplate)(attributes)); + return HtmlUtils.setHtml(this.$el, HtmlUtils.template(signatoryEditorTemplate)(attributes)); }, setSignatoryName: function(event) { @@ -127,10 +128,9 @@ function($, _, Backbone, gettext, deleteItem: function(event) { // Remove the specified model from the collection - if (event && event.preventDefault) { event.preventDefault(); } var model = this.model; var self = this; - var titleTextTemplate = _.template(gettext('Delete "<%= signatoryName %>" from the list of signatories?')); + var titleTextTemplate = _.template(gettext('Delete "<%- signatoryName %>" from the list of signatories?')); var confirm = new PromptView.Warning({ title: titleTextTemplate({signatoryName: model.get('name')}), message: gettext('This action cannot be undone.'), @@ -148,9 +148,9 @@ function($, _, Backbone, gettext, deleting.show(); model.destroy({ wait: true, - success: function(model) { + success: function(model2) { deleting.hide(); - self.eventAgg.trigger('onSignatoryRemoved', model); + self.eventAgg.trigger('onSignatoryRemoved', model2); } }); } @@ -165,18 +165,20 @@ function($, _, Backbone, gettext, } } }); + if (event && event.preventDefault) { event.preventDefault(); } confirm.show(); }, uploadSignatureImage: function(event) { + var upload, self, modal; event.preventDefault(); - var upload = new FileUploadModel({ + upload = new FileUploadModel({ title: gettext('Upload signature image.'), message: gettext('Image must be in PNG format.'), mimeTypes: ['image/png'] }); - var self = this; - var modal = new FileUploadDialog({ + self = this; + modal = new FileUploadDialog({ model: upload, onSuccess: function(response) { self.model.set('signature_image_path', response.asset.url); @@ -192,12 +194,13 @@ function($, _, Backbone, gettext, */ toggleValidationErrorMessage: function(modelAttribute) { var selector = 'div.add-signatory-' + modelAttribute; + var errorMessage; if (!this.model.isValid() && _.has(this.model.validationError, modelAttribute)) { // Show the error message if it is not exist before. if (!$(selector).hasClass('error')) { - var errorMessage = this.model.validationError[modelAttribute]; + errorMessage = this.model.validationError[modelAttribute]; $(selector).addClass('error'); - $(selector).append("" + errorMessage + ''); + $(selector).append(HtmlUtils.joinHtml(HtmlUtils.HTML(""), errorMessage, HtmlUtils.HTML('')).toString()); // eslint-disable-line max-len } } else { // Remove the error message. diff --git a/cms/static/js/maintenance/force_publish_course.js b/cms/static/js/maintenance/force_publish_course.js index 65e93ff725f..e7eed221d67 100644 --- a/cms/static/js/maintenance/force_publish_course.js +++ b/cms/static/js/maintenance/force_publish_course.js @@ -22,7 +22,11 @@ function($, _, gettext, ViewUtils, StringUtils, HtmlUtils) { showError = function(containerElSelector, error) { var errorWrapperElSelector, errorHtml; errorWrapperElSelector = containerElSelector + ' .wrapper-error'; - errorHtml = '
' + error + '
'; + errorHtml = HtmlUtils.joinHtml( + HtmlUtils.HTML('
'), + error, + HtmlUtils.HTML('
') + ); HtmlUtils.setHtml($(errorWrapperElSelector), HtmlUtils.HTML(errorHtml)); $(errorWrapperElSelector).css('display', 'inline-block'); $(errorWrapperElSelector).fadeOut(5000); diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js index 394883d4809..c0d8c506f4f 100644 --- a/cms/static/js/models/settings/course_details.js +++ b/cms/static/js/models/settings/course_details.js @@ -1,5 +1,8 @@ -define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js/utils/date_utils'], - function(Backbone, _, gettext, ValidationHelpers, DateUtils) { +define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js/utils/date_utils', + 'edx-ui-toolkit/js/utils/string-utils' +], + function(Backbone, _, gettext, ValidationHelpers, DateUtils, StringUtils) { + 'use strict'; var CourseDetails = Backbone.Model.extend({ defaults: { org: '', @@ -51,11 +54,17 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) { errors.end_date = gettext('The course end date must be later than the course start date.'); } - if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) { - errors.enrollment_start = gettext('The course start date must be later than the enrollment start date.'); + if (newattrs.start_date && newattrs.enrollment_start && + newattrs.start_date < newattrs.enrollment_start) { + errors.enrollment_start = gettext( + 'The course start date must be later than the enrollment start date.' + ); } - if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) { - errors.enrollment_end = gettext('The enrollment start date cannot be after the enrollment end date.'); + if (newattrs.enrollment_start && newattrs.enrollment_end && + newattrs.enrollment_start >= newattrs.enrollment_end) { + errors.enrollment_end = gettext( + 'The enrollment start date cannot be after the enrollment end date.' + ); } if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) { errors.enrollment_end = gettext('The enrollment end date cannot be after the course end date.'); @@ -78,7 +87,9 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js max: 100 }; if (!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)) { - errors.entrance_exam_minimum_score_pct = interpolate(gettext('Please enter an integer between %(min)s and %(max)s.'), range, true); + errors.entrance_exam_minimum_score_pct = StringUtils.interpolate(gettext( + 'Please enter an integer between %(min)s and %(max)s.' + ), range, true); } } if (!_.isEmpty(errors)) return errors; @@ -90,7 +101,8 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js set_videosource: function(newsource) { // newsource either is