diff --git a/ietf/ietfauth/forms.py b/ietf/ietfauth/forms.py index 0bda0b57d..8bf9cd63f 100644 --- a/ietf/ietfauth/forms.py +++ b/ietf/ietfauth/forms.py @@ -15,7 +15,7 @@ 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)") @@ -32,9 +32,12 @@ class RegistrationForm(forms.Form): class PasswordForm(forms.Form): - password = forms.CharField(widget=PasswordStrengthInput) - password_confirmation = forms.CharField(widget=PasswordConfirmationInput, - help_text="Enter the same password as above, for verification.") + 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", "") @@ -43,12 +46,6 @@ class PasswordForm(forms.Form): raise forms.ValidationError("The two password fields didn't match.") return password_confirmation -class PersonPasswordForm(forms.ModelForm, PasswordForm): - class Meta: - model = Person - fields = ['name', 'ascii'] - - def ascii_cleaner(supposedly_ascii): outside_printable_ascii_pattern = r'[^\x20-\x7F]' if re.search(outside_printable_ascii_pattern, supposedly_ascii): @@ -64,6 +61,26 @@ def prevent_system_name(name): 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', ] @@ -179,7 +196,9 @@ 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) + new_password_confirmation = forms.CharField(widget=PasswordConfirmationInput( + confirm_with='new_password', + attrs={'class':'password_confirmation'})) def __init__(self, user, data=None): self.user = user diff --git a/ietf/ietfauth/tests.py b/ietf/ietfauth/tests.py index 5687a5e38..f1e8184ff 100644 --- a/ietf/ietfauth/tests.py +++ b/ietf/ietfauth/tests.py @@ -127,7 +127,7 @@ class IetfAuthTests(TestCase): empty_outbox() r = self.client.post(url, { 'email': email }) self.assertEqual(r.status_code, 200) - self.assertIn("Account created", unicontent(r)) + self.assertIn("Account request received", unicontent(r)) self.assertEqual(len(outbox), 1) # go to confirm page @@ -141,7 +141,7 @@ class IetfAuthTests(TestCase): self.assertEqual(User.objects.filter(username=email).count(), 0) # confirm - r = self.client.post(confirm_url, { 'password': 'secret', 'password_confirmation': 'secret' }) + r = self.client.post(confirm_url, { 'name': 'User Name', 'ascii': 'User Name', 'password': 'secret', 'password_confirmation': 'secret' }) self.assertEqual(r.status_code, 200) self.assertEqual(User.objects.filter(username=email).count(), 1) self.assertEqual(Person.objects.filter(user__username=email).count(), 1) diff --git a/ietf/ietfauth/views.py b/ietf/ietfauth/views.py index 9a9e43164..c1424d0b7 100644 --- a/ietf/ietfauth/views.py +++ b/ietf/ietfauth/views.py @@ -54,7 +54,7 @@ import debug # pyflakes:ignore from ietf.group.models import Role, Group from ietf.ietfauth.forms import ( RegistrationForm, PasswordForm, ResetPasswordForm, TestEmailForm, WhitelistForm, ChangePasswordForm, get_person_form, RoleEmailForm, - NewEmailForm, ChangeUsernameForm ) + NewEmailForm, ChangeUsernameForm, PersonPasswordForm) from ietf.ietfauth.htpasswd import update_htpasswd_file from ietf.ietfauth.utils import role_required from ietf.mailinglists.models import Subscribed, Whitelisted @@ -138,7 +138,7 @@ def confirm_account(request, auth): success = False if request.method == 'POST': - form = PasswordForm(request.POST) + form = PersonPasswordForm(request.POST) if form.is_valid(): password = form.cleaned_data["password"] @@ -157,9 +157,11 @@ def confirm_account(request, auth): person = email_obj.person if not person: + name = form.cleaned_data["name"] + ascii = form.cleaned_data["ascii"] person = Person.objects.create(user=user, - name=email, - ascii=email) + name=name, + ascii=ascii) if not email_obj: email_obj = Email.objects.create(address=email, person=person) else: @@ -172,7 +174,7 @@ def confirm_account(request, auth): success = True else: - form = PasswordForm() + form = PersonPasswordForm() return render(request, 'registration/confirm_account.html', { 'form': form, diff --git a/ietf/person/tests.py b/ietf/person/tests.py index 1e8e91973..cf17b44e8 100644 --- a/ietf/person/tests.py +++ b/ietf/person/tests.py @@ -11,7 +11,7 @@ import debug # pyflakes:ignore from ietf.person.factories import EmailFactory,PersonFactory from ietf.person.models import Person from ietf.utils.test_data import make_test_data -from ietf.utils.test_utils import TestCase +from ietf.utils.test_utils import TestCase, unicontent from ietf.utils.mail import outbox, empty_outbox @@ -42,7 +42,7 @@ class PersonTests(TestCase): url = urlreverse("ietf.person.views.profile", kwargs={ "email_or_name": person.plain_name()}) r = self.client.get(url) self.assertEqual(r.status_code, 200) - self.assertIn(person.photo_name(), r.content.decode(r.charset)) + self.assertIn(person.photo_name(), unicontent(r)) q = PyQuery(r.content) self.assertIn("Photo of %s"%person, q("div.bio-text img.bio-photo").attr("alt")) diff --git a/ietf/static/ietf/js/password_strength.js b/ietf/static/ietf/js/password_strength.js index e441c1346..b7d12e2bc 100644 --- a/ietf/static/ietf/js/password_strength.js +++ b/ietf/static/ietf/js/password_strength.js @@ -24,8 +24,8 @@ $('.' + self.config.passwordClass).on('keyup', function() { var password_strength_bar = $(this).parent().find('.password_strength_bar'); - var password_strength_info = $(this).parent().find('.password_strength_info'); - var password_strength_offline_info = $(this).parent().parent().parent().find('.password_strength_offline_info'); + var password_strength_info = $(this).parent().find('.password_strength_info'); + var password_strength_offline_info = $(this).parent().parent().parent().find('.password_strength_offline_info'); if( $(this).val() ) { var result = zxcvbn( $(this).val() ); @@ -39,12 +39,12 @@ } password_strength_bar.width( ((result.score+1)/5)*100 + '%' ).attr('aria-valuenow', result.score + 1); - // henrik@levkowetz.com -- this is the only changed line: - password_strength_info.find('.password_strength_time').html(result.crack_times_display.online_no_throttling_10_per_second); - password_strength_info.removeClass('hidden'); + // henrik@levkowetz.com -- this is the only changed line: + password_strength_info.find('.password_strength_time').html(result.crack_times_display.online_no_throttling_10_per_second); + password_strength_info.removeClass('hidden'); - password_strength_offline_info.find('.password_strength_time').html(result.crack_times_display.offline_slow_hashing_1e4_per_second); - password_strength_offline_info.removeClass('hidden'); + password_strength_offline_info.find('.password_strength_time').html(result.crack_times_display.offline_slow_hashing_1e4_per_second); + password_strength_offline_info.removeClass('hidden'); } else { password_strength_bar.removeClass('progress-bar-success').addClass('progress-bar-warning'); password_strength_bar.width( '0%' ).attr('aria-valuenow', 0); diff --git a/ietf/templates/registration/confirm_account.html b/ietf/templates/registration/confirm_account.html index 8cb03fed5..7ace0d32c 100644 --- a/ietf/templates/registration/confirm_account.html +++ b/ietf/templates/registration/confirm_account.html @@ -31,7 +31,7 @@ {% bootstrap_form form %} {% buttons %} - + {% endbuttons %} {% endif %} diff --git a/ietf/templates/registration/create.html b/ietf/templates/registration/create.html index 7bb32242c..3ea025118 100644 --- a/ietf/templates/registration/create.html +++ b/ietf/templates/registration/create.html @@ -10,7 +10,7 @@ {% origin %} {% if to_email %} -
Your account creation request has been successfully received.
diff --git a/ietf/utils/test_utils.py b/ietf/utils/test_utils.py index 67ef1f338..d7a269cdd 100644 --- a/ietf/utils/test_utils.py +++ b/ietf/utils/test_utils.py @@ -265,13 +265,7 @@ def login_testing_unauthorized(test_case, username, url, password=None): def unicontent(r): "Return a HttpResponse object's content as unicode" - content_type = r._headers.get("content-type", "text/html; charset=utf-8") - if 'charset=' in content_type: - mediatype, charset = content_type.split(';') - encoding = charset.split('=')[1].strip() - else: - encoding = 'utf-8' - return r.content.decode(encoding) + return r.content.decode(r.charset) def reload_db_objects(*objects): """Rerequest the given arguments from the database so they're refreshed, to be used like