mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2024-11-22 17:16:34 +03:00
registration with email verification:
- rebuild login view - check email verification in LoginSerializer depends on allauth settings - add test for registration with email verification
This commit is contained in:
parent
f14b3b03f7
commit
de1fb3d81f
|
@ -1,3 +1,4 @@
|
||||||
|
from django.views.generic import TemplateView
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import patterns, url
|
||||||
|
|
||||||
from .views import Register, VerifyEmail
|
from .views import Register, VerifyEmail
|
||||||
|
@ -6,5 +7,11 @@ urlpatterns = patterns('',
|
||||||
url(r'^$', Register.as_view(), name='rest_register'),
|
url(r'^$', Register.as_view(), name='rest_register'),
|
||||||
url(r'^verify-email/(?P<activation_key>\w+)/$', VerifyEmail.as_view(),
|
url(r'^verify-email/(?P<activation_key>\w+)/$', VerifyEmail.as_view(),
|
||||||
name='verify_email'),
|
name='verify_email'),
|
||||||
|
|
||||||
|
url(r'^account-email-verification-sent/$', TemplateView.as_view(),
|
||||||
|
name='account_email_verification_sent'),
|
||||||
|
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
||||||
|
name='account_confirm_email'),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,25 @@ from django.conf import settings
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.serializers import _resolve_model
|
from rest_framework.serializers import _resolve_model
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
|
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
||||||
|
|
||||||
|
|
||||||
profile_model_path = lambda: getattr(settings, 'REST_PROFILE_MODULE', None)
|
profile_model_path = lambda: getattr(settings, 'REST_PROFILE_MODULE', None)
|
||||||
|
|
||||||
class LoginSerializer(serializers.Serializer):
|
|
||||||
username = serializers.CharField(max_length=30)
|
class LoginSerializer(AuthTokenSerializer):
|
||||||
password = serializers.CharField(max_length=128)
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
attrs = super(LoginSerializer, self).validate(attrs)
|
||||||
|
|
||||||
|
if 'rest_auth.registration' in settings.INSTALLED_APPS:
|
||||||
|
from allauth.account import app_settings
|
||||||
|
if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY:
|
||||||
|
user = attrs['user']
|
||||||
|
email_address = user.emailaddress_set.get(email=user.email)
|
||||||
|
if not email_address.verified:
|
||||||
|
raise serializers.ValidationError('E-mail is not verified.')
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class TokenSerializer(serializers.ModelSerializer):
|
class TokenSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -8,8 +8,10 @@ from django.test import TestCase
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
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.test.utils import override_settings
|
||||||
|
|
||||||
from rest_framework.serializers import _resolve_model
|
from rest_framework.serializers import _resolve_model
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
|
||||||
class APIClient(Client):
|
class APIClient(Client):
|
||||||
|
@ -133,6 +135,9 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
"password2": PASS
|
"password2": PASS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REGISTRATION_DATA_WITH_EMAIL = REGISTRATION_DATA.copy()
|
||||||
|
REGISTRATION_DATA_WITH_EMAIL['email'] = EMAIL
|
||||||
|
|
||||||
BASIC_USER_DATA = {
|
BASIC_USER_DATA = {
|
||||||
'first_name': "John",
|
'first_name': "John",
|
||||||
'last_name': 'Smith',
|
'last_name': 'Smith',
|
||||||
|
@ -164,8 +169,8 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
"username": self.USERNAME,
|
"username": self.USERNAME,
|
||||||
"password": self.PASS
|
"password": self.PASS
|
||||||
}
|
}
|
||||||
# there is no users in db so it should throw error (401)
|
# there is no users in db so it should throw error (400)
|
||||||
self.post(self.login_url, data=payload, status_code=401)
|
self.post(self.login_url, data=payload, status_code=400)
|
||||||
|
|
||||||
self.post(self.password_change_url, status_code=403)
|
self.post(self.password_change_url, status_code=403)
|
||||||
|
|
||||||
|
@ -181,14 +186,14 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
# test inactive user
|
# test inactive user
|
||||||
user.is_active = False
|
user.is_active = False
|
||||||
user.save()
|
user.save()
|
||||||
self.post(self.login_url, data=payload, status_code=401)
|
self.post(self.login_url, data=payload, status_code=400)
|
||||||
|
|
||||||
# test wrong username/password
|
# test wrong username/password
|
||||||
payload = {
|
payload = {
|
||||||
"username": self.USERNAME + '?',
|
"username": self.USERNAME + '?',
|
||||||
"password": self.PASS
|
"password": self.PASS
|
||||||
}
|
}
|
||||||
self.post(self.login_url, data=payload, status_code=401)
|
self.post(self.login_url, data=payload, status_code=400)
|
||||||
|
|
||||||
# test empty payload
|
# test empty payload
|
||||||
self.post(self.login_url, data={}, status_code=400)
|
self.post(self.login_url, data={}, status_code=400)
|
||||||
|
@ -210,7 +215,7 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
status_code=200)
|
status_code=200)
|
||||||
|
|
||||||
# user should not be able to login using old password
|
# user should not be able to login using old password
|
||||||
self.post(self.login_url, data=login_payload, status_code=401)
|
self.post(self.login_url, data=login_payload, status_code=400)
|
||||||
|
|
||||||
# new password should work
|
# new password should work
|
||||||
login_payload['password'] = new_password_payload['new_password1']
|
login_payload['password'] = new_password_payload['new_password1']
|
||||||
|
@ -302,3 +307,33 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
self.assertEqual(User.objects.all().count(), user_count + 1)
|
self.assertEqual(User.objects.all().count(), user_count + 1)
|
||||||
new_user = get_user_model().objects.latest('id')
|
new_user = get_user_model().objects.latest('id')
|
||||||
self.assertEqual(new_user.username, self.REGISTRATION_DATA['username'])
|
self.assertEqual(new_user.username, self.REGISTRATION_DATA['username'])
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"username": self.USERNAME,
|
||||||
|
"password": self.PASS
|
||||||
|
}
|
||||||
|
self.post(self.login_url, data=payload, status_code=200)
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
ACCOUNT_EMAIL_VERIFICATION='mandatory',
|
||||||
|
ACCOUNT_EMAIL_REQUIRED=True
|
||||||
|
)
|
||||||
|
def test_registration_with_email_verification(self):
|
||||||
|
user_count = User.objects.all().count()
|
||||||
|
mail_count = len(mail.outbox)
|
||||||
|
|
||||||
|
# test empty payload
|
||||||
|
self.post(self.register_url, data={}, status_code=400)
|
||||||
|
|
||||||
|
self.post(self.register_url, data=self.REGISTRATION_DATA_WITH_EMAIL, status_code=201)
|
||||||
|
self.assertEqual(User.objects.all().count(), user_count + 1)
|
||||||
|
self.assertEqual(len(mail.outbox), mail_count + 1)
|
||||||
|
new_user = get_user_model().objects.latest('id')
|
||||||
|
self.assertEqual(new_user.username, self.REGISTRATION_DATA['username'])
|
||||||
|
|
||||||
|
# email is not verified yet
|
||||||
|
payload = {
|
||||||
|
"username": self.USERNAME,
|
||||||
|
"password": self.PASS
|
||||||
|
}
|
||||||
|
self.post(self.login_url, data=payload, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import patterns, url, include
|
from django.conf.urls import patterns, url, include
|
||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from rest_auth.views import Login, Logout, UserDetails, \
|
from rest_auth.views import Login, Logout, UserDetails, \
|
||||||
PasswordChange, PasswordReset, PasswordResetConfirm
|
PasswordChange, PasswordReset, PasswordResetConfirm
|
||||||
|
@ -27,5 +28,9 @@ if getattr(settings, 'IS_TEST', False):
|
||||||
from django.contrib.auth.tests import urls
|
from django.contrib.auth.tests import urls
|
||||||
urlpatterns += patterns('',
|
urlpatterns += patterns('',
|
||||||
url(r'^rest-registration/', include('registration.urls')),
|
url(r'^rest-registration/', include('registration.urls')),
|
||||||
url(r'^test-admin/', include(urls))
|
url(r'^test-admin/', include(urls)),
|
||||||
|
url(r'^account-email-verification-sent/$', TemplateView.as_view(),
|
||||||
|
name='account_email_verification_sent'),
|
||||||
|
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
||||||
|
name='account_confirm_email'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,29 +62,18 @@ class Login(LoggedOutRESTAPIView, GenericAPIView):
|
||||||
# Create a serializer with request.DATA
|
# Create a serializer with request.DATA
|
||||||
serializer = self.serializer_class(data=request.DATA)
|
serializer = self.serializer_class(data=request.DATA)
|
||||||
|
|
||||||
if serializer.is_valid():
|
if not serializer.is_valid():
|
||||||
# Authenticate the credentials by grabbing Django User object
|
|
||||||
user = authenticate(username=serializer.data['username'],
|
|
||||||
password=serializer.data['password'])
|
|
||||||
|
|
||||||
if user and user.is_authenticated():
|
|
||||||
if user.is_active:
|
|
||||||
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
|
||||||
login(request, user)
|
|
||||||
|
|
||||||
# Return REST Token object with OK HTTP status
|
|
||||||
token, created = self.token_model.objects.get_or_create(user=user)
|
|
||||||
return Response(self.token_serializer(token).data,
|
|
||||||
status=status.HTTP_200_OK)
|
|
||||||
else:
|
|
||||||
return Response({'error': 'This account is disabled.'},
|
|
||||||
status=status.HTTP_401_UNAUTHORIZED)
|
|
||||||
else:
|
|
||||||
return Response({'error': 'Invalid Username/Password.'},
|
|
||||||
status=status.HTTP_401_UNAUTHORIZED)
|
|
||||||
else:
|
|
||||||
return Response(serializer.errors,
|
return Response(serializer.errors,
|
||||||
status=status.HTTP_400_BAD_REQUEST)
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
user = serializer.object['user']
|
||||||
|
token, created = self.token_model.objects.get_or_create(user=user)
|
||||||
|
|
||||||
|
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
||||||
|
login(request, user)
|
||||||
|
|
||||||
|
return Response(self.token_serializer(token).data,
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class Logout(LoggedInRESTAPIView):
|
class Logout(LoggedInRESTAPIView):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user