Add json escaping to Studio

Make escaping for json simpler and more consistent in Mako templates
- add escape_json_dumps to escape and json.dumps
- add escape_js_str to escape javascript string
- refactor Studio to use escape_json_dumps in Mako templates

TNL-2646: Escape json.dumps
This commit is contained in:
Robert Raposa
2015-10-06 17:06:00 -04:00
parent 0964bf280f
commit 3682fac832
35 changed files with 173 additions and 168 deletions

View File

@@ -2,8 +2,9 @@
<%namespace name='static' file='static_content.html'/>
<%!
from django.utils.translation import ugettext as _
from django.template.defaultfilters import escapejs
import json
from openedx.core.lib.js_utils import (
escape_json_dumps, escape_js_string
)
%>
<!doctype html>
<!--[if lte IE 9]><html class="ie9 lte9" lang="${LANGUAGE_CODE}"><![endif]-->
@@ -41,7 +42,7 @@ import json
<a class="nav-skip" href="#content">${_("Skip to main content")}</a>
<script type="text/javascript">
window.baseUrl = ${json.dumps(settings.STATIC_URL)};
window.baseUrl = "${escape_js_string(settings.STATIC_URL) | n}";
var require = {baseUrl: window.baseUrl};
</script>
<script type="text/javascript" src="${static.url("js/vendor/require.js")}"></script>
@@ -79,14 +80,14 @@ import json
% if context_course:
require(['js/factories/course'], function(CourseFactory) {
CourseFactory({
id: "${context_course.id | escapejs}",
id: "${escape_js_string(context_course.id) | n}",
name: "${context_course.display_name_with_default | h}",
url_name: "${context_course.location.name | h}",
org: "${context_course.location.org | h}",
num: "${context_course.location.course | h}",
display_course_number: "${_(context_course.display_coursenumber)}",
revision: "${context_course.location.revision | h}",
self_paced: ${json.dumps(context_course.self_paced)}
self_paced: ${escape_json_dumps(context_course.self_paced) | n}
});
});
% endif

View File

@@ -2,9 +2,9 @@
<%def name="online_help_token()"><% return "certificates" %></%def>
<%namespace name='static' file='static_content.html'/>
<%!
import json
from contentstore import utils
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Course Certificates")}</%block>
@@ -30,7 +30,7 @@ CMS.User.isGlobalStaff = '${is_global_staff}'=='True' ? true : false;
<%block name="requirejs">
require(["js/certificates/factories/certificates_page_factory"], function(CertificatesPageFactory) {
CertificatesPageFactory(${json.dumps(certificates)}, "${certificate_url}", "${course_outline_url}", ${json.dumps(course_modes)}, ${json.dumps(certificate_web_view_url)}, ${json.dumps(is_active)}, ${json.dumps(certificate_activation_handler_url)} );
CertificatesPageFactory(${escape_json_dumps(certificates) | n}, "${certificate_url}", "${course_outline_url}", ${escape_json_dumps(course_modes) | n}, ${escape_json_dumps(certificate_web_view_url) | n}, ${escape_json_dumps(is_active) | n}, ${escape_json_dumps(certificate_activation_handler_url) | n} );
});
</%block>

View File

@@ -8,10 +8,9 @@ else:
%>
</%def>
<%!
import json
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${xblock.display_name_with_default} ${xblock_type_display_name(xblock) | h}</%block>
<%block name="bodyclass">is-signedin course container view-container</%block>
@@ -33,10 +32,11 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/container"], function(ContainerFactory) {
ContainerFactory(
${component_templates | n}, ${json.dumps(xblock_info) | n},
${ escape_json_dumps(component_templates) | n },
${ escape_json_dumps(xblock_info) | n },
"${action | h}",
{
isUnitPage: ${json.dumps(is_unit_page)},
isUnitPage: ${ escape_json_dumps(is_unit_page) | n },
canEdit: true
}
);

View File

@@ -2,9 +2,9 @@
<%def name="online_help_token()"><% return "updates" %></%def>
<%namespace name='static' file='static_content.html'/>
<%!
import json
from django.utils.translation import ugettext as _
from django.template.defaultfilters import escapejs
from openedx.core.lib.js_utils import escape_json_dumps
%>
## TODO decode course # from context_course into title.
@@ -26,7 +26,7 @@ from django.template.defaultfilters import escapejs
"${updates_url}",
"${handouts_locator | escapejs}",
"${base_asset_url}",
${json.dumps(push_notification_enabled)}
${escape_json_dumps(push_notification_enabled) | n}
);
});
</%block>

View File

@@ -1,10 +1,10 @@
<%inherit file="base.html" />
<%def name="online_help_token()"><% return "outline" %></%def>
<%!
import json
import logging
from util.date_utils import get_default_time_display
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
from contentstore.utils import reverse_usage_url
from microsite_configuration import microsite
%>
@@ -15,7 +15,7 @@ from microsite_configuration import microsite
<%block name="requirejs">
require(["js/factories/outline"], function (OutlineFactory) {
OutlineFactory(${json.dumps(course_structure) | n}, ${json.dumps(initial_state) | n});
OutlineFactory(${escape_json_dumps(course_structure) | n}, ${escape_json_dumps(initial_state) | n});
});
</%block>

View File

@@ -11,7 +11,7 @@ else:
<%!
from django.utils.translation import ugettext as _
import json
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">
%if library:
@@ -24,11 +24,11 @@ else:
<%block name="requirejs">
% if in_err:
var hasUnit = ${json.dumps(bool(unit))},
var hasUnit = ${escape_json_dumps(bool(unit)) | n},
editUnitUrl = "${edit_unit_url or ""}",
courselikeHomeUrl = "${courselike_home_url or ""}",
is_library = ${json.dumps(library)}
errMsg = ${json.dumps(raw_err_msg or "")};
is_library = ${escape_json_dumps(library) | n}
errMsg = ${escape_json_dumps(raw_err_msg or "") | n};
require(["js/factories/export"], function(ExportFactory) {
ExportFactory(hasUnit, editUnitUrl, courselikeHomeUrl, is_library, errMsg);

View File

@@ -3,9 +3,9 @@
<%def name="experiment_group_configurations_help_token()"><% return "group_configurations" %></%def>
<%namespace name='static' file='static_content.html'/>
<%!
import json
from contentstore import utils
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Group Configurations")}</%block>
@@ -21,7 +21,7 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/group_configurations"], function(GroupConfigurationsFactory) {
GroupConfigurationsFactory(${json.dumps(should_show_experiment_groups)}, ${json.dumps(experiment_group_configurations)}, ${json.dumps(content_group_configuration)}, "${group_configuration_url}", "${course_outline_url}");
GroupConfigurationsFactory(${escape_json_dumps(should_show_experiment_groups) | n}, ${escape_json_dumps(experiment_group_configurations) | n}, ${escape_json_dumps(content_group_configuration) | n}, "${group_configuration_url}", "${course_outline_url}");
});
</%block>

View File

@@ -10,7 +10,7 @@ else:
<%namespace name='static' file='static_content.html'/>
<%!
from django.utils.translation import ugettext as _
import json
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">
%if library:
@@ -239,6 +239,6 @@ else:
<%block name="requirejs">
require(["js/factories/import"], function(ImportFactory) {
ImportFactory("${import_status_url}", ${json.dumps(library)});
ImportFactory("${import_status_url}", ${escape_json_dumps(library) | n});
});
</%block>

View File

@@ -1,10 +1,9 @@
<%inherit file="base.html" />
<%def name="online_help_token()"><% return "content_libraries" %></%def>
<%!
import json
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${context_library.display_name_with_default} ${xblock_type_display_name(context_library)}</%block>
<%block name="bodyclass">is-signedin course container view-container view-library</%block>
@@ -25,8 +24,8 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/library"], function(LibraryFactory) {
LibraryFactory(
${component_templates | n},
${json.dumps(xblock_info) | n},
${escape_json_dumps(component_templates) | n},
${escape_json_dumps(xblock_info) | n},
{
isUnitPage: false,
page_size: 10,

View File

@@ -1,8 +1,8 @@
<%inherit file="base.html" />
<%!
import json
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%def name="online_help_token()"><% return "team_course" %></%def>
<%block name="title">${_("Course Team Settings")}</%block>
@@ -115,7 +115,7 @@ from django.core.urlresolvers import reverse
require(["js/factories/manage_users"], function(ManageCourseUsersFactory) {
ManageCourseUsersFactory(
"${context_course.display_name | h}",
${json.dumps(users)},
${escape_json_dumps(users) | n},
"${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': unicode(context_course.id), 'email': '@@EMAIL@@'})}",
${ request.user.id },
${str(allow_actions).lower()}

View File

@@ -1,8 +1,8 @@
<%inherit file="base.html" />
<%!
import json
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%def name="online_help_token()"><% return "team_library" %></%def>
<%block name="title">${_("Library User Access")}</%block>
@@ -108,7 +108,7 @@ from django.core.urlresolvers import reverse
require(["js/factories/manage_users_lib"], function(ManageLibraryUsersFactory) {
ManageLibraryUsersFactory(
"${context_library.display_name_with_default | h}",
${json.dumps(users)},
${escape_json_dumps(users) | n},
"${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': library_key, 'email': '@@EMAIL@@'})}",
${ request.user.id },
${str(allow_actions).lower()}

View File

@@ -5,10 +5,10 @@
<%namespace name='static' file='static_content.html'/>
<%!
import json
import urllib
from django.utils.translation import ugettext as _
from contentstore import utils
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="header_extras">
@@ -31,7 +31,7 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
<%block name="requirejs">
require(["js/factories/settings"], function(SettingsFactory) {
SettingsFactory("${details_url}", ${json.dumps(show_min_grade_warning)});
SettingsFactory("${details_url}", ${escape_json_dumps(show_min_grade_warning) | n});
});
</%block>

View File

@@ -4,7 +4,7 @@
<%!
from django.utils.translation import ugettext as _
from contentstore import utils
from openedx.core.lib.json_utils import escape_json_dumps
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Advanced Settings")}</%block>
<%block name="bodyclass">is-signedin course advanced view-settings</%block>

View File

@@ -8,6 +8,8 @@
import json
from contentstore import utils
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
from models.settings.course_details import CourseSettingsEncoder
%>
<%block name="header_extras">
@@ -23,7 +25,7 @@
</%block>
<%block name="requirejs">
require(["js/factories/settings_graders"], function(SettingsGradersFactory) {
SettingsGradersFactory(_.extend(${course_details|n}, {is_credit_course: ${json.dumps(is_credit_course)}}), "${grading_url}");
SettingsGradersFactory(_.extend(${escape_json_dumps(course_details, cls=CourseSettingsEncoder) | n}, {is_credit_course: ${escape_json_dumps(is_credit_course) | n}}), "${grading_url}");
});
</%block>

View File

@@ -2,7 +2,7 @@
from django.utils.translation import ugettext as _
from contentstore.views.helpers import xblock_studio_url
from contentstore.utils import is_visible_to_specific_content_groups
import json
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%
xblock_url = xblock_studio_url(xblock)
@@ -10,7 +10,7 @@ show_inline = xblock.has_children and not xblock_url
section_class = "level-nesting" if show_inline else "level-element"
collapsible_class = "is-collapsible" if xblock.has_children else ""
label = xblock.display_name_with_default or xblock.scope_ids.block_type
messages = json.dumps(xblock.validate().to_json())
messages = xblock.validate().to_json()
%>
<%namespace name='static' file='static_content.html'/>
@@ -24,7 +24,7 @@ messages = json.dumps(xblock.validate().to_json())
<script>
require(["jquery", "js/factories/xblock_validation"], function($, XBlockValidationFactory) {
XBlockValidationFactory(
${messages},
${escape_json_dumps(messages) | n},
$.parseJSON("${bool(xblock_url)}".toLowerCase()), // xblock_url will be None or a string
$.parseJSON("${bool(is_root)}".toLowerCase()), // is_root will be None or a boolean
$('div.xblock-validation-messages[data-locator="${xblock.location | h}"]')

View File

@@ -2,8 +2,8 @@
<%def name="online_help_token()"><% return "textbooks" %></%def>
<%namespace name='static' file='static_content.html'/>
<%!
import json
from django.utils.translation import ugettext as _
from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Textbooks")}</%block>
@@ -28,7 +28,7 @@ CMS.URL.LMS_BASE = "${settings.LMS_BASE}"
</%block>
<%block name="requirejs">
require(["js/factories/textbooks"], function(TextbooksFactory) {
TextbooksFactory(${json.dumps(textbooks)});
TextbooksFactory(${escape_json_dumps(textbooks) | n});
});
</%block>