237 lines
9.2 KiB
Python
237 lines
9.2 KiB
Python
import re
|
|
from unidecode import unidecode
|
|
|
|
from django import forms
|
|
from django.conf import settings
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import models
|
|
from django.contrib.auth.models import User
|
|
from django.utils.html import mark_safe
|
|
from django.urls import reverse as urlreverse
|
|
|
|
from django_password_strength.widgets import PasswordStrengthInput, PasswordConfirmationInput
|
|
|
|
import debug # pyflakes:ignore
|
|
|
|
from ietf.person.models import Person, Email
|
|
from ietf.mailinglists.models import Whitelisted
|
|
from ietf.utils.text import isascii
|
|
|
|
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.')
|
|
if User.objects.filter(username=email).exists():
|
|
raise forms.ValidationError('An account with the email address you provided already exists.')
|
|
return email
|
|
|
|
|
|
class PasswordForm(forms.Form):
|
|
password = forms.CharField(widget=PasswordStrengthInput(attrs={'class':'password_strength'}))
|
|
password_confirmation = forms.CharField(widget=PasswordConfirmationInput(
|
|
confirm_with='password',
|
|
attrs={'class':'password_confirmation'}),
|
|
help_text="Enter the same password as above, for verification.",)
|
|
|
|
|
|
def clean_password_confirmation(self):
|
|
password = self.cleaned_data.get("password", "")
|
|
password_confirmation = self.cleaned_data["password_confirmation"]
|
|
if password != password_confirmation:
|
|
raise forms.ValidationError("The two password fields didn't match.")
|
|
return password_confirmation
|
|
|
|
def ascii_cleaner(supposedly_ascii):
|
|
outside_printable_ascii_pattern = r'[^\x20-\x7F]'
|
|
if re.search(outside_printable_ascii_pattern, supposedly_ascii):
|
|
raise forms.ValidationError("Only unaccented Latin characters are allowed.")
|
|
return supposedly_ascii
|
|
|
|
def prevent_at_symbol(name):
|
|
if "@" in name:
|
|
raise forms.ValidationError("Please fill in name - this looks like an email address (@ is not allowed in names).")
|
|
|
|
def prevent_system_name(name):
|
|
name_without_spaces = name.replace(" ", "").replace("\t", "")
|
|
if "(system)" in name_without_spaces.lower():
|
|
raise forms.ValidationError("Please pick another name - this name is reserved.")
|
|
|
|
class PersonPasswordForm(forms.ModelForm, PasswordForm):
|
|
|
|
class Meta:
|
|
model = Person
|
|
fields = ['name', 'ascii']
|
|
|
|
def clean_name(self):
|
|
name = self.cleaned_data.get('name', '')
|
|
prevent_at_symbol(name)
|
|
prevent_system_name(name)
|
|
|
|
return name
|
|
|
|
def clean_ascii(self):
|
|
ascii = self.cleaned_data.get('ascii', '')
|
|
if not isascii(ascii):
|
|
raise forms.ValidationError("Ascii name contains non-ASCII characters.")
|
|
|
|
return ascii
|
|
|
|
def get_person_form(*args, **kwargs):
|
|
|
|
exclude_list = ['time', 'user', 'photo_thumb', 'photo', ]
|
|
|
|
person = kwargs['instance']
|
|
roles = person.role_set.all()
|
|
if not roles:
|
|
exclude_list += ['biography', 'photo', ]
|
|
|
|
class PersonForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Person
|
|
exclude = exclude_list
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(PersonForm, self).__init__(*args, **kwargs)
|
|
|
|
# blank ascii if it's the same as name
|
|
self.fields["ascii"].required = self.fields["ascii"].widget.is_required = False
|
|
self.fields["ascii"].help_text += " " + "Leave blank to use auto-reconstructed Latin version of name."
|
|
|
|
if self.initial.get("ascii") == self.initial.get("name"):
|
|
self.initial["ascii"] = ""
|
|
|
|
self.unidecoded_ascii = False
|
|
|
|
if self.data and not self.data.get("ascii", "").strip():
|
|
self.data = self.data.copy()
|
|
name = self.data["name"]
|
|
reconstructed_name = unidecode(name)
|
|
self.data["ascii"] = reconstructed_name
|
|
self.unidecoded_ascii = name != reconstructed_name
|
|
|
|
def clean_name(self):
|
|
name = self.cleaned_data.get("name") or u""
|
|
prevent_at_symbol(name)
|
|
prevent_system_name(name)
|
|
return name
|
|
|
|
def clean_ascii(self):
|
|
if self.unidecoded_ascii:
|
|
raise forms.ValidationError("Name contained non-ASCII characters, and was automatically reconstructed using only Latin characters. Check the result - if you are happy, just hit Submit again.")
|
|
|
|
name = self.cleaned_data.get("ascii") or u""
|
|
prevent_at_symbol(name)
|
|
prevent_system_name(name)
|
|
return ascii_cleaner(name)
|
|
|
|
def clean_ascii_short(self):
|
|
name = self.cleaned_data.get("ascii_short") or u""
|
|
prevent_at_symbol(name)
|
|
prevent_system_name(name)
|
|
return ascii_cleaner(name)
|
|
|
|
return PersonForm(*args, **kwargs)
|
|
|
|
|
|
class NewEmailForm(forms.Form):
|
|
new_email = forms.EmailField(label="New email address", required=False)
|
|
|
|
def clean_new_email(self):
|
|
email = self.cleaned_data.get("new_email", "")
|
|
if email:
|
|
existing = Email.objects.filter(address=email).first()
|
|
if existing:
|
|
raise forms.ValidationError("Email address '%s' is already assigned to account '%s' (%s)" % (existing, existing.person and existing.person.user, existing.person))
|
|
|
|
for pat in settings.EXLUDED_PERSONAL_EMAIL_REGEX_PATTERNS:
|
|
if re.search(pat, email):
|
|
raise ValidationError("This email address is not valid in a datatracker account")
|
|
|
|
return email
|
|
|
|
|
|
class RoleEmailForm(forms.Form):
|
|
email = forms.ModelChoiceField(label="Role email", queryset=Email.objects.all())
|
|
|
|
def __init__(self, role, *args, **kwargs):
|
|
super(RoleEmailForm, self).__init__(*args, **kwargs)
|
|
|
|
f = self.fields["email"]
|
|
f.label = u"%s in %s" % (role.name, role.group.acronym.upper())
|
|
f.help_text = u"Email to use for <i>%s</i> role in %s" % (role.name, role.group.name)
|
|
f.queryset = f.queryset.filter(models.Q(person=role.person_id) | models.Q(role=role)).distinct()
|
|
f.initial = role.email_id
|
|
f.choices = [(e.pk, e.address if e.active else u"({})".format(e.address)) for e in f.queryset]
|
|
|
|
|
|
class ResetPasswordForm(forms.Form):
|
|
username = forms.EmailField(label="Your email (lowercase)")
|
|
|
|
def clean_username(self):
|
|
import ietf.ietfauth.views
|
|
username = self.cleaned_data["username"]
|
|
if not User.objects.filter(username=username).exists():
|
|
raise forms.ValidationError(mark_safe("Didn't find a matching account. If you don't have an account yet, you can <a href=\"{}\">create one</a>.".format(urlreverse(ietf.ietfauth.views.create_account))))
|
|
return username
|
|
|
|
|
|
class TestEmailForm(forms.Form):
|
|
email = forms.EmailField(required=False)
|
|
|
|
class WhitelistForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Whitelisted
|
|
exclude = ['by', 'time' ]
|
|
|
|
|
|
from django import forms
|
|
|
|
|
|
class ChangePasswordForm(forms.Form):
|
|
current_password = forms.CharField(widget=forms.PasswordInput)
|
|
|
|
new_password = forms.CharField(widget=PasswordStrengthInput(attrs={'class':'password_strength'}))
|
|
new_password_confirmation = forms.CharField(widget=PasswordConfirmationInput(
|
|
confirm_with='new_password',
|
|
attrs={'class':'password_confirmation'}))
|
|
|
|
def __init__(self, user, data=None):
|
|
self.user = user
|
|
super(ChangePasswordForm, self).__init__(data)
|
|
|
|
def clean_current_password(self):
|
|
password = self.cleaned_data.get('current_password', None)
|
|
if not self.user.check_password(password):
|
|
raise ValidationError('Invalid password')
|
|
return password
|
|
|
|
def clean(self):
|
|
new_password = self.cleaned_data.get('new_password', None)
|
|
conf_password = self.cleaned_data.get('new_password_confirmation', None)
|
|
if not new_password == conf_password:
|
|
raise ValidationError("The password confirmation is different than the new password")
|
|
|
|
|
|
class ChangeUsernameForm(forms.Form):
|
|
username = forms.ChoiceField(choices=['-','--------'])
|
|
password = forms.CharField(widget=forms.PasswordInput, help_text="Confirm the change with your password")
|
|
|
|
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 ]
|
|
self.fields['username'] = forms.ChoiceField(choices=choices)
|
|
|
|
def clean_password(self):
|
|
password = self.cleaned_data['password']
|
|
if not self.user.check_password(password):
|
|
raise ValidationError('Invalid password')
|
|
return password
|