-
-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feature] Allowed authentication with email or phone number #206
Closes #206 Co-authored-by: Federico Capoano <federico.capoano@gmail.com>
- Loading branch information
1 parent
4569b60
commit 69cd57a
Showing
6 changed files
with
164 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from django.contrib.auth import get_user_model | ||
from django.contrib.auth.backends import ModelBackend | ||
from django.db.models import Q | ||
|
||
User = get_user_model() | ||
|
||
|
||
class UsersAuthenticationBackend(ModelBackend): | ||
def authenticate(self, request, username=None, password=None, **kwargs): | ||
queryset = self.get_users(username) | ||
try: | ||
# can not use queryset.first() because it orders the queryset | ||
# by pk before returning the first object which is not what we want | ||
user = queryset[0] | ||
except IndexError: | ||
return None | ||
if user.check_password(password) and self.user_can_authenticate(user): | ||
return user | ||
return None | ||
|
||
def get_users(self, identifier): | ||
return User.objects.filter( | ||
Q(email=identifier) | Q(phone_number=identifier) | Q(username=identifier) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
from uuid import UUID | ||
|
||
from django.test import TestCase | ||
from django.test.utils import override_settings | ||
|
||
from openwisp_users.backends import UsersAuthenticationBackend | ||
|
||
from .utils import TestOrganizationMixin | ||
|
||
auth_backend = UsersAuthenticationBackend() | ||
|
||
|
||
class TestBackends(TestOrganizationMixin, TestCase): | ||
def _test_user_auth_backend_helper(self, username, password, pk): | ||
self.client.login(username=username, password=password) | ||
self.assertIn('_auth_user_id', self.client.session) | ||
self.assertEqual( | ||
UUID(self.client.session['_auth_user_id'], version=4), pk, | ||
) | ||
self.client.logout() | ||
self.assertNotIn('_auth_user_id', self.client.session) | ||
|
||
@override_settings( | ||
AUTHENTICATION_BACKENDS=('openwisp_users.backends.UsersAuthenticationBackend',) | ||
) | ||
def test_user_auth_backend(self): | ||
user = self._create_user( | ||
username='tester', | ||
email='tester@gmail.com', | ||
phone_number='+237675579231', | ||
password='tester', | ||
) | ||
with self.subTest('Test login with username'): | ||
self._test_user_auth_backend_helper('tester', 'tester', user.pk) | ||
|
||
with self.subTest('Test login with email'): | ||
self._test_user_auth_backend_helper('tester@gmail.com', 'tester', user.pk) | ||
|
||
with self.subTest('Test login with phone_number'): | ||
self._test_user_auth_backend_helper('+237675579231', 'tester', user.pk) | ||
|
||
@override_settings( | ||
AUTHENTICATION_BACKENDS=('openwisp_users.backends.UsersAuthenticationBackend',) | ||
) | ||
def test_user_with_email_as_username_auth_backend(self): | ||
user = self._create_user( | ||
username='tester', | ||
email='tester@gmail.com', | ||
phone_number='+237675579231', | ||
password='tester', | ||
) | ||
self._create_user( | ||
username='tester@gmail.com', | ||
email='tester1@gmail.com', | ||
phone_number='+237675579232', | ||
password='tester1', | ||
) | ||
self._test_user_auth_backend_helper(user.email, 'tester', user.pk) | ||
|
||
@override_settings( | ||
AUTHENTICATION_BACKENDS=('openwisp_users.backends.UsersAuthenticationBackend',) | ||
) | ||
def test_user_with_phone_number_as_username_auth_backend(self): | ||
user = self._create_user( | ||
username='tester', | ||
email='tester@gmail.com', | ||
phone_number='+237675579231', | ||
password='tester', | ||
) | ||
self._create_user( | ||
username='+237675579231', | ||
email='tester1@gmail.com', | ||
phone_number='+237675579232', | ||
password='tester1', | ||
) | ||
self._test_user_auth_backend_helper(user.phone_number, 'tester', user.pk) | ||
|
||
def test_auth_backend_get_user(self): | ||
user = self._create_user( | ||
username='tester', | ||
email='tester@gmail.com', | ||
phone_number='+237675579231', | ||
password='tester', | ||
) | ||
user1 = self._create_user( | ||
username='tester1', | ||
email='tester1@gmail.com', | ||
phone_number='+237675579232', | ||
password='tester1', | ||
) | ||
|
||
with self.subTest('get user with invalid identifier'): | ||
self.assertEqual(len(auth_backend.get_users('invalid')), 0) | ||
|
||
with self.subTest('get user with email'): | ||
user1.username = user.email | ||
user1.save() | ||
self.assertEqual(auth_backend.get_users(user.email)[0], user) | ||
|
||
with self.subTest('get user with phone_number'): | ||
user1.username = user.phone_number | ||
user1.save() | ||
self.assertEqual(auth_backend.get_users(user.phone_number)[0], user) | ||
|
||
with self.subTest('get user with username'): | ||
self.assertEqual(auth_backend.get_users(user.username)[0], user) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters