From 0c7623d530201882d994b20877a571afdfdcaea3 Mon Sep 17 00:00:00 2001 From: Phil McGachey Date: Mon, 8 Jun 2015 21:38:34 -0400 Subject: [PATCH] [LTI Provider] Fix bug preventing unenrolled users from accessing content Change https://github.com/edx/edx-platform/pull/8240 refactored the LTI provider template rendering code and introduced an issue where a user was required to be enrolled in a course before that course's content could be accessed over LTI. According to the LTI design spec: https://docs.google.com/document/d/185hdPvIxcKtiDOLjb4sTGovA_WYXWz5Cd79gCzQwBms we delegate access control over LTI content to the LTI consumer, rather than requiring that users enroll in edX courses explicitly (and that admins keep edX and LTI provider enrollemnts consistent when students add or drop courses). This change fixes the immediate issue, which is disrupting the LTI Provider pilot currently running at Harvard. --- lms/djangoapps/courseware/testutils.py | 2 +- lms/djangoapps/courseware/views.py | 4 ++-- lms/djangoapps/lti_provider/tests/test_views.py | 5 +++++ lms/djangoapps/lti_provider/views.py | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/courseware/testutils.py b/lms/djangoapps/courseware/testutils.py index d9664b7077..97518ef0dc 100644 --- a/lms/djangoapps/courseware/testutils.py +++ b/lms/djangoapps/courseware/testutils.py @@ -155,7 +155,7 @@ class RenderXBlockTestMixin(object): self.setup_user(admin=False, enroll=True, login=False) self.verify_response(expected_response_code=302) - def test_fail_unenrolled_student(self): + def test_unenrolled_student(self): self.setup_course() self.setup_user(admin=False, enroll=False, login=True) self.verify_response(expected_response_code=302) diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 295e6db11c..19742d1b79 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -1389,7 +1389,7 @@ def _track_successful_certificate_generation(user_id, course_id): # pylint: dis @require_http_methods(["GET", "POST"]) -def render_xblock(request, usage_key_string): +def render_xblock(request, usage_key_string, check_if_enrolled=True): """ Returns an HttpResponse with HTML content for the xBlock with the given usage_key. The returned HTML is a chromeless rendering of the xBlock (excluding content of the containing courseware). @@ -1400,7 +1400,7 @@ def render_xblock(request, usage_key_string): with modulestore().bulk_operations(course_key): # verify the user has access to the course, including enrollment check - course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) + course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=check_if_enrolled) # get the block, which verifies whether the user has access to the block. block, _ = get_module_by_usage_id( diff --git a/lms/djangoapps/lti_provider/tests/test_views.py b/lms/djangoapps/lti_provider/tests/test_views.py index 58b2b80999..26e5b1a89b 100644 --- a/lms/djangoapps/lti_provider/tests/test_views.py +++ b/lms/djangoapps/lti_provider/tests/test_views.py @@ -282,3 +282,8 @@ class LtiRunTestRender(LtiTestMixin, RenderXBlockTestMixin, ModuleStoreTestCase) ) SignatureValidator.verify = MagicMock(return_value=True) return self.client.post(lti_launch_url, data=LTI_DEFAULT_PARAMS) + + def test_unenrolled_student(self): + self.setup_course() + self.setup_user(admin=False, enroll=False, login=True) + self.verify_response() diff --git a/lms/djangoapps/lti_provider/views.py b/lms/djangoapps/lti_provider/views.py index 6fb9e5093d..454a236252 100644 --- a/lms/djangoapps/lti_provider/views.py +++ b/lms/djangoapps/lti_provider/views.py @@ -205,7 +205,7 @@ def render_courseware(request, usage_key): """ # return an HttpResponse object that contains the template and necessary context to render the courseware. from courseware.views import render_xblock - return render_xblock(request, unicode(usage_key)) + return render_xblock(request, unicode(usage_key), check_if_enrolled=False) def parse_course_and_usage_keys(course_id, usage_id):