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
This commit is contained in:
parent
8a8cf5b811
commit
858d855eff
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"))
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
{% bootstrap_form form %}
|
||||
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Set password</button>
|
||||
<button type="submit" class="btn btn-primary">Set name and password</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{% origin %}
|
||||
|
||||
{% if to_email %}
|
||||
<h1>Account created successfully</h1>
|
||||
<h1>Account request received.</h1>
|
||||
|
||||
<p>Your account creation request has been successfully received.</p>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue