Skip to content

Commit 858d855

Browse files
committed
Changed the new account creation to require a proper name at the same time as the account password is set, before actually creating the account. Also tweaked the password strength and confirmation code.
- Legacy-Id: 12892
1 parent 8a8cf5b commit 858d855

8 files changed

Lines changed: 51 additions & 36 deletions

File tree

ietf/ietfauth/forms.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from ietf.person.models import Person, Email
1717
from ietf.mailinglists.models import Whitelisted
18-
18+
from ietf.utils.text import isascii
1919

2020
class RegistrationForm(forms.Form):
2121
email = forms.EmailField(label="Your email (lowercase)")
@@ -32,9 +32,12 @@ def clean_email(self):
3232

3333

3434
class PasswordForm(forms.Form):
35-
password = forms.CharField(widget=PasswordStrengthInput)
36-
password_confirmation = forms.CharField(widget=PasswordConfirmationInput,
37-
help_text="Enter the same password as above, for verification.")
35+
password = forms.CharField(widget=PasswordStrengthInput(attrs={'class':'password_strength'}))
36+
password_confirmation = forms.CharField(widget=PasswordConfirmationInput(
37+
confirm_with='password',
38+
attrs={'class':'password_confirmation'}),
39+
help_text="Enter the same password as above, for verification.",)
40+
3841

3942
def clean_password_confirmation(self):
4043
password = self.cleaned_data.get("password", "")
@@ -43,12 +46,6 @@ def clean_password_confirmation(self):
4346
raise forms.ValidationError("The two password fields didn't match.")
4447
return password_confirmation
4548

46-
class PersonPasswordForm(forms.ModelForm, PasswordForm):
47-
class Meta:
48-
model = Person
49-
fields = ['name', 'ascii']
50-
51-
5249
def ascii_cleaner(supposedly_ascii):
5350
outside_printable_ascii_pattern = r'[^\x20-\x7F]'
5451
if re.search(outside_printable_ascii_pattern, supposedly_ascii):
@@ -64,6 +61,26 @@ def prevent_system_name(name):
6461
if "(system)" in name_without_spaces.lower():
6562
raise forms.ValidationError("Please pick another name - this name is reserved.")
6663

64+
class PersonPasswordForm(forms.ModelForm, PasswordForm):
65+
66+
class Meta:
67+
model = Person
68+
fields = ['name', 'ascii']
69+
70+
def clean_name(self):
71+
name = self.cleaned_data.get('name', '')
72+
prevent_at_symbol(name)
73+
prevent_system_name(name)
74+
75+
return name
76+
77+
def clean_ascii(self):
78+
ascii = self.cleaned_data.get('ascii', '')
79+
if not isascii(ascii):
80+
raise forms.ValidationError("Ascii name contains non-ASCII characters.")
81+
82+
return ascii
83+
6784
def get_person_form(*args, **kwargs):
6885

6986
exclude_list = ['time', 'user', 'photo_thumb', 'photo', ]
@@ -179,7 +196,9 @@ class ChangePasswordForm(forms.Form):
179196
current_password = forms.CharField(widget=forms.PasswordInput)
180197

181198
new_password = forms.CharField(widget=PasswordStrengthInput(attrs={'class':'password_strength'}))
182-
new_password_confirmation = forms.CharField(widget=PasswordConfirmationInput)
199+
new_password_confirmation = forms.CharField(widget=PasswordConfirmationInput(
200+
confirm_with='new_password',
201+
attrs={'class':'password_confirmation'}))
183202

184203
def __init__(self, user, data=None):
185204
self.user = user

ietf/ietfauth/tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def register_and_verify(self, email):
127127
empty_outbox()
128128
r = self.client.post(url, { 'email': email })
129129
self.assertEqual(r.status_code, 200)
130-
self.assertIn("Account created", unicontent(r))
130+
self.assertIn("Account request received", unicontent(r))
131131
self.assertEqual(len(outbox), 1)
132132

133133
# go to confirm page
@@ -141,7 +141,7 @@ def register_and_verify(self, email):
141141
self.assertEqual(User.objects.filter(username=email).count(), 0)
142142

143143
# confirm
144-
r = self.client.post(confirm_url, { 'password': 'secret', 'password_confirmation': 'secret' })
144+
r = self.client.post(confirm_url, { 'name': 'User Name', 'ascii': 'User Name', 'password': 'secret', 'password_confirmation': 'secret' })
145145
self.assertEqual(r.status_code, 200)
146146
self.assertEqual(User.objects.filter(username=email).count(), 1)
147147
self.assertEqual(Person.objects.filter(user__username=email).count(), 1)

ietf/ietfauth/views.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
from ietf.group.models import Role, Group
5555
from ietf.ietfauth.forms import ( RegistrationForm, PasswordForm, ResetPasswordForm, TestEmailForm,
5656
WhitelistForm, ChangePasswordForm, get_person_form, RoleEmailForm,
57-
NewEmailForm, ChangeUsernameForm )
57+
NewEmailForm, ChangeUsernameForm, PersonPasswordForm)
5858
from ietf.ietfauth.htpasswd import update_htpasswd_file
5959
from ietf.ietfauth.utils import role_required
6060
from ietf.mailinglists.models import Subscribed, Whitelisted
@@ -138,7 +138,7 @@ def confirm_account(request, auth):
138138

139139
success = False
140140
if request.method == 'POST':
141-
form = PasswordForm(request.POST)
141+
form = PersonPasswordForm(request.POST)
142142
if form.is_valid():
143143
password = form.cleaned_data["password"]
144144

@@ -157,9 +157,11 @@ def confirm_account(request, auth):
157157
person = email_obj.person
158158

159159
if not person:
160+
name = form.cleaned_data["name"]
161+
ascii = form.cleaned_data["ascii"]
160162
person = Person.objects.create(user=user,
161-
name=email,
162-
ascii=email)
163+
name=name,
164+
ascii=ascii)
163165
if not email_obj:
164166
email_obj = Email.objects.create(address=email, person=person)
165167
else:
@@ -172,7 +174,7 @@ def confirm_account(request, auth):
172174

173175
success = True
174176
else:
175-
form = PasswordForm()
177+
form = PersonPasswordForm()
176178

177179
return render(request, 'registration/confirm_account.html', {
178180
'form': form,

ietf/person/tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from ietf.person.factories import EmailFactory,PersonFactory
1212
from ietf.person.models import Person
1313
from ietf.utils.test_data import make_test_data
14-
from ietf.utils.test_utils import TestCase
14+
from ietf.utils.test_utils import TestCase, unicontent
1515
from ietf.utils.mail import outbox, empty_outbox
1616

1717

@@ -42,7 +42,7 @@ def test_profile(self):
4242
url = urlreverse("ietf.person.views.profile", kwargs={ "email_or_name": person.plain_name()})
4343
r = self.client.get(url)
4444
self.assertEqual(r.status_code, 200)
45-
self.assertIn(person.photo_name(), r.content.decode(r.charset))
45+
self.assertIn(person.photo_name(), unicontent(r))
4646
q = PyQuery(r.content)
4747
self.assertIn("Photo of %s"%person, q("div.bio-text img.bio-photo").attr("alt"))
4848

ietf/static/ietf/js/password_strength.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424

2525
$('.' + self.config.passwordClass).on('keyup', function() {
2626
var password_strength_bar = $(this).parent().find('.password_strength_bar');
27-
var password_strength_info = $(this).parent().find('.password_strength_info');
28-
var password_strength_offline_info = $(this).parent().parent().parent().find('.password_strength_offline_info');
27+
var password_strength_info = $(this).parent().find('.password_strength_info');
28+
var password_strength_offline_info = $(this).parent().parent().parent().find('.password_strength_offline_info');
2929

3030
if( $(this).val() ) {
3131
var result = zxcvbn( $(this).val() );
@@ -39,12 +39,12 @@
3939
}
4040

4141
password_strength_bar.width( ((result.score+1)/5)*100 + '%' ).attr('aria-valuenow', result.score + 1);
42-
// henrik@levkowetz.com -- this is the only changed line:
43-
password_strength_info.find('.password_strength_time').html(result.crack_times_display.online_no_throttling_10_per_second);
44-
password_strength_info.removeClass('hidden');
42+
// henrik@levkowetz.com -- this is the only changed line:
43+
password_strength_info.find('.password_strength_time').html(result.crack_times_display.online_no_throttling_10_per_second);
44+
password_strength_info.removeClass('hidden');
4545

46-
password_strength_offline_info.find('.password_strength_time').html(result.crack_times_display.offline_slow_hashing_1e4_per_second);
47-
password_strength_offline_info.removeClass('hidden');
46+
password_strength_offline_info.find('.password_strength_time').html(result.crack_times_display.offline_slow_hashing_1e4_per_second);
47+
password_strength_offline_info.removeClass('hidden');
4848
} else {
4949
password_strength_bar.removeClass('progress-bar-success').addClass('progress-bar-warning');
5050
password_strength_bar.width( '0%' ).attr('aria-valuenow', 0);

ietf/templates/registration/confirm_account.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ <h1>Complete account creation</h1>
3131
{% bootstrap_form form %}
3232

3333
{% buttons %}
34-
<button type="submit" class="btn btn-primary">Set password</button>
34+
<button type="submit" class="btn btn-primary">Set name and password</button>
3535
{% endbuttons %}
3636
</form>
3737
{% endif %}

ietf/templates/registration/create.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
{% origin %}
1111

1212
{% if to_email %}
13-
<h1>Account created successfully</h1>
13+
<h1>Account request received.</h1>
1414

1515
<p>Your account creation request has been successfully received.</p>
1616

ietf/utils/test_utils.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,7 @@ def login_testing_unauthorized(test_case, username, url, password=None):
265265

266266
def unicontent(r):
267267
"Return a HttpResponse object's content as unicode"
268-
content_type = r._headers.get("content-type", "text/html; charset=utf-8")
269-
if 'charset=' in content_type:
270-
mediatype, charset = content_type.split(';')
271-
encoding = charset.split('=')[1].strip()
272-
else:
273-
encoding = 'utf-8'
274-
return r.content.decode(encoding)
268+
return r.content.decode(r.charset)
275269

276270
def reload_db_objects(*objects):
277271
"""Rerequest the given arguments from the database so they're refreshed, to be used like

0 commit comments

Comments
 (0)