Commit 32ce8428 authored by Okhin's avatar Okhin

Fixing the auth backend to allow username or email validation

parent 2c0989b3
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
class EmailOrUsernameModelBackend(ModelBackend):
"""
Authentification backend to allow email
overide AUTHENTICATION_BACKENDS with
fabauth.auth_backends.EmailOrUsernameModelBackend
We allow for email or username to be used as a login.
Case insensitive.
"""
def authenticate(self, username=None, password=None, **kwargs):
if "@" in username:
kwargs = {"email": username}
else:
kwargs = {"username": username}
def authenticate(self, request, username=None, password=None):
# If we call this function, it means we're not authenticated yet.
# Since we're going through the classic Model backend first, it means
# that the user does not exists.
UserModel = get_user_model()
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
user = UserModel.objects.get(email=username)
if user.check_password(raw_password=password):
return user
except User.DoesNotExist:
except UserModel.DoesNotExist:
# The User does not exist. Hashing the password anyway,
# to limit Time attacks efficiency
UserModel().set_password(raw_password=password)
return None
def get_user(self, user_id):
# This is used to get the User objects
UserModel = get_user_model()
print("get_user: {}".format(user_id))
try:
return UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
from django.test import TestCase
from django.test import Client
from django.test import Client, override_settings
from django_factory_boy import auth as auth_factories
AUTHENTICATION_BACKENDS = [
@override_settings(AUTHENTICATION_BACKENDS=[
# Default
"django.contrib.auth.backends.ModelBackend",
# Email or Username for login
"core.auth_backends.EmailOrUsernameModelBackend"
]
])
class ApiTest(TestCase):
def setUp(self):
self.client = Client()
self.user = auth_factories.UserFactory(password="dummypassword")
def test_authenticate(self):
with self.settings(AUTHENTICATION_BACKENDS=AUTHENTICATION_BACKENDS):
# username, wrong password
login_status = self.client.login(
username=self.user.username,
password="notthepassword"
)
assert not login_status
# username, correct password
login_status = self.client.login(
username=self.user.username,
password="dummypassword"
)
assert login_status
# email, wrong password
login_status = self.client.login(
username=self.user.email,
password="notthepassowrd"
)
assert not login_status
# email, correct password
login_status = self.client.login(
username=self.user.email,
password="dummypassword"
)
assert login_status
# username, wrong user
login_status = self.client.login(
username="{}-2".format(self.user.username),
password="dummypassword"
)
assert not login_status
# email, wrong user
login_status = self.client.login(
username="{}-2".format(self.user.email),
password="dummypassword"
)
assert not login_status
# username, wrong password
login_status = self.client.login(
username=self.user.username,
password="notthepassword"
)
assert not login_status
# username, correct password
login_status = self.client.login(
username=self.user.username,
password="dummypassword"
)
assert login_status
# email, wrong password
login_status = self.client.login(
username=self.user.email,
password="notthepassowrd"
)
assert not login_status
# email, correct password
login_status = self.client.login(
username=self.user.email,
password="dummypassword"
)
assert login_status
# username, wrong user
login_status = self.client.login(
username="{}-2".format(self.user.username),
password="dummypassword"
)
assert not login_status
# email, wrong user
login_status = self.client.login(
username="{}-2".format(self.user.email),
password="dummypassword"
)
assert not login_status
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment