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
        ))
Esempio n. 2
0
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
    ]
Esempio n. 3
0
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
    ]
Esempio n. 4
0
 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
Esempio n. 5
0
    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
Esempio n. 6
0
 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
Esempio n. 7
0
    def process_request(self, request):
        """
        If a user's UserPreference contains a language preference, use the user's preference.
        Save the current language preference cookie as the user's preferred language.
        """
        cookie_lang = lang_pref_helpers.get_language_cookie(request)
        if cookie_lang:
            if request.user.is_authenticated:
                # DarkLangMiddleware will take care of this so don't change anything
                if DarkLangConfig.current().enabled and get_user_preference(request.user, DARK_LANGUAGE_KEY):
                    return
                set_user_preference(request.user, LANGUAGE_KEY, cookie_lang)
            else:
                request._anonymous_user_cookie_lang = cookie_lang  # lint-amnesty, pylint: disable=protected-access

            accept_header = request.META.get(LANGUAGE_HEADER, None)
            if accept_header:
                current_langs = parse_accept_lang_header(accept_header)
                # Promote the cookie_lang over any language currently in the accept header
                current_langs = [(lang, qvalue) for (lang, qvalue) in current_langs if lang != cookie_lang]
                current_langs.insert(0, (cookie_lang, 1))
                accept_header = ",".join(f"{lang};q={qvalue}" for (lang, qvalue) in current_langs)
            else:
                accept_header = cookie_lang
            request.META[LANGUAGE_HEADER] = accept_header

            # Allow the new cookie setting to update the language in the user's session
            if LANGUAGE_SESSION_KEY in request.session and request.session[LANGUAGE_SESSION_KEY] != cookie_lang:
                del request.session[LANGUAGE_SESSION_KEY]
Esempio n. 8
0
    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
Esempio n. 9
0
    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
        ))
Esempio n. 10
0
    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):
                lang_pref_helpers.set_language_cookie(request, response, user_pref)
            else:
                lang_pref_helpers.unset_language_cookie(response)

        return response
Esempio n. 11
0
 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
Esempio n. 12
0
    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)
Esempio n. 13
0
 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
Esempio n. 14
0
 def released_langs(self):
     """
     Current list of released languages
     """
     language_options = DarkLangConfig.current().released_languages_list
     language_code = configuration_helpers.get_value('LANGUAGE_CODE')
     if language_code not in language_options:
         language_options.append(language_code)
     return language_options
Esempio n. 15
0
    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)
Esempio n. 16
0
    def process_response(self, request, response):
        """
        Apply user's dark lang preference as a cookie for future requests.
        """
        if DarkLangConfig.current().enabled:
            self._set_site_or_microsite_language(request, response)
            self._activate_preview_language(request, response)

        return response
Esempio n. 17
0
    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
Esempio n. 18
0
    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
Esempio n. 19
0
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
    ]
Esempio n. 20
0
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
Esempio n. 21
0
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