Merge pull request #2939 from edx/zub/story/disableunicodecourseids
Enable/disable unicodes in course id's
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#pylint: disable=E1101
|
||||
|
||||
import json
|
||||
@@ -1423,6 +1424,15 @@ class ContentStoreTest(ModuleStoreTestCase):
|
||||
self.assertTrue(CourseEnrollment.is_enrolled(self.user, _get_course_id(test_course_data)))
|
||||
return test_course_data
|
||||
|
||||
def assert_create_course_failed(self, error_message):
|
||||
"""
|
||||
Checks that the course not created.
|
||||
"""
|
||||
resp = self.client.ajax_post('/course', self.course_data)
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
data = parse_json(resp)
|
||||
self.assertEqual(data['error'], error_message)
|
||||
|
||||
def test_create_course_check_forum_seeding(self):
|
||||
"""Test new course creation and verify forum seeding """
|
||||
test_course_data = self.assert_created_course(number_suffix=uuid4().hex)
|
||||
@@ -1562,6 +1572,21 @@ class ContentStoreTest(ModuleStoreTestCase):
|
||||
auth.add_users(self.user, CourseCreatorRole(), self.user)
|
||||
self.assert_created_course()
|
||||
|
||||
def test_create_course_with_unicode_in_id_disabled(self):
|
||||
"""
|
||||
Test new course creation with feature setting: ALLOW_UNICODE_COURSE_ID disabled.
|
||||
"""
|
||||
with mock.patch.dict('django.conf.settings.FEATURES', {'ALLOW_UNICODE_COURSE_ID': False}):
|
||||
error_message = "Special characters not allowed in organization, course number, and course run."
|
||||
self.course_data['org'] = u'Юникода'
|
||||
self.assert_create_course_failed(error_message)
|
||||
|
||||
self.course_data['number'] = u'échantillon'
|
||||
self.assert_create_course_failed(error_message)
|
||||
|
||||
self.course_data['run'] = u'όνομα'
|
||||
self.assert_create_course_failed(error_message)
|
||||
|
||||
def assert_course_permission_denied(self):
|
||||
"""
|
||||
Checks that the course did not get created due to a PermissionError.
|
||||
@@ -2073,7 +2098,7 @@ def _course_factory_create_course():
|
||||
|
||||
def _get_course_id(test_course_data):
|
||||
"""Returns the course ID (org/number/run)."""
|
||||
return "{org}/{number}/{run}".format(**test_course_data)
|
||||
return u"{org}/{number}/{run}".format(**test_course_data)
|
||||
|
||||
|
||||
def _test_no_locations(test, resp, status_code=200, html=True):
|
||||
|
||||
@@ -36,6 +36,7 @@ from models.settings.course_details import CourseDetails, CourseSettingsEncoder
|
||||
from models.settings.course_grading import CourseGradingModel
|
||||
from models.settings.course_metadata import CourseMetadata
|
||||
from util.json_request import expect_json
|
||||
from util.string_utils import _has_non_ascii_characters
|
||||
|
||||
from .access import has_course_access
|
||||
from .tabs import initialize_course_tabs
|
||||
@@ -266,6 +267,7 @@ def course_listing(request):
|
||||
'user': request.user,
|
||||
'request_course_creator_url': reverse('contentstore.views.request_course_creator'),
|
||||
'course_creator_status': _get_course_creator_status(request.user),
|
||||
'allow_unicode_course_id': settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID', False)
|
||||
})
|
||||
|
||||
|
||||
@@ -313,6 +315,14 @@ def create_new_course(request):
|
||||
display_name = request.json.get('display_name')
|
||||
run = request.json.get('run')
|
||||
|
||||
# allow/disable unicode characters in course_id according to settings
|
||||
if not settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID'):
|
||||
if _has_non_ascii_characters(org) or _has_non_ascii_characters(number) or _has_non_ascii_characters(run):
|
||||
return JsonResponse(
|
||||
{'error': _('Special characters not allowed in organization, course number, and course run.')},
|
||||
status=400
|
||||
)
|
||||
|
||||
try:
|
||||
dest_location = Location(u'i4x', org, number, u'course', run)
|
||||
except InvalidLocationError as error:
|
||||
|
||||
@@ -86,6 +86,9 @@ FEATURES = {
|
||||
|
||||
# Turn on/off Microsites feature
|
||||
'USE_MICROSITES': False,
|
||||
|
||||
# Allow creating courses with non-ascii characters in the course id
|
||||
'ALLOW_UNICODE_COURSE_ID': False,
|
||||
}
|
||||
ENABLE_JASMINE = False
|
||||
|
||||
|
||||
@@ -84,8 +84,15 @@ require(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
|
||||
if (required) {
|
||||
return required;
|
||||
}
|
||||
if (/\s/g.test(item)) {
|
||||
return gettext('Please do not use any spaces in this field.');
|
||||
if ($('.allow-unicode-course-id').val() === 'True'){
|
||||
if (/\s/g.test(item)) {
|
||||
return gettext('Please do not use any spaces in this field.');
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item !== encodeURIComponent(item)) {
|
||||
return gettext('Please do not use any spaces or special characters in this field.');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
@@ -123,6 +123,7 @@ require(["domReady!", "jquery", "jquery.form", "js/index"], function(doc, $) {
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<input type="hidden" value="${ allow_unicode_course_id }" class="allow-unicode-course-id" />
|
||||
<input type="submit" value="${_('Create')}" class="action action-primary new-course-save" />
|
||||
<input type="button" value="${_('Cancel')}" class="action action-secondary action-cancel new-course-cancel" />
|
||||
</div>
|
||||
|
||||
@@ -10,3 +10,17 @@ def str_to_bool(str):
|
||||
An error will be thrown for non-string input (besides None).
|
||||
"""
|
||||
return False if str is None else str.lower() == "true"
|
||||
|
||||
|
||||
def _has_non_ascii_characters(data_string):
|
||||
"""
|
||||
Check if provided string contains non ascii characters
|
||||
|
||||
:param data_string: basestring or unicode object
|
||||
"""
|
||||
try:
|
||||
data_string.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user