Exemplo n.º 1
0
 def clean_password(self):
     """Enforce password policies (if applicable)"""
     password = self.cleaned_data["password"]
     if (
             self.enforce_username_neq_password and
             "username" in self.cleaned_data and
             self.cleaned_data["username"] == password
     ):
         raise ValidationError(_("Username and password fields cannot match"))
     if self.enforce_password_policy:
         try:
             validate_password_length(password)
             validate_password_complexity(password)
             validate_password_dictionary(password)
         except ValidationError, err:
             raise ValidationError(_("Password: "******"; ".join(err.messages))
 def test_validate_password_max_length(self):
     self.password = '******'
     with self.assertRaisesRegexp(ValidationError,"[u'Invalid Length (must be 6 characters or less)']"):
         validate_password_length(self.password)
Exemplo n.º 3
0
def create_account(
        request,
        post_override=None):  # pylint: disable-msg=too-many-statements
    """
    JSON call to create new edX account.
    Used by form in signup_modal.html, which is included into navigation.html
    """
    js = {'success': False}  # pylint: disable-msg=invalid-name

    post_vars = post_override if post_override else request.POST

    # allow for microsites to define their own set of required/optional/hidden fields
    extra_fields = microsite.get_value(
        'REGISTRATION_EXTRA_FIELDS',
        getattr(settings, 'REGISTRATION_EXTRA_FIELDS', {}))

    if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH') and pipeline.running(
            request):
        post_vars = dict(post_vars.items())
        post_vars.update({'password': pipeline.make_random_password()})

    # if doing signup for an external authorization, then get email, password, name from the eamap
    # don't use the ones from the form, since the user could have hacked those
    # unless originally we didn't get a valid email or name from the external auth
    DoExternalAuth = 'ExternalAuthMap' in request.session
    if DoExternalAuth:
        eamap = request.session['ExternalAuthMap']
        try:
            validate_email(eamap.external_email)
            email = eamap.external_email
        except ValidationError:
            email = post_vars.get('email', '')
        if eamap.external_name.strip() == '':
            name = post_vars.get('name', '')
        else:
            name = eamap.external_name
        password = eamap.internal_password
        post_vars = dict(post_vars.items())
        post_vars.update(dict(email=email, name=name, password=password))
        log.debug(u'In create_account with external_auth: user = %s, email=%s',
                  name, email)

    # Confirm we have a properly formed request
    for a in ['username', 'email', 'password', 'name']:
        if a not in post_vars:
            js['value'] = _("Error (401 {field}). E-mail us.").format(field=a)
            js['field'] = a
            return JsonResponse(js, status=400)

    if extra_fields.get('honor_code', 'required') == 'required' and \
            post_vars.get('honor_code', 'false') != u'true':
        js['value'] = _("To enroll, you must follow the honor code.").format(
            field=a)
        js['field'] = 'honor_code'
        return JsonResponse(js, status=400)

    # Can't have terms of service for certain SHIB users, like at Stanford
    tos_required = (not settings.FEATURES.get("AUTH_USE_SHIB")
                    or not settings.FEATURES.get("SHIB_DISABLE_TOS")
                    or not DoExternalAuth
                    or not eamap.external_domain.startswith(
                        external_auth.views.SHIBBOLETH_DOMAIN_PREFIX))

    if tos_required:
        if post_vars.get('terms_of_service', 'false') != u'true':
            js['value'] = _("You must accept the terms of service.").format(
                field=a)
            js['field'] = 'terms_of_service'
            return JsonResponse(js, status=400)

    # Confirm appropriate fields are there.
    # TODO: Check e-mail format is correct.
    # TODO: Confirm e-mail is not from a generic domain (mailinator, etc.)? Not sure if
    # this is a good idea
    # TODO: Check password is sane

    required_post_vars = ['username', 'email', 'name', 'password']
    required_post_vars += [
        fieldname for fieldname, val in extra_fields.items()
        if val == 'required'
    ]
    if tos_required:
        required_post_vars.append('terms_of_service')

    for field_name in required_post_vars:
        if field_name in ('gender', 'level_of_education'):
            min_length = 1
        else:
            min_length = 2

        if field_name not in post_vars or len(
                post_vars[field_name]) < min_length:
            error_str = {
                'username':
                _('Username must be minimum of two characters long'),
                'email':
                _('A properly formatted e-mail is required'),
                'name':
                _('Your legal name must be a minimum of two characters long'),
                'password':
                _('A valid password is required'),
                'terms_of_service':
                _('Accepting Terms of Service is required'),
                'honor_code':
                _('Agreeing to the Honor Code is required'),
                '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')
            }

            if field_name in error_str:
                js['value'] = error_str[field_name]
            else:
                js['value'] = _('You are missing one or more required fields')

            js['field'] = field_name
            return JsonResponse(js, status=400)

        max_length = 75
        if field_name == 'username':
            max_length = 30

        if field_name in ('email', 'username') and len(
                post_vars[field_name]) > max_length:
            error_str = {
                'username':
                _('Username cannot be more than {0} characters long').format(
                    max_length),
                'email':
                _('Email cannot be more than {0} characters long').format(
                    max_length)
            }
            js['value'] = error_str[field_name]
            js['field'] = field_name
            return JsonResponse(js, status=400)

    try:
        validate_email(post_vars['email'])
        email_domain = post_vars['email'].split('@')[-1]
        white_list_domain = settings.FEATURES.get('WHITE_LIST_DOMAIN', [])
        mth = [x for x in white_list_domain if re.search(x, email_domain)]
        if not mth:
            raise ValidationError(_(u'Enter a valid e-mail.'), code='invalid')
    except ValidationError:
        js['value'] = _("Valid e-mail is required.").format(field=a)
        js['field'] = 'email'
        return JsonResponse(js, status=400)

    try:
        validate_slug(post_vars['username'])
    except ValidationError:
        js['value'] = _(
            "Username should only consist of A-Z and 0-9, with no spaces."
        ).format(field=a)
        js['field'] = 'username'
        return JsonResponse(js, status=400)

    # enforce password complexity as an optional feature
    # but not if we're doing ext auth b/c those pws never get used and are auto-generated so might not pass validation
    if settings.FEATURES.get('ENFORCE_PASSWORD_POLICY',
                             False) and not DoExternalAuth:
        try:
            password = post_vars['password']

            validate_password_length(password)
            validate_password_complexity(password)
            validate_password_dictionary(password)
        except ValidationError, err:
            js['value'] = _('Password: '******'; '.join(err.messages)
            js['field'] = 'password'
            return JsonResponse(js, status=400)
 def test_validate_password_min_length(self):
     self.password = ''
     with self.assertRaisesRegexp(ValidationError,"[u'Invalid Length (must be 1 characters or more)']"):
         validate_password_length(self.password)