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.request.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.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access with self._patch_edxmako_current_request(strategy.request): student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user) # pylint: disable=protected-access # Monkey-patch storage for messaging; pylint: disable=protected-access request._messages = fallback.FallbackStorage(request) middleware.ExceptionMiddleware().process_exception( request, exceptions.AuthAlreadyAssociated(self.provider.backend_name, 'account is already in use.')) self.assert_account_settings_context_looks_correct( account_settings_context(request), user, duplicate=True, 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') request.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.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access # First we expect that we're in the unlinked state, and that there # really is no association in the backend. self.assert_account_settings_context_looks_correct( account_settings_context(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.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME)) # Set the cookie and try again self.set_logged_in_cookies(request) # Fire off the auth pipeline to link. self.assert_redirect_to_dashboard_looks_correct( actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=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_account_settings_context_looks_correct( account_settings_context(request), request.user, linked=True)
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') request.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_cookies(request) # Instrument the pipeline to get to the dashboard with the full # expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access with self._patch_edxmako_current_request(strategy.request): student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user) # pylint: disable=protected-access # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(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.backend, 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_account_settings_context_looks_correct(account_settings_context(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) # 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.request.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.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access with self._patch_edxmako_current_request(strategy.request): student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user) # pylint: disable=protected-access # Monkey-patch storage for messaging; pylint: disable=protected-access request._messages = fallback.FallbackStorage(request) middleware.ExceptionMiddleware().process_exception( request, exceptions.AuthAlreadyAssociated(self.provider.backend_name, 'account is already in use.')) self.assert_account_settings_context_looks_correct( account_settings_context(request), duplicate=True, linked=True)
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_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" ) request.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.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access # First we expect that we're in the unlinked state, and that there # really is no association in the backend. self.assert_account_settings_context_looks_correct( account_settings_context(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.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, ) ) # Set the cookie and try again self.set_logged_in_cookies(request) # Fire off the auth pipeline to link. self.assert_redirect_to_dashboard_looks_correct( actions.do_complete( request.backend, social_views._do_login, request.user, None, # pylint: disable=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_account_settings_context_looks_correct(account_settings_context(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.request.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.provider_id, pipeline.AUTH_ENTRY_LOGIN)) ) # Next, the provider makes a request against /auth/complete/<provider> # to resume the pipeline. # pylint: disable=protected-access self.assert_redirect_to_login_looks_correct(actions.do_complete(request.backend, social_views._do_login)) # 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. with self._patch_edxmako_current_request(strategy.request): 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.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, ) ) # Set the cookie and try again self.set_logged_in_cookies(request) self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(request.backend, social_views._do_login, user=user) ) self.assert_account_settings_context_looks_correct(account_settings_context(request), user)
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.request.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.provider_id, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider> # to resume the pipeline. # pylint: disable=protected-access self.assert_redirect_to_login_looks_correct(actions.do_complete(request.backend, social_views._do_login, request=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. with self._patch_edxmako_current_request(strategy.request): 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.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request )) # Set the cookie and try again self.set_logged_in_cookies(request) self.assert_redirect_to_dashboard_looks_correct( actions.do_complete(request.backend, social_views._do_login, user=user, request=request)) self.assert_account_settings_context_looks_correct(account_settings_context(request))
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)) 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)) 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)
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)) 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)) 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)
def test_full_pipeline_succeeds_for_unlinking_testshib_account(self): # First, create, the request and strategy that store pipeline state, # configure the backend, and mock out wire traffic. self.provider = self._configure_testshib_provider() request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') request.backend.auth_complete = 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) request.user = user # We're already logged in, so simulate that the cookie is set correctly self.set_logged_in_cookies(request) # linking a learner with enterprise customer. enterprise_customer = EnterpriseCustomerFactory() assert EnterpriseCustomerUser.objects.count() == 0, "Precondition check: no link records should exist" EnterpriseCustomerUser.objects.link_user(enterprise_customer, user.email) self.assertTrue( EnterpriseCustomerUser.objects.filter(enterprise_customer=enterprise_customer, user_id=user.id).count() == 1 ) EnterpriseCustomerIdentityProvider.objects.get_or_create(enterprise_customer=enterprise_customer, provider_id=self.provider.provider_id) # Instrument the pipeline to get to the dashboard with the full expected state. self.client.get( pipeline.get_login_url(self.provider.provider_id, pipeline.AUTH_ENTRY_LOGIN)) actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access request=request) with self._patch_edxmako_current_request(strategy.request): student_views.signin_user(strategy.request) student_views.login_user(strategy.request) actions.do_complete(request.backend, social_views._do_login, user=user, # pylint: disable=protected-access request=request) # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=True) self.assert_social_auth_exists_for_user(request.user, strategy) # Fire off the disconnect pipeline without the user information. actions.do_disconnect( request.backend, None, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request ) self.assertFalse( EnterpriseCustomerUser.objects.filter(enterprise_customer=enterprise_customer, user_id=user.id).count() == 0 ) # Fire off the disconnect pipeline to unlink. self.assert_redirect_to_dashboard_looks_correct( actions.do_disconnect( request.backend, user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME, request=request ) ) # Now we expect to be in the unlinked state, with no backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), linked=False) self.assert_social_auth_does_not_exist_for_user(user, strategy) self.assertTrue( EnterpriseCustomerUser.objects.filter(enterprise_customer=enterprise_customer, user_id=user.id).count() == 0 )