Commit 7a9991e9 by Mushtaq Ali

Studio homepage escaping

parent a26d5764
......@@ -9,6 +9,9 @@ from mock import patch, Mock
import ddt
from django.test import RequestFactory
from django.test.client import Client
from common.test.utils import XssTestMixin
from xmodule.course_module import CourseSummary
from contentstore.views.course import (_accessible_courses_list, _accessible_courses_list_from_groups,
......@@ -30,7 +33,7 @@ USER_COURSES_COUNT = 50
@ddt.ddt
class TestCourseListing(ModuleStoreTestCase):
class TestCourseListing(ModuleStoreTestCase, XssTestMixin):
"""
Unit tests for getting the list of courses for a logged in user
"""
......@@ -72,6 +75,30 @@ class TestCourseListing(ModuleStoreTestCase):
self.client.logout()
ModuleStoreTestCase.tearDown(self)
def test_course_listing_is_escaped(self):
"""
Tests course listing returns escaped data.
"""
escaping_content = "<script>alert('ESCAPE')</script>"
# Make user staff to access course listing
self.user.is_staff = True
self.user.save() # pylint: disable=no-member
self.client = Client()
self.client.login(username=self.user.username, password='test')
# Change 'display_coursenumber' field and update the course.
course = CourseFactory.create()
course.display_coursenumber = escaping_content
course = self.store.update_item(course, self.user.id) # pylint: disable=no-member
self.assertEqual(course.display_coursenumber, escaping_content)
# Check if response is escaped
response = self.client.get('/home')
self.assertEqual(response.status_code, 200)
self.assert_no_xss(response, escaping_content)
def test_get_course_list(self):
"""
Test getting courses with new access group format e.g. 'instructor_edx.course.run'
......
......@@ -10,6 +10,7 @@ from provider.constants import CONFIDENTIAL
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
from openedx.core.djangolib.markup import escape
from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
......@@ -63,7 +64,7 @@ class TestProgramListing(ProgramsApiConfigMixin, ProgramsDataMixin, SharedModule
self.mock_programs_api(data={'results': []})
response = self.client.get(self.studio_home)
self.assertIn("You haven't created any programs yet.", response.content)
self.assertIn(escape("You haven't created any programs yet."), response.content)
# When data is provided, expect a program listing.
self.mock_programs_api()
......
<%! from django.utils.translation import ugettext as _ %>
<%! from openedx.core.djangolib.markup import HTML, ugettext as _ %>
<%page expression_filter="h"/>
<%inherit file="base.html" />
......@@ -79,7 +80,10 @@
## Translators: This is an example for the name of the organization sponsoring a course, seen when filling out the form to create a new course. The organization name cannot contain spaces.
## Translators: "e.g. UniversityX or OrganizationX" is a placeholder displayed when user put no data into this field.
<input class="new-course-org" id="new-course-org" type="text" name="new-course-org" required placeholder="${_('e.g. UniversityX or OrganizationX')}" aria-describedby="tip-new-course-org tip-error-new-course-org" />
<span class="tip" id="tip-new-course-org">${_("The name of the organization sponsoring the course.")} <strong>${_("Note: The organization name is part of the course URL")}</strong> ${_("This cannot be changed, but you can set a different display name in Advanced Settings later.")}</span>
<span class="tip" id="tip-new-course-org">${_("The name of the organization sponsoring the course. {strong_start}Note: The organization name is part of the course URL.{strong_end} This cannot be changed, but you can set a different display name in Advanced Settings later.").format(
strong_start=HTML('<strong>'),
strong_end=HTML('</strong>'),
)}</span>
<span class="tip tip-error is-hiding" id="tip-error-new-course-org"></span>
</li>
......@@ -89,7 +93,10 @@
## seen when filling out the form to create a new course. The number here is
## short for "Computer Science 101". It can contain letters but cannot contain spaces.
<input class="new-course-number" id="new-course-number" type="text" name="new-course-number" required placeholder="${_('e.g. CS101')}" aria-describedby="tip-new-course-number tip-error-new-course-number" />
<span class="tip" id="tip-new-course-number">${_("The unique number that identifies your course within your organization.")} <strong>${_("Note: This is part of your course URL, so no spaces or special characters are allowed and it cannot be changed.")}</strong></span>
<span class="tip" id="tip-new-course-number">${_("The unique number that identifies your course within your organization. {strong_start}Note: This is part of your course URL, so no spaces or special characters are allowed and it cannot be changed.{strong_end}").format(
strong_start=HTML('<strong>'),
strong_end=HTML('</strong>'),
)}</span>
<span class="tip tip-error is-hiding" id="tip-error-new-course-number"></span>
</li>
......@@ -98,7 +105,10 @@
## Translators: This is an example for the "run" used to identify different
## instances of a course, seen when filling out the form to create a new course.
<input class="new-course-run" id="new-course-run" type="text" name="new-course-run" required placeholder="${_('e.g. 2014_T1')}" aria-describedby="tip-new-course-run tip-error-new-course-run" />
<span class="tip" id="tip-new-course-run">${_("The term in which your course will run.")} <strong>${_("Note: This is part of your course URL, so no spaces or special characters are allowed and it cannot be changed.")}</strong></span>
<span class="tip" id="tip-new-course-run">${_("The term in which your course will run. {strong_start}Note: This is part of your course URL, so no spaces or special characters are allowed and it cannot be changed.{strong_end}").format(
strong_start=HTML('<strong>'),
strong_end=HTML('</strong>'),
)}</span>
<span class="tip tip-error is-hiding" id="tip-error-new-course-run"></span>
</li>
</ol>
......@@ -155,7 +165,10 @@
## for "Computer Science Problems". The example number may contain letters
## but must not contain spaces.
<input class="new-library-number" id="new-library-number" type="text" name="new-library-number" required placeholder="${_('e.g. CSPROB')}" aria-describedby="tip-new-library-number tip-error-new-library-number" />
<span class="tip" id="tip-new-library-number">${_("The unique code that identifies this library.")} <strong>${_("Note: This is part of your library URL, so no spaces or special characters are allowed.")}</strong> ${_("This cannot be changed.")}</span>
<span class="tip" id="tip-new-library-number">${_("The unique code that identifies this library. {strong_start}Note: This is part of your library URL, so no spaces or special characters are allowed.{strong_end} This cannot be changed.").format(
strong_start=HTML('<strong>'),
strong_end=HTML('</strong>'),
)}</span>
<span class="tip tip-error is-hiding" id="tip-error-new-library-number"></span>
</li>
</ol>
......@@ -181,10 +194,10 @@
%for course_info in sorted(in_process_course_actions, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''):
<!-- STATE: re-run is processing -->
%if course_info['is_in_progress']:
<li class="wrapper-course has-status" data-course-key="${course_info['course_key'] | h}">
<li class="wrapper-course has-status" data-course-key="${course_info['course_key']}">
<div class="course-item course-rerun is-processing">
<div class="course-details" href="#">
<h3 class="course-title">${course_info['display_name'] | h}</h3>
<h3 class="course-title">${course_info['display_name']}</h3>
<div class="course-metadata">
<span class="course-org metadata-item">
......@@ -216,8 +229,8 @@
<div class="status-message">
<p class="copy">${_('The new course will be added to your course list in 5-10 minutes. Return to this page or {link_start}refresh it{link_end} to update the course list. The new course will need some manual configuration.').format(
link_start='<a href="#" class="action-reload">',
link_end='</a>',
link_start=HTML('<a href="#" class="action-reload">'),
link_end=HTML('</a>'),
)}</p>
</div>
</li>
......@@ -227,10 +240,10 @@
<!-- STATE: re-run has error -->
%if course_info['is_failed']:
<li class="wrapper-course has-status" data-course-key="${course_info['course_key'] | h}">
<li class="wrapper-course has-status" data-course-key="${course_info['course_key']}">
<div class="course-item course-rerun has-error">
<div class="course-details" href="#">
<h3 class="course-title">${course_info['display_name'] | h}</h3>
<h3 class="course-title">${course_info['display_name']}</h3>
<div class="course-metadata">
<span class="course-org metadata-item">
......@@ -296,9 +309,9 @@
<div class="courses courses-tab active">
<ul class="list-courses">
%for course_info in sorted(courses, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''):
<li class="course-item" data-course-key="${course_info['course_key'] | h}">
<li class="course-item" data-course-key="${course_info['course_key']}">
<a class="course-link" href="${course_info['url']}">
<h3 class="course-title">${course_info['display_name'] | h}</h3>
<h3 class="course-title">${course_info['display_name']}</h3>
<div class="course-metadata">
<span class="course-org metadata-item">
......@@ -450,7 +463,7 @@
%for library_info in sorted(libraries, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''):
<li class="course-item">
<a class="library-link" href="${library_info['url']}">
<h3 class="course-title">${library_info['display_name'] | h}</h3>
<h3 class="course-title">${library_info['display_name']}</h3>
<div class="course-metadata">
<span class="course-org metadata-item">
......@@ -508,12 +521,12 @@
<li class="course-item">
<a class="program-link" href=${program_authoring_url + str(program['id'])}>
<h3 class="course-title">${program['name'] | h}</h3>
<h3 class="course-title">${program['name']}</h3>
<div class="course-metadata">
<span class="course-org metadata-item">
<!-- As of this writing, programs can only be owned by one organization. If that constraint is relaxed, this will need to be revisited. -->
<span class="label">${_("Organization:")}</span> <span class="value">${program['organizations'][0]['key'] | h}</span>
<span class="label">${_("Organization:")}</span> <span class="value">${program['organizations'][0]['key']}</span>
</span>
</div>
</a>
......@@ -565,8 +578,8 @@
<p>${_("In order to create courses in {studio_name}, you must {link_start}contact {platform_name} staff to help you create a course{link_end}.").format(
studio_name=settings.STUDIO_NAME,
platform_name=settings.PLATFORM_NAME,
link_start='<a href="mailto:{email}">'.format(email=settings.FEATURES.get('STUDIO_REQUEST_EMAIL','')),
link_end="</a>",
link_start=HTML('<a href="mailto:{email}">').format(email=settings.FEATURES.get('STUDIO_REQUEST_EMAIL','')),
link_end=HTML("</a>"),
)}</p>
</div>
% endif
......@@ -580,17 +593,11 @@
% elif course_creator_status == "denied":
<div class="bit">
<h3 class="title title-3">${_("Can I create courses in {studio_name}?").format(studio_name=settings.STUDIO_NAME)}</h3>
<%!
from django.conf import settings
help_link_start = '<a href="mailto:{email}">'.format(email=settings.TECH_SUPPORT_EMAIL)
help_link_end = '</a>'
%>
<p>${_("Your request to author courses in {studio_name} has been denied. Please {link_start}contact {platform_name} Staff with further questions{link_end}.").format(
studio_name=settings.STUDIO_NAME,
platform_name=settings.PLATFORM_NAME,
link_start=help_link_start,
link_end=help_link_end,
link_start=HTML('<a href="mailto:{email}">').format(email=settings.TECH_SUPPORT_EMAIL),
link_end=HTML('</a>'),
)}</p>
</div>
......@@ -603,14 +610,14 @@ help_link_end = '</a>'
<section class="content">
<article class="content-primary" role="main">
<div class="introduction">
<h2 class="title">${_("Thanks for signing up, %(name)s!") % dict(name= user.username)}</h2>
<h2 class="title">${_("Thanks for signing up, {name}!").format(name=user.username)}</h2>
</div>
<div class="notice notice-incontext notice-instruction notice-instruction-verification">
<div class="msg">
<h3 class="title">${_("We need to verify your email address")}</h3>
<div class="copy">
<p>${_('Almost there! In order to complete your sign up we need you to verify your email address (%(email)s). An activation message and next steps should be waiting for you there.') % dict(email=user.email)}</p>
<p>${_('Almost there! In order to complete your sign up we need you to verify your email address ({email}). An activation message and next steps should be waiting for you there.').format(email=user.email)}</p>
</div>
</div>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment