def process_darklang_request(self, request): """ Proccess the request to Set or clear the DarkLang depending on the incoming request. Arguments: request (Request): The Django Request Object Returns: HttpResponse: View containing the form for setting the preview lang with the status included in the context """ context = { 'disable_courseware_js': True, 'uses_pattern_library': True } response = None if not DarkLangConfig.current().enabled: message = _('Preview Language is currently disabled') context.update({'form_submit_message': message}) context.update({'success': False}) response = render_to_response(self.template_name, context, request=request) elif 'set_language' in request.POST: # Set the Preview Language response = self._set_preview_language(request, context) elif 'reset' in request.POST: # Reset and clear the language preference response = self._clear_preview_language(request, context) return response
def handle(self, *args, **options): """ Execute the command. """ old_lang_code = options['old_lang_code'] new_lang_code = options['new_lang_code'] chunk_size = options['chunk_size'] sleep_time_secs = options['sleep_time_secs'] start = options['start_id'] end = start + chunk_size # Make sure we're changing to a code that actually exists. Presumably it's safe to move away from a code that # doesn't. dark_lang_config = DarkLangConfig.current() langs = [lang_code[0] for lang_code in settings.LANGUAGES] langs += dark_lang_config.released_languages_list langs += dark_lang_config.beta_languages_list if dark_lang_config.enable_beta_languages else [] if new_lang_code not in langs: raise CommandError(u'{} is not a configured language code in settings.LANGUAGES ' 'or the current DarkLangConfig.'.format(new_lang_code)) max_id = UserPreference.objects.all().aggregate(Max('id'))['id__max'] print(u'Updating user language preferences from {} to {}. ' u'Start id is {}, current max id is {}. ' u'Chunk size is of {}'.format(old_lang_code, new_lang_code, start, max_id, chunk_size)) updated_count = 0 while True: # On the last time through catch any new rows added since this run began if end >= max_id: print('Last round, includes all new rows added since this run started.') id_query = Q(id__gte=start) else: id_query = Q(id__gte=start) & Q(id__lt=end) curr = UserPreference.objects.filter( id_query, key='pref-lang', value=old_lang_code ).update(value=new_lang_code) updated_count += curr print(u'Updated rows {} to {}, {} rows affected'.format(start, end - 1, curr)) if end >= max_id: break start = end end += chunk_size sleep(sleep_time_secs) print(u'Finished! Updated {} total preferences from {} to {}'.format( updated_count, old_lang_code, new_lang_code ))
def _user_can_preview_languages(self, user): """ Returns true if the specified user can preview languages. """ if not DarkLangConfig.current().enabled: return False return user and not user.is_anonymous
def released_languages(): """Retrieve the list of released languages. Constructs a list of Language tuples by intersecting the list of valid language tuples with the list of released language codes. Returns: list of Language: Languages in which full translations are available. Example: >>> print released_languages() [Language(code='en', name=u'English'), Language(code='fr', name=u'Français')] """ released_language_codes = DarkLangConfig.current().released_languages_list default_language_code = settings.LANGUAGE_CODE if default_language_code not in released_language_codes: released_language_codes.append(default_language_code) released_language_codes.sort() # Intersect the list of valid language tuples with the list # of released language codes return [ Language(language_info[0], language_info[1]) for language_info in settings.LANGUAGES if language_info[0] in released_language_codes ]
def beta_langs(self): """ Current list of released languages """ language_options = DarkLangConfig.current().beta_languages_list if settings.LANGUAGE_CODE not in language_options: language_options.append(settings.LANGUAGE_CODE) return language_options
def test_partial_match_esar_es(self): # If I release 'es', 'es-AR' should get 'es', not English DarkLangConfig(released_languages=('es, en'), changed_by=self.user, enabled=True).save() self.assertAcceptEquals( 'es;q=1.0', self.process_middleware_request(accept='es-AR;q=1.0, pt;q=0.5'))
def test_accept_chinese_language_codes(self): DarkLangConfig(released_languages=('zh-cn, zh-hk, zh-tw'), changed_by=self.user, enabled=True).save() self.assertAcceptEquals( 'zh-cn;q=1.0, zh-tw;q=0.5, zh-hk;q=0.3', self.process_middleware_request( accept='zh-Hans;q=1.0, zh-Hant-TW;q=0.5, zh-HK;q=0.3'))
def process_request(self, request): """ Prevent user from requesting un-released languages except by using the preview-lang query string. """ if not DarkLangConfig.current().enabled: return self._clean_accept_headers(request) self._activate_preview_language(request)
def handle(self, *args, **options): """ Execute the command. """ old_lang_code = options['old_lang_code'] new_lang_code = options['new_lang_code'] chunk_size = options['chunk_size'] sleep_time_secs = options['sleep_time_secs'] start = options['start_id'] end = start + chunk_size # Make sure we're changing to a code that actually exists. Presumably it's safe to move away from a code that # doesn't. dark_lang_config = DarkLangConfig.current() langs = [lang_code[0] for lang_code in settings.LANGUAGES] langs += dark_lang_config.released_languages_list langs += dark_lang_config.beta_languages_list if dark_lang_config.enable_beta_languages else [] if new_lang_code not in langs: raise CommandError(u'{} is not a configured language code in settings.LANGUAGES ' 'or the current DarkLangConfig.'.format(new_lang_code)) max_id = UserPreference.objects.all().aggregate(Max('id'))['id__max'] print(u'Updating user language preferences from {} to {}. ' u'Start id is {}, current max id is {}. ' u'Chunk size is of {}'.format(old_lang_code, new_lang_code, start, max_id, chunk_size)) updated_count = 0 while True: # On the last time through catch any new rows added since this run began if end >= max_id: print('Last round, includes all new rows added since this run started.') id_query = Q(id__gte=start) else: id_query = Q(id__gte=start) & Q(id__lt=end) curr = UserPreference.objects.filter( id_query, key='pref-lang', value=old_lang_code ).update(value=new_lang_code) updated_count += curr print(u'Updated rows {} to {}, {} rows affected'.format(start, end - 1, curr)) if end >= max_id: break start = end end += chunk_size sleep(sleep_time_secs) print('Finished! Updated {} total preferences from {} to {}'.format(updated_count, old_lang_code, new_lang_code))
def release_languages(self, languages): """ Release a set of languages using the dark lang interface. languages is a list of comma-separated lang codes, eg, 'ar, es-419' """ user = User() user.save() DarkLangConfig(released_languages=languages, changed_by=user, enabled=True).save()
def test_exact_match_gets_priority(self, accept_header, expected): # Release 'es-419, es, es-es' DarkLangConfig( released_languages=('es-419, es, es-es'), changed_by=self.user, enabled=True ).save() self.assertAcceptEquals( expected, self.process_middleware_request(accept=accept_header) )
def setUp(self): super(DarkLangMiddlewareTests, self).setUp() self.user = UserFactory.build(username='******', email='*****@*****.**', password='******') self.user.save() self.client = Client() self.client.login(username=self.user.username, password='******') DarkLangConfig( released_languages='rel', changed_by=self.user, enabled=True ).save()
def test_context(self, mock_enterprise_customer_for_request): self.request.site = SiteFactory.create() UserPreferenceFactory(user=self.user, key='pref-lang', value='lt-lt') DarkLangConfig(released_languages='en', changed_by=self.user, enabled=True, beta_languages='lt-lt', enable_beta_languages=True).save() mock_enterprise_customer_for_request.return_value = {} with override_settings(LANGUAGES=[EN, LT_LT], LANGUAGE_CODE='en'): context = account_settings_context(self.request) user_accounts_api_url = reverse( "accounts_api", kwargs={'username': self.user.username}) self.assertEqual(context['user_accounts_api_url'], user_accounts_api_url) user_preferences_api_url = reverse( 'preferences_api', kwargs={'username': self.user.username}) self.assertEqual(context['user_preferences_api_url'], user_preferences_api_url) for attribute in self.FIELDS: self.assertIn(attribute, context['fields']) self.assertEqual( context['user_accounts_api_url'], reverse("accounts_api", kwargs={'username': self.user.username})) self.assertEqual( context['user_preferences_api_url'], reverse('preferences_api', kwargs={'username': self.user.username})) self.assertEqual(context['duplicate_provider'], 'facebook') self.assertEqual(context['auth']['providers'][0]['name'], 'Facebook') self.assertEqual(context['auth']['providers'][1]['name'], 'Google') self.assertEqual(context['sync_learner_profile_data'], False) self.assertEqual(context['edx_support_url'], settings.SUPPORT_SITE_LINK) self.assertEqual(context['enterprise_name'], None) self.assertEqual(context['enterprise_readonly_account_fields'], { 'fields': list(get_enterprise_readonly_account_fields(self.user)) }) expected_beta_language = { 'code': 'lt-lt', 'name': settings.LANGUAGE_DICT.get('lt-lt') } self.assertEqual(context['beta_language'], expected_beta_language)
def test_partial_match_es419(self, accept_header, expected): # Release es-419 DarkLangConfig( released_languages=('es-419, en'), changed_by=self.user, enabled=True ).save() self.assertAcceptEquals( expected, self.process_middleware_request(accept=accept_header) )
def test_partial_match_es_la(self, latin_america_code): # We need to figure out the best way to implement this. There are a ton of LA country # codes that ought to fall back to 'es-419' rather than 'es-es'. # http://unstats.un.org/unsd/methods/m49/m49regin.htm#americas # If I release 'es, es-419' # Latin American codes should get es-419 DarkLangConfig(released_languages=('es, es-419'), changed_by=self.user, enabled=True).save() self.assertAcceptEquals( 'es-419;q=1.0', self.process_middleware_request( accept='{};q=1.0, pt;q=0.5'.format(latin_america_code)))
def test_released_languages(self, default_lang, languages, dark_lang_released, expected_languages): """ Tests for the released languages. """ with override_settings(LANGUAGES=languages, LANGUAGE_CODE=default_lang): user = User() user.save() DarkLangConfig(released_languages=', '.join(dark_lang_released), changed_by=user, enabled=True).save() released_languages = language_api.released_languages() self.assertEqual(released_languages, expected_languages)
def test_accept_mixed_case(self): self.assertAcceptEquals( 'rel;q=1.0, rel;q=0.5', self.process_middleware_request(accept='rel-TER;q=1.0, REL;q=0.5')) DarkLangConfig(released_languages='REL-TER', changed_by=self.user, enabled=True).save() # Since we have only released "rel-ter", the requested code "rel" will # fuzzy match to "rel-ter", in addition to "rel-ter" exact matching "rel-ter" self.assertAcceptEquals( 'rel-ter;q=1.0, rel-ter;q=0.5', self.process_middleware_request(accept='rel-ter;q=1.0, rel;q=0.5'))
def setUp(self): """ Set up the environment for the test case and ensures correct DarkLang configurations. """ super(DefaultLocaleMiddlewareTest, self).setUp() self.middleware = DefaultLocaleMiddleware() self.request_factory = RequestFactory() self.user = UserFactory() DarkLangConfig( released_languages='en,ar,eo', changed_by=self.user, enabled=True ).save()
def test_beta_languages(self): """ Tests for the beta languages. """ with override_settings(LANGUAGES=[EN, ES_419, LT_LT], LANGUAGE_CODE='en'): user = User() user.save() DarkLangConfig(released_languages='es-419', changed_by=user, enabled=True, beta_languages='lt-lt', enable_beta_languages=True).save() released_languages = language_api.released_languages() expected_languages = [EN, ES_419, LT_LT] self.assertEqual(released_languages, expected_languages)
def test_accept_multiple_released_langs(self): DarkLangConfig(released_languages=('rel, unrel'), changed_by=self.user, enabled=True).save() self.assertAcceptEquals( 'rel;q=1.0, unrel;q=0.5', self.process_middleware_request(accept='rel;q=1.0, unrel;q=0.5')) self.assertAcceptEquals( 'rel;q=1.0, unrel;q=0.5', self.process_middleware_request( accept='rel;q=1.0, notrel;q=0.3, unrel;q=0.5')) self.assertAcceptEquals( 'rel;q=1.0, unrel;q=0.5', self.process_middleware_request( accept='notrel;q=0.3, rel;q=1.0, unrel;q=0.5'))
def test_i18n(self): """ Test that a block's rendered content respects the Accept-Language header and returns translated content. """ block_id = library_api.create_library_block(self.library.key, "problem", "i18n_problem").usage_key new_olx = """ <problem display_name="New Multi Choice Question" max_attempts="5"> <multiplechoiceresponse> <p>This is a normal capa problem. It has "maximum attempts" set to **5**.</p> <label>Blockstore is designed to store.</label> <choicegroup type="MultipleChoice"> <choice correct="false">XBlock metadata only</choice> <choice correct="true">XBlock data/metadata and associated static asset files</choice> <choice correct="false">Static asset files for XBlocks and courseware</choice> <choice correct="false">XModule metadata only</choice> </choicegroup> </multiplechoiceresponse> </problem> """.strip() library_api.set_library_block_olx(block_id, new_olx) library_api.publish_changes(self.library.key) # Enable the dummy language in darklang DarkLangConfig(released_languages='eo', changed_by=self.student_a, enabled=True).save() client = APIClient() # View the problem without specifying a language default_public_view = client.get( URL_BLOCK_RENDER_VIEW.format(block_key=block_id, view_name='public_view')) assert 'Submit' in default_public_view.data['content'] assert 'Süßmït' not in default_public_view.data['content'] # View the problem and request the dummy language dummy_public_view = client.get(URL_BLOCK_RENDER_VIEW.format( block_key=block_id, view_name='public_view'), HTTP_ACCEPT_LANGUAGE='eo') assert 'Süßmït' in dummy_public_view.data['content'] assert 'Submit' not in dummy_public_view.data['content']
def test_include_language_selector(self, theme, language, include_language_selector): self._set_feature_flag(True) DarkLangConfig(released_languages='en,eo,es-419,fr', enabled=True, changed_by=User().save()).save() with with_comprehensive_theme_context(theme): params = { key: val for key, val in [ ('language', language), ('include-language-selector', include_language_selector) ] if val } resp = self._get_footer(accepts="text/html", params=params) self.assertEqual(resp.status_code, 200) if include_language_selector: selected_language = language if language else 'en' self._verify_language_selector(resp.content, selected_language) else: self.assertNotIn('footer-language-selector', resp.content)
def _fuzzy_match(self, lang_code): """Returns a fuzzy match for lang_code""" match = None dark_lang_config = DarkLangConfig.current() if dark_lang_config.enable_beta_languages: langs = self.released_langs + self.beta_langs else: langs = self.released_langs if lang_code in langs: match = lang_code else: lang_prefix = lang_code.partition('-')[0] for released_lang in langs: released_prefix = released_lang.partition('-')[0] if lang_prefix == released_prefix: match = released_lang return match
def test_disabled(self): DarkLangConfig(enabled=False, changed_by=self.user).save() self.assertAcceptEquals( 'notrel;q=0.3, rel;q=1.0, unrel;q=0.5', self.process_middleware_request( accept='notrel;q=0.3, rel;q=1.0, unrel;q=0.5')) # With DarkLang disabled the clear should not change the session language self._set_client_session_language('rel') self._post_clear_preview_lang() self.client.get('/home') self.assert_session_lang_equals('rel', self.client.session) # Test that setting the preview language with DarkLang disabled does nothing self._set_client_session_language('unrel') self._post_set_preview_lang('rel') self.client.get('/home') self.assert_session_lang_equals('unrel', self.client.session)
def process_response(self, request, response): # lint-amnesty, pylint: disable=missing-function-docstring # If the user is logged in, check for their language preference. Also check for real user # if current user is a masquerading user, user_pref = None current_user = None if hasattr(request, 'user'): current_user = getattr(request.user, 'real_user', request.user) if current_user and current_user.is_authenticated: # DarkLangMiddleware has already set this cookie if DarkLangConfig.current().enabled and get_user_preference(current_user, DARK_LANGUAGE_KEY): return response anonymous_cookie_lang = getattr(request, '_anonymous_user_cookie_lang', None) if anonymous_cookie_lang: user_pref = anonymous_cookie_lang set_user_preference(current_user, LANGUAGE_KEY, anonymous_cookie_lang) else: # Get the user's language preference try: user_pref = get_user_preference(current_user, LANGUAGE_KEY) except (UserAPIRequestError, UserAPIInternalError): # If we can't find the user preferences, then don't modify the cookie pass # If set, set the user_pref in the LANGUAGE_COOKIE_NAME if user_pref and not is_request_from_mobile_app(request): response.set_cookie( settings.LANGUAGE_COOKIE_NAME, value=user_pref, domain=settings.SHARED_COOKIE_DOMAIN, max_age=COOKIE_DURATION, secure=request.is_secure() ) else: response.delete_cookie( settings.LANGUAGE_COOKIE_NAME, domain=settings.SHARED_COOKIE_DOMAIN ) return response
def test_course_expiration_banner_with_unicode(self, mock_strftime_localized, mock_get_date_string): """ Ensure that switching to other languages that have unicode in their date representations will not cause the course home page to 404. """ fake_unicode_start_time = u"üñîçø∂é_ßtå®t_tîµé" mock_strftime_localized.return_value = fake_unicode_start_time date_string = u'<span class="localized-datetime" data-format="shortDate" \ data-datetime="{formatted_date}" data-language="{language}">{formatted_date_localized}</span>' mock_get_date_string.return_value = date_string config = CourseDurationLimitConfig(course=CourseOverview.get_from_id( self.course.id), enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC)) config.save() url = course_home_url(self.course) user = self.create_user_for_course(self.course, CourseUserType.UNENROLLED) CourseEnrollment.enroll(user, self.course.id) language = 'eo' DarkLangConfig(released_languages=language, changed_by=user, enabled=True).save() response = self.client.get(url, HTTP_ACCEPT_LANGUAGE=language) self.assertEqual(response.status_code, 200) self.assertEqual(response['Content-Language'], language) # Check that if the string is incorrectly not marked as unicode we still get the error with mock.patch( "openedx.features.course_duration_limits.access.get_date_string", return_value=date_string.encode('utf-8')): response = self.client.get(url, HTTP_ACCEPT_LANGUAGE=language) self.assertEqual(response.status_code, 500)
def released_languages(): """Retrieve the list of released languages. Constructs a list of Language tuples by intersecting the list of valid language tuples with the list of released language codes. Returns: list of Language: Languages in which full translations are available. Example: >>> print released_languages() [Language(code='en', name=u'English'), Language(code='fr', name=u'Français')] """ dark_lang_config = DarkLangConfig.current() released_language_codes = dark_lang_config.released_languages_list default_language_code = settings.LANGUAGE_CODE if default_language_code not in released_language_codes: released_language_codes.append(default_language_code) if dark_lang_config.enable_beta_languages: beta_language_codes = dark_lang_config.beta_languages_list if beta_language_codes not in released_language_codes: released_language_codes = released_language_codes + beta_language_codes released_language_codes.sort() # Intersect the list of valid language tuples with the list # of released language codes return [ Language(language_info[0], language_info[1]) for language_info in settings.LANGUAGES if language_info[0] in released_language_codes ]
def released_languages(): """Retrieve the list of released languages. Constructs a list of Language tuples by intersecting the list of valid language tuples with the list of released language codes. If request comes from a Microsite, it will look for the LANGUAGE_LIST in the microsite configuration Returns: list of Language: Languages in which full translations are available. Example: >>> print released_languages() [Language(code='en', name=u'English'), Language(code='fr', name=u'Français')] """ released_language_codes = DarkLangConfig.current().released_languages_list default_language_code = configuration_helpers.get_value('LANGUAGE_CODE') site_languages = configuration_helpers.get_value('LANGUAGE_LIST', None) if site_languages is not None: released_language_codes = site_languages if default_language_code not in released_language_codes: released_language_codes.append(default_language_code) released_language_codes.sort() # Intersect the list of valid language tuples with the list # of released language codes return [ Language(language_info[0], language_info[1]) for language_info in settings.LANGUAGES if language_info[0] in released_language_codes ]
def test_closest_released_language(self, released_languages, course_language, expected_language): DarkLangConfig(released_languages=released_languages, enabled=True, changed_by=self.user).save() course_overview = CourseOverviewFactory.create(language=course_language) self.assertEqual(course_overview.closest_released_language, expected_language)
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 = [(unicode(year), unicode(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 = get_enterprise_customer_for_learner(user=request.user) update_account_settings_context_for_enterprise(context, enterprise_customer) 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 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