Merge ~maxiberta/canonical-identity-provider:skip-username-validation-if-unchanged into canonical-identity-provider:master

Proposed by Maximiliano Bertacchini
Status: Merged
Approved by: Maximiliano Bertacchini
Approved revision: 6e67aed5a2cec86ad92628a9c74e97d4abddf214
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~maxiberta/canonical-identity-provider:skip-username-validation-if-unchanged
Merge into: canonical-identity-provider:master
Diff against target: 61 lines (+29/-4)
2 files modified
src/identityprovider/forms.py (+14/-4)
src/identityprovider/tests/test_forms.py (+15/-0)
Reviewer Review Type Date Requested Status
Daniel Manrique (community) Approve
Review via email: mp+397386@code.launchpad.net

Commit message

Skip username validation in EditAccountForm if unchanged

Description of the change

The introduction of detailed username validation errors added form field validators on the username field. But, these validators run *before* the form's custom clean_username(), which contains the logic for skipping if unchanged.

https://docs.djangoproject.com/en/1.11/ref/forms/validation/#form-and-field-validation

To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

+1, I think this was my fault right? :(

review: Approve
6e67aed... by Maximiliano Bertacchini

Fix new username validation test

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/identityprovider/forms.py b/src/identityprovider/forms.py
index a23f2ba..61ab346 100644
--- a/src/identityprovider/forms.py
+++ b/src/identityprovider/forms.py
@@ -374,8 +374,7 @@ class EditAccountForm(ResetPasswordFormMixin, forms.ModelForm):
374 placeholder = _('Verify your email address first')374 placeholder = _('Verify your email address first')
375 self.fields['username'] = UsernameField(375 self.fields['username'] = UsernameField(
376 required=False, placeholder=placeholder,376 required=False, placeholder=placeholder,
377 disabled=disabled, extra_class="p-form-validation__input",377 disabled=disabled, extra_class="p-form-validation__input")
378 validators=get_username_validators())
379 if self.instance.person is not None or require_username:378 if self.instance.person is not None or require_username:
380 self.fields['username'].required = True379 self.fields['username'].required = True
381380
@@ -426,8 +425,19 @@ class EditAccountForm(ResetPasswordFormMixin, forms.ModelForm):
426 # are now considered "distasteful".425 # are now considered "distasteful".
427 if username == self.instance.person_name:426 if username == self.instance.person_name:
428 return username427 return username
429 if not valid_username(username):428
430 raise forms.ValidationError(INVALID_USERNAME_MSG % username)429 errors = []
430 for validator in USERNAME_VALIDATORS:
431 try:
432 validator.__call__(username)
433 except forms.ValidationError as ex:
434 errors.append(ex)
435 if errors:
436 if gargoyle.is_active('USERNAME_DETAILED_ERRORS'):
437 raise forms.ValidationError(errors)
438 else:
439 raise forms.ValidationError(INVALID_USERNAME_MSG % username)
440
431 if username and username != self.instance.person_name:441 if username and username != self.instance.person_name:
432 # The username is going to change, so ask LP to do a dry442 # The username is going to change, so ask LP to do a dry
433 # run to see if it will fail.443 # run to see if it will fail.
diff --git a/src/identityprovider/tests/test_forms.py b/src/identityprovider/tests/test_forms.py
index 9ffa2e3..6b2c4a6 100644
--- a/src/identityprovider/tests/test_forms.py
+++ b/src/identityprovider/tests/test_forms.py
@@ -740,6 +740,21 @@ class EditAccountFormTestCase(FormBaseTestCase):
740 ['Capital letters are not allowed.',740 ['Capital letters are not allowed.',
741 'Must contain only lowercase letters, hyphens and numbers.']})741 'Must contain only lowercase letters, hyphens and numbers.']})
742742
743 @switches(USERNAME_DETAILED_ERRORS=True)
744 def test_username_validation_skipped_if_unchanged(self):
745 self.factory.make_person(name='x', account=self.account)
746 data = {
747 'username': 'x',
748 'oldpassword': DEFAULT_USER_PASSWORD,
749 'password': 'testingpass',
750 'passwordconfirm': 'testingpass',
751 'displayname': self.account.displayname,
752 'preferred_email': self.account.preferredemail.id,
753 }
754 form = EditAccountForm(
755 data=data, instance=self.account, enable_username=True)
756 self.assertTrue(form.is_valid())
757
743758
744class EditAccountFormDevicePrefsEnabledTestCase(EditAccountFormTestCase):759class EditAccountFormDevicePrefsEnabledTestCase(EditAccountFormTestCase):
745760

Subscribers

People subscribed via source and target branches