diff --git a/ietf/ietfauth/forms.py b/ietf/ietfauth/forms.py index 9b8ee22e0b..b36153318f 100644 --- a/ietf/ietfauth/forms.py +++ b/ietf/ietfauth/forms.py @@ -10,6 +10,7 @@ from django.core.exceptions import ValidationError from django.db import models from django.contrib.auth.models import User +from django.contrib.auth.validators import ASCIIUsernameValidator import debug # pyflakes:ignore @@ -20,16 +21,35 @@ from .widgets import PasswordStrengthInput, PasswordConfirmationInput +class UsernameEmailValidator(ASCIIUsernameValidator): + message=( + 'This value may contain only unaccented lowercase letters (a-z), ' + 'digits (0-9), and the special characters "@", ".", "+", "-", and "_".' + ) + + def __call__(self, value): + if value.lower() != value: + raise forms.ValidationError( + ( + "The supplied address contained uppercase letters. " + "Please use a lowercase email address." + ), + code="invalid_case", + params={"value": value}, + ) + super().__call__(value) + + +validate_username_email = UsernameEmailValidator() + + +class UsernameEmailField(forms.EmailField): + """Email that is suitable for a username""" + default_validators = forms.EmailField.default_validators + [validate_username_email] + + class RegistrationForm(forms.Form): - email = forms.EmailField(label="Your email (lowercase)") - - def clean_email(self): - email = self.cleaned_data.get('email', '') - if not email: - return email - if email.lower() != email: - raise forms.ValidationError('The supplied address contained uppercase letters. Please use a lowercase email address.') - return email + email = UsernameEmailField(label="Your email (lowercase)") class PasswordForm(forms.Form): @@ -230,10 +250,19 @@ def __init__(self, user, *args, **kwargs): assert isinstance(user, User) super(ChangeUsernameForm, self).__init__(*args, **kwargs) self.user = user - emails = user.person.email_set.filter(active=True) - choices = [ (email.address, email.address) for email in emails ] + choices = [(email.address, email.address) for email in self._allowed_emails(user)] self.fields['username'] = forms.ChoiceField(choices=choices) + @staticmethod + def _allowed_emails(user): + for email in user.person.email_set.filter(active=True): + try: + validate_username_email(email.address) + except ValidationError: + pass + else: + yield email + def clean_password(self): password = self.cleaned_data['password'] if not self.user.check_password(password): diff --git a/ietf/templates/registration/change_username.html b/ietf/templates/registration/change_username.html index 159a373031..b73af57ac6 100644 --- a/ietf/templates/registration/change_username.html +++ b/ietf/templates/registration/change_username.html @@ -13,6 +13,9 @@