mirror of
				https://github.com/Tivix/django-rest-auth.git
				synced 2025-11-04 09:37:35 +03:00 
			
		
		
		
	Merge pull request #150 from Tivix/pr/141
Ability to login using e-mail (without allauth)
This commit is contained in:
		
						commit
						d63232224e
					
				| 
						 | 
				
			
			@ -7,6 +7,7 @@ Basic
 | 
			
		|||
- /rest-auth/login/ (POST)
 | 
			
		||||
 | 
			
		||||
    - username (string)
 | 
			
		||||
    - email (string)
 | 
			
		||||
    - password (string)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,29 +19,31 @@ class LoginSerializer(serializers.Serializer):
 | 
			
		|||
    email = serializers.EmailField(required=False, allow_blank=True)
 | 
			
		||||
    password = serializers.CharField(style={'input_type': 'password'})
 | 
			
		||||
 | 
			
		||||
    def validate(self, attrs):
 | 
			
		||||
        username = attrs.get('username')
 | 
			
		||||
        email = attrs.get('email')
 | 
			
		||||
        password = attrs.get('password')
 | 
			
		||||
    def _validate_email(self, email, password):
 | 
			
		||||
        user = None
 | 
			
		||||
 | 
			
		||||
        if 'allauth' in settings.INSTALLED_APPS:
 | 
			
		||||
            from allauth.account import app_settings
 | 
			
		||||
            # Authentication through email
 | 
			
		||||
            if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.EMAIL:
 | 
			
		||||
        if email and password:
 | 
			
		||||
            user = authenticate(email=email, password=password)
 | 
			
		||||
        else:
 | 
			
		||||
            msg = _('Must include "email" and "password".')
 | 
			
		||||
            raise exceptions.ValidationError(msg)
 | 
			
		||||
            # Authentication through username
 | 
			
		||||
            elif app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME:
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
            # Authentication through either username or email
 | 
			
		||||
            else:
 | 
			
		||||
 | 
			
		||||
        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:
 | 
			
		||||
| 
						 | 
				
			
			@ -50,12 +52,40 @@ class LoginSerializer(serializers.Serializer):
 | 
			
		|||
            msg = _('Must include either "username" or "email" and "password".')
 | 
			
		||||
            raise exceptions.ValidationError(msg)
 | 
			
		||||
 | 
			
		||||
        elif username and password:
 | 
			
		||||
            user = authenticate(username=username, password=password)
 | 
			
		||||
        return user
 | 
			
		||||
 | 
			
		||||
    def validate(self, attrs):
 | 
			
		||||
        username = attrs.get('username')
 | 
			
		||||
        email = attrs.get('email')
 | 
			
		||||
        password = attrs.get('password')
 | 
			
		||||
 | 
			
		||||
        user = None
 | 
			
		||||
 | 
			
		||||
        if 'allauth' in settings.INSTALLED_APPS:
 | 
			
		||||
            from allauth.account import app_settings
 | 
			
		||||
 | 
			
		||||
            # Authentication through email
 | 
			
		||||
            if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.EMAIL:
 | 
			
		||||
                user = self._validate_email(email, password)
 | 
			
		||||
 | 
			
		||||
            # Authentication through username
 | 
			
		||||
            if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME:
 | 
			
		||||
                user = self._validate_username(username, password)
 | 
			
		||||
 | 
			
		||||
            # Authentication through either username or email
 | 
			
		||||
            else:
 | 
			
		||||
                user = self._validate_username_email(username, email, password)
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            msg = _('Must include "username" and "password".')
 | 
			
		||||
            raise exceptions.ValidationError(msg)
 | 
			
		||||
            # Authentication without using allauth
 | 
			
		||||
            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?
 | 
			
		||||
        if user:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ from django.core.urlresolvers import reverse
 | 
			
		|||
from django.test import TestCase
 | 
			
		||||
from django.contrib.auth import get_user_model
 | 
			
		||||
from django.core import mail
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.test.utils import override_settings
 | 
			
		||||
from django.utils.encoding import force_text
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +91,51 @@ class APITestCase1(TestCase, BaseAPITestCase):
 | 
			
		|||
        # test empty payload
 | 
			
		||||
        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):
 | 
			
		||||
        login_payload = {
 | 
			
		||||
            "username": self.USERNAME,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user