Commit a0904cff by Carson Gee

Merge pull request #5 from mitocw/mitx-hotfix-rc-20140828

Mitx hotfix rc 20140828
parents c99ac45a de9ff565
""" """
Script for exporting all courseware from Mongo to a directory Script for exporting all courseware from Mongo to a directory and listing the courses which failed to export
""" """
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.xml_exporter import export_to_xml from xmodule.modulestore.xml_exporter import export_to_xml
...@@ -8,35 +8,52 @@ from xmodule.contentstore.django import contentstore ...@@ -8,35 +8,52 @@ from xmodule.contentstore.django import contentstore
class Command(BaseCommand): class Command(BaseCommand):
"""Export all courses from mongo to the specified data directory""" """
help = 'Export all courses from mongo to the specified data directory' Export all courses from mongo to the specified data directory and list the courses which failed to export
"""
help = 'Export all courses from mongo to the specified data directory and list the courses which failed to export'
def handle(self, *args, **options): def handle(self, *args, **options):
"Execute the command" """
Execute the command
"""
if len(args) != 1: if len(args) != 1:
raise CommandError("export requires one argument: <output path>") raise CommandError("export requires one argument: <output path>")
output_path = args[0] output_path = args[0]
courses, failed_export_courses = export_courses_to_output_path(output_path)
cs = contentstore()
ms = modulestore() print("=" * 80)
root_dir = output_path print(u"=" * 30 + u"> Export summary")
courses = ms.get_courses() print(u"Total number of courses to export: {0}".format(len(courses)))
print(u"Total number of courses which failed to export: {0}".format(len(failed_export_courses)))
print("%d courses to export:" % len(courses)) print(u"List of export failed courses ids:")
cids = [x.id for x in courses] print(u"\n".join(failed_export_courses))
print(cids) print("=" * 80)
for course_id in cids:
def export_courses_to_output_path(output_path):
print("-"*77) """
print("Exporting course id = {0} to {1}".format(course_id, output_path)) Export all courses to target directory and return the list of courses which failed to export
"""
if 1: content_store = contentstore()
try: module_store = modulestore()
course_dir = course_id.replace('/', '...') root_dir = output_path
export_to_xml(ms, cs, course_id, root_dir, course_dir) courses = module_store.get_courses()
except Exception as err:
print("="*30 + "> Oops, failed to export %s" % course_id) course_ids = [x.id for x in courses]
print("Error:") failed_export_courses = []
print(err)
for course_id in course_ids:
print(u"-" * 80)
print(u"Exporting course id = {0} to {1}".format(course_id, output_path))
try:
course_dir = course_id.to_deprecated_string().replace('/', '...')
export_to_xml(module_store, content_store, course_id, root_dir, course_dir)
except Exception as err: # pylint: disable=broad-except
failed_export_courses.append(unicode(course_id))
print(u"=" * 30 + u"> Oops, failed to export {0}".format(course_id))
print(u"Error:")
print(err)
return courses, failed_export_courses
"""
Test for export all courses.
"""
import shutil
from tempfile import mkdtemp
from contentstore.management.commands.export_all_courses import export_courses_to_output_path
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
class ExportAllCourses(ModuleStoreTestCase):
"""
Tests exporting all courses.
"""
def setUp(self):
""" Common setup. """
self.store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo)
self.temp_dir = mkdtemp()
self.first_course = CourseFactory.create(org="test", course="course1", display_name="run1")
self.second_course = CourseFactory.create(org="test", course="course2", display_name="run2")
def test_export_all_courses(self):
"""
Test exporting good and faulty courses
"""
# check that both courses exported successfully
courses, failed_export_courses = export_courses_to_output_path(self.temp_dir)
self.assertEqual(len(courses), 2)
self.assertEqual(len(failed_export_courses), 0)
# manually make second course faulty and check that it fails on export
second_course_id = self.second_course.id
self.store.collection.update(
{'_id.org': second_course_id.org, '_id.course': second_course_id.course, '_id.name': second_course_id.run},
{'$set': {'metadata.tags': 'crash'}}
)
courses, failed_export_courses = export_courses_to_output_path(self.temp_dir)
self.assertEqual(len(courses), 2)
self.assertEqual(len(failed_export_courses), 1)
self.assertEqual(failed_export_courses[0], unicode(second_course_id))
def tearDown(self):
""" Common cleanup. """
shutil.rmtree(self.temp_dir)
...@@ -734,16 +734,18 @@ oauth_consumer_key="", oauth_signature="frVp4JuvT1mVXlxktiAUjQ7%2F1cw%3D"'} ...@@ -734,16 +734,18 @@ oauth_consumer_key="", oauth_signature="frVp4JuvT1mVXlxktiAUjQ7%2F1cw%3D"'}
oauth_headers = dict(oauth_params) oauth_headers = dict(oauth_params)
oauth_signature = oauth_headers.pop('oauth_signature') oauth_signature = oauth_headers.pop('oauth_signature')
mock_request = mock.Mock( mock_request = mock.Mock(
uri=unicode(urllib.unquote(request.url)), uri=unicode(urllib.unquote(self.get_outcome_service_url())),
http_method=unicode(request.method), http_method=unicode(request.method),
params=oauth_headers.items(), params=oauth_headers.items(),
signature=oauth_signature signature=oauth_signature
) )
if oauth_body_hash != oauth_headers.get('oauth_body_hash'): if oauth_body_hash != oauth_headers.get('oauth_body_hash'):
log.error("OAuth body hash verification failed, provided: {} calculated: {}, for url: {}, body is: {}".format(oauth_headers.get('oauth_body_hash'),oauth_body_hash,self.get_outcome_service_url(),request.body))
raise LTIError("OAuth body hash verification is failed.") raise LTIError("OAuth body hash verification is failed.")
if not signature.verify_hmac_sha1(mock_request, client_secret): if not signature.verify_hmac_sha1(mock_request, client_secret):
log.error("OAuth signature verification failed, for url:{}".format(oauth_headers,self.get_outcome_service_url()))
raise LTIError("OAuth signature verification is failed.") raise LTIError("OAuth signature verification is failed.")
def get_client_key_secret(self): def get_client_key_secret(self):
......
...@@ -55,7 +55,10 @@ class CustomTagDescriptor(RawDescriptor): ...@@ -55,7 +55,10 @@ class CustomTagDescriptor(RawDescriptor):
# cdodge: look up the template as a module # cdodge: look up the template as a module
template_loc = self.location.replace(category='custom_tag_template', name=template_name) template_loc = self.location.replace(category='custom_tag_template', name=template_name)
template_module = system.load_item(template_loc) try:
template_module = system.load_item(template_loc)
except:
template_module = system.load_item(template_loc.for_branch('draft'))
template_module_data = template_module.data template_module_data = template_module.data
template = Template(template_module_data) template = Template(template_module_data)
return template.render(**params) return template.render(**params)
......
...@@ -331,6 +331,49 @@ class LTIModuleTest(LogicTest): ...@@ -331,6 +331,49 @@ class LTIModuleTest(LogicTest):
except LTIError as err: except LTIError as err:
self.fail("verify_oauth_body_sign() raised LTIError: " + err.message) self.fail("verify_oauth_body_sign() raised LTIError: " + err.message)
@patch('xmodule.lti_module.LTIModule.get_outcome_service_url', Mock(return_value=u'https://testurl/'))
@patch('xmodule.lti_module.LTIModule.get_client_key_secret',
Mock(return_value=(u'__consumer_key__', u'__lti_secret__')))
def test_failed_verify_oauth_body_sign_proxy_mangle_url(self):
"""
Oauth signing verify fail.
"""
try:
request = self.get_signed_grade_mock_request_with_correct_signature()
self.xmodule.verify_oauth_body_sign(request)
# we should verify against get_outcome_service_url not request url
# proxy and load balancer along the way may change url presented to the method
request.uri = 'http://testurl/'
self.xmodule.verify_oauth_body_sign(request)
except LTIError as err:
self.fail("verify_oauth_body_sign() raised LTIError: " + err.message)
pass
def get_signed_grade_mock_request_with_correct_signature(self):
mock_request = Mock()
mock_request.headers = {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': u'OAuth realm="https://testurl/", oauth_body_hash="wwzA3s8gScKD1VpJ7jMt9b%2BMj9Q%3D", \
oauth_nonce="18821463", oauth_timestamp="1409321145", \
oauth_consumer_key="__consumer_key__", oauth_signature_method="HMAC-SHA1", \
oauth_version="1.0", oauth_signature="fHsE1hhIz76/msUoMR3Lyb7Aou4%3D"'
}
mock_request.url = u'https://testurl'
mock_request.http_method = u'POST'
mock_request.method = mock_request.http_method
mock_request.body = '<?xml version=\'1.0\' encoding=\'utf-8\'?>\n\
<imsx_POXEnvelopeRequest xmlns="http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">\
<imsx_POXHeader><imsx_POXRequestHeaderInfo><imsx_version>V1.0</imsx_version>\
<imsx_messageIdentifier>edX_fix</imsx_messageIdentifier></imsx_POXRequestHeaderInfo>\
</imsx_POXHeader><imsx_POXBody><replaceResultRequest><resultRecord><sourcedGUID>\
<sourcedId>MITxLTI/MITxLTI/201x:localhost%3A8000-i4x-MITxLTI-MITxLTI-lti-3751833a214a4f66a0d18f63234207f2:363979ef768ca171b50f9d1bfb322131</sourcedId>\
</sourcedGUID><result><resultScore><language>en</language><textString>0.32</textString></resultScore>\
</result></resultRecord></replaceResultRequest></imsx_POXBody></imsx_POXEnvelopeRequest>'
return mock_request
def test_wrong_xml_namespace(self): def test_wrong_xml_namespace(self):
""" """
Test wrong XML Namespace. Test wrong XML Namespace.
......
...@@ -76,8 +76,9 @@ Annotator.Plugin.Flagging = (function(_super) { ...@@ -76,8 +76,9 @@ Annotator.Plugin.Flagging = (function(_super) {
*/ */
Flagging.prototype.updateField = function(field, annotation) { Flagging.prototype.updateField = function(field, annotation) {
// figure out whether annotation is of image or not // figure out whether annotation is of type image or if ova is not defined (meaning it
var user_email = annotation.media === "image" ? // it doesn't have a type yet, but it is still an image).
var user_email = (annotation.media === "image" || typeof ova === 'undefined') ?
osda.options.optionsAnnotator.permissions.user.id: osda.options.optionsAnnotator.permissions.user.id:
ova.options.optionsAnnotator.permissions.user.id; ova.options.optionsAnnotator.permissions.user.id;
......
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