Remove Local Server Call on Logistration
LEARNER-966
This commit is contained in:
@@ -5,13 +5,12 @@ import logging
|
||||
import urlparse
|
||||
from datetime import datetime
|
||||
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.urlresolvers import resolve, reverse
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
@@ -20,7 +19,7 @@ from django_countries import countries
|
||||
|
||||
import third_party_auth
|
||||
from commerce.models import CommerceConfiguration
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from lms.djangoapps.commerce.utils import EcommerceService
|
||||
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
|
||||
from openedx.core.djangoapps.external_auth.login_and_register import login as external_auth_login
|
||||
@@ -30,6 +29,11 @@ from openedx.core.djangoapps.programs.models import ProgramsApiConfig
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site
|
||||
from openedx.core.djangoapps.user_api.accounts.api import request_password_change
|
||||
from openedx.core.djangoapps.user_api.api import (
|
||||
RegistrationFormFactory,
|
||||
get_login_session_form,
|
||||
get_password_reset_form
|
||||
)
|
||||
from openedx.core.djangoapps.user_api.errors import UserNotFound
|
||||
from openedx.core.lib.edx_api_utils import get_edx_api_data
|
||||
from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES
|
||||
@@ -385,43 +389,14 @@ def _get_form_descriptions(request):
|
||||
values are the JSON-serialized form descriptions.
|
||||
|
||||
"""
|
||||
|
||||
return {
|
||||
'login': _local_server_get('/user_api/v1/account/login_session/', request.session),
|
||||
'registration': _local_server_get('/user_api/v1/account/registration/', request.session),
|
||||
'password_reset': _local_server_get('/user_api/v1/account/password_reset/', request.session)
|
||||
'password_reset': get_password_reset_form().to_json(),
|
||||
'login': get_login_session_form().to_json(),
|
||||
'registration': RegistrationFormFactory().get_registration_form(request).to_json()
|
||||
}
|
||||
|
||||
|
||||
def _local_server_get(url, session):
|
||||
"""Simulate a server-server GET request for an in-process API.
|
||||
|
||||
Arguments:
|
||||
url (str): The URL of the request (excluding the protocol and domain)
|
||||
session (SessionStore): The session of the original request,
|
||||
used to get past the CSRF checks.
|
||||
|
||||
Returns:
|
||||
str: The content of the response
|
||||
|
||||
"""
|
||||
# Since the user API is currently run in-process,
|
||||
# we simulate the server-server API call by constructing
|
||||
# our own request object. We don't need to include much
|
||||
# information in the request except for the session
|
||||
# (to get past through CSRF validation)
|
||||
request = HttpRequest()
|
||||
request.method = "GET"
|
||||
request.session = session
|
||||
|
||||
# Call the Django view function, simulating
|
||||
# the server-server API call
|
||||
view, args, kwargs = resolve(url)
|
||||
response = view(request, *args, **kwargs)
|
||||
|
||||
# Return the content of the response
|
||||
return response.content
|
||||
|
||||
|
||||
def _external_auth_intercept(request, mode):
|
||||
"""Allow external auth to intercept a login/registration request.
|
||||
|
||||
|
||||
813
openedx/core/djangoapps/user_api/api.py
Normal file
813
openedx/core/djangoapps/user_api/api.py
Normal file
@@ -0,0 +1,813 @@
|
||||
import copy
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django_countries import countries
|
||||
|
||||
import accounts
|
||||
import third_party_auth
|
||||
from edxmako.shortcuts import marketing_link
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.user_api.helpers import FormDescription
|
||||
from openedx.features.enterprise_support.api import enterprise_customer_for_request
|
||||
from student.forms import get_registration_extension_form
|
||||
from student.models import UserProfile
|
||||
|
||||
|
||||
def get_password_reset_form():
|
||||
"""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"username@domain.com")
|
||||
|
||||
# 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=configuration_helpers.get_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": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
return form_desc
|
||||
|
||||
|
||||
def get_login_session_form():
|
||||
"""Return a description of the login 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("user_api_login_session"))
|
||||
|
||||
# Translators: This label appears above a field on the login 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 login form meant to hold the user's email address.
|
||||
email_placeholder = _(u"username@domain.com")
|
||||
|
||||
# Translators: These instructions appear on the login form, immediately
|
||||
# below a field meant to hold the user's email address.
|
||||
email_instructions = _("The email address you used to register with {platform_name}").format(
|
||||
platform_name=configuration_helpers.get_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": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
# Translators: This label appears above a field on the login form
|
||||
# meant to hold the user's password.
|
||||
password_label = _(u"Password")
|
||||
|
||||
form_desc.add_field(
|
||||
"password",
|
||||
label=password_label,
|
||||
field_type="password",
|
||||
restrictions={
|
||||
"max_length": accounts.PASSWORD_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"remember",
|
||||
field_type="checkbox",
|
||||
label=_("Remember me"),
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
|
||||
return form_desc
|
||||
|
||||
|
||||
class RegistrationFormFactory(object):
|
||||
"""HTTP end-points for creating a new user. """
|
||||
|
||||
DEFAULT_FIELDS = ["email", "name", "username", "password"]
|
||||
|
||||
EXTRA_FIELDS = [
|
||||
"confirm_email",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"city",
|
||||
"state",
|
||||
"country",
|
||||
"gender",
|
||||
"year_of_birth",
|
||||
"level_of_education",
|
||||
"company",
|
||||
"title",
|
||||
"mailing_address",
|
||||
"goals",
|
||||
"honor_code",
|
||||
"terms_of_service",
|
||||
]
|
||||
|
||||
def _is_field_visible(self, field_name):
|
||||
"""Check whether a field is visible based on Django settings. """
|
||||
return self._extra_fields_setting.get(field_name) in ["required", "optional"]
|
||||
|
||||
def _is_field_required(self, field_name):
|
||||
"""Check whether a field is required based on Django settings. """
|
||||
return self._extra_fields_setting.get(field_name) == "required"
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Backwards compatibility: Honor code is required by default, unless
|
||||
# explicitly set to "optional" in Django settings.
|
||||
self._extra_fields_setting = copy.deepcopy(configuration_helpers.get_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 = {}
|
||||
valid_fields = self.DEFAULT_FIELDS + self.EXTRA_FIELDS
|
||||
for field_name in valid_fields:
|
||||
handler = getattr(self, "_add_{field_name}_field".format(field_name=field_name))
|
||||
self.field_handlers[field_name] = handler
|
||||
|
||||
field_order = configuration_helpers.get_value('REGISTRATION_FIELD_ORDER')
|
||||
if not field_order:
|
||||
field_order = settings.REGISTRATION_FIELD_ORDER or valid_fields
|
||||
|
||||
# Check that all of the valid_fields are in the field order and vice versa, if not set to the default order
|
||||
if set(valid_fields) != set(field_order):
|
||||
field_order = valid_fields
|
||||
|
||||
self.field_order = field_order
|
||||
|
||||
def get_registration_form(self, request):
|
||||
"""Return a description of the registration form.
|
||||
This decouples clients from the API definition:
|
||||
if the API decides to modify the form, clients won't need
|
||||
to be updated.
|
||||
This is especially important for the registration form,
|
||||
since different edx-platform installations might
|
||||
collect different demographic information.
|
||||
See `user_api.helpers.FormDescription` for examples
|
||||
of the JSON-encoded form description.
|
||||
Arguments:
|
||||
request (HttpRequest)
|
||||
Returns:
|
||||
HttpResponse
|
||||
"""
|
||||
form_desc = FormDescription("post", reverse("user_api_registration"))
|
||||
self._apply_third_party_auth_overrides(request, form_desc)
|
||||
|
||||
# Custom form fields can be added via the form set in settings.REGISTRATION_EXTENSION_FORM
|
||||
custom_form = get_registration_extension_form()
|
||||
|
||||
if custom_form:
|
||||
# Default fields are always required
|
||||
for field_name in self.DEFAULT_FIELDS:
|
||||
self.field_handlers[field_name](form_desc, required=True)
|
||||
|
||||
for field_name, field in custom_form.fields.items():
|
||||
restrictions = {}
|
||||
if getattr(field, 'max_length', None):
|
||||
restrictions['max_length'] = field.max_length
|
||||
if getattr(field, 'min_length', None):
|
||||
restrictions['min_length'] = field.min_length
|
||||
field_options = getattr(
|
||||
getattr(custom_form, 'Meta', None), 'serialization_options', {}
|
||||
).get(field_name, {})
|
||||
field_type = field_options.get('field_type', FormDescription.FIELD_TYPE_MAP.get(field.__class__))
|
||||
if not field_type:
|
||||
raise ImproperlyConfigured(
|
||||
"Field type '{}' not recognized for registration extension field '{}'.".format(
|
||||
field_type,
|
||||
field_name
|
||||
)
|
||||
)
|
||||
form_desc.add_field(
|
||||
field_name, label=field.label,
|
||||
default=field_options.get('default'),
|
||||
field_type=field_options.get('field_type', FormDescription.FIELD_TYPE_MAP.get(field.__class__)),
|
||||
placeholder=field.initial, instructions=field.help_text, required=field.required,
|
||||
restrictions=restrictions,
|
||||
options=getattr(field, 'choices', None), error_messages=field.error_messages,
|
||||
include_default_option=field_options.get('include_default_option'),
|
||||
)
|
||||
|
||||
# Extra fields configured in Django settings
|
||||
# may be required, optional, or hidden
|
||||
for field_name in self.EXTRA_FIELDS:
|
||||
if self._is_field_visible(field_name):
|
||||
self.field_handlers[field_name](
|
||||
form_desc,
|
||||
required=self._is_field_required(field_name)
|
||||
)
|
||||
else:
|
||||
# Go through the fields in the fields order and add them if they are required or visible
|
||||
for field_name in self.field_order:
|
||||
if field_name in self.DEFAULT_FIELDS:
|
||||
self.field_handlers[field_name](form_desc, required=True)
|
||||
elif self._is_field_visible(field_name):
|
||||
self.field_handlers[field_name](
|
||||
form_desc,
|
||||
required=self._is_field_required(field_name)
|
||||
)
|
||||
|
||||
return form_desc
|
||||
|
||||
def _add_email_field(self, form_desc, required=True):
|
||||
"""Add an email 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 label appears above a field on the registration 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 registration form meant to hold the user's email address.
|
||||
email_placeholder = _(u"username@domain.com")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's email address.
|
||||
email_instructions = _(u"This is what you will use to login.")
|
||||
|
||||
form_desc.add_field(
|
||||
"email",
|
||||
field_type="email",
|
||||
label=email_label,
|
||||
placeholder=email_placeholder,
|
||||
instructions=email_instructions,
|
||||
restrictions={
|
||||
"min_length": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_confirm_email_field(self, form_desc, required=True):
|
||||
"""Add an email confirmation 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 label appears above a field on the registration form
|
||||
# meant to confirm the user's email address.
|
||||
email_label = _(u"Confirm Email")
|
||||
error_msg = accounts.REQUIRED_FIELD_CONFIRM_EMAIL_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"confirm_email",
|
||||
label=email_label,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_name_field(self, form_desc, required=True):
|
||||
"""Add a name 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 label appears above a field on the registration form
|
||||
# meant to hold the user's full name.
|
||||
name_label = _(u"Full Name")
|
||||
|
||||
# Translators: This example name is used as a placeholder in
|
||||
# a field on the registration form meant to hold the user's name.
|
||||
name_placeholder = _(u"Jane Q. Learner")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's full name.
|
||||
name_instructions = _(u"This name will be used on any certificates that you earn.")
|
||||
|
||||
form_desc.add_field(
|
||||
"name",
|
||||
label=name_label,
|
||||
placeholder=name_placeholder,
|
||||
instructions=name_instructions,
|
||||
restrictions={
|
||||
"max_length": accounts.NAME_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_username_field(self, form_desc, required=True):
|
||||
"""Add a username 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 label appears above a field on the registration form
|
||||
# meant to hold the user's public username.
|
||||
username_label = _(u"Public Username")
|
||||
|
||||
username_instructions = _(
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's public username.
|
||||
u"The name that will identify you in your courses. "
|
||||
u"It cannot be changed later."
|
||||
)
|
||||
|
||||
# Translators: This example username is used as a placeholder in
|
||||
# a field on the registration form meant to hold the user's username.
|
||||
username_placeholder = _(u"Jane_Q_Learner")
|
||||
|
||||
form_desc.add_field(
|
||||
"username",
|
||||
label=username_label,
|
||||
instructions=username_instructions,
|
||||
placeholder=username_placeholder,
|
||||
restrictions={
|
||||
"min_length": accounts.USERNAME_MIN_LENGTH,
|
||||
"max_length": accounts.USERNAME_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_password_field(self, form_desc, required=True):
|
||||
"""Add a password 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 label appears above a field on the registration form
|
||||
# meant to hold the user's password.
|
||||
password_label = _(u"Password")
|
||||
|
||||
form_desc.add_field(
|
||||
"password",
|
||||
label=password_label,
|
||||
field_type="password",
|
||||
restrictions={
|
||||
"min_length": accounts.PASSWORD_MIN_LENGTH,
|
||||
"max_length": accounts.PASSWORD_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_level_of_education_field(self, form_desc, required=True):
|
||||
"""Add a level of education 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the user's highest completed level of education.
|
||||
education_level_label = _(u"Highest level of education completed")
|
||||
error_msg = accounts.REQUIRED_FIELD_LEVEL_OF_EDUCATION_MSG
|
||||
|
||||
# The labels are marked for translation in UserProfile model definition.
|
||||
options = [(name, _(label)) for name, label in UserProfile.LEVEL_OF_EDUCATION_CHOICES] # pylint: disable=translation-of-non-string
|
||||
form_desc.add_field(
|
||||
"level_of_education",
|
||||
label=education_level_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_gender_field(self, form_desc, required=True):
|
||||
"""Add a gender 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the user's gender.
|
||||
gender_label = _(u"Gender")
|
||||
|
||||
# The labels are marked for translation in UserProfile model definition.
|
||||
options = [(name, _(label)) for name, label in UserProfile.GENDER_CHOICES] # pylint: disable=translation-of-non-string
|
||||
form_desc.add_field(
|
||||
"gender",
|
||||
label=gender_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_year_of_birth_field(self, form_desc, required=True):
|
||||
"""Add a year of birth 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the user's year of birth.
|
||||
yob_label = _(u"Year of birth")
|
||||
|
||||
options = [(unicode(year), unicode(year)) for year in UserProfile.VALID_YEARS]
|
||||
form_desc.add_field(
|
||||
"year_of_birth",
|
||||
label=yob_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_mailing_address_field(self, form_desc, required=True):
|
||||
"""Add a mailing address 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 label appears above a field on the registration form
|
||||
# meant to hold the user's mailing address.
|
||||
mailing_address_label = _(u"Mailing address")
|
||||
error_msg = accounts.REQUIRED_FIELD_MAILING_ADDRESS_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"mailing_address",
|
||||
label=mailing_address_label,
|
||||
field_type="textarea",
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME)
|
||||
)
|
||||
error_msg = accounts.REQUIRED_FIELD_GOALS_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"goals",
|
||||
label=goals_label,
|
||||
field_type="textarea",
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_city_field(self, form_desc, required=True):
|
||||
"""Add a city 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 label appears above a field on the registration form
|
||||
# which allows the user to input the city in which they live.
|
||||
city_label = _(u"City")
|
||||
error_msg = accounts.REQUIRED_FIELD_CITY_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"city",
|
||||
label=city_label,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_state_field(self, form_desc, required=False):
|
||||
"""Add a State/Province/Region field to a form description.
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the State/Province/Region in which they live.
|
||||
state_label = _(u"State/Province/Region")
|
||||
|
||||
form_desc.add_field(
|
||||
"state",
|
||||
label=state_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_company_field(self, form_desc, required=False):
|
||||
"""Add a Company field to a form description.
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Company
|
||||
company_label = _(u"Company")
|
||||
|
||||
form_desc.add_field(
|
||||
"company",
|
||||
label=company_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_title_field(self, form_desc, required=False):
|
||||
"""Add a Title field to a form description.
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Title
|
||||
title_label = _(u"Title")
|
||||
|
||||
form_desc.add_field(
|
||||
"title",
|
||||
label=title_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_first_name_field(self, form_desc, required=False):
|
||||
"""Add a First Name field to a form description.
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the First Name
|
||||
first_name_label = _(u"First Name")
|
||||
|
||||
form_desc.add_field(
|
||||
"first_name",
|
||||
label=first_name_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_last_name_field(self, form_desc, required=False):
|
||||
"""Add a Last Name field to a form description.
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the First Name
|
||||
last_name_label = _(u"Last Name")
|
||||
|
||||
form_desc.add_field(
|
||||
"last_name",
|
||||
label=last_name_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_country_field(self, form_desc, required=True):
|
||||
"""Add a country 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the country in which the user lives.
|
||||
country_label = _(u"Country")
|
||||
error_msg = accounts.REQUIRED_FIELD_COUNTRY_MSG
|
||||
|
||||
# If we set a country code, make sure it's uppercase for the sake of the form.
|
||||
default_country = form_desc._field_overrides.get('country', {}).get('defaultValue')
|
||||
if default_country:
|
||||
form_desc.override_field_properties(
|
||||
'country',
|
||||
default=default_country.upper()
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"country",
|
||||
label=country_label,
|
||||
field_type="select",
|
||||
options=list(countries),
|
||||
include_default_option=True,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
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_label = _(u"Honor Code")
|
||||
terms_link = marketing_link("HONOR")
|
||||
terms_text = _(u"Review the 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_label = _(u"Terms of Service and Honor Code")
|
||||
terms_link = marketing_link("HONOR")
|
||||
terms_text = _(u"Review the Terms of Service and Honor Code")
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"honor_code",
|
||||
label=label,
|
||||
field_type="checkbox",
|
||||
default=False,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
},
|
||||
supplementalLink=terms_link,
|
||||
supplementalText=terms_text
|
||||
)
|
||||
|
||||
def _add_terms_of_service_field(self, form_desc, required=True):
|
||||
"""Add a terms of service 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 is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
terms_label = _(u"Terms of Service")
|
||||
terms_link = marketing_link("TOS")
|
||||
terms_text = _(u"Review the Terms of Service")
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"terms_of_service",
|
||||
label=label,
|
||||
field_type="checkbox",
|
||||
default=False,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
},
|
||||
supplementalLink=terms_link,
|
||||
supplementalText=terms_text
|
||||
)
|
||||
|
||||
def _apply_third_party_auth_overrides(self, request, form_desc):
|
||||
"""Modify the registration form if the user has authenticated with a third-party provider.
|
||||
If a user has successfully authenticated with a third-party provider,
|
||||
but does not yet have an account with EdX, we want to fill in
|
||||
the registration form with any info that we get from the
|
||||
provider.
|
||||
This will also hide the password field, since we assign users a default
|
||||
(random) password on the assumption that they will be using
|
||||
third-party auth to log in.
|
||||
Arguments:
|
||||
request (HttpRequest): The request for the registration form, used
|
||||
to determine if the user has successfully authenticated
|
||||
with a third-party provider.
|
||||
form_desc (FormDescription): The registration form description
|
||||
"""
|
||||
if third_party_auth.is_enabled():
|
||||
running_pipeline = third_party_auth.pipeline.get(request)
|
||||
if running_pipeline:
|
||||
current_provider = third_party_auth.provider.Registry.get_from_pipeline(running_pipeline)
|
||||
|
||||
if current_provider:
|
||||
# Override username / email / full name
|
||||
field_overrides = current_provider.get_register_form_data(
|
||||
running_pipeline.get('kwargs')
|
||||
)
|
||||
|
||||
# When the TPA Provider is configured to skip the registration form and we are in an
|
||||
# enterprise context, we need to hide all fields except for terms of service and
|
||||
# ensure that the user explicitly checks that field.
|
||||
hide_registration_fields_except_tos = (current_provider.skip_registration_form and
|
||||
enterprise_customer_for_request(request))
|
||||
|
||||
for field_name in self.DEFAULT_FIELDS + self.EXTRA_FIELDS:
|
||||
if field_name in field_overrides:
|
||||
form_desc.override_field_properties(
|
||||
field_name, default=field_overrides[field_name]
|
||||
)
|
||||
|
||||
if (field_name not in ['terms_of_service', 'honor_code']
|
||||
and field_overrides[field_name]
|
||||
and hide_registration_fields_except_tos):
|
||||
|
||||
form_desc.override_field_properties(
|
||||
field_name,
|
||||
field_type="hidden",
|
||||
label="",
|
||||
instructions="",
|
||||
)
|
||||
|
||||
# Hide the password field
|
||||
form_desc.override_field_properties(
|
||||
"password",
|
||||
default="",
|
||||
field_type="hidden",
|
||||
required=False,
|
||||
label="",
|
||||
instructions="",
|
||||
restrictions={}
|
||||
)
|
||||
# used to identify that request is running third party social auth
|
||||
form_desc.add_field(
|
||||
"social_auth_provider",
|
||||
field_type="hidden",
|
||||
label="",
|
||||
default=current_provider.name if current_provider.name else "Third Party",
|
||||
required=False,
|
||||
)
|
||||
@@ -609,7 +609,7 @@ class LoginSessionViewTest(UserAPITestCase):
|
||||
"placeholder": "",
|
||||
"instructions": "",
|
||||
"restrictions": {
|
||||
"max_length": PASSWORD_MAX_LENGTH
|
||||
"max_length": PASSWORD_MAX_LENGTH,
|
||||
},
|
||||
"errorMessages": {},
|
||||
"supplementalText": "",
|
||||
@@ -1098,7 +1098,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
|
||||
provider = self.configure_google_provider(enabled=True)
|
||||
with simulate_running_pipeline(
|
||||
"openedx.core.djangoapps.user_api.views.third_party_auth.pipeline", "google-oauth2",
|
||||
"openedx.core.djangoapps.user_api.api.third_party_auth.pipeline", "google-oauth2",
|
||||
email="bob@example.com",
|
||||
fullname="Bob",
|
||||
username="Bob123",
|
||||
@@ -1203,7 +1203,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
}
|
||||
)
|
||||
|
||||
@mock.patch('openedx.core.djangoapps.user_api.views._')
|
||||
@mock.patch('openedx.core.djangoapps.user_api.api._')
|
||||
def test_register_form_level_of_education_translations(self, fake_gettext):
|
||||
fake_gettext.side_effect = lambda text: text + ' TRANSLATED'
|
||||
|
||||
@@ -1249,7 +1249,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
}
|
||||
)
|
||||
|
||||
@mock.patch('openedx.core.djangoapps.user_api.views._')
|
||||
@mock.patch('openedx.core.djangoapps.user_api.api._')
|
||||
def test_register_form_gender_translations(self, fake_gettext):
|
||||
fake_gettext.side_effect = lambda text: text + ' TRANSLATED'
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
"""HTTP end-points for the User API. """
|
||||
import copy
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import NON_FIELD_ERRORS, ImproperlyConfigured, PermissionDenied, ValidationError
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import NON_FIELD_ERRORS, PermissionDenied, ValidationError
|
||||
from django.http import HttpResponse, HttpResponseForbidden
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.csrf import csrf_exempt, csrf_protect, ensure_csrf_cookie
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
from django_countries import countries
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx import locator
|
||||
@@ -19,25 +15,24 @@ from rest_framework import authentication, generics, status, viewsets
|
||||
from rest_framework.exceptions import ParseError
|
||||
from rest_framework.views import APIView
|
||||
|
||||
import third_party_auth
|
||||
import accounts
|
||||
from django_comment_common.models import Role
|
||||
from edxmako.shortcuts import marketing_link
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.user_api.accounts.api import check_account_exists
|
||||
from openedx.core.djangoapps.user_api.api import (
|
||||
RegistrationFormFactory,
|
||||
get_login_session_form,
|
||||
get_password_reset_form
|
||||
)
|
||||
from openedx.core.djangoapps.user_api.helpers import require_post_params, shim_student_view
|
||||
from openedx.core.djangoapps.user_api.models import UserPreference
|
||||
from openedx.core.djangoapps.user_api.preferences.api import get_country_time_zones, update_email_opt_in
|
||||
from openedx.core.djangoapps.user_api.serializers import CountryTimeZoneSerializer, UserPreferenceSerializer, UserSerializer
|
||||
from openedx.core.lib.api.authentication import SessionAuthenticationAllowInactiveUser
|
||||
from openedx.core.lib.api.permissions import ApiKeyHeaderPermission
|
||||
from openedx.features.enterprise_support.api import enterprise_customer_for_request
|
||||
from student.cookies import set_logged_in_cookies
|
||||
from student.forms import get_registration_extension_form
|
||||
from student.views import create_account_with_params, AccountValidationError
|
||||
from student.views import AccountValidationError, create_account_with_params
|
||||
from util.json_request import JsonResponse
|
||||
|
||||
import accounts
|
||||
from .helpers import FormDescription, require_post_params, shim_student_view
|
||||
from .models import UserPreference, UserProfile
|
||||
from .preferences.api import get_country_time_zones, update_email_opt_in
|
||||
from .serializers import CountryTimeZoneSerializer, UserPreferenceSerializer, UserSerializer
|
||||
|
||||
|
||||
class LoginSessionView(APIView):
|
||||
"""HTTP end-points for logging in users. """
|
||||
@@ -48,69 +43,7 @@ class LoginSessionView(APIView):
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
def get(self, request):
|
||||
"""Return a description of the login 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("user_api_login_session"))
|
||||
|
||||
# Translators: This label appears above a field on the login 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 login form meant to hold the user's email address.
|
||||
email_placeholder = _(u"username@domain.com")
|
||||
|
||||
# Translators: These instructions appear on the login form, immediately
|
||||
# below a field meant to hold the user's email address.
|
||||
email_instructions = _("The email address you used to register with {platform_name}").format(
|
||||
platform_name=configuration_helpers.get_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": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
# Translators: This label appears above a field on the login form
|
||||
# meant to hold the user's password.
|
||||
password_label = _(u"Password")
|
||||
|
||||
form_desc.add_field(
|
||||
"password",
|
||||
label=password_label,
|
||||
field_type="password",
|
||||
restrictions={
|
||||
"max_length": accounts.PASSWORD_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"remember",
|
||||
field_type="checkbox",
|
||||
label=_("Remember me"),
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
|
||||
return HttpResponse(form_desc.to_json(), content_type="application/json")
|
||||
return HttpResponse(get_login_session_form().to_json(), content_type="application/json")
|
||||
|
||||
@method_decorator(require_post_params(["email", "password"]))
|
||||
@method_decorator(csrf_protect)
|
||||
@@ -157,151 +90,14 @@ class LoginSessionView(APIView):
|
||||
class RegistrationView(APIView):
|
||||
"""HTTP end-points for creating a new user. """
|
||||
|
||||
DEFAULT_FIELDS = ["email", "name", "username", "password"]
|
||||
|
||||
EXTRA_FIELDS = [
|
||||
"confirm_email",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"city",
|
||||
"state",
|
||||
"country",
|
||||
"gender",
|
||||
"year_of_birth",
|
||||
"level_of_education",
|
||||
"company",
|
||||
"title",
|
||||
"mailing_address",
|
||||
"goals",
|
||||
"honor_code",
|
||||
"terms_of_service",
|
||||
]
|
||||
|
||||
# This end-point is available to anonymous users,
|
||||
# so do not require authentication.
|
||||
authentication_classes = []
|
||||
|
||||
def _is_field_visible(self, field_name):
|
||||
"""Check whether a field is visible based on Django settings. """
|
||||
return self._extra_fields_setting.get(field_name) in ["required", "optional"]
|
||||
|
||||
def _is_field_required(self, field_name):
|
||||
"""Check whether a field is required based on Django settings. """
|
||||
return self._extra_fields_setting.get(field_name) == "required"
|
||||
|
||||
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(configuration_helpers.get_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 = {}
|
||||
valid_fields = self.DEFAULT_FIELDS + self.EXTRA_FIELDS
|
||||
for field_name in valid_fields:
|
||||
handler = getattr(self, "_add_{field_name}_field".format(field_name=field_name))
|
||||
self.field_handlers[field_name] = handler
|
||||
|
||||
field_order = configuration_helpers.get_value('REGISTRATION_FIELD_ORDER')
|
||||
if not field_order:
|
||||
field_order = settings.REGISTRATION_FIELD_ORDER or valid_fields
|
||||
|
||||
# Check that all of the valid_fields are in the field order and vice versa, if not set to the default order
|
||||
if set(valid_fields) != set(field_order):
|
||||
field_order = valid_fields
|
||||
|
||||
self.field_order = field_order
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
def get(self, request):
|
||||
"""Return a description of the registration form.
|
||||
|
||||
This decouples clients from the API definition:
|
||||
if the API decides to modify the form, clients won't need
|
||||
to be updated.
|
||||
|
||||
This is especially important for the registration form,
|
||||
since different edx-platform installations might
|
||||
collect different demographic information.
|
||||
|
||||
See `user_api.helpers.FormDescription` for examples
|
||||
of the JSON-encoded form description.
|
||||
|
||||
Arguments:
|
||||
request (HttpRequest)
|
||||
|
||||
Returns:
|
||||
HttpResponse
|
||||
|
||||
"""
|
||||
form_desc = FormDescription("post", reverse("user_api_registration"))
|
||||
self._apply_third_party_auth_overrides(request, form_desc)
|
||||
|
||||
# Custom form fields can be added via the form set in settings.REGISTRATION_EXTENSION_FORM
|
||||
custom_form = get_registration_extension_form()
|
||||
|
||||
if custom_form:
|
||||
# Default fields are always required
|
||||
for field_name in self.DEFAULT_FIELDS:
|
||||
self.field_handlers[field_name](form_desc, required=True)
|
||||
|
||||
for field_name, field in custom_form.fields.items():
|
||||
restrictions = {}
|
||||
if getattr(field, 'max_length', None):
|
||||
restrictions['max_length'] = field.max_length
|
||||
if getattr(field, 'min_length', None):
|
||||
restrictions['min_length'] = field.min_length
|
||||
field_options = getattr(
|
||||
getattr(custom_form, 'Meta', None), 'serialization_options', {}
|
||||
).get(field_name, {})
|
||||
field_type = field_options.get('field_type', FormDescription.FIELD_TYPE_MAP.get(field.__class__))
|
||||
if not field_type:
|
||||
raise ImproperlyConfigured(
|
||||
"Field type '{}' not recognized for registration extension field '{}'.".format(
|
||||
field_type,
|
||||
field_name
|
||||
)
|
||||
)
|
||||
form_desc.add_field(
|
||||
field_name, label=field.label,
|
||||
default=field_options.get('default'),
|
||||
field_type=field_options.get('field_type', FormDescription.FIELD_TYPE_MAP.get(field.__class__)),
|
||||
placeholder=field.initial, instructions=field.help_text, required=field.required,
|
||||
restrictions=restrictions,
|
||||
options=getattr(field, 'choices', None), error_messages=field.error_messages,
|
||||
include_default_option=field_options.get('include_default_option'),
|
||||
)
|
||||
|
||||
# Extra fields configured in Django settings
|
||||
# may be required, optional, or hidden
|
||||
for field_name in self.EXTRA_FIELDS:
|
||||
if self._is_field_visible(field_name):
|
||||
self.field_handlers[field_name](
|
||||
form_desc,
|
||||
required=self._is_field_required(field_name)
|
||||
)
|
||||
else:
|
||||
# Go through the fields in the fields order and add them if they are required or visible
|
||||
for field_name in self.field_order:
|
||||
if field_name in self.DEFAULT_FIELDS:
|
||||
self.field_handlers[field_name](form_desc, required=True)
|
||||
elif self._is_field_visible(field_name):
|
||||
self.field_handlers[field_name](
|
||||
form_desc,
|
||||
required=self._is_field_required(field_name)
|
||||
)
|
||||
|
||||
return HttpResponse(form_desc.to_json(), content_type="application/json")
|
||||
return HttpResponse(RegistrationFormFactory().get_registration_form(request).to_json(),
|
||||
content_type="application/json")
|
||||
|
||||
@method_decorator(csrf_exempt)
|
||||
def post(self, request):
|
||||
@@ -377,616 +173,6 @@ class RegistrationView(APIView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super(RegistrationView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def _add_email_field(self, form_desc, required=True):
|
||||
"""Add an email 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 label appears above a field on the registration 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 registration form meant to hold the user's email address.
|
||||
email_placeholder = _(u"username@domain.com")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's email address.
|
||||
email_instructions = _(u"This is what you will use to login.")
|
||||
|
||||
form_desc.add_field(
|
||||
"email",
|
||||
field_type="email",
|
||||
label=email_label,
|
||||
placeholder=email_placeholder,
|
||||
instructions=email_instructions,
|
||||
restrictions={
|
||||
"min_length": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_confirm_email_field(self, form_desc, required=True):
|
||||
"""Add an email confirmation 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 label appears above a field on the registration form
|
||||
# meant to confirm the user's email address.
|
||||
email_label = _(u"Confirm Email")
|
||||
error_msg = accounts.REQUIRED_FIELD_CONFIRM_EMAIL_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"confirm_email",
|
||||
label=email_label,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_name_field(self, form_desc, required=True):
|
||||
"""Add a name 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 label appears above a field on the registration form
|
||||
# meant to hold the user's full name.
|
||||
name_label = _(u"Full Name")
|
||||
|
||||
# Translators: This example name is used as a placeholder in
|
||||
# a field on the registration form meant to hold the user's name.
|
||||
name_placeholder = _(u"Jane Q. Learner")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's full name.
|
||||
name_instructions = _(u"This name will be used on any certificates that you earn.")
|
||||
|
||||
form_desc.add_field(
|
||||
"name",
|
||||
label=name_label,
|
||||
placeholder=name_placeholder,
|
||||
instructions=name_instructions,
|
||||
restrictions={
|
||||
"max_length": accounts.NAME_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_username_field(self, form_desc, required=True):
|
||||
"""Add a username 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 label appears above a field on the registration form
|
||||
# meant to hold the user's public username.
|
||||
username_label = _(u"Public Username")
|
||||
|
||||
username_instructions = _(
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's public username.
|
||||
u"The name that will identify you in your courses. "
|
||||
u"It cannot be changed later."
|
||||
)
|
||||
|
||||
# Translators: This example username is used as a placeholder in
|
||||
# a field on the registration form meant to hold the user's username.
|
||||
username_placeholder = _(u"Jane_Q_Learner")
|
||||
|
||||
form_desc.add_field(
|
||||
"username",
|
||||
label=username_label,
|
||||
instructions=username_instructions,
|
||||
placeholder=username_placeholder,
|
||||
restrictions={
|
||||
"min_length": accounts.USERNAME_MIN_LENGTH,
|
||||
"max_length": accounts.USERNAME_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_password_field(self, form_desc, required=True):
|
||||
"""Add a password 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 label appears above a field on the registration form
|
||||
# meant to hold the user's password.
|
||||
password_label = _(u"Password")
|
||||
|
||||
form_desc.add_field(
|
||||
"password",
|
||||
label=password_label,
|
||||
field_type="password",
|
||||
restrictions={
|
||||
"min_length": accounts.PASSWORD_MIN_LENGTH,
|
||||
"max_length": accounts.PASSWORD_MAX_LENGTH,
|
||||
},
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_level_of_education_field(self, form_desc, required=True):
|
||||
"""Add a level of education 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the user's highest completed level of education.
|
||||
education_level_label = _(u"Highest level of education completed")
|
||||
error_msg = accounts.REQUIRED_FIELD_LEVEL_OF_EDUCATION_MSG
|
||||
|
||||
# The labels are marked for translation in UserProfile model definition.
|
||||
options = [(name, _(label)) for name, label in UserProfile.LEVEL_OF_EDUCATION_CHOICES] # pylint: disable=translation-of-non-string
|
||||
form_desc.add_field(
|
||||
"level_of_education",
|
||||
label=education_level_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_gender_field(self, form_desc, required=True):
|
||||
"""Add a gender 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the user's gender.
|
||||
gender_label = _(u"Gender")
|
||||
|
||||
# The labels are marked for translation in UserProfile model definition.
|
||||
options = [(name, _(label)) for name, label in UserProfile.GENDER_CHOICES] # pylint: disable=translation-of-non-string
|
||||
form_desc.add_field(
|
||||
"gender",
|
||||
label=gender_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_year_of_birth_field(self, form_desc, required=True):
|
||||
"""Add a year of birth 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the user's year of birth.
|
||||
yob_label = _(u"Year of birth")
|
||||
|
||||
options = [(unicode(year), unicode(year)) for year in UserProfile.VALID_YEARS]
|
||||
form_desc.add_field(
|
||||
"year_of_birth",
|
||||
label=yob_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_mailing_address_field(self, form_desc, required=True):
|
||||
"""Add a mailing address 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 label appears above a field on the registration form
|
||||
# meant to hold the user's mailing address.
|
||||
mailing_address_label = _(u"Mailing address")
|
||||
error_msg = accounts.REQUIRED_FIELD_MAILING_ADDRESS_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"mailing_address",
|
||||
label=mailing_address_label,
|
||||
field_type="textarea",
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME)
|
||||
)
|
||||
error_msg = accounts.REQUIRED_FIELD_GOALS_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"goals",
|
||||
label=goals_label,
|
||||
field_type="textarea",
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_city_field(self, form_desc, required=True):
|
||||
"""Add a city 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 label appears above a field on the registration form
|
||||
# which allows the user to input the city in which they live.
|
||||
city_label = _(u"City")
|
||||
error_msg = accounts.REQUIRED_FIELD_CITY_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
"city",
|
||||
label=city_label,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_state_field(self, form_desc, required=False):
|
||||
"""Add a State/Province/Region field to a form description.
|
||||
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the State/Province/Region in which they live.
|
||||
state_label = _(u"State/Province/Region")
|
||||
|
||||
form_desc.add_field(
|
||||
"state",
|
||||
label=state_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_company_field(self, form_desc, required=False):
|
||||
"""Add a Company field to a form description.
|
||||
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Company
|
||||
company_label = _(u"Company")
|
||||
|
||||
form_desc.add_field(
|
||||
"company",
|
||||
label=company_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_title_field(self, form_desc, required=False):
|
||||
"""Add a Title field to a form description.
|
||||
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Title
|
||||
title_label = _(u"Title")
|
||||
|
||||
form_desc.add_field(
|
||||
"title",
|
||||
label=title_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_first_name_field(self, form_desc, required=False):
|
||||
"""Add a First Name field to a form description.
|
||||
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the First Name
|
||||
first_name_label = _(u"First Name")
|
||||
|
||||
form_desc.add_field(
|
||||
"first_name",
|
||||
label=first_name_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_last_name_field(self, form_desc, required=False):
|
||||
"""Add a Last Name field to a form description.
|
||||
|
||||
Arguments:
|
||||
form_desc: A form description
|
||||
|
||||
Keyword Arguments:
|
||||
required (bool): Whether this field is required; defaults to False
|
||||
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the First Name
|
||||
last_name_label = _(u"Last Name")
|
||||
|
||||
form_desc.add_field(
|
||||
"last_name",
|
||||
label=last_name_label,
|
||||
required=required
|
||||
)
|
||||
|
||||
def _add_country_field(self, form_desc, required=True):
|
||||
"""Add a country 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 label appears above a dropdown menu on the registration
|
||||
# form used to select the country in which the user lives.
|
||||
country_label = _(u"Country")
|
||||
error_msg = accounts.REQUIRED_FIELD_COUNTRY_MSG
|
||||
|
||||
# If we set a country code, make sure it's uppercase for the sake of the form.
|
||||
default_country = form_desc._field_overrides.get('country', {}).get('defaultValue')
|
||||
if default_country:
|
||||
form_desc.override_field_properties(
|
||||
'country',
|
||||
default=default_country.upper()
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"country",
|
||||
label=country_label,
|
||||
field_type="select",
|
||||
options=list(countries),
|
||||
include_default_option=True,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
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_label = _(u"Honor Code")
|
||||
terms_link = marketing_link("HONOR")
|
||||
terms_text = _(u"Review the 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_label = _(u"Terms of Service and Honor Code")
|
||||
terms_link = marketing_link("HONOR")
|
||||
terms_text = _(u"Review the Terms of Service and Honor Code")
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"honor_code",
|
||||
label=label,
|
||||
field_type="checkbox",
|
||||
default=False,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
},
|
||||
supplementalLink=terms_link,
|
||||
supplementalText=terms_text
|
||||
)
|
||||
|
||||
def _add_terms_of_service_field(self, form_desc, required=True):
|
||||
"""Add a terms of service 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 is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
terms_label = _(u"Terms of Service")
|
||||
terms_link = marketing_link("TOS")
|
||||
terms_text = _(u"Review the Terms of Service")
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
# 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=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
form_desc.add_field(
|
||||
"terms_of_service",
|
||||
label=label,
|
||||
field_type="checkbox",
|
||||
default=False,
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
},
|
||||
supplementalLink=terms_link,
|
||||
supplementalText=terms_text
|
||||
)
|
||||
|
||||
def _apply_third_party_auth_overrides(self, request, form_desc):
|
||||
"""Modify the registration form if the user has authenticated with a third-party provider.
|
||||
|
||||
If a user has successfully authenticated with a third-party provider,
|
||||
but does not yet have an account with EdX, we want to fill in
|
||||
the registration form with any info that we get from the
|
||||
provider.
|
||||
|
||||
This will also hide the password field, since we assign users a default
|
||||
(random) password on the assumption that they will be using
|
||||
third-party auth to log in.
|
||||
|
||||
Arguments:
|
||||
request (HttpRequest): The request for the registration form, used
|
||||
to determine if the user has successfully authenticated
|
||||
with a third-party provider.
|
||||
|
||||
form_desc (FormDescription): The registration form description
|
||||
|
||||
"""
|
||||
if third_party_auth.is_enabled():
|
||||
running_pipeline = third_party_auth.pipeline.get(request)
|
||||
if running_pipeline:
|
||||
current_provider = third_party_auth.provider.Registry.get_from_pipeline(running_pipeline)
|
||||
|
||||
if current_provider:
|
||||
# Override username / email / full name
|
||||
field_overrides = current_provider.get_register_form_data(
|
||||
running_pipeline.get('kwargs')
|
||||
)
|
||||
|
||||
# When the TPA Provider is configured to skip the registration form and we are in an
|
||||
# enterprise context, we need to hide all fields except for terms of service and
|
||||
# ensure that the user explicitly checks that field.
|
||||
hide_registration_fields_except_tos = (current_provider.skip_registration_form and
|
||||
enterprise_customer_for_request(request))
|
||||
|
||||
for field_name in self.DEFAULT_FIELDS + self.EXTRA_FIELDS:
|
||||
if field_name in field_overrides:
|
||||
form_desc.override_field_properties(
|
||||
field_name, default=field_overrides[field_name]
|
||||
)
|
||||
|
||||
if (field_name not in ['terms_of_service', 'honor_code']
|
||||
and field_overrides[field_name]
|
||||
and hide_registration_fields_except_tos):
|
||||
|
||||
form_desc.override_field_properties(
|
||||
field_name,
|
||||
field_type="hidden",
|
||||
label="",
|
||||
instructions="",
|
||||
)
|
||||
|
||||
# Hide the password field
|
||||
form_desc.override_field_properties(
|
||||
"password",
|
||||
default="",
|
||||
field_type="hidden",
|
||||
required=False,
|
||||
label="",
|
||||
instructions="",
|
||||
restrictions={}
|
||||
)
|
||||
# used to identify that request is running third party social auth
|
||||
form_desc.add_field(
|
||||
"social_auth_provider",
|
||||
field_type="hidden",
|
||||
label="",
|
||||
default=current_provider.name if current_provider.name else "Third Party",
|
||||
required=False,
|
||||
)
|
||||
|
||||
|
||||
class PasswordResetView(APIView):
|
||||
"""HTTP end-point for GETting a description of the password reset form. """
|
||||
@@ -997,48 +183,7 @@ class PasswordResetView(APIView):
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
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"username@domain.com")
|
||||
|
||||
# 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=configuration_helpers.get_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": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
return HttpResponse(form_desc.to_json(), content_type="application/json")
|
||||
return HttpResponse(get_password_reset_form().to_json(), content_type="application/json")
|
||||
|
||||
|
||||
class UserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
|
||||
Reference in New Issue
Block a user