Skip to content

Commit bb39a7d

Browse files
authored
feat: warn users about username vs email (#19012)
* feat: warn users about username vs email Users open supports cases when trying to log in using their email address, and end up opening up support cases. Provide them instant feedback instead. --------- Signed-off-by: Mike Fiedler <miketheman@gmail.com>
1 parent a220ded commit bb39a7d

File tree

3 files changed

+68
-21
lines changed

3 files changed

+68
-21
lines changed

tests/unit/accounts/test_forms.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,32 @@ def test_validate_username_with_null_bytes(self, pyramid_config):
6969
assert not form.validate()
7070
assert str(form.username.errors.pop()) == "Null bytes are not allowed."
7171

72+
@pytest.mark.parametrize(
73+
"email_username",
74+
[
75+
"user@example.com",
76+
"test.user@example.org",
77+
"admin@test.co.uk",
78+
" user@example.com ",
79+
],
80+
)
81+
def test_validate_username_with_email_address(self, pyramid_config, email_username):
82+
request = pretend.stub()
83+
user_service = pretend.stub()
84+
breach_service = pretend.stub()
85+
form = forms.LoginForm(
86+
formdata=MultiDict({"username": email_username}),
87+
request=request,
88+
user_service=user_service,
89+
breach_service=breach_service,
90+
)
91+
92+
assert not form.validate()
93+
assert str(form.username.errors.pop()) == (
94+
"Usernames are not the same as email addresses. "
95+
"Enter your username instead of your email address."
96+
)
97+
7298
def test_validate_username_with_no_user(self):
7399
request = pretend.stub()
74100
user_service = pretend.stub(

warehouse/accounts/forms.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ def __call__(self, form, field):
6767
raise wtforms.validators.StopValidation(self.message)
6868

6969

70+
def _check_for_email_in_username(form, field):
71+
"""
72+
Validator that checks if the username field contains an email address.
73+
This helps users who mistakenly enter their email instead of username.
74+
"""
75+
if field.data and "@" in field.data.strip():
76+
raise wtforms.validators.StopValidation(
77+
message=_(
78+
"Usernames are not the same as email addresses. "
79+
"Enter your username instead of your email address."
80+
)
81+
)
82+
83+
7084
def _check_for_existing_username(form: LoginForm, field):
7185
field.data = field.data.strip()
7286

@@ -81,6 +95,7 @@ class UsernameMixin:
8195
validators=[
8296
wtforms.validators.InputRequired(),
8397
PreventNullBytesValidator(),
98+
_check_for_email_in_username,
8499
_check_for_existing_username,
85100
],
86101
)

warehouse/locale/messages.pot

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ msgstr ""
1414
msgid "Locale updated"
1515
msgstr ""
1616

17-
#: warehouse/accounts/forms.py:42 warehouse/accounts/forms.py:280
17+
#: warehouse/accounts/forms.py:42 warehouse/accounts/forms.py:295
1818
msgid "The email address isn't valid. Try again."
1919
msgstr ""
2020

@@ -33,92 +33,98 @@ msgstr ""
3333
msgid "Null bytes are not allowed."
3434
msgstr ""
3535

36-
#: warehouse/accounts/forms.py:76
36+
#: warehouse/accounts/forms.py:78
37+
msgid ""
38+
"Usernames are not the same as email addresses. Enter your username "
39+
"instead of your email address."
40+
msgstr ""
41+
42+
#: warehouse/accounts/forms.py:90
3743
msgid "No user found with that username"
3844
msgstr ""
3945

40-
#: warehouse/accounts/forms.py:97
46+
#: warehouse/accounts/forms.py:112
4147
#, python-brace-format
4248
msgid "TOTP code must be ${totp_length} digits."
4349
msgstr ""
4450

45-
#: warehouse/accounts/forms.py:117
51+
#: warehouse/accounts/forms.py:132
4652
#, python-brace-format
4753
msgid "Recovery Codes must be ${recovery_code_length} characters."
4854
msgstr ""
4955

50-
#: warehouse/accounts/forms.py:131
56+
#: warehouse/accounts/forms.py:146
5157
msgid "Choose a username with 50 characters or less."
5258
msgstr ""
5359

54-
#: warehouse/accounts/forms.py:149
60+
#: warehouse/accounts/forms.py:164
5561
msgid ""
5662
"This username is already being used by another account. Choose a "
5763
"different username."
5864
msgstr ""
5965

60-
#: warehouse/accounts/forms.py:162 warehouse/accounts/forms.py:211
61-
#: warehouse/accounts/forms.py:224
66+
#: warehouse/accounts/forms.py:177 warehouse/accounts/forms.py:226
67+
#: warehouse/accounts/forms.py:239
6268
msgid "Password too long."
6369
msgstr ""
6470

65-
#: warehouse/accounts/forms.py:194
71+
#: warehouse/accounts/forms.py:209
6672
#, python-brace-format
6773
msgid ""
6874
"There have been too many unsuccessful login attempts. You have been "
6975
"locked out for ${time}. Please try again later."
7076
msgstr ""
7177

72-
#: warehouse/accounts/forms.py:227
78+
#: warehouse/accounts/forms.py:242
7379
msgid "Your passwords don't match. Try again."
7480
msgstr ""
7581

76-
#: warehouse/accounts/forms.py:261
82+
#: warehouse/accounts/forms.py:276
7783
msgid "The email address is too long. Try again."
7884
msgstr ""
7985

80-
#: warehouse/accounts/forms.py:333
86+
#: warehouse/accounts/forms.py:348
8187
msgid "You can't use an email address from this domain. Use a different email."
8288
msgstr ""
8389

84-
#: warehouse/accounts/forms.py:348
90+
#: warehouse/accounts/forms.py:363
8591
msgid ""
8692
"This email address is already being used by this account. Use a different"
8793
" email."
8894
msgstr ""
8995

90-
#: warehouse/accounts/forms.py:359
96+
#: warehouse/accounts/forms.py:374
9197
msgid ""
9298
"This email address is already being used by another account. Use a "
9399
"different email."
94100
msgstr ""
95101

96-
#: warehouse/accounts/forms.py:399 warehouse/manage/forms.py:131
102+
#: warehouse/accounts/forms.py:414 warehouse/manage/forms.py:131
97103
#: warehouse/manage/forms.py:786
98104
msgid "The name is too long. Choose a name with 100 characters or less."
99105
msgstr ""
100106

101-
#: warehouse/accounts/forms.py:405
107+
#: warehouse/accounts/forms.py:420
102108
msgid "URLs are not allowed in the name field."
103109
msgstr ""
104110

105-
#: warehouse/accounts/forms.py:494
111+
#: warehouse/accounts/forms.py:509
106112
msgid "Invalid TOTP code."
107113
msgstr ""
108114

109-
#: warehouse/accounts/forms.py:511
115+
#: warehouse/accounts/forms.py:526
110116
msgid "Invalid WebAuthn assertion: Bad payload"
111117
msgstr ""
112118

113-
#: warehouse/accounts/forms.py:580
119+
#: warehouse/accounts/forms.py:595
114120
msgid "Invalid recovery code."
115121
msgstr ""
116122

117-
#: warehouse/accounts/forms.py:589
123+
#: warehouse/accounts/forms.py:604
118124
msgid "Recovery code has been previously used."
119125
msgstr ""
120126

121-
#: warehouse/accounts/forms.py:619
127+
#: warehouse/accounts/forms.py:634
122128
msgid "The username isn't valid. Try again."
123129
msgstr ""
124130

0 commit comments

Comments
 (0)