[extensions-web/wip/ne0sight] auth: allow logging in with both login or email



commit aaab48a7e122584b5b19b8f3b555e18898a33779
Author: Yuri Konotopov <ykonotopov gnome org>
Date:   Sun Nov 24 21:05:06 2019 +0400

    auth: allow logging in with both login or email

 sweettooth/auth/backends.py | 29 +++++++++++++++++++++++++++++
 sweettooth/auth/forms.py    | 11 +++++++++--
 sweettooth/auth/tests.py    | 20 +++++++++++++++++++-
 sweettooth/settings.py      |  2 ++
 4 files changed, 59 insertions(+), 3 deletions(-)
---
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..a48008d 100644
--- a/sweettooth/auth/tests.py
+++ b/sweettooth/auth/tests.py
@@ -16,13 +16,14 @@ class AuthTests(TestCase):
         'password2': 'swordfish',
     }
 
-    def test_email_uniqueness(self):
+    def setUp(self):
         User.objects.create(
             username='bob',
             email=self.valid_data['email'],
             password=self.valid_data['password1']
         )
 
+    def test_email_uniqueness(self):
         form = AutoFocusRegistrationForm(
             data=self.valid_data.copy()
         )
@@ -38,3 +39,20 @@ class AuthTests(TestCase):
             data=data
         )
         self.assertTrue(form.is_valid())
+
+    def test_auth_username_email(self):
+        self.assertTrue(self.client.login(
+            username=self.valid_data[User.USERNAME_FIELD],
+            password=self.valid_data['password1'])
+
+        self.assertTrue(self.client.login(
+            username=self.valid_data['email'],
+            password=self.valid_data['password1'])
+
+        self.assertFalse(self.client.login(
+            username=self.valid_data[User.USERNAME_FIELD],
+            password="P@ssw0rd")
+
+        self.assertFalse(self.client.login(
+            username=self.valid_data['email'],
+            password="P@ssw0rd")
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]