Example #1
0
 def test_password_bad_max_length_validation_decision(self):
     password = '******' * (password_max_length() + 1)
     msg = u'Enter a password with at most {0} characters.'.format(password_max_length())
     self.assertValidationDecision(
         {'password': password},
         {"password": msg}
     )
Example #2
0
 def test_password_bad_max_length_validation_decision(self):
     password = '******' * (password_max_length() + 1)
     msg = u'Enter a password with at most {0} characters.'.format(password_max_length())
     self.assertValidationDecision(
         {'password': password},
         {"password": msg}
     )
Example #3
0
    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")

        restrictions = {
            "min_length": password_min_length(),
            "max_length": password_max_length(),
        }

        complexities = password_complexity()
        for key, value in complexities.iteritems():
            api_key = key.lower().replace(' ', '_')
            restrictions[api_key] = value

        form_desc.add_field(
            "password",
            label=password_label,
            field_type="password",
            instructions=password_instructions(),
            restrictions=restrictions,
            required=required
        )
Example #4
0
    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")

        restrictions = {
            "min_length": password_min_length(),
            "max_length": password_max_length(),
        }

        complexities = password_complexity()
        for key, value in complexities.iteritems():
            api_key = key.lower().replace(' ', '_')
            restrictions[api_key] = value

        form_desc.add_field("password",
                            label=password_label,
                            field_type="password",
                            instructions=password_instructions(),
                            restrictions=restrictions,
                            required=required)
Example #5
0
    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": password_min_length(),
                "max_length": password_max_length(),
            },
            required=required
        )
Example #6
0
def get_login_session_form(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"))
    _apply_third_party_auth_overrides(request, form_desc)

    # 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"*****@*****.**")

    # 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": password_max_length(),
        }
    )

    form_desc.add_field(
        "remember",
        field_type="checkbox",
        label=_("Remember me"),
        default=False,
        required=False,
    )

    return form_desc
Example #7
0
def get_login_session_form(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"))
    _apply_third_party_auth_overrides(request, form_desc)

    # 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"*****@*****.**")

    # 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": password_max_length(),
                        })

    form_desc.add_field(
        "remember",
        field_type="checkbox",
        label=_("Remember me"),
        default=False,
        required=False,
    )

    return form_desc
Example #8
0
class AccountCreationForm(forms.Form):
    """
    A form to for account creation data. It is currently only used for
    validation, not rendering.
    """

    _EMAIL_INVALID_MSG = _("A properly formatted e-mail is required")
    _PASSWORD_INVALID_MSG = _("A valid password is required")
    _NAME_TOO_SHORT_MSG = _(
        "Your legal name must be a minimum of two characters long")

    # TODO: Resolve repetition

    username = UsernameField()

    email = forms.EmailField(
        max_length=accounts_settings.EMAIL_MAX_LENGTH,
        min_length=accounts_settings.EMAIL_MIN_LENGTH,
        error_messages={
            "required":
            _EMAIL_INVALID_MSG,
            "invalid":
            _EMAIL_INVALID_MSG,
            "max_length":
            _("Email cannot be more than %(limit_value)s characters long"),
        })
    password = forms.CharField(min_length=password_min_length(),
                               max_length=password_max_length(),
                               error_messages={
                                   "required": _PASSWORD_INVALID_MSG,
                                   "min_length": _PASSWORD_INVALID_MSG,
                                   "max_length": _PASSWORD_INVALID_MSG,
                               })
    name = forms.CharField(min_length=accounts_settings.NAME_MIN_LENGTH,
                           error_messages={
                               "required": _NAME_TOO_SHORT_MSG,
                               "min_length": _NAME_TOO_SHORT_MSG,
                           },
                           validators=[validate_name])

    def __init__(self,
                 data=None,
                 extra_fields=None,
                 extended_profile_fields=None,
                 enforce_password_policy=False,
                 tos_required=True):
        super(AccountCreationForm, self).__init__(data)

        extra_fields = extra_fields or {}
        self.extended_profile_fields = extended_profile_fields or {}
        self.enforce_password_policy = enforce_password_policy
        if tos_required:
            self.fields["terms_of_service"] = TrueField(
                error_messages={
                    "required": _("You must accept the terms of service.")
                })

        # TODO: These messages don't say anything about minimum length
        error_message_dict = {
            "level_of_education": _("A level of education is required"),
            "gender": _("Your gender is required"),
            "year_of_birth": _("Your year of birth is required"),
            "mailing_address": _("Your mailing address is required"),
            "goals": _("A description of your goals is required"),
            "city": _("A city is required"),
            "country": _("A country is required")
        }
        for field_name, field_value in extra_fields.items():
            if field_name not in self.fields:
                if field_name == "honor_code":
                    if field_value == "required":
                        self.fields[field_name] = TrueField(
                            error_messages={
                                "required":
                                _("To enroll, you must follow the honor code.")
                            })
                else:
                    required = field_value == "required"
                    min_length = 1 if field_name in (
                        "gender", "level_of_education") else 2
                    error_message = error_message_dict.get(
                        field_name,
                        _("You are missing one or more required fields"))
                    self.fields[field_name] = forms.CharField(
                        required=required,
                        min_length=min_length,
                        error_messages={
                            "required": error_message,
                            "min_length": error_message,
                        })

        for field in self.extended_profile_fields:
            if field not in self.fields:
                self.fields[field] = forms.CharField(required=False)

    def clean_password(self):
        """Enforce password policies (if applicable)"""
        password = self.cleaned_data["password"]
        if self.enforce_password_policy:
            validate_password(password,
                              username=self.cleaned_data.get('username'))
        return password

    def clean_email(self):
        """ Enforce email restrictions (if applicable) """
        email = self.cleaned_data["email"]
        if settings.REGISTRATION_EMAIL_PATTERNS_ALLOWED is not None:
            # This Open edX instance has restrictions on what email addresses are allowed.
            allowed_patterns = settings.REGISTRATION_EMAIL_PATTERNS_ALLOWED
            # We append a '$' to the regexs to prevent the common mistake of using a
            # pattern like '.*@edx\\.org' which would match '*****@*****.**'
            if not any(
                    re.match(pattern + "$", email)
                    for pattern in allowed_patterns):
                # This email is not on the whitelist of allowed emails. Check if
                # they may have been manually invited by an instructor and if not,
                # reject the registration.
                if not CourseEnrollmentAllowed.objects.filter(
                        email=email).exists():
                    raise ValidationError(_("Unauthorized email address."))
        if email_exists_or_retired(email):
            raise ValidationError(
                _("It looks like {email} belongs to an existing account. Try again with a different email address."
                  ).format(email=email))
        return email

    def clean_year_of_birth(self):
        """
        Parse year_of_birth to an integer, but just use None instead of raising
        an error if it is malformed
        """
        try:
            year_str = self.cleaned_data["year_of_birth"]
            return int(year_str) if year_str is not None else None
        except ValueError:
            return None

    @property
    def cleaned_extended_profile(self):
        """
        Return a dictionary containing the extended_profile_fields and values
        """
        return {
            key: value
            for key, value in self.cleaned_data.items()
            if key in self.extended_profile_fields and value is not None
        }
Example #9
0
    None,
    u'',
    u'a',
    'no_domain',
    'no+domain',
    '@',
    '@domain.com',
    'test@no_extension',
    u'fŕáńḱ@example.com',

    # Long email -- subtract the length of the @domain
    # except for one character (so we exceed the max length limit)
    u'{user}@example.com'.format(user=(u'e' * (EMAIL_MAX_LENGTH - 11)))
]

INVALID_PASSWORDS = [None, u'', u'a', u'a' * (password_max_length() + 1)]

INVALID_COUNTRIES = [None, "", "--"]

VALID_NAMES = ['Validation Bot', u'Validation Bot']

VALID_USERNAMES_UNICODE = [
    u'Enchanté',
    u'username_with_@',
    u'username with spaces',
    u'eastern_arabic_numbers_١٢٣',
]

VALID_USERNAMES = [
    u'username', u'a' * USERNAME_MIN_LENGTH, u'a' * USERNAME_MAX_LENGTH,
    u'-' * USERNAME_MIN_LENGTH, u'-' * USERNAME_MAX_LENGTH, u'_username_',
Example #10
0
 def test_password_bad_max_length_validation_decision(self):
     password = '******' * (password_max_length() + 1)
     msg = u'Password: Invalid Length (must be {0} characters or fewer)'.format(
         password_max_length())
     self.assertValidationDecision({'password': password},
                                   {"password": msg})
Example #11
0
    '@domain.com',
    'test@no_extension',
    u'fŕáńḱ@example.com',

    # Long email -- subtract the length of the @domain
    # except for one character (so we exceed the max length limit)
    u'{user}@example.com'.format(
        user=(u'e' * (EMAIL_MAX_LENGTH - 11))
    )
]

INVALID_PASSWORDS = [
    None,
    u'',
    u'a',
    u'a' * (password_max_length() + 1)
]

INVALID_COUNTRIES = [
    None,
    "",
    "--"
]

VALID_NAMES = [
    'Validation Bot',
    u'Validation Bot'
]

VALID_USERNAMES_UNICODE = [
    u'Enchanté',