コード例 #1
0
    def _add_honor_code_field(self, form_desc, required=True):
        """Add an honor code field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Separate terms of service and honor code checkboxes
        if self._is_field_visible("terms_of_service"):
            terms_text = _(u"Honor Code")

        # Combine terms of service and honor code checkboxes
        else:
            # Translators: This is a legal document users must agree to
            # in order to register a new account.
            terms_text = _(u"Terms of Service and Honor Code")

        terms_link = u"<a href=\"{url}\">{terms_text}</a>".format(
            url=marketing_link("HONOR"),
            terms_text=terms_text
        )

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        label = _(u"I agree to the {platform_name} {terms_of_service}.").format(
            platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
            terms_of_service=terms_link
        )

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        error_msg = _(u"You must agree to the {platform_name} {terms_of_service}.").format(
            platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
            terms_of_service=terms_link
        )

        form_desc.add_field(
            "honor_code",
            label=label,
            field_type="checkbox",
            default=False,
            required=required,
            error_messages={
                "required": error_msg
            }
        )
コード例 #2
0
ファイル: views.py プロジェクト: AndreySonetico/edx-platform
    def _add_honor_code_field(self, form_desc, required=True):
        """Add an honor code field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Separate terms of service and honor code checkboxes
        if self._is_field_visible("terms_of_service"):
            terms_text = _(u"Honor Code")

        # Combine terms of service and honor code checkboxes
        else:
            # Translators: This is a legal document users must agree to
            # in order to register a new account.
            terms_text = _(u"Terms of Service and Honor Code")

        terms_link = u"<a href=\"{url}\">{terms_text}</a>".format(
            url=marketing_link("HONOR"),
            terms_text=terms_text
        )

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        label = _(u"I agree to the {platform_name} {terms_of_service}.").format(
            platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
            terms_of_service=terms_link
        )

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        error_msg = _(u"You must agree to the {platform_name} {terms_of_service}.").format(
            platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
            terms_of_service=terms_link
        )

        form_desc.add_field(
            "honor_code",
            label=label,
            field_type="checkbox",
            default=False,
            required=required,
            error_messages={
                "required": error_msg
            }
        )
コード例 #3
0
    def __init__(self, *args, **kwargs):
        super(RegistrationView, self).__init__(*args, **kwargs)

        # Backwards compatibility: Honor code is required by default, unless
        # explicitly set to "optional" in Django settings.
        self._extra_fields_setting = copy.deepcopy(
            get_themed_value('REGISTRATION_EXTRA_FIELDS'))
        if not self._extra_fields_setting:
            self._extra_fields_setting = copy.deepcopy(
                settings.REGISTRATION_EXTRA_FIELDS)
        self._extra_fields_setting[
            "honor_code"] = self._extra_fields_setting.get(
                "honor_code", "required")

        # Check that the setting is configured correctly
        for field_name in self.EXTRA_FIELDS:
            if self._extra_fields_setting.get(field_name, "hidden") not in [
                    "required", "optional", "hidden"
            ]:
                msg = u"Setting REGISTRATION_EXTRA_FIELDS values must be either required, optional, or hidden."
                raise ImproperlyConfigured(msg)

        # Map field names to the instance method used to add the field to the form
        self.field_handlers = {}
        for field_name in self.DEFAULT_FIELDS + self.EXTRA_FIELDS:
            handler = getattr(
                self, "_add_{field_name}_field".format(field_name=field_name))
            self.field_handlers[field_name] = handler
コード例 #4
0
 def get_setting(self, name):
     """ Get the value of a setting, or raise KeyError """
     if name == "ORG_INFO":
         return json.loads(self.org_info_str)
     if name == "SP_ENTITY_ID":
         return self.entity_id
     if name == "SP_PUBLIC_CERT":
         if self.public_key:
             return self.public_key
         # To allow instances to avoid storing keys in the DB, the key pair can also be set via Django:
         return getattr(settings, 'SOCIAL_AUTH_SAML_SP_PUBLIC_CERT', '')
     if name == "SP_PRIVATE_KEY":
         if self.private_key:
             return self.private_key
         # To allow instances to avoid storing keys in the DB, the private key can also be set via Django:
         return getattr(settings, 'SOCIAL_AUTH_SAML_SP_PRIVATE_KEY', '')
     other_config = json.loads(self.other_config_str)
     if name in ("TECHNICAL_CONTACT", "SUPPORT_CONTACT"):
         contact = {
             "givenName":
             "{} Support".format(
                 get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)),
             "emailAddress":
             settings.TECH_SUPPORT_EMAIL
         }
         contact.update(other_config.get(name, {}))
         return contact
     return other_config[
         name]  # SECURITY_CONFIG, SP_EXTRA, or similar extra settings
コード例 #5
0
ファイル: views.py プロジェクト: AndreySonetico/edx-platform
def get_or_create_root():
    """
    Returns the root article, or creates it if it doesn't exist.
    """
    try:
        root = URLPath.root()
        if not root.article:
            root.delete()
            raise NoRootURL
        return root
    except NoRootURL:
        pass

    starting_content = "\n".join((
        _("Welcome to the {platform_name} Wiki").format(platform_name=get_themed_value('PLATFORM_NAME',
                                                                                       settings.PLATFORM_NAME)),
        "===",
        _("Visit a course wiki to add an article."),
    ))

    root = URLPath.create_root(title=_("Wiki"), content=starting_content)
    article = root.article
    article.group = None
    article.group_read = True
    article.group_write = False
    article.other_read = True
    article.other_write = False
    article.save()

    return root
コード例 #6
0
ファイル: models.py プロジェクト: AndreySonetico/edx-platform
 def get_setting(self, name):
     """ Get the value of a setting, or raise KeyError """
     if name == "ORG_INFO":
         return json.loads(self.org_info_str)
     if name == "SP_ENTITY_ID":
         return self.entity_id
     if name == "SP_PUBLIC_CERT":
         if self.public_key:
             return self.public_key
         # To allow instances to avoid storing keys in the DB, the key pair can also be set via Django:
         return getattr(settings, 'SOCIAL_AUTH_SAML_SP_PUBLIC_CERT', '')
     if name == "SP_PRIVATE_KEY":
         if self.private_key:
             return self.private_key
         # To allow instances to avoid storing keys in the DB, the private key can also be set via Django:
         return getattr(settings, 'SOCIAL_AUTH_SAML_SP_PRIVATE_KEY', '')
     other_config = json.loads(self.other_config_str)
     if name in ("TECHNICAL_CONTACT", "SUPPORT_CONTACT"):
         contact = {
             "givenName": "{} Support".format(get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)),
             "emailAddress": settings.TECH_SUPPORT_EMAIL
         }
         contact.update(other_config.get(name, {}))
         return contact
     return other_config[name]  # SECURITY_CONFIG, SP_EXTRA, or similar extra settings
コード例 #7
0
ファイル: models.py プロジェクト: AndreySonetico/edx-platform
def _send_decision_email(instance):
    """ Send an email to requesting user with the decision made about their request. """
    context = {
        'name': instance.user.username,
        'api_management_url': urlunsplit(
            (
                'https' if settings.HTTPS == 'on' else 'http',
                instance.site.domain,
                reverse('api_admin:api-status'),
                '',
                '',
            )
        ),
        'authentication_docs_url': settings.AUTH_DOCUMENTATION_URL,
        'api_docs_url': settings.API_DOCUMENTATION_URL,
        'support_email_address': settings.API_ACCESS_FROM_EMAIL,
        'platform_name': get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)
    }

    message = render_to_string(
        'api_admin/api_access_request_email_{status}.txt'.format(status=instance.status),
        context
    )
    try:
        send_mail(
            _('API access request'),
            message,
            settings.API_ACCESS_FROM_EMAIL,
            [instance.user.email],
            fail_silently=False
        )
        instance.contacted = True
    except SMTPException:
        log.exception('Error sending API user notification email for request [%s].', instance.id)
コード例 #8
0
ファイル: views.py プロジェクト: workrocks/edx-platform
def get_or_create_root():
    """
    Returns the root article, or creates it if it doesn't exist.
    """
    try:
        root = URLPath.root()
        if not root.article:
            root.delete()
            raise NoRootURL
        return root
    except NoRootURL:
        pass

    starting_content = "\n".join((
        _("Welcome to the {platform_name} Wiki").format(
            platform_name=get_themed_value('PLATFORM_NAME',
                                           settings.PLATFORM_NAME)),
        "===",
        _("Visit a course wiki to add an article."),
    ))

    root = URLPath.create_root(title=_("Wiki"), content=starting_content)
    article = root.article
    article.group = None
    article.group_read = True
    article.group_write = False
    article.other_read = True
    article.other_write = False
    article.save()

    return root
コード例 #9
0
ファイル: views.py プロジェクト: AndreySonetico/edx-platform
    def get(self, request):
        """Return a description of the password reset form.

        This decouples clients from the API definition:
        if the API decides to modify the form, clients won't need
        to be updated.

        See `user_api.helpers.FormDescription` for examples
        of the JSON-encoded form description.

        Returns:
            HttpResponse

        """
        form_desc = FormDescription("post", reverse("password_change_request"))

        # Translators: This label appears above a field on the password reset
        # form meant to hold the user's email address.
        email_label = _(u"Email")

        # Translators: This example email address is used as a placeholder in
        # a field on the password reset form meant to hold the user's email address.
        email_placeholder = _(u"*****@*****.**")

        # Translators: These instructions appear on the password reset form,
        # immediately below a field meant to hold the user's email address.
        email_instructions = _(u"The email address you used to register with {platform_name}").format(
            platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)
        )

        form_desc.add_field(
            "email",
            field_type="email",
            label=email_label,
            placeholder=email_placeholder,
            instructions=email_instructions,
            restrictions={
                "min_length": EMAIL_MIN_LENGTH,
                "max_length": EMAIL_MAX_LENGTH,
            }
        )

        return HttpResponse(form_desc.to_json(), content_type="application/json")
コード例 #10
0
    def get(self, request):
        """Return a description of the password reset form.

        This decouples clients from the API definition:
        if the API decides to modify the form, clients won't need
        to be updated.

        See `user_api.helpers.FormDescription` for examples
        of the JSON-encoded form description.

        Returns:
            HttpResponse

        """
        form_desc = FormDescription("post", reverse("password_change_request"))

        # Translators: This label appears above a field on the password reset
        # form meant to hold the user's email address.
        email_label = _(u"Email")

        # Translators: This example email address is used as a placeholder in
        # a field on the password reset form meant to hold the user's email address.
        email_placeholder = _(u"*****@*****.**")

        # Translators: These instructions appear on the password reset form,
        # immediately below a field meant to hold the user's email address.
        email_instructions = _(
            u"The email address you used to register with {platform_name}"
        ).format(platform_name=get_themed_value('PLATFORM_NAME',
                                                settings.PLATFORM_NAME))

        form_desc.add_field("email",
                            field_type="email",
                            label=email_label,
                            placeholder=email_placeholder,
                            instructions=email_instructions,
                            restrictions={
                                "min_length": EMAIL_MIN_LENGTH,
                                "max_length": EMAIL_MAX_LENGTH,
                            })

        return HttpResponse(form_desc.to_json(),
                            content_type="application/json")
コード例 #11
0
    def _add_goals_field(self, form_desc, required=True):
        """Add a goals field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This phrase appears above a field on the registration form
        # meant to hold the user's reasons for registering with edX.
        goals_label = _(u"Tell us why you're interested in {platform_name}"
                        ).format(platform_name=get_themed_value(
                            "PLATFORM_NAME", settings.PLATFORM_NAME))

        form_desc.add_field("goals",
                            label=goals_label,
                            field_type="textarea",
                            required=required)
コード例 #12
0
ファイル: views.py プロジェクト: AndreySonetico/edx-platform
    def __init__(self, *args, **kwargs):
        super(RegistrationView, self).__init__(*args, **kwargs)

        # Backwards compatibility: Honor code is required by default, unless
        # explicitly set to "optional" in Django settings.
        self._extra_fields_setting = copy.deepcopy(get_themed_value('REGISTRATION_EXTRA_FIELDS'))
        if not self._extra_fields_setting:
            self._extra_fields_setting = copy.deepcopy(settings.REGISTRATION_EXTRA_FIELDS)
        self._extra_fields_setting["honor_code"] = self._extra_fields_setting.get("honor_code", "required")

        # Check that the setting is configured correctly
        for field_name in self.EXTRA_FIELDS:
            if self._extra_fields_setting.get(field_name, "hidden") not in ["required", "optional", "hidden"]:
                msg = u"Setting REGISTRATION_EXTRA_FIELDS values must be either required, optional, or hidden."
                raise ImproperlyConfigured(msg)

        # Map field names to the instance method used to add the field to the form
        self.field_handlers = {}
        for field_name in self.DEFAULT_FIELDS + self.EXTRA_FIELDS:
            handler = getattr(self, "_add_{field_name}_field".format(field_name=field_name))
            self.field_handlers[field_name] = handler
コード例 #13
0
    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
        if self.check_test(value):
            final_attrs['checked'] = 'checked'
        if not (value is True or value is False or value is None or value == ''):
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_text(value)

        # Translators: link_start and link_end are HTML tags for a link to the terms of service.
        # platform_name is the name of this Open edX installation.
        label = _('I, and my company, accept the {link_start}{platform_name} API Terms of Service{link_end}.').format(
            platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
            link_start='<a href="{url}" target="_blank">'.format(url=reverse('api_admin:api-tos')),
            link_end='</a>',
        )

        html = '<input{{}} /> <label class="tos-checkbox-label" for="{id}">{label}</label>'.format(
            id=final_attrs['id'],
            label=label
        )
        return format_html(html, flatatt(final_attrs))
コード例 #14
0
ファイル: views.py プロジェクト: AndreySonetico/edx-platform
    def _add_goals_field(self, form_desc, required=True):
        """Add a goals field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This phrase appears above a field on the registration form
        # meant to hold the user's reasons for registering with edX.
        goals_label = _(u"Tell us why you're interested in {platform_name}").format(
            platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME)
        )

        form_desc.add_field(
            "goals",
            label=goals_label,
            field_type="textarea",
            required=required
        )
コード例 #15
0
def _send_decision_email(instance):
    """ Send an email to requesting user with the decision made about their request. """
    context = {
        'name':
        instance.user.username,
        'api_management_url':
        urlunsplit((
            'https' if settings.HTTPS == 'on' else 'http',
            instance.site.domain,
            reverse('api_admin:api-status'),
            '',
            '',
        )),
        'authentication_docs_url':
        settings.AUTH_DOCUMENTATION_URL,
        'api_docs_url':
        settings.API_DOCUMENTATION_URL,
        'support_email_address':
        settings.API_ACCESS_FROM_EMAIL,
        'platform_name':
        get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)
    }

    message = render_to_string(
        'api_admin/api_access_request_email_{status}.txt'.format(
            status=instance.status), context)
    try:
        send_mail(_('API access request'),
                  message,
                  settings.API_ACCESS_FROM_EMAIL, [instance.user.email],
                  fail_silently=False)
        instance.contacted = True
    except SMTPException:
        log.exception(
            'Error sending API user notification email for request [%s].',
            instance.id)
コード例 #16
0
ファイル: widgets.py プロジェクト: workrocks/edx-platform
    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
        if self.check_test(value):
            final_attrs['checked'] = 'checked'
        if not (value is True or value is False or value is None
                or value == ''):
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_text(value)

        # Translators: link_start and link_end are HTML tags for a link to the terms of service.
        # platform_name is the name of this Open edX installation.
        label = _(
            'I, and my company, accept the {link_start}{platform_name} API Terms of Service{link_end}.'
        ).format(
            platform_name=get_themed_value('PLATFORM_NAME',
                                           settings.PLATFORM_NAME),
            link_start='<a href="{url}" target="_blank">'.format(
                url=reverse('api_admin:api-tos')),
            link_end='</a>',
        )

        html = '<input{{}} /> <label class="tos-checkbox-label" for="{id}">{label}</label>'.format(
            id=final_attrs['id'], label=label)
        return format_html(html, flatatt(final_attrs))
コード例 #17
0
ファイル: views.py プロジェクト: imranariffin/edx-platform
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 = []

    context = {
        'auth': {},
        'duplicate_provider': None,
        'fields': {
            'country': {
                'options': list(countries),
            }, 'gender': {
                'options': [(choice[0], _(choice[1])) for choice in UserProfile.GENDER_CHOICES],  # pylint: disable=translation-of-non-string
            }, 'language': {
                'options': released_languages(),
            }, 'level_of_education': {
                'options': [(choice[0], _(choice[1])) for choice in UserProfile.LEVEL_OF_EDUCATION_CHOICES],  # pylint: disable=translation-of-non-string
            }, 'password': {
                'url': reverse('password_reset'),
            }, 'year_of_birth': {
                'options': year_of_birth_options,
            }, 'preferred_language': {
                'options': all_languages(),
            }, 'time_zone': {
                'options': UserPreference.TIME_ZONE_CHOICES,
                'enabled': settings.FEATURES.get('ENABLE_TIME_ZONE_PREFERENCE'),
            }
        },
        'platform_name': get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
        '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.current().show_program_listing,
        'order_history': user_orders
    }

    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),
        } for state in auth_states]

    return context
コード例 #18
0
ファイル: views.py プロジェクト: imranariffin/edx-platform
def login_and_registration_form(request, initial_mode="login"):
    """Render the combined login/registration form, defaulting to login

    This relies on the JS to asynchronously load the actual form from
    the user_api.

    Keyword Args:
        initial_mode (string): Either "login" or "register".

    """
    # Determine the URL to redirect to following login/registration/third_party_auth
    redirect_to = get_next_url_for_login_page(request)

    # If we're already logged in, redirect to the dashboard
    if request.user.is_authenticated():
        return redirect(redirect_to)

    # Retrieve the form descriptions from the user API
    form_descriptions = _get_form_descriptions(request)

    # If this is a themed site, revert to the old login/registration pages.
    # We need to do this for now to support existing themes.
    # Themed sites can use the new logistration page by setting
    # 'ENABLE_COMBINED_LOGIN_REGISTRATION' in their theme/microsite
    # configuration settings.
    if is_request_in_themed_site() and not get_themed_value('ENABLE_COMBINED_LOGIN_REGISTRATION', False):
        if initial_mode == "login":
            return old_login_view(request)
        elif initial_mode == "register":
            return old_register_view(request)

    # Allow external auth to intercept and handle the request
    ext_auth_response = _external_auth_intercept(request, initial_mode)
    if ext_auth_response is not None:
        return ext_auth_response

    # Our ?next= URL may itself contain a parameter 'tpa_hint=x' that we need to check.
    # If present, we display a login page focused on third-party auth with that provider.
    third_party_auth_hint = None
    if '?' in redirect_to:
        try:
            next_args = urlparse.parse_qs(urlparse.urlparse(redirect_to).query)
            provider_id = next_args['tpa_hint'][0]
            if third_party_auth.provider.Registry.get(provider_id=provider_id):
                third_party_auth_hint = provider_id
                initial_mode = "hinted_login"
        except (KeyError, ValueError, IndexError):
            pass

    # Otherwise, render the combined login/registration page
    context = {
        'data': {
            'login_redirect_url': redirect_to,
            'initial_mode': initial_mode,
            'third_party_auth': _third_party_auth_context(request, redirect_to),
            'third_party_auth_hint': third_party_auth_hint or '',
            'platform_name': get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),

            # Include form descriptions retrieved from the user API.
            # We could have the JS client make these requests directly,
            # but we include them in the initial page load to avoid
            # the additional round-trip to the server.
            'login_form_desc': json.loads(form_descriptions['login']),
            'registration_form_desc': json.loads(form_descriptions['registration']),
            'password_reset_form_desc': json.loads(form_descriptions['password_reset']),
        },
        'login_redirect_url': redirect_to,  # This gets added to the query string of the "Sign In" button in header
        'responsive': True,
        'allow_iframing': True,
        'disable_courseware_js': True,
        'disable_footer': True,
    }

    return render_to_response('student_account/login_and_register.html', context)
コード例 #19
0
ファイル: views.py プロジェクト: moonshot/edx-platform
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 = []

    context = {
        "auth": {},
        "duplicate_provider": None,
        "fields": {
            "country": {"options": list(countries)},
            "gender": {
                "options": [
                    (choice[0], _(choice[1])) for choice in UserProfile.GENDER_CHOICES
                ]  # pylint: disable=translation-of-non-string
            },
            "language": {"options": released_languages()},
            "level_of_education": {
                "options": [
                    (choice[0], _(choice[1])) for choice in UserProfile.LEVEL_OF_EDUCATION_CHOICES
                ]  # pylint: disable=translation-of-non-string
            },
            "password": {"url": reverse("password_reset")},
            "year_of_birth": {"options": year_of_birth_options},
            "preferred_language": {"options": all_languages()},
            "time_zone": {
                "options": TIME_ZONE_CHOICES,
                "enabled": settings.FEATURES.get("ENABLE_TIME_ZONE_PREFERENCE"),
            },
        },
        "platform_name": get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
        "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.current().show_program_listing,
        "order_history": user_orders,
    }

    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),
            }
            for state in auth_states
        ]

    return context
コード例 #20
0
ファイル: views.py プロジェクト: chaitanyakale/edx-platform
def _record_feedback_in_zendesk(
        realname,
        email,
        subject,
        details,
        tags,
        additional_info,
        group_name=None,
        require_update=False,
        support_email=None
):
    """
    Create a new user-requested Zendesk ticket.

    Once created, the ticket will be updated with a private comment containing
    additional information from the browser and server, such as HTTP headers
    and user state. Returns a boolean value indicating whether ticket creation
    was successful, regardless of whether the private comment update succeeded.

    If `group_name` is provided, attaches the ticket to the matching Zendesk group.

    If `require_update` is provided, returns False when the update does not
    succeed. This allows using the private comment to add necessary information
    which the user will not see in followup emails from support.
    """
    zendesk_api = _ZendeskApi()

    additional_info_string = (
        u"Additional information:\n\n" +
        u"\n".join(u"%s: %s" % (key, value) for (key, value) in additional_info.items() if value is not None)
    )

    # Tag all issues with LMS to distinguish channel in Zendesk; requested by student support team
    zendesk_tags = list(tags.values()) + ["LMS"]

    # Per edX support, we would like to be able to route white label feedback items
    # via tagging
    white_label_org = get_themed_value('course_org_filter')
    if white_label_org:
        zendesk_tags = zendesk_tags + ["whitelabel_{org}".format(org=white_label_org)]

    new_ticket = {
        "ticket": {
            "requester": {"name": realname, "email": email},
            "subject": subject,
            "comment": {"body": details},
            "tags": zendesk_tags
        }
    }
    group = None
    if group_name is not None:
        group = zendesk_api.get_group(group_name)
        if group is not None:
            new_ticket['ticket']['group_id'] = group['id']
    if support_email is not None:
        # If we do not include the `recipient` key here, Zendesk will default to using its default reply
        # email address when support agents respond to tickets. By setting the `recipient` key here,
        # we can ensure that WL site users are responded to via the correct Zendesk support email address.
        new_ticket['ticket']['recipient'] = support_email
    try:
        ticket_id = zendesk_api.create_ticket(new_ticket)
        if group_name is not None and group is None:
            # Support uses Zendesk groups to track tickets. In case we
            # haven't been able to correctly group this ticket, log its ID
            # so it can be found later.
            log.warning('Unable to find group named %s for Zendesk ticket with ID %s.', group_name, ticket_id)
    except zendesk.ZendeskError:
        log.exception("Error creating Zendesk ticket")
        return False

    # Additional information is provided as a private update so the information
    # is not visible to the user.
    ticket_update = {"ticket": {"comment": {"public": False, "body": additional_info_string}}}
    try:
        zendesk_api.update_ticket(ticket_id, ticket_update)
    except zendesk.ZendeskError:
        log.exception("Error updating Zendesk ticket with ID %s.", ticket_id)
        # The update is not strictly necessary, so do not indicate
        # failure to the user unless it has been requested with
        # `require_update`.
        if require_update:
            return False
    return True
コード例 #21
0
ファイル: views.py プロジェクト: chaitanyakale/edx-platform
def submit_feedback(request):
    """
    Create a new user-requested ticket, currently implemented with Zendesk.

    If feedback submission is not enabled, any request will raise `Http404`.
    If any configuration parameter (`ZENDESK_URL`, `ZENDESK_USER`, or
    `ZENDESK_API_KEY`) is missing, any request will raise an `Exception`.
    The request must be a POST request specifying `subject` and `details`.
    If the user is not authenticated, the request must also specify `name` and
    `email`. If the user is authenticated, the `name` and `email` will be
    populated from the user's information. If any required parameter is
    missing, a 400 error will be returned indicating which field is missing and
    providing an error message. If Zendesk ticket creation fails, 500 error
    will be returned with no body; if ticket creation succeeds, an empty
    successful response (200) will be returned.
    """
    if not settings.FEATURES.get('ENABLE_FEEDBACK_SUBMISSION', False):
        raise Http404()
    if request.method != "POST":
        return HttpResponseNotAllowed(["POST"])
    if (
        not settings.ZENDESK_URL or
        not settings.ZENDESK_USER or
        not settings.ZENDESK_API_KEY
    ):
        raise Exception("Zendesk enabled but not configured")

    def build_error_response(status_code, field, err_msg):
        return HttpResponse(json.dumps({"field": field, "error": err_msg}), status=status_code)

    additional_info = {}

    required_fields = ["subject", "details"]
    if not request.user.is_authenticated():
        required_fields += ["name", "email"]
    required_field_errs = {
        "subject": "Please provide a subject.",
        "details": "Please provide details.",
        "name": "Please provide your name.",
        "email": "Please provide a valid e-mail.",
    }

    for field in required_fields:
        if field not in request.POST or not request.POST[field]:
            return build_error_response(400, field, required_field_errs[field])

    subject = request.POST["subject"]
    details = request.POST["details"]
    tags = dict(
        [(tag, request.POST[tag]) for tag in ["issue_type", "course_id"] if tag in request.POST]
    )

    if request.user.is_authenticated():
        realname = request.user.profile.name
        email = request.user.email
        additional_info["username"] = request.user.username
    else:
        realname = request.POST["name"]
        email = request.POST["email"]
        try:
            validate_email(email)
        except ValidationError:
            return build_error_response(400, "email", required_field_errs["email"])

    for header, pretty in [
        ("HTTP_REFERER", "Page"),
        ("HTTP_USER_AGENT", "Browser"),
        ("REMOTE_ADDR", "Client IP"),
        ("SERVER_NAME", "Host")
    ]:
        additional_info[pretty] = request.META.get(header)

    success = _record_feedback_in_zendesk(
        realname,
        email,
        subject,
        details,
        tags,
        additional_info,
        support_email=get_themed_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
    )
    _record_feedback_in_datadog(tags)

    return HttpResponse(status=(200 if success else 500))
コード例 #22
0
ファイル: views.py プロジェクト: workrocks/edx-platform
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 = []

    context = {
        'auth': {},
        'duplicate_provider':
        None,
        'fields': {
            'country': {
                'options': list(countries),
            },
            'gender': {
                'options': [(choice[0], _(choice[1]))
                            for choice in UserProfile.GENDER_CHOICES],  # pylint: disable=translation-of-non-string
            },
            'language': {
                'options': released_languages(),
            },
            'level_of_education': {
                'options':
                [(choice[0], _(choice[1]))
                 for choice in UserProfile.LEVEL_OF_EDUCATION_CHOICES],  # pylint: disable=translation-of-non-string
            },
            'password': {
                'url': reverse('password_reset'),
            },
            'year_of_birth': {
                'options': year_of_birth_options,
            },
            'preferred_language': {
                'options': all_languages(),
            },
            'time_zone': {
                'options': UserPreference.TIME_ZONE_CHOICES,
                'enabled':
                settings.FEATURES.get('ENABLE_TIME_ZONE_PREFERENCE'),
            }
        },
        'platform_name':
        get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
        '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.current().show_program_listing,
        'order_history':
        user_orders
    }

    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),
            } for state in auth_states
        ]

    return context
コード例 #23
0
ファイル: views.py プロジェクト: workrocks/edx-platform
def login_and_registration_form(request, initial_mode="login"):
    """Render the combined login/registration form, defaulting to login

    This relies on the JS to asynchronously load the actual form from
    the user_api.

    Keyword Args:
        initial_mode (string): Either "login" or "register".

    """
    # Determine the URL to redirect to following login/registration/third_party_auth
    redirect_to = get_next_url_for_login_page(request)

    # If we're already logged in, redirect to the dashboard
    if request.user.is_authenticated():
        return redirect(redirect_to)

    # Retrieve the form descriptions from the user API
    form_descriptions = _get_form_descriptions(request)

    # If this is a themed site, revert to the old login/registration pages.
    # We need to do this for now to support existing themes.
    # Themed sites can use the new logistration page by setting
    # 'ENABLE_COMBINED_LOGIN_REGISTRATION' in their theme/microsite
    # configuration settings.
    if is_request_in_themed_site() and not get_themed_value(
            'ENABLE_COMBINED_LOGIN_REGISTRATION', False):
        if initial_mode == "login":
            return old_login_view(request)
        elif initial_mode == "register":
            return old_register_view(request)

    # Allow external auth to intercept and handle the request
    ext_auth_response = _external_auth_intercept(request, initial_mode)
    if ext_auth_response is not None:
        return ext_auth_response

    # Our ?next= URL may itself contain a parameter 'tpa_hint=x' that we need to check.
    # If present, we display a login page focused on third-party auth with that provider.
    third_party_auth_hint = None
    if '?' in redirect_to:
        try:
            next_args = urlparse.parse_qs(urlparse.urlparse(redirect_to).query)
            provider_id = next_args['tpa_hint'][0]
            if third_party_auth.provider.Registry.get(provider_id=provider_id):
                third_party_auth_hint = provider_id
                initial_mode = "hinted_login"
        except (KeyError, ValueError, IndexError):
            pass

    # Otherwise, render the combined login/registration page
    context = {
        'data': {
            'login_redirect_url':
            redirect_to,
            'initial_mode':
            initial_mode,
            'third_party_auth':
            _third_party_auth_context(request, redirect_to),
            'third_party_auth_hint':
            third_party_auth_hint or '',
            'platform_name':
            get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),

            # Include form descriptions retrieved from the user API.
            # We could have the JS client make these requests directly,
            # but we include them in the initial page load to avoid
            # the additional round-trip to the server.
            'login_form_desc':
            json.loads(form_descriptions['login']),
            'registration_form_desc':
            json.loads(form_descriptions['registration']),
            'password_reset_form_desc':
            json.loads(form_descriptions['password_reset']),
        },
        'login_redirect_url':
        redirect_to,  # This gets added to the query string of the "Sign In" button in header
        'responsive': True,
        'allow_iframing': True,
        'disable_courseware_js': True,
        'disable_footer': True,
    }

    return render_to_response('student_account/login_and_register.html',
                              context)