[extensions-web/wip/ne0sight] auth: allow logging in with both login or email
- From: Yuri Konotopov <ykonotopov src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [extensions-web/wip/ne0sight] auth: allow logging in with both login or email
- Date: Sun, 24 Nov 2019 17:41:25 +0000 (UTC)
commit 62053a42e0a912ca31679114d0a83c735b8e3d7d
Author: Yuri Konotopov <ykonotopov gnome org>
Date: Sun Nov 24 21:05:06 2019 +0400
auth: allow logging in with both login or email
po/extensions-web.pot | 24 ++++++++++++++----------
sweettooth/auth/backends.py | 29 +++++++++++++++++++++++++++++
sweettooth/auth/forms.py | 11 +++++++++--
sweettooth/auth/tests.py | 42 +++++++++++++++++++++++++++++++++---------
sweettooth/settings.py | 2 ++
5 files changed, 87 insertions(+), 21 deletions(-)
---
diff --git a/po/extensions-web.pot b/po/extensions-web.pot
index 85450eb..62b4732 100644
--- a/po/extensions-web.pot
+++ b/po/extensions-web.pot
@@ -9,36 +9,40 @@ msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: ykonotopov gnome org\n"
-"POT-Creation-Date: 2019-01-22 14:52+0000\n"
+"POT-Creation-Date: 2019-11-24 17:14+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: sweettooth/auth/forms.py:39 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:26 extensions-web-domain-django:1
+msgid "Username or email"
+msgstr ""
+
+#: sweettooth/auth/forms.py:46 extensions-web-domain-django:1
msgid "Username"
msgstr ""
-#: sweettooth/auth/forms.py:40 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:47 extensions-web-domain-django:1
msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."
msgstr ""
-#: sweettooth/auth/forms.py:41 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:48 extensions-web-domain-django:1
msgid "This value may contain only letters, numbers and @/./+/-/_ characters."
msgstr ""
-#: sweettooth/auth/forms.py:43 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:50 extensions-web-domain-django:1
msgid "Email"
msgstr ""
-#: sweettooth/auth/forms.py:44 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:51 extensions-web-domain-django:1
msgid "Password"
msgstr ""
-#: sweettooth/auth/forms.py:45 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:52 extensions-web-domain-django:1
msgid "Password confirmation"
msgstr ""
-#: sweettooth/auth/forms.py:46 extensions-web-domain-django:1
+#: sweettooth/auth/forms.py:53 extensions-web-domain-django:1
msgid "Enter the same password as above, for verification."
msgstr ""
@@ -54,13 +58,13 @@ msgstr ""
msgid "Log in"
msgstr ""
-#: sweettooth/auth/templates/registration/login.html:37
+#: sweettooth/auth/templates/registration/login.html:36
#: sweettooth/auth/templates/registration/login_popup_form.html:17
#: extensions-web-domain-django:1
msgid "Don't have an account?"
msgstr ""
-#: sweettooth/auth/templates/registration/login.html:38
+#: sweettooth/auth/templates/registration/login.html:37
#: sweettooth/auth/templates/registration/login_popup_form.html:19
#: extensions-web-domain-django:1
msgid "Register"
diff --git a/sweettooth/auth/backends.py b/sweettooth/auth/backends.py
new file mode 100644
index 0000000..2486572
--- /dev/null
+++ b/sweettooth/auth/backends.py
@@ -0,0 +1,29 @@
+"""
+ GNOME Shell extensions repository
+ Copyright (C) 2019 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
+
+from django.contrib.auth.backends import ModelBackend, UserModel
+from django.contrib.auth.models import User
+
+class LoginEmailAuthentication(ModelBackend):
+ def authenticate(self, request, username=None, password=None, **kwargs):
+ user = super().authenticate(request, username=username, password=password, **kwargs)
+ if user is not None:
+ return user
+
+ if username is not None:
+ try:
+ user = UserModel.objects.get(email=username)
+ except UserModel.DoesNotExist:
+ # Run the default password hasher once to reduce the timing
+ # difference between an existing and a nonexistent user (#20760).
+ UserModel().set_password(password)
+ else:
+ if user.check_password(password) and self.user_can_authenticate(user):
+ return user
diff --git a/sweettooth/auth/forms.py b/sweettooth/auth/forms.py
index a240654..902c396 100644
--- a/sweettooth/auth/forms.py
+++ b/sweettooth/auth/forms.py
@@ -20,6 +20,12 @@ class AutoFocusForm(object):
self.fields[field].widget.attrs['autofocus'] = 'autofocus'
break
+class LoginOrEmailAuthenticationForm(object):
+ def __init__(self, *a, **kw):
+ super().__init__(*a, **kw)
+ self.fields['username'].label = _('Username or email')
+
+
class InlineForm(object):
def __init__(self, *a, **kw):
super().__init__(*a, **kw)
@@ -28,10 +34,11 @@ class InlineForm(object):
field.widget.attrs['class'] = 'form-control'
class InlineAuthenticationForm(PlainOutputForm, AutoFocusForm,
- InlineForm, auth_forms.AuthenticationForm):
+ InlineForm, LoginOrEmailAuthenticationForm, auth_forms.AuthenticationForm):
pass
-class AuthenticationForm(AutoFocusForm, auth_forms.AuthenticationForm):
+class AuthenticationForm(LoginOrEmailAuthenticationForm, AutoFocusForm,
+ auth_forms.AuthenticationForm):
pass
class RegistrationForm(RegistrationFormUniqueEmail):
diff --git a/sweettooth/auth/tests.py b/sweettooth/auth/tests.py
index 627b71d..623d7f0 100644
--- a/sweettooth/auth/tests.py
+++ b/sweettooth/auth/tests.py
@@ -9,6 +9,11 @@ User = get_user_model()
# registration/tests/test_forms.py
class AuthTests(TestCase):
+ registration_data = {
+ User.USERNAME_FIELD: 'bob',
+ 'email': 'bob example com',
+ 'password': 'mysecretpassword'
+ }
valid_data = {
User.USERNAME_FIELD: 'alice',
'email': 'alice example com',
@@ -16,15 +21,19 @@ class AuthTests(TestCase):
'password2': 'swordfish',
}
- def test_email_uniqueness(self):
- User.objects.create(
- username='bob',
- email=self.valid_data['email'],
- password=self.valid_data['password1']
+ @classmethod
+ def setUp(cls):
+ User.objects.create_user(
+ username=cls.registration_data[User.USERNAME_FIELD],
+ email=cls.registration_data['email'],
+ password=cls.registration_data['password']
)
+ def test_email_uniqueness(self):
+ data = self.valid_data.copy()
+ data.update(email = self.registration_data['email'])
form = AutoFocusRegistrationForm(
- data=self.valid_data.copy()
+ data=data
)
self.assertFalse(form.is_valid())
self.assertEqual(
@@ -32,9 +41,24 @@ class AuthTests(TestCase):
[text_type(validators.DUPLICATE_EMAIL)]
)
- data = self.valid_data.copy()
- data.update(email='bob example com')
form = AutoFocusRegistrationForm(
- data=data
+ data=self.valid_data.copy()
)
self.assertTrue(form.is_valid())
+
+ def test_auth_username_email(self):
+ self.assertTrue(self.client.login(
+ username=self.registration_data[User.USERNAME_FIELD],
+ password=self.registration_data['password']))
+
+ self.assertTrue(self.client.login(
+ username=self.registration_data['email'],
+ password=self.registration_data['password']))
+
+ self.assertFalse(self.client.login(
+ username=self.registration_data[User.USERNAME_FIELD],
+ password=self.valid_data['password1']))
+
+ self.assertFalse(self.client.login(
+ username=self.registration_data['email'],
+ password=self.valid_data['password1']))
diff --git a/sweettooth/settings.py b/sweettooth/settings.py
index 08341a5..7bce914 100644
--- a/sweettooth/settings.py
+++ b/sweettooth/settings.py
@@ -67,6 +67,8 @@ MIDDLEWARE = (
'django.contrib.messages.middleware.MessageMiddleware',
)
+AUTHENTICATION_BACKENDS = ['sweettooth.auth.backends.LoginEmailAuthentication']
+
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]