def test_states_for_enabled_providers_user_has_no_account_associated_with( self): # Enable two providers - Google and LinkedIn: google_provider = self.configure_google_provider(enabled=True) linkedin_provider = self.configure_linkedin_provider(enabled=True) assert len(provider.Registry.enabled()) == 2 states = pipeline.get_provider_user_states(self.user) assert not list(social_models.DjangoStorage.user.objects.all()) assert 2 == len(states) google_state = [ state for state in states if state.provider.provider_id == google_provider.provider_id ][0] linkedin_state = [ state for state in states if state.provider.provider_id == linkedin_provider.provider_id ][0] assert not google_state.has_account assert google_provider.provider_id == google_state.provider.provider_id # Also check the row ID. Note this 'id' changes whenever the configuration does: assert google_provider.id == google_state.provider.id assert self.user == google_state.user assert not linkedin_state.has_account assert linkedin_provider.provider_id == linkedin_state.provider.provider_id assert linkedin_provider.id == linkedin_state.provider.id assert self.user == linkedin_state.user
def do_get(self, request, identifier): """ Fulfill the request, now that the identifier has been specified. """ is_unprivileged = self.is_unprivileged_query(request, identifier) if is_unprivileged: if not getattr(settings, 'ALLOW_UNPRIVILEGED_SSO_PROVIDER_QUERY', False): return Response(status=status.HTTP_403_FORBIDDEN) try: user = User.objects.get(**{identifier.kind: identifier.value}) except User.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) providers = pipeline.get_provider_user_states(user) active_providers = [ self.get_provider_data(assoc, is_unprivileged) for assoc in providers if assoc.has_account ] # In the future this can be trivially modified to return the inactive/disconnected providers as well. return Response({"active": active_providers})
def test_states_for_enabled_providers_user_has_accounts_associated_with( self): # Enable two providers - Google and LinkedIn: google_provider = self.configure_google_provider(enabled=True) linkedin_provider = self.configure_linkedin_provider(enabled=True) user_social_auth_google = social_models.DjangoStorage.user.create_social_auth( self.user, 'uid', google_provider.backend_name) user_social_auth_linkedin = social_models.DjangoStorage.user.create_social_auth( self.user, 'uid', linkedin_provider.backend_name) states = pipeline.get_provider_user_states(self.user) assert 2 == len(states) google_state = [ state for state in states if state.provider.provider_id == google_provider.provider_id ][0] linkedin_state = [ state for state in states if state.provider.provider_id == linkedin_provider.provider_id ][0] assert google_state.has_account assert google_provider.provider_id == google_state.provider.provider_id # Also check the row ID. Note this 'id' changes whenever the configuration does: assert google_provider.id == google_state.provider.id assert self.user == google_state.user assert user_social_auth_google.id == google_state.association_id assert linkedin_state.has_account assert linkedin_provider.provider_id == linkedin_state.provider.provider_id assert linkedin_provider.id == linkedin_state.provider.id assert self.user == linkedin_state.user assert user_social_auth_linkedin.id == linkedin_state.association_id
def test_states_for_enabled_providers_user_has_no_account_associated_with( self): # Enable two providers - Google and LinkedIn: google_provider = self.configure_google_provider(enabled=True) linkedin_provider = self.configure_linkedin_provider(enabled=True) self.assertEqual(len(provider.Registry.enabled()), 2) states = pipeline.get_provider_user_states(self.user) self.assertEqual( [], [x for x in social_models.DjangoStorage.user.objects.all()]) # lint-amnesty, pylint: disable=unnecessary-comprehension self.assertEqual(2, len(states)) google_state = [ state for state in states if state.provider.provider_id == google_provider.provider_id ][0] linkedin_state = [ state for state in states if state.provider.provider_id == linkedin_provider.provider_id ][0] self.assertFalse(google_state.has_account) self.assertEqual(google_provider.provider_id, google_state.provider.provider_id) # Also check the row ID. Note this 'id' changes whenever the configuration does: self.assertEqual(google_provider.id, google_state.provider.id) self.assertEqual(self.user, google_state.user) self.assertFalse(linkedin_state.has_account) self.assertEqual(linkedin_provider.provider_id, linkedin_state.provider.provider_id) self.assertEqual(linkedin_provider.id, linkedin_state.provider.id) self.assertEqual(self.user, linkedin_state.user)
def test_state_not_returned_for_disabled_provider(self): disabled_provider = self.configure_google_provider(enabled=False) enabled_provider = self.configure_facebook_provider(enabled=True) social_models.DjangoStorage.user.create_social_auth(self.user, 'uid', disabled_provider.backend_name) states = pipeline.get_provider_user_states(self.user) assert 1 == len(states) assert disabled_provider.provider_id not in (state.provider.provider_id for state in states) assert enabled_provider.provider_id in (state.provider.provider_id for state in states)
def get(self, request): """ GET /api/third_party_auth/v0/providers/user_status/ **GET Response Values** ``` { "accepts_logins": true, "name": "Google", "disconnect_url": "/auth/disconnect/google-oauth2/?", "connect_url": "/auth/login/google-oauth2/?auth_entry=account_settings&next=%2Faccount%2Fsettings", "connected": false, "id": "oa2-google-oauth2" } ``` """ tpa_states = [] for state in pipeline.get_provider_user_states(request.user): # We only want to include providers if they are either currently available to be logged # in with, or if the user is already authenticated with them. if state.provider.display_for_login or state.has_account: tpa_states.append({ 'id': state.provider.provider_id, 'name': state.provider. name, # The name of the provider e.g. Facebook 'connected': state. has_account, # Whether the user's edX account is connected with the provider. # If the user is not connected, they should be directed to this page to authenticate # with the particular provider, as long as the provider supports initiating a login. 'connect_url': pipeline.get_login_url( state.provider.provider_id, pipeline.AUTH_ENTRY_ACCOUNT_SETTINGS, # The url the user should be directed to after the auth process has completed. redirect_url=reverse('account_settings'), ), 'accepts_logins': state.provider.accepts_logins, # If the user is connected, sending a POST request to this url removes the connection # information for this provider from their edX account. 'disconnect_url': pipeline.get_disconnect_url(state.provider.provider_id, state.association_id), }) return Response(tpa_states)
def get_social_oauth_providers_data(self): """ Get the context data related to the social auth providers Returns: dict: A dictionary containing the data for social oauth SSO providers """ context = {'providers': [], 'is_any_social_auth_connected': False} if third_party_auth.is_enabled(): auth_states = pipeline.get_provider_user_states(self.request.user) for state in auth_states: if state.provider.display_for_login or state.has_account: if state.has_account: context['is_any_social_auth_connected'] = True context['providers'].append({ 'id': state.provider.provider_id, 'name': state.provider.name, 'connected': state.has_account, 'accepts_logins': state.provider.accepts_logins, 'disconnect_url': pipeline.get_disconnect_url(state.provider.provider_id, state.association_id), 'connect_url': pipeline.get_login_url( state.provider.provider_id, pipeline.AUTH_ENTRY_ACCOUNT_SETTINGS, redirect_url=reverse('adg_account_settings'), ), **ACCOUNT_INFO.get(state.provider.provider_id) }) return context
def account_settings_context(request): """ Context for the account settings page. Args: request: The request object. Returns: dict """ user = request.user year_of_birth_options = [(six.text_type(year), six.text_type(year)) for year in UserProfile.VALID_YEARS] try: user_orders = get_user_orders(user) except: # pylint: disable=bare-except log.exception('Error fetching order history from Otto.') # Return empty order list as account settings page expect a list and # it will be broken if exception raised user_orders = [] beta_language = {} dark_lang_config = DarkLangConfig.current() if dark_lang_config.enable_beta_languages: user_preferences = get_user_preferences(user) pref_language = user_preferences.get('pref-lang') if pref_language in dark_lang_config.beta_languages_list: beta_language['code'] = pref_language beta_language['name'] = settings.LANGUAGE_DICT.get(pref_language) context = { 'auth': {}, 'duplicate_provider': None, 'nav_hidden': True, 'fields': { 'country': { 'options': list(countries), }, 'gender': { 'options': [(choice[0], _(choice[1])) for choice in UserProfile.GENDER_CHOICES], }, 'language': { 'options': released_languages(), }, 'level_of_education': { 'options': [(choice[0], _(choice[1])) for choice in UserProfile.LEVEL_OF_EDUCATION_CHOICES], }, 'password': { 'url': reverse('password_reset'), }, 'year_of_birth': { 'options': year_of_birth_options, }, 'preferred_language': { 'options': all_languages(), }, 'time_zone': { 'options': TIME_ZONE_CHOICES, } }, 'platform_name': configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), 'password_reset_support_link': configuration_helpers.get_value('PASSWORD_RESET_SUPPORT_LINK', settings.PASSWORD_RESET_SUPPORT_LINK) or settings.SUPPORT_SITE_LINK, 'user_accounts_api_url': reverse("accounts_api", kwargs={'username': user.username}), 'user_preferences_api_url': reverse('preferences_api', kwargs={'username': user.username}), 'disable_courseware_js': True, 'show_program_listing': ProgramsApiConfig.is_enabled(), 'show_dashboard_tabs': True, 'order_history': user_orders, 'disable_order_history_tab': should_redirect_to_order_history_microfrontend(), 'enable_account_deletion': configuration_helpers.get_value( 'ENABLE_ACCOUNT_DELETION', settings.FEATURES.get('ENABLE_ACCOUNT_DELETION', False)), 'extended_profile_fields': _get_extended_profile_fields(), 'beta_language': beta_language, } enterprise_customer = enterprise_customer_for_request(request) update_account_settings_context_for_enterprise(context, enterprise_customer, user) if third_party_auth.is_enabled(): # If the account on the third party provider is already connected with another edX account, # we display a message to the user. context['duplicate_provider'] = pipeline.get_duplicate_provider( messages.get_messages(request)) auth_states = pipeline.get_provider_user_states(user) context['auth']['providers'] = [ { 'id': state.provider.provider_id, 'name': state.provider.name, # The name of the provider e.g. Facebook 'connected': state. has_account, # Whether the user's edX account is connected with the provider. # If the user is not connected, they should be directed to this page to authenticate # with the particular provider, as long as the provider supports initiating a login. 'connect_url': pipeline.get_login_url( state.provider.provider_id, pipeline.AUTH_ENTRY_ACCOUNT_SETTINGS, # The url the user should be directed to after the auth process has completed. redirect_url=reverse('account_settings'), ), 'accepts_logins': state.provider.accepts_logins, # If the user is connected, sending a POST request to this url removes the connection # information for this provider from their edX account. 'disconnect_url': pipeline.get_disconnect_url(state.provider.provider_id, state.association_id), # We only want to include providers if they are either currently available to be logged # in with, or if the user is already authenticated with them. } for state in auth_states if state.provider.display_for_login or state.has_account ] return context
def test_returns_empty_list_if_no_enabled_providers(self): assert not provider.Registry.enabled() assert not pipeline.get_provider_user_states(self.user)
def test_returns_empty_list_if_no_enabled_providers(self): self.assertFalse(provider.Registry.enabled()) self.assertEqual([], pipeline.get_provider_user_states(self.user))