Skip to content

Commit

Permalink
Merge pull request #24258 from edx/aakbar/backport-sustaining-xss-fix
Browse files Browse the repository at this point in the history
Aakbar/backport sustaining xss fix
  • Loading branch information
Ali-D-Akbar authored Jun 19, 2020
2 parents b73e1ba + 1ab907b commit 54bf9f6
Show file tree
Hide file tree
Showing 16 changed files with 213 additions and 174 deletions.
7 changes: 4 additions & 3 deletions cms/static/js/certificates/views/certificate_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 5 additions & 9 deletions cms/static/js/certificates/views/certificate_preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -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
Expand All @@ -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({
Expand Down
15 changes: 8 additions & 7 deletions cms/static/js/certificates/views/signatory_details.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down
27 changes: 15 additions & 12 deletions cms/static/js/certificates/views/signatory_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.'),
Expand All @@ -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);
}
});
}
Expand All @@ -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);
Expand All @@ -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("<span class='message-error'>" + errorMessage + '</span>');
$(selector).append(HtmlUtils.joinHtml(HtmlUtils.HTML("<span class='message-error'>"), errorMessage, HtmlUtils.HTML('</span>')).toString()); // eslint-disable-line max-len
}
} else {
// Remove the error message.
Expand Down
6 changes: 5 additions & 1 deletion cms/static/js/maintenance/force_publish_course.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ function($, _, gettext, ViewUtils, StringUtils, HtmlUtils) {
showError = function(containerElSelector, error) {
var errorWrapperElSelector, errorHtml;
errorWrapperElSelector = containerElSelector + ' .wrapper-error';
errorHtml = '<div class="error" aria-live="polite" id="course-id-error">' + error + '</div>';
errorHtml = HtmlUtils.joinHtml(
HtmlUtils.HTML('<div class="error" aria-live="polite" id="course-id-error">'),
error,
HtmlUtils.HTML('</div>')
);
HtmlUtils.setHtml($(errorWrapperElSelector), HtmlUtils.HTML(errorHtml));
$(errorWrapperElSelector).css('display', 'inline-block');
$(errorWrapperElSelector).fadeOut(5000);
Expand Down
28 changes: 20 additions & 8 deletions cms/static/js/models/settings/course_details.js
Original file line number Diff line number Diff line change
@@ -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: '',
Expand Down Expand Up @@ -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.');
Expand All @@ -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;
Expand All @@ -90,7 +101,8 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js
set_videosource: function(newsource) {
// newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string
// returns the videosource for the preview which iss the key whose speed is closest to 1
if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({intro_video: null}, {validate: true});
if (_.isEmpty(newsource) &&
!_.isEmpty(this.get('intro_video'))) this.set({intro_video: null}, {validate: true});
// TODO remove all whitespace w/in string
else {
if (this.get('intro_video') !== newsource) this.set('intro_video', newsource, {validate: true});
Expand Down
27 changes: 18 additions & 9 deletions cms/static/js/models/settings/course_grading_policy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* globals _ */
define(['backbone', 'js/models/location', 'js/collections/course_grader'],
function(Backbone, Location, CourseGraderCollection) {
define(['backbone', 'js/models/location', 'js/collections/course_grader', 'edx-ui-toolkit/js/utils/string-utils'],
function(Backbone, Location, CourseGraderCollection, StringUtils) {
'use strict';
var CourseGradingPolicy = Backbone.Model.extend({
defaults: {
graders: null, // CourseGraderCollection
Expand Down Expand Up @@ -37,9 +38,15 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader'],
},
gracePeriodToDate: function() {
var newDate = new Date();
if (this.has('grace_period') && this.get('grace_period').hours) { newDate.setHours(this.get('grace_period').hours); } else newDate.setHours(0);
if (this.has('grace_period') && this.get('grace_period').minutes) { newDate.setMinutes(this.get('grace_period').minutes); } else newDate.setMinutes(0);
if (this.has('grace_period') && this.get('grace_period').seconds) { newDate.setSeconds(this.get('grace_period').seconds); } else newDate.setSeconds(0);
if (this.has('grace_period') && this.get('grace_period').hours) {
newDate.setHours(this.get('grace_period').hours);
} else newDate.setHours(0);
if (this.has('grace_period') && this.get('grace_period').minutes) {
newDate.setMinutes(this.get('grace_period').minutes);
} else newDate.setMinutes(0);
if (this.has('grace_period') && this.get('grace_period').seconds) {
newDate.setSeconds(this.get('grace_period').seconds);
} else newDate.setSeconds(0);

return newDate;
},
Expand All @@ -62,6 +69,7 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader'],
return parseInt(minimum_grade_credit);
},
validate: function(attrs) {
var minimumGradeCutoff;
if (_.has(attrs, 'grace_period')) {
if (attrs.grace_period === null) {
return {
Expand All @@ -71,12 +79,13 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader'],
}
if (this.get('is_credit_course') && _.has(attrs, 'minimum_grade_credit')) {
// Getting minimum grade cutoff value
var minimum_grade_cutoff = _.min(_.values(attrs.grade_cutoffs));
if (isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || attrs.minimum_grade_credit < minimum_grade_cutoff) {
minimumGradeCutoff = _.min(_.values(attrs.grade_cutoffs));
if (isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null ||
attrs.minimum_grade_credit < minimumGradeCutoff) {
return {
minimum_grade_credit: interpolate(
minimum_grade_credit: StringUtils.interpolate(
gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'),
{minimum_grade_cutoff: minimum_grade_cutoff * 100},
{minimum_grade_cutoff: minimumGradeCutoff * 100},
true
)
};
Expand Down
1 change: 1 addition & 0 deletions cms/static/js/views/abstract_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ define(['js/views/baseview', 'underscore'], function(BaseView, _) {
// Backbone model cid is only unique within the collection.
this.uniqueId = _.uniqueId(templateName + '_');
this.template = this.loadTemplate(templateName);
// xss-lint: disable=javascript-jquery-html
this.$el.html(this.template({model: this.model, uniqueId: this.uniqueId}));
this.listenTo(this.model, 'change', this.render);
this.render();
Expand Down
Loading

0 comments on commit 54bf9f6

Please sign in to comment.