def test_externalauth_login_required_course_context(self): """ Tests the redirects when visiting course-specific URL with @login_required. Should vary by course depending on its enrollment_domain """ target_url = reverse('courseware', args=[text_type(self.course.id)]) noshib_response = self.client.get(target_url, follow=True, HTTP_ACCEPT="text/html") self.assertEqual(noshib_response.redirect_chain[-1], (expected_redirect_url('/login?next={url}'.format(url=target_url)), 302)) self.assertContains(noshib_response, (u"Sign in or Register | {platform_name}" .format(platform_name=settings.PLATFORM_NAME))) self.assertEqual(noshib_response.status_code, 200) target_url_shib = reverse('courseware', args=[text_type(self.shib_course.id)]) shib_response = self.client.get(**{'path': target_url_shib, 'follow': True, 'REMOTE_USER': self.extauth.external_id, 'Shib-Identity-Provider': 'https://idp.stanford.edu/', 'HTTP_ACCEPT': "text/html"}) # Test that the shib-login redirect page with ?next= and the desired page are part of the redirect chain # The 'courseware' page actually causes a redirect itself, so it's not the end of the chain and we # won't test its contents self.assertEqual(shib_response.redirect_chain[-3], (expected_redirect_url('/shib-login/?next={url}'.format(url=target_url_shib)), 302)) self.assertEqual(shib_response.redirect_chain[-2], (expected_redirect_url(target_url_shib), 302)) self.assertEqual(shib_response.status_code, 200)
def test_wiki_redirect(self): """ Test that requesting wiki URLs redirect properly to or out of classes. An enrolled in student going from /courses/edX/toy/2012_Fall/progress to /wiki/some/fake/wiki/page/ will redirect to /courses/edX/toy/2012_Fall/wiki/some/fake/wiki/page/ An unenrolled student going to /courses/edX/toy/2012_Fall/wiki/some/fake/wiki/page/ will be redirected to /wiki/some/fake/wiki/page/ """ self.login(self.student, self.password) self.enroll(self.toy) referer = reverse("progress", kwargs={'course_id': text_type(self.toy.id)}) destination = reverse("wiki:get", kwargs={'path': 'some/fake/wiki/page/'}) redirected_to = referer.replace("progress", "wiki/some/fake/wiki/page/") resp = self.client.get(destination, HTTP_REFERER=referer) self.assertEqual(resp.status_code, 302) self.assertEqual(resp['Location'], expected_redirect_url(redirected_to)) # Now we test that the student will be redirected away from that page if the course doesn't exist # We do this in the same test because we want to make sure the redirected_to is constructed correctly # This is a location like /courses/*/wiki/* , but with an invalid course ID bad_course_wiki_page = redirected_to.replace(self.toy.location.course, "bad_course") resp = self.client.get(bad_course_wiki_page, HTTP_REFERER=referer) self.assertEqual(resp.status_code, 302) self.assertEqual(resp['Location'], expected_redirect_url(destination))
def test_wiki_redirect(self): """ Test that requesting wiki URLs redirect properly to or out of classes. An enrolled in student going from /courses/edX/toy/2012_Fall/progress to /wiki/some/fake/wiki/page/ will redirect to /courses/edX/toy/2012_Fall/wiki/some/fake/wiki/page/ An unenrolled student going to /courses/edX/toy/2012_Fall/wiki/some/fake/wiki/page/ will be redirected to /wiki/some/fake/wiki/page/ """ self.login(self.student, self.password) self.enroll(self.toy) referer = reverse("progress", kwargs={'course_id': self.toy.id.to_deprecated_string()}) destination = reverse("wiki:get", kwargs={'path': 'some/fake/wiki/page/'}) redirected_to = referer.replace("progress", "wiki/some/fake/wiki/page/") resp = self.client.get(destination, HTTP_REFERER=referer) self.assertEqual(resp.status_code, 302) self.assertEqual(resp['Location'], expected_redirect_url(redirected_to)) # Now we test that the student will be redirected away from that page if the course doesn't exist # We do this in the same test because we want to make sure the redirected_to is constructed correctly # This is a location like /courses/*/wiki/* , but with an invalid course ID bad_course_wiki_page = redirected_to.replace(self.toy.location.course, "bad_course") resp = self.client.get(bad_course_wiki_page, HTTP_REFERER=referer) self.assertEqual(resp.status_code, 302) self.assertEqual(resp['Location'], expected_redirect_url(destination))
def _test_return_login(self, user_is_activated=True, previous_session_timed_out=False): """ Test logging in to an account that is already linked. """ # Make sure we're not logged in: dashboard_response = self.client.get(reverse('dashboard')) self.assertEqual(dashboard_response.status_code, 302) # The user goes to the login page, and sees a button to login with this provider: provider_login_url = self._check_login_page() # The user clicks on the provider's login button: try_login_response = self.client.get(provider_login_url) # The user should be redirected to the provider: self.assertEqual(try_login_response.status_code, 302) login_response = self.do_provider_login(try_login_response['Location']) # If the previous session was manually logged out, there will be one weird redirect # required to set the login cookie (it sticks around if the main session times out): if not previous_session_timed_out: self.assertEqual(login_response.status_code, 302) expected_url = expected_redirect_url(self.complete_url, hostname=self.hostname) # TODO: Remove Django 1.11 upgrade shim # SHIM: Get rid of this logic post-upgrade if django.VERSION >= (1, 9): expected_url = "{}?".format(expected_url) self.assertEqual(login_response['Location'], expected_url) # And then we should be redirected to the dashboard: login_response = self.client.get(login_response['Location']) self.assertEqual(login_response.status_code, 302) if user_is_activated: url_expected = reverse('dashboard') else: url_expected = reverse('third_party_inactive_redirect') + '?next=' + reverse('dashboard') self.assertEqual(login_response['Location'], expected_redirect_url(url_expected, hostname=self.hostname)) # Now we are logged in: dashboard_response = self.client.get(reverse('dashboard')) self.assertEqual(dashboard_response.status_code, 200)
def test_login(self): self.user = UserFactory.create() # pylint: disable=attribute-defined-outside-init # The user goes to the login page, and sees a button to login with this provider: provider_login_url = self._check_login_page() # The user clicks on the provider's button: try_login_response = self.client.get(provider_login_url) # The user should be redirected to the provider's login page: self.assertEqual(try_login_response.status_code, 302) complete_response = self.do_provider_login(try_login_response['Location']) # We should be redirected to the login screen since this account is not linked to an edX account: self.assertEqual(complete_response.status_code, 302) self.assertEqual(complete_response['Location'], expected_redirect_url(self.login_page_url, hostname=self.hostname)) login_response = self.client.get(self.login_page_url) tpa_context = login_response.context["data"]["third_party_auth"] self.assertEqual(tpa_context["errorMessage"], None) # Check that the "You've successfully signed into [PROVIDER_NAME]" message is shown. self.assertEqual(tpa_context["currentProvider"], self.PROVIDER_NAME) # Now the user enters their username and password. # The AJAX on the page will log them in: ajax_login_response = self.client.post( reverse('user_api_login_session'), {'email': self.user.email, 'password': '******'} ) self.assertEqual(ajax_login_response.status_code, 200) # Then the AJAX will finish the third party auth: continue_response = self.client.get(tpa_context["finishAuthUrl"]) # And we should be redirected to the dashboard: self.assertEqual(continue_response.status_code, 302) self.assertEqual(continue_response['Location'], expected_redirect_url(reverse('dashboard'), hostname=self.hostname)) # Now check that we can login again: self.client.logout() self._test_return_login()
def test_register(self, **extra_defaults): # The user goes to the register page, and sees a button to register with the provider: provider_register_url = self._check_register_page() # The user clicks on the Dummy button: try_login_response = self.client.get(provider_register_url) # The user should be redirected to the provider's login page: self.assertEqual(try_login_response.status_code, 302) provider_response = self.do_provider_login(try_login_response['Location']) # We should be redirected to the register screen since this account is not linked to an edX account: self.assertEqual(provider_response.status_code, 302) self.assertEqual(provider_response['Location'], expected_redirect_url(self.register_page_url, hostname=self.hostname)) register_response = self.client.get(self.register_page_url) tpa_context = register_response.context["data"]["third_party_auth"] self.assertEqual(tpa_context["errorMessage"], None) # Check that the "You've successfully signed into [PROVIDER_NAME]" message is shown. self.assertEqual(tpa_context["currentProvider"], self.PROVIDER_NAME) # Check that the data (e.g. email) from the provider is displayed in the form: form_data = register_response.context['data']['registration_form_desc'] form_fields = {field['name']: field for field in form_data['fields']} self.assertEqual(form_fields['email']['defaultValue'], self.USER_EMAIL) self.assertEqual(form_fields['name']['defaultValue'], self.USER_NAME) self.assertEqual(form_fields['username']['defaultValue'], self.USER_USERNAME) for field_name, value in extra_defaults.items(): self.assertEqual(form_fields[field_name]['defaultValue'], value) registration_values = { 'email': '*****@*****.**', 'name': 'My Customized Name', 'username': '******', 'honor_code': True, } # Now complete the form: ajax_register_response = self.client.post( reverse('user_api_registration'), registration_values ) self.assertEqual(ajax_register_response.status_code, 200) # Then the AJAX will finish the third party auth: continue_response = self.client.get(tpa_context["finishAuthUrl"]) # And we should be redirected to the dashboard: self.assertEqual(continue_response.status_code, 302) self.assertEqual(continue_response['Location'], expected_redirect_url(reverse('dashboard'), hostname=self.hostname)) # Now check that we can login again, whether or not we have yet verified the account: self.client.logout() self._test_return_login(user_is_activated=False) self.client.logout() self.verify_user_email('*****@*****.**') self._test_return_login(user_is_activated=True)
def test_ssl_cms_redirection(self): """ Auto signup auth user and ensure they return to the original url they visited after being logged in. """ course = CourseFactory.create( org='MITx', number='999', display_name='Robot Super Course' ) with self._create_ssl_request('/') as request: external_auth_views.ssl_login(request) user = User.objects.get(email=self.USER_EMAIL) CourseEnrollment.enroll(user, course.id) CourseStaffRole(course.id).add_users(user) course_private_url = reverse('course_handler', args=(unicode(course.id),)) self.assertNotIn(SESSION_KEY, self.client.session) response = self.client.get( course_private_url, follow=True, SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL), HTTP_ACCEPT='text/html' ) self.assertEqual((expected_redirect_url(course_private_url), 302), response.redirect_chain[-1]) self.assertIn(SESSION_KEY, self.client.session)
def create_course_page(self, course): """ Test that loading the course wiki page creates the wiki page. The user must be enrolled in the course to see the page. """ course_wiki_home = reverse('course_wiki', kwargs={'course_id': text_type(course.id)}) referer = reverse("progress", kwargs={'course_id': text_type(course.id)}) resp = self.client.get(course_wiki_home, follow=True, HTTP_REFERER=referer) course_wiki_page = referer.replace('progress', 'wiki/' + course.wiki_slug + "/") ending_location = resp.redirect_chain[-1][0] self.assertEquals(ending_location, expected_redirect_url(course_wiki_page)) self.assertEquals(resp.status_code, 200) self.has_course_navigator(resp) self.assertContains( resp, '<h3 class="entry-title">{}</h3>'.format( course.display_name_with_default))
def test_login_required_dashboard(self): """ Tests redirects to when @login_required to dashboard, which should always be the normal login, since there is no course context """ response = self.client.get(reverse('dashboard')) self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], expected_redirect_url('/login?next=/dashboard'))
def test_settings_tpa_hinted_login_dialog_disabled(self, url_name, auth_entry): """Test that the dialog doesn't show up for hinted logins when disabled via settings.THIRD_PARTY_AUTH_HINT. """ self.google_provider.skip_hinted_login_dialog = True self.google_provider.save() params = [("next", "/courses/something/")] response = self.client.get(reverse(url_name), params, HTTP_ACCEPT="text/html") self.assertRedirects( response, expected_redirect_url('auth/login/google-oauth2/?auth_entry={}&next=%2Fcourses%2Fsomething%2F%3Ftpa_hint%3Doa2-google-oauth2'.format(auth_entry)), target_status_code=302 )
def test_registration_page_bypass(self): """ This tests to make sure when immediate signup is on that the user doesn't get presented with the registration page. """ response = self.client.get( reverse('register_user'), follow=True, SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)) self.assertEquals((expected_redirect_url('/dashboard'), 302), response.redirect_chain[-1]) self.assertIn(SESSION_KEY, self.client.session)
def test_login_before_metadata_fetched(self): self._configure_testshib_provider(fetch_metadata=False) # The user goes to the login page, and sees a button to login with TestShib: testshib_login_url = self._check_login_page() # The user clicks on the TestShib button: try_login_response = self.client.get(testshib_login_url) # The user should be redirected to back to the login page: self.assertEqual(try_login_response.status_code, 302) self.assertEqual(try_login_response['Location'], expected_redirect_url(self.login_page_url, hostname=self.hostname)) # When loading the login page, the user will see an error message: response = self.client.get(self.login_page_url) self.assertEqual(response.status_code, 200) self.assertIn('Authentication with TestShib is currently unavailable.', response.content)
def test_default_login_decorator_ssl(self): """ Make sure that SSL login happens if it is enabled on protected views instead of showing the login form. """ response = self.client.get(reverse('dashboard'), follows=True) self.assertEqual(response.status_code, 302) self.assertIn(reverse('signin_user'), response['location']) response = self.client.get( reverse('dashboard'), follow=True, SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)) self.assertEquals((expected_redirect_url('/dashboard'), 302), response.redirect_chain[-1]) self.assertIn(SESSION_KEY, self.client.session)
def test_shib_login_enrollment(self): """ A functionality test that a student with an existing shib login can auto-enroll in a class with GET or POST params. Also tests the direction functionality of the 'next' GET/POST param """ student = UserFactory.create() extauth = ExternalAuthMap( external_id='*****@*****.**', external_email='', external_domain='shib:https://idp.stanford.edu/', external_credentials="", internal_password="******", user=student) student.set_password("password") student.save() extauth.save() course = CourseFactory.create( org='Stanford', number='123', display_name='Shib Only', enrollment_domain='shib:https://idp.stanford.edu/', user_id=self.test_user_id, ) # use django test client for sessions and url processing # no enrollment before trying self.assertFalse(CourseEnrollment.is_enrolled(student, course.id)) self.client.logout() params = [('course_id', text_type(course.id)), ('enrollment_action', 'enroll'), ('next', '/testredirect')] request_kwargs = { 'path': '/shib-login/', 'data': dict(params), 'follow': False, 'REMOTE_USER': '******', 'Shib-Identity-Provider': 'https://idp.stanford.edu/', 'HTTP_ACCEPT': "text/html" } response = self.client.get(**request_kwargs) # successful login is a redirect to the URL that handles auto-enrollment self.assertEqual(response.status_code, 302) self.assertEqual( response['location'], expected_redirect_url('/account/finish_auth?{}'.format( urlencode(params))))
def test_shib_login_enrollment(self): """ A functionality test that a student with an existing shib login can auto-enroll in a class with GET or POST params. Also tests the direction functionality of the 'next' GET/POST param """ student = UserFactory.create() extauth = ExternalAuthMap(external_id='*****@*****.**', external_email='', external_domain='shib:https://idp.stanford.edu/', external_credentials="", internal_password="******", user=student) student.set_password("password") student.save() extauth.save() course = CourseFactory.create( org='Stanford', number='123', display_name='Shib Only', enrollment_domain='shib:https://idp.stanford.edu/', user_id=self.test_user_id, ) # use django test client for sessions and url processing # no enrollment before trying self.assertFalse(CourseEnrollment.is_enrolled(student, course.id)) self.client.logout() params = [ ('course_id', text_type(course.id)), ('enrollment_action', 'enroll'), ('next', '/testredirect') ] request_kwargs = {'path': '/shib-login/', 'data': dict(params), 'follow': False, 'REMOTE_USER': '******', 'Shib-Identity-Provider': 'https://idp.stanford.edu/', 'HTTP_ACCEPT': "text/html"} response = self.client.get(**request_kwargs) # successful login is a redirect to the URL that handles auto-enrollment self.assertEqual(response.status_code, 302) self.assertEqual(response['location'], expected_redirect_url('/account/finish_auth?{}'.format(urlencode(params))))
def test_signin_page_bypass(self): """ This tests to make sure when ssl authentication is on that user doesn't get presented with the login page if they have a certificate. """ # Test that they do signin if they don't have a cert response = self.client.get(reverse('signin_user')) self.assertEqual(200, response.status_code) self.assertIn('login-and-registration-container', response.content) # And get directly logged in otherwise response = self.client.get( reverse('signin_user'), follow=True, SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)) self.assertEquals((expected_redirect_url('/dashboard'), 302), response.redirect_chain[-1]) self.assertIn(SESSION_KEY, self.client.session)
def create_course_page(self, course): """ Test that loading the course wiki page creates the wiki page. The user must be enrolled in the course to see the page. """ course_wiki_home = reverse('course_wiki', kwargs={'course_id': text_type(course.id)}) referer = reverse("progress", kwargs={'course_id': text_type(course.id)}) resp = self.client.get(course_wiki_home, follow=True, HTTP_REFERER=referer) course_wiki_page = referer.replace('progress', 'wiki/' + course.wiki_slug + "/") ending_location = resp.redirect_chain[-1][0] self.assertEquals(ending_location, expected_redirect_url(course_wiki_page)) self.assertEquals(resp.status_code, 200) self.has_course_navigator(resp) self.assertContains(resp, '<h3 class="entry-title">{}</h3>'.format(course.display_name_with_default))
def test_ssl_logout(self): """ Because the branding view is cached for anonymous users and we use that to login users, the browser wasn't actually making the request to that view as the redirect was being cached. This caused a redirect loop, and this test confirms that that won't happen. Test is only in LMS because we don't use / in studio to login SSL users. """ response = self.client.get( reverse('dashboard'), follow=True, SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)) self.assertEquals((expected_redirect_url('/dashboard'), 302), response.redirect_chain[-1]) self.assertIn(SESSION_KEY, self.client.session) response = self.client.get( reverse('logout'), follow=True, SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL) ) # Make sure that even though we logged out, we have logged back in self.assertIn(SESSION_KEY, self.client.session)
def test_custom_form_error(self): """ Use the Google provider to test the custom login/register failure redirects. """ # The pipeline starts by a user GETting /auth/login/google-oauth2/?auth_entry=custom1 # Synthesize that request and check that it redirects to the correct # provider page. auth_entry = 'custom1' # See definition in lms/envs/test.py login_url = pipeline.get_login_url(self.provider.provider_id, auth_entry) login_url += "&next=/misc/final-destination" self.assert_redirect_to_provider_looks_correct(self.client.get(login_url)) def fake_auth_complete_error(_inst, *_args, **_kwargs): """ Mock the backend's auth_complete() method """ raise AuthException("Mock login failed") # Next, the provider makes a request against /auth/complete/<provider>. complete_url = pipeline.get_complete_url(self.provider.backend_name) with patch.object(self.provider.backend_class, 'auth_complete', fake_auth_complete_error): response = self.client.get(complete_url) # This should redirect to the custom error URL self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], expected_redirect_url('/misc/my-custom-sso-error-page', hostname='example.none'))
def test_custom_form(self): """ Use the Google provider to test the custom login/register form feature. """ # The pipeline starts by a user GETting /auth/login/google-oauth2/?auth_entry=custom1 # Synthesize that request and check that it redirects to the correct # provider page. auth_entry = 'custom1' # See definition in lms/envs/test.py login_url = pipeline.get_login_url(self.provider.provider_id, auth_entry) login_url += "&next=/misc/final-destination" self.assert_redirect_to_provider_looks_correct(self.client.get(login_url)) def fake_auth_complete(inst, *args, **kwargs): """ Mock the backend's auth_complete() method """ kwargs.update({'response': self.get_response_data(), 'backend': inst}) return inst.strategy.authenticate(*args, **kwargs) # Next, the provider makes a request against /auth/complete/<provider>. complete_url = pipeline.get_complete_url(self.provider.backend_name) with patch.object(self.provider.backend_class, 'auth_complete', fake_auth_complete): response = self.client.get(complete_url) # This should redirect to the custom login/register form: self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], expected_redirect_url('/auth/custom_auth_entry', hostname='example.none')) response = self.client.get(response['Location']) self.assertEqual(response.status_code, 200) self.assertIn('action="/misc/my-custom-registration-form" method="post"', response.content) data_decoded = base64.b64decode(response.context['data']) # pylint: disable=no-member data_parsed = json.loads(data_decoded) # The user's details get passed to the custom page as a base64 encoded query parameter: self.assertEqual(data_parsed, { 'auth_entry': 'custom1', 'backend_name': 'google-oauth2', 'provider_id': 'oa2-google-oauth2', 'user_details': { 'username': '******', 'email': '*****@*****.**', 'fullname': 'name_value', 'first_name': 'given_name_value', 'last_name': 'family_name_value', }, }) # Check the hash that is used to confirm the user's data in the GET parameter is correct secret_key = settings.THIRD_PARTY_AUTH_CUSTOM_AUTH_FORMS['custom1']['secret_key'] hmac_expected = hmac.new(secret_key, msg=data_decoded, digestmod=hashlib.sha256).digest() self.assertEqual(base64.b64decode(response.context['hmac']), hmac_expected) # pylint: disable=no-member # Now our custom registration form creates or logs in the user: email, password = data_parsed['user_details']['email'], 'random_password' created_user = UserFactory(email=email, password=password) login_response = self.client.post(reverse('login'), {'email': email, 'password': password}) self.assertEqual(login_response.status_code, 200) # Now our custom login/registration page must resume the pipeline: response = self.client.get(complete_url) self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], expected_redirect_url('/misc/final-destination', hostname='example.none')) _, strategy = self.get_request_and_strategy() self.assert_social_auth_exists_for_user(created_user, strategy)
def test_lti_login(self): # The user initiates a login from an external site (uri, _headers, body) = self.lti.sign( uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={ 'user_id': LTI_USER_ID, 'custom_tpa_next': '/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll', }) login_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body) # The user should be redirected to the registration form self.assertEqual(login_response.status_code, 302) self.assertTrue(login_response['Location'].endswith( reverse('signin_user'))) register_response = self.client.get(login_response['Location']) self.assertEqual(register_response.status_code, 200) self.assertIn('"currentProvider": "LTI Test Tool Consumer"', register_response.content) self.assertIn('"errorMessage": null', register_response.content) # Now complete the form: ajax_register_response = self.client.post( reverse('user_api_registration'), { 'email': EMAIL, 'name': 'Myself', 'username': EDX_USER_ID, 'honor_code': True, }) self.assertEqual(ajax_register_response.status_code, 200) continue_response = self.client.get(self.url_prefix + LTI_TPA_COMPLETE_URL) # The user should be redirected to the finish_auth view which will enroll them. # FinishAuthView.js reads the URL parameters directly from $.url self.assertEqual(continue_response.status_code, 302) self.assertEqual( continue_response['Location'], expected_redirect_url( '/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll' )) # Now check that we can login again self.client.logout() self.verify_user_email(EMAIL) (uri, _headers, body) = self.lti.sign(uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={'user_id': LTI_USER_ID}) login_2_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body) # The user should be redirected to the dashboard self.assertEqual(login_2_response.status_code, 302) expected_url = expected_redirect_url(LTI_TPA_COMPLETE_URL) # TODO: Remove Django 1.11 upgrade shim # SHIM: Get rid of this logic post-upgrade if django.VERSION >= (1, 9): expected_url = "{}?".format(expected_url) self.assertEqual(login_2_response['Location'], expected_url) continue_2_response = self.client.get(login_2_response['Location']) self.assertEqual(continue_2_response.status_code, 302) self.assertTrue(continue_2_response['Location'].endswith( reverse('dashboard'))) # Check that the user was created correctly user = User.objects.get(email=EMAIL) self.assertEqual(user.username, EDX_USER_ID)
def test_lti_login(self): # The user initiates a login from an external site (uri, _headers, body) = self.lti.sign( uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={ 'user_id': LTI_USER_ID, 'custom_tpa_next': '/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll', } ) login_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body) # The user should be redirected to the registration form self.assertEqual(login_response.status_code, 302) self.assertTrue(login_response['Location'].endswith(reverse('signin_user'))) register_response = self.client.get(login_response['Location']) self.assertEqual(register_response.status_code, 200) self.assertIn('"currentProvider": "LTI Test Tool Consumer"', register_response.content) self.assertIn('"errorMessage": null', register_response.content) # Now complete the form: ajax_register_response = self.client.post( reverse('user_api_registration'), { 'email': EMAIL, 'name': 'Myself', 'username': EDX_USER_ID, 'honor_code': True, } ) self.assertEqual(ajax_register_response.status_code, 200) continue_response = self.client.get(self.url_prefix + LTI_TPA_COMPLETE_URL) # The user should be redirected to the finish_auth view which will enroll them. # FinishAuthView.js reads the URL parameters directly from $.url self.assertEqual(continue_response.status_code, 302) self.assertEqual( continue_response['Location'], expected_redirect_url('/account/finish_auth/?course_id=my_course_id&enrollment_action=enroll') ) # Now check that we can login again self.client.logout() self.verify_user_email(EMAIL) (uri, _headers, body) = self.lti.sign( uri=self.url_prefix + LTI_TPA_LOGIN_URL, http_method='POST', headers={'Content-Type': FORM_ENCODED}, body={'user_id': LTI_USER_ID} ) login_2_response = self.client.post(path=uri, content_type=FORM_ENCODED, data=body) # The user should be redirected to the dashboard self.assertEqual(login_2_response.status_code, 302) expected_url = expected_redirect_url(LTI_TPA_COMPLETE_URL) # TODO: Remove Django 1.11 upgrade shim # SHIM: Get rid of this logic post-upgrade if django.VERSION >= (1, 9): expected_url = "{}?".format(expected_url) self.assertEqual(login_2_response['Location'], expected_url) continue_2_response = self.client.get(login_2_response['Location']) self.assertEqual(continue_2_response.status_code, 302) self.assertTrue(continue_2_response['Location'].endswith(reverse('dashboard'))) # Check that the user was created correctly user = User.objects.get(email=EMAIL) self.assertEqual(user.username, EDX_USER_ID)