Merge pull request #150 from Tivix/pr/141

Ability to login using e-mail (without allauth)
This commit is contained in:
mariodev 2016-01-06 18:16:51 +01:00
commit d63232224e
3 changed files with 100 additions and 23 deletions

View File

@ -7,6 +7,7 @@ Basic
- /rest-auth/login/ (POST) - /rest-auth/login/ (POST)
- username (string) - username (string)
- email (string)
- password (string) - password (string)

View File

@ -19,43 +19,73 @@ class LoginSerializer(serializers.Serializer):
email = serializers.EmailField(required=False, allow_blank=True) email = serializers.EmailField(required=False, allow_blank=True)
password = serializers.CharField(style={'input_type': 'password'}) password = serializers.CharField(style={'input_type': 'password'})
def _validate_email(self, email, password):
user = None
if email and password:
user = authenticate(email=email, password=password)
else:
msg = _('Must include "email" and "password".')
raise exceptions.ValidationError(msg)
return user
def _validate_username(self, username, password):
user = None
if username and password:
user = authenticate(username=username, password=password)
else:
msg = _('Must include "username" and "password".')
raise exceptions.ValidationError(msg)
return user
def _validate_username_email(self, username, email, password):
user = None
if email and password:
user = authenticate(email=email, password=password)
elif username and password:
user = authenticate(username=username, password=password)
else:
msg = _('Must include either "username" or "email" and "password".')
raise exceptions.ValidationError(msg)
return user
def validate(self, attrs): def validate(self, attrs):
username = attrs.get('username') username = attrs.get('username')
email = attrs.get('email') email = attrs.get('email')
password = attrs.get('password') password = attrs.get('password')
user = None
if 'allauth' in settings.INSTALLED_APPS: if 'allauth' in settings.INSTALLED_APPS:
from allauth.account import app_settings from allauth.account import app_settings
# Authentication through email # Authentication through email
if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.EMAIL: if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.EMAIL:
if email and password: user = self._validate_email(email, password)
user = authenticate(email=email, password=password)
else:
msg = _('Must include "email" and "password".')
raise exceptions.ValidationError(msg)
# Authentication through username # Authentication through username
elif app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME: if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME:
if username and password: user = self._validate_username(username, password)
user = authenticate(username=username, password=password)
else:
msg = _('Must include "username" and "password".')
raise exceptions.ValidationError(msg)
# Authentication through either username or email # Authentication through either username or email
else: else:
if email and password: user = self._validate_username_email(username, email, password)
user = authenticate(email=email, password=password)
elif username and password:
user = authenticate(username=username, password=password)
else:
msg = _('Must include either "username" or "email" and "password".')
raise exceptions.ValidationError(msg)
elif username and password:
user = authenticate(username=username, password=password)
else: else:
msg = _('Must include "username" and "password".') # Authentication without using allauth
raise exceptions.ValidationError(msg) if email:
try:
username = UserModel.objects.get(email__iexact=email).username
except UserModel.DoesNotExist:
pass
if username:
user = self._validate_username_email(username, '', password)
# Did we get back an active user? # Did we get back an active user?
if user: if user:

View File

@ -2,6 +2,7 @@ from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core import mail from django.core import mail
from django.conf import settings
from django.test.utils import override_settings from django.test.utils import override_settings
from django.utils.encoding import force_text from django.utils.encoding import force_text
@ -90,6 +91,51 @@ class APITestCase1(TestCase, BaseAPITestCase):
# test empty payload # test empty payload
self.post(self.login_url, data={}, status_code=400) self.post(self.login_url, data={}, status_code=400)
def test_login_by_email(self):
# starting test without allauth app
settings.INSTALLED_APPS.remove('allauth')
payload = {
"email": self.EMAIL.lower(),
"password": self.PASS
}
# there is no users in db so it should throw error (400)
self.post(self.login_url, data=payload, status_code=400)
self.post(self.password_change_url, status_code=403)
# create user
user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS)
# test auth by email
self.post(self.login_url, data=payload, status_code=200)
self.assertEqual('key' in self.response.json.keys(), True)
self.token = self.response.json['key']
# test auth by email in different case
payload = {
"email": self.EMAIL.upper(),
"password": self.PASS
}
self.post(self.login_url, data=payload, status_code=200)
self.assertEqual('key' in self.response.json.keys(), True)
self.token = self.response.json['key']
# test inactive user
user.is_active = False
user.save()
self.post(self.login_url, data=payload, status_code=400)
# test wrong email/password
payload = {
"email": 't' + self.EMAIL,
"password": self.PASS
}
self.post(self.login_url, data=payload, status_code=400)
# test empty payload
self.post(self.login_url, data={}, status_code=400)
def test_password_change(self): def test_password_change(self):
login_payload = { login_payload = {
"username": self.USERNAME, "username": self.USERNAME,