Commit be4e9cb5 by Alexander Kryklia

Merge pull request #3040 from edx/oleg/fix-resource-link-id

LTI resource_link_id. BLD-768.
parents 28f366a9 882a1e0f
...@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes, ...@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected. the top. Include a label indicating the component affected.
Blades: Update LTI resource_link_id parameter. BLD-768.
Blades: Transcript translations should be displayed in their source language (BLD-935). Blades: Transcript translations should be displayed in their source language (BLD-935).
Blades: Create an upload modal for video transcript translations (BLD-751). Blades: Create an upload modal for video transcript translations (BLD-751).
......
...@@ -309,8 +309,26 @@ class LTIModule(LTIFields, XModule): ...@@ -309,8 +309,26 @@ class LTIModule(LTIFields, XModule):
context and imported into another system or context. context and imported into another system or context.
This parameter is required. This parameter is required.
Example: u'edx.org-i4x-2-3-lti-31de800015cf4afb973356dbe81496df'
Hostname, edx.org,
makes resource_link_id change on import to another system.
Last part of location, location.name - 31de800015cf4afb973356dbe81496df,
is random hash, updated by course_id,
this makes resource_link_id unique inside single course.
First part of location is tag-org-course-category, i4x-2-3-lti.
Location.name itself does not change on import to another course,
but org and course_id change.
So together with org and course_id in a form of
i4x-2-3-lti-31de800015cf4afb973356dbe81496df this part of resource_link_id:
makes resource_link_id to be unique among courses inside same system.
""" """
return unicode(urllib.quote(self.id)) return unicode(urllib.quote("{}-{}".format(self.system.hostname, self.location.html_id())))
def get_lis_result_sourcedid(self): def get_lis_result_sourcedid(self):
""" """
......
...@@ -59,9 +59,9 @@ class LTIModuleTest(LogicTest): ...@@ -59,9 +59,9 @@ class LTIModuleTest(LogicTest):
self.user_id = self.xmodule.runtime.anonymous_student_id self.user_id = self.xmodule.runtime.anonymous_student_id
self.lti_id = self.xmodule.lti_id self.lti_id = self.xmodule.lti_id
self.module_id = '//MITx/999/lti/' self.unquoted_resource_link_id= u'{}-i4x-2-3-lti-31de800015cf4afb973356dbe81496df'.format(self.xmodule.runtime.hostname)
sourcedId = u':'.join(urllib.quote(i) for i in (self.lti_id, self.module_id, self.user_id)) sourcedId = u':'.join(urllib.quote(i) for i in (self.lti_id, self.unquoted_resource_link_id, self.user_id))
self.DEFAULTS = { self.DEFAULTS = {
'sourcedId': sourcedId, 'sourcedId': sourcedId,
...@@ -255,16 +255,20 @@ class LTIModuleTest(LogicTest): ...@@ -255,16 +255,20 @@ class LTIModuleTest(LogicTest):
self.assertEqual(real_outcome_service_url, expected_outcome_service_url) self.assertEqual(real_outcome_service_url, expected_outcome_service_url)
def test_resource_link_id(self): def test_resource_link_id(self):
with patch('xmodule.lti_module.LTIModule.id', new_callable=PropertyMock) as mock_id: with patch('xmodule.lti_module.LTIModule.location', new_callable=PropertyMock) as mock_location:
mock_id.return_value = self.module_id self.xmodule.location.html_id = lambda: 'i4x-2-3-lti-31de800015cf4afb973356dbe81496df'
expected_resource_link_id = unicode(urllib.quote(self.module_id)) expected_resource_link_id = unicode(urllib.quote(self.unquoted_resource_link_id))
real_resource_link_id = self.xmodule.get_resource_link_id() real_resource_link_id = self.xmodule.get_resource_link_id()
self.assertEqual(real_resource_link_id, expected_resource_link_id) self.assertEqual(real_resource_link_id, expected_resource_link_id)
def test_lis_result_sourcedid(self): def test_lis_result_sourcedid(self):
with patch('xmodule.lti_module.LTIModule.id', new_callable=PropertyMock) as mock_id: with patch('xmodule.lti_module.LTIModule.location', new_callable=PropertyMock) as mock_location:
mock_id.return_value = self.module_id self.xmodule.location.html_id = lambda: 'i4x-2-3-lti-31de800015cf4afb973356dbe81496df'
expected_sourcedId = u':'.join(urllib.quote(i) for i in (self.lti_id, self.module_id, self.user_id)) expected_sourcedId = u':'.join(urllib.quote(i) for i in (
self.lti_id,
urllib.quote(self.unquoted_resource_link_id),
self.user_id
))
real_lis_result_sourcedid = self.xmodule.get_lis_result_sourcedid() real_lis_result_sourcedid = self.xmodule.get_lis_result_sourcedid()
self.assertEqual(real_lis_result_sourcedid, expected_sourcedId) self.assertEqual(real_lis_result_sourcedid, expected_sourcedId)
......
...@@ -28,17 +28,18 @@ class TestLTI(BaseTestXmodule): ...@@ -28,17 +28,18 @@ class TestLTI(BaseTestXmodule):
mocked_decoded_signature = u'my_signature=' mocked_decoded_signature = u'my_signature='
lti_id = self.item_descriptor.lti_id lti_id = self.item_descriptor.lti_id
module_id = unicode(urllib.quote(self.item_descriptor.id))
user_id = unicode(self.item_descriptor.xmodule_runtime.anonymous_student_id) user_id = unicode(self.item_descriptor.xmodule_runtime.anonymous_student_id)
hostname = self.item_descriptor.xmodule_runtime.hostname
resource_link_id = unicode(urllib.quote('{}-{}'.format(hostname, self.item_descriptor.location.html_id())))
sourcedId = "{id}:{resource_link}:{user_id}".format( sourcedId = "{id}:{resource_link}:{user_id}".format(
id=urllib.quote(lti_id), id=urllib.quote(lti_id),
resource_link=urllib.quote(module_id), resource_link=urllib.quote(resource_link_id),
user_id=urllib.quote(user_id) user_id=urllib.quote(user_id)
) )
lis_outcome_service_url = 'https://{host}{path}'.format( lis_outcome_service_url = 'https://{host}{path}'.format(
host=self.item_descriptor.xmodule_runtime.hostname, host=hostname,
path=self.item_descriptor.xmodule_runtime.handler_url(self.item_descriptor, 'grade_handler', thirdparty=True).rstrip('/?') path=self.item_descriptor.xmodule_runtime.handler_url(self.item_descriptor, 'grade_handler', thirdparty=True).rstrip('/?')
) )
self.correct_headers = { self.correct_headers = {
...@@ -49,7 +50,7 @@ class TestLTI(BaseTestXmodule): ...@@ -49,7 +50,7 @@ class TestLTI(BaseTestXmodule):
u'lti_version': 'LTI-1p0', u'lti_version': 'LTI-1p0',
u'roles': u'Student', u'roles': u'Student',
u'resource_link_id': module_id, u'resource_link_id': resource_link_id,
u'lis_result_sourcedid': sourcedId, u'lis_result_sourcedid': sourcedId,
u'oauth_nonce': mocked_nonce, u'oauth_nonce': mocked_nonce,
......
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