def test_full_pipeline_succeeds_for_unlinking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(strategy, social_views._do_login, user=user) # pylint: disable-msg=protected-access # First we expect that we're in the linked state, with a backend entry. self.assert_dashboard_response_looks_correct(student_views.dashboard(request), user, linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) # Fire off the disconnect pipeline to unlink. self.assert_redirect_to_dashboard_looks_correct(actions.do_disconnect( request.social_strategy, request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME)) # Now we expect to be in the unlinked state, with no backend entry. self.assert_dashboard_response_looks_correct(student_views.dashboard(request), user, linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy)
def test_full_pipeline_succeeds_for_unlinking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) # We're already logged in, so simulate that the cookie is set correctly self.set_logged_in_cookie(request) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(strategy, social_views._do_login, user=user) # pylint: disable-msg=protected-access # First we expect that we're in the linked state, with a backend entry. self.assert_dashboard_response_looks_correct(student_views.dashboard(request), user, linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) # Fire off the disconnect pipeline to unlink. self.assert_redirect_to_dashboard_looks_correct(actions.do_disconnect( request.social_strategy, request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME)) # Now we expect to be in the unlinked state, with no backend entry. self.assert_dashboard_response_looks_correct(student_views.dashboard(request), user, linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy)
def test_already_associated_exception_populates_dashboard_with_error(self): # Instrument the pipeline with an exception. We test that the # exception is raised correctly separately, so it's ok that we're # raising it artificially here. This makes the linked=True artificial # in the final assert because in practice the account would be # unlinked, but getting that behavior is cumbersome here and already # covered in other tests. Using linked=True does, however, let us test # that the duplicate error has no effect on the state of the controls. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.client.get('/login') self.client.get(pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(strategy, social_views._do_login, user=user) # pylint: disable-msg=protected-access # Monkey-patch storage for messaging; pylint: disable-msg=protected-access request._messages = fallback.FallbackStorage(request) middleware.ExceptionMiddleware().process_exception( request, exceptions.AuthAlreadyAssociated(self.PROVIDER_CLASS.BACKEND_CLASS.name, 'account is already in use.')) self.assert_dashboard_response_looks_correct( student_views.dashboard(request), user, duplicate=True, linked=True)
def test_full_pipeline_succeeds_registering_new_account(self): # First, create, the request and strategy that store pipeline state. # Mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # Begin! Grab the registration page and check the login control on it. self.assert_register_response_before_pipeline_looks_correct(self.client.get('/register')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider>. # pylint:disable-msg=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(strategy, social_views._do_login)) mako_middleware_process_request(strategy.request) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the registration form. self.assert_register_response_in_pipeline_looks_correct( student_views.register_user(strategy.request), pipeline.get(request)['kwargs']) # Next, we invoke the view that handles the POST. Not all providers # supply email. Manually add it as the user would have to; this # also serves as a test of overriding provider values. Always provide a # password for us to check that we override it properly. overridden_password = strategy.request.POST.get('password') email = '*****@*****.**' if not strategy.request.POST.get('email'): strategy.request.POST = self.get_registration_post_vars({'email': email}) # The user must not exist yet... with self.assertRaises(auth_models.User.DoesNotExist): self.get_user_by_email(strategy, email) # ...but when we invoke create_account the existing edX view will make # it, but not social auths. The pipeline creates those later. self.assert_json_success_response_looks_correct(student_views.create_account(strategy.request)) # We've overridden the user's password, so authenticate() with the old # value won't work: created_user = self.get_user_by_email(strategy, email) self.assert_password_overridden_by_pipeline(overridden_password, created_user.username) # At this point the user object exists, but there is no associated # social auth. self.assert_social_auth_does_not_exist_for_user(created_user, strategy) # Pick the pipeline back up. This will create the account association # and send the user to the dashboard, where the association will be # displayed. self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(strategy, social_views._do_login, user=created_user)) self.assert_social_auth_exists_for_user(created_user, strategy) self.assert_dashboard_response_looks_correct(student_views.dashboard(request), created_user, linked=True)
def test_full_pipeline_succeeds_registering_new_account(self): # First, create, the request and strategy that store pipeline state. # Mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # Begin! Grab the registration page and check the login control on it. self.assert_register_response_before_pipeline_looks_correct(self.client.get('/register')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider>. # pylint:disable-msg=protected-access self.assert_redirect_to_register_looks_correct(actions.do_complete(strategy, social_views._do_login)) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the registration form. self.assert_register_response_in_pipeline_looks_correct( student_views.register_user(strategy.request), pipeline.get(request)['kwargs']) # Next, we invoke the view that handles the POST. Not all providers # supply email. Manually add it as the user would have to; this # also serves as a test of overriding provider values. Always provide a # password for us to check that we override it properly. overridden_password = strategy.request.POST.get('password') email = '*****@*****.**' if not strategy.request.POST.get('email'): strategy.request.POST = self.get_registration_post_vars({'email': email}) # The user must not exist yet... with self.assertRaises(auth_models.User.DoesNotExist): self.get_user_by_email(strategy, email) # ...but when we invoke create_account the existing edX view will make # it, but not social auths. The pipeline creates those later. self.assert_json_success_response_looks_correct(student_views.create_account(strategy.request)) # We've overridden the user's password, so authenticate() with the old # value won't work: created_user = self.get_user_by_email(strategy, email) self.assert_password_overridden_by_pipeline(overridden_password, created_user.username) # At this point the user object exists, but there is no associated # social auth. self.assert_social_auth_does_not_exist_for_user(created_user, strategy) # Pick the pipeline back up. This will create the account association # and send the user to the dashboard, where the association will be # displayed. self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(strategy, social_views._do_login, user=created_user)) self.assert_social_auth_exists_for_user(created_user, strategy) self.assert_dashboard_response_looks_correct(student_views.dashboard(request), created_user, linked=True)
def test_full_pipeline_succeeds_for_linking_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() request.user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username(), skip_social_auth=True) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access # First we expect that we're in the unlinked state, and that there # really is no association in the backend. self.assert_dashboard_response_looks_correct(student_views.dashboard(request), request.user, linked=False) self.assert_social_auth_does_not_exist_for_user(request.user, strategy) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME )) # Set the cookie and try again self.set_logged_in_cookie(request) # Fire off the auth pipeline to link. self.assert_redirect_to_dashboard_looks_correct(actions.do_complete( request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME)) # Now we expect to be in the linked state, with a backend entry. self.assert_social_auth_exists_for_user(request.user, strategy) self.assert_dashboard_response_looks_correct(student_views.dashboard(request), request.user, linked=True)
def test_full_pipeline_succeeds_for_signing_in_to_existing_active_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() user = self.create_user_models_for_existing_account( strategy, '*****@*****.**', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.assertTrue(user.is_active) # Begin! Ensure that the login form contains expected controls before # the user starts the pipeline. self.assert_login_response_before_pipeline_looks_correct(self.client.get('/login')) # The pipeline starts by a user GETting /auth/login/<provider>. # Synthesize that request and check that it redirects to the correct # provider page. self.assert_redirect_to_provider_looks_correct(self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider> # to resume the pipeline. # pylint: disable-msg=protected-access self.assert_redirect_to_login_looks_correct(actions.do_complete(strategy, social_views._do_login)) mako_middleware_process_request(strategy.request) # At this point we know the pipeline has resumed correctly. Next we # fire off the view that displays the login form and posts it via JS. self.assert_login_response_in_pipeline_looks_correct(student_views.signin_user(strategy.request)) # Next, we invoke the view that handles the POST, and expect it # redirects to /auth/complete. In the browser ajax handlers will # redirect the user to the dashboard; we invoke it manually here. self.assert_json_success_response_looks_correct(student_views.login_user(strategy.request)) # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME )) # Set the cookie and try again self.set_logged_in_cookie(request) self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(strategy, social_views._do_login, user=user)) self.assert_dashboard_response_looks_correct(student_views.dashboard(request), user)