mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2024-11-23 01:26:39 +03:00
Merge branch 'master' into custom-token
This commit is contained in:
commit
c087899311
|
@ -1,8 +1,8 @@
|
||||||
from django.conf.urls import patterns, include, url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.views.generic import TemplateView, RedirectView
|
from django.views.generic import TemplateView, RedirectView
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = [
|
||||||
url(r'^$', TemplateView.as_view(template_name="home.html"), name='home'),
|
url(r'^$', TemplateView.as_view(template_name="home.html"), name='home'),
|
||||||
url(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
|
url(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
|
||||||
name='signup'),
|
name='signup'),
|
||||||
|
@ -36,4 +36,4 @@ urlpatterns = patterns('',
|
||||||
url(r'^account/', include('allauth.urls')),
|
url(r'^account/', include('allauth.urls')),
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'),
|
url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'),
|
||||||
)
|
]
|
||||||
|
|
|
@ -7,6 +7,7 @@ Basic
|
||||||
- /rest-auth/login/ (POST)
|
- /rest-auth/login/ (POST)
|
||||||
|
|
||||||
- username (string)
|
- username (string)
|
||||||
|
- email (string)
|
||||||
- password (string)
|
- password (string)
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,16 +56,6 @@ Registration
|
||||||
- password2
|
- password2
|
||||||
- email
|
- email
|
||||||
|
|
||||||
.. note:: This endpoint is based on ``allauth.account.views.SignupView`` and uses the same form as in this view. To override fields you have to create custom Signup Form and define it in django settings:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
ACCOUNT_FORMS = {
|
|
||||||
'signup': 'path.to.custom.SignupForm'
|
|
||||||
}
|
|
||||||
|
|
||||||
See allauth documentation for more details.
|
|
||||||
|
|
||||||
- /rest-auth/registration/verify-email/ (POST)
|
- /rest-auth/registration/verify-email/ (POST)
|
||||||
|
|
||||||
- key
|
- key
|
||||||
|
|
|
@ -29,6 +29,13 @@ Configuration
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- **REST_AUTH_REGISTRATION_SERIALIZERS**
|
||||||
|
|
||||||
|
You can define your custom serializers for registration endpoint.
|
||||||
|
Possible key values:
|
||||||
|
|
||||||
|
- REGISTER_SERIALIZER - serializer class in ``rest_auth.register.views.RegisterView``, default value ``rest_auth.register.serializers.RegisterSerializer``
|
||||||
|
|
||||||
- **REST_AUTH_TOKEN_MODEL** - model class for tokens, default value ``rest_framework.authtoken.models``
|
- **REST_AUTH_TOKEN_MODEL** - model class for tokens, default value ``rest_framework.authtoken.models``
|
||||||
|
|
||||||
- **REST_AUTH_TOKEN_CREATOR** - callable to create tokens, default value ``rest_auth.utils.default_create_token``.
|
- **REST_AUTH_TOKEN_CREATOR** - callable to create tokens, default value ``rest_auth.utils.default_create_token``.
|
||||||
|
|
|
@ -38,7 +38,7 @@ You're good to go now!
|
||||||
Registration (optional)
|
Registration (optional)
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
1. If you want to enable standard registration process you will need to install ``django-allauth`` - see this doc for installation http://django-allauth.readthedocs.org/en/latest/installation.html.
|
1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install django-rest-auth[extras]`` or ``pip install django-rest-auth[with_social]``.
|
||||||
|
|
||||||
2. Add ``allauth``, ``allauth.account`` and ``rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py:
|
2. Add ``allauth``, ``allauth.account`` and ``rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py:
|
||||||
|
|
||||||
|
|
11
rest_auth/registration/app_settings.py
Normal file
11
rest_auth/registration/app_settings.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from rest_auth.registration.serializers import (
|
||||||
|
RegisterSerializer as DefaultRegisterSerializer)
|
||||||
|
from ..utils import import_callable
|
||||||
|
|
||||||
|
|
||||||
|
serializers = getattr(settings, 'REST_AUTH_REGISTER_SERIALIZERS', {})
|
||||||
|
|
||||||
|
RegisterSerializer = import_callable(
|
||||||
|
serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer))
|
|
@ -1,6 +1,15 @@
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
try:
|
||||||
|
from allauth.account import app_settings as allauth_settings
|
||||||
|
from allauth.utils import (email_address_exists,
|
||||||
|
get_username_max_length)
|
||||||
|
from allauth.account.adapter import get_adapter
|
||||||
|
from allauth.account.utils import setup_user_email
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError('allauth needs to be added to INSTALLED_APPS.')
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
# Import is needed only if we are using social login, in which
|
# Import is needed only if we are using social login, in which
|
||||||
|
@ -109,3 +118,57 @@ class SocialLoginSerializer(serializers.Serializer):
|
||||||
attrs['user'] = login.account.user
|
attrs['user'] = login.account.user
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterSerializer(serializers.Serializer):
|
||||||
|
username = serializers.CharField(
|
||||||
|
max_length=get_username_max_length(),
|
||||||
|
min_length=allauth_settings.USERNAME_MIN_LENGTH,
|
||||||
|
required=allauth_settings.USERNAME_REQUIRED
|
||||||
|
)
|
||||||
|
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
|
||||||
|
password1 = serializers.CharField(required=True, write_only=True)
|
||||||
|
password2 = serializers.CharField(required=True, write_only=True)
|
||||||
|
|
||||||
|
def validate_username(self, username):
|
||||||
|
username = get_adapter().clean_username(username)
|
||||||
|
return username
|
||||||
|
|
||||||
|
def validate_email(self, email):
|
||||||
|
email = get_adapter().clean_email(email)
|
||||||
|
if allauth_settings.UNIQUE_EMAIL:
|
||||||
|
if email and email_address_exists(email):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"A user is already registered with this e-mail address.")
|
||||||
|
return email
|
||||||
|
|
||||||
|
def validate_password1(self, password):
|
||||||
|
return get_adapter().clean_password(password)
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
if data['password1'] != data['password2']:
|
||||||
|
raise serializers.ValidationError("The two password fields didn't match.")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def custom_signup(self, request, user):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_cleaned_data(self):
|
||||||
|
return {
|
||||||
|
'username': self.validated_data.get('username', ''),
|
||||||
|
'password1': self.validated_data.get('password1', ''),
|
||||||
|
'email': self.validated_data.get('email', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
def save(self, request):
|
||||||
|
adapter = get_adapter()
|
||||||
|
user = adapter.new_user(request)
|
||||||
|
self.cleaned_data = self.get_cleaned_data()
|
||||||
|
adapter.save_user(request, user, self)
|
||||||
|
self.custom_signup(request, user)
|
||||||
|
setup_user_email(request, user, [])
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
class VerifyEmailSerializer(serializers.Serializer):
|
||||||
|
key = serializers.CharField()
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from .views import RegisterView, VerifyEmailView
|
from .views import RegisterView, VerifyEmailView
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'',
|
|
||||||
url(r'^$', RegisterView.as_view(), name='rest_register'),
|
url(r'^$', RegisterView.as_view(), name='rest_register'),
|
||||||
url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'),
|
url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'),
|
||||||
|
|
||||||
|
@ -21,4 +20,4 @@ urlpatterns = patterns(
|
||||||
# djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
|
# djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
|
||||||
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
||||||
name='account_confirm_email'),
|
name='account_confirm_email'),
|
||||||
)
|
]
|
||||||
|
|
|
@ -1,77 +1,44 @@
|
||||||
from django.http import HttpRequest
|
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.generics import CreateAPIView
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
from rest_framework.exceptions import MethodNotAllowed
|
||||||
|
|
||||||
from allauth.account.views import SignupView, ConfirmEmailView
|
from allauth.account.views import ConfirmEmailView
|
||||||
from allauth.account.utils import complete_signup
|
from allauth.account.utils import complete_signup
|
||||||
from allauth.account import app_settings
|
from allauth.account import app_settings as allauth_settings
|
||||||
|
|
||||||
from rest_auth.app_settings import TokenSerializer
|
from rest_auth.app_settings import (TokenSerializer,
|
||||||
from rest_auth.registration.serializers import SocialLoginSerializer
|
create_token)
|
||||||
|
from rest_auth.registration.serializers import (SocialLoginSerializer,
|
||||||
|
VerifyEmailSerializer)
|
||||||
from rest_auth.views import LoginView
|
from rest_auth.views import LoginView
|
||||||
from rest_auth.models import TokenModel
|
from rest_auth.models import TokenModel
|
||||||
|
from .app_settings import RegisterSerializer
|
||||||
|
|
||||||
|
|
||||||
class RegisterView(APIView, SignupView):
|
class RegisterView(CreateAPIView):
|
||||||
"""
|
serializer_class = RegisterSerializer
|
||||||
Accepts the credentials and creates a new user
|
|
||||||
if user does not exist already
|
|
||||||
Return the REST Token if the credentials are valid and authenticated.
|
|
||||||
Calls allauth complete_signup method
|
|
||||||
|
|
||||||
Accept the following POST parameters: username, email, password
|
|
||||||
Return the REST Framework Token Object's key.
|
|
||||||
"""
|
|
||||||
|
|
||||||
permission_classes = (AllowAny, )
|
permission_classes = (AllowAny, )
|
||||||
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
|
||||||
token_model = TokenModel
|
token_model = TokenModel
|
||||||
serializer_class = TokenSerializer
|
|
||||||
|
|
||||||
def get(self, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
user = self.perform_create(serializer)
|
||||||
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
return Response(TokenSerializer(user.auth_token).data,
|
||||||
|
status=status.HTTP_201_CREATED,
|
||||||
|
headers=headers)
|
||||||
|
|
||||||
def put(self, *args, **kwargs):
|
def perform_create(self, serializer):
|
||||||
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
user = serializer.save(self.request)
|
||||||
|
create_token(self.token_model, user, serializer)
|
||||||
def form_valid(self, form):
|
complete_signup(self.request._request, user,
|
||||||
self.user = form.save(self.request)
|
allauth_settings.EMAIL_VERIFICATION,
|
||||||
self.token, created = self.token_model.objects.get_or_create(
|
None)
|
||||||
user=self.user
|
return user
|
||||||
)
|
|
||||||
if isinstance(self.request, HttpRequest):
|
|
||||||
request = self.request
|
|
||||||
else:
|
|
||||||
request = self.request._request
|
|
||||||
return complete_signup(request, self.user,
|
|
||||||
app_settings.EMAIL_VERIFICATION,
|
|
||||||
self.get_success_url())
|
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
|
||||||
kwargs = super(RegisterView, self).get_form_kwargs(*args, **kwargs)
|
|
||||||
kwargs['data'] = self.request.data
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
self.initial = {}
|
|
||||||
form_class = self.get_form_class()
|
|
||||||
self.form = self.get_form(form_class)
|
|
||||||
if self.form.is_valid():
|
|
||||||
self.form_valid(self.form)
|
|
||||||
return self.get_response()
|
|
||||||
else:
|
|
||||||
return self.get_response_with_errors()
|
|
||||||
|
|
||||||
def get_response(self):
|
|
||||||
# serializer = self.user_serializer_class(instance=self.user)
|
|
||||||
serializer = self.serializer_class(instance=self.token,
|
|
||||||
context={'request': self.request})
|
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
||||||
|
|
||||||
def get_response_with_errors(self):
|
|
||||||
return Response(self.form.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
|
|
||||||
class VerifyEmailView(APIView, ConfirmEmailView):
|
class VerifyEmailView(APIView, ConfirmEmailView):
|
||||||
|
@ -80,10 +47,12 @@ class VerifyEmailView(APIView, ConfirmEmailView):
|
||||||
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
||||||
|
|
||||||
def get(self, *args, **kwargs):
|
def get(self, *args, **kwargs):
|
||||||
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
raise MethodNotAllowed('GET')
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
self.kwargs['key'] = self.request.data.get('key', '')
|
serializer = VerifyEmailSerializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
self.kwargs['key'] = serializer.validated_data['key']
|
||||||
confirmation = self.get_object()
|
confirmation = self.get_object()
|
||||||
confirmation.confirm(self.request)
|
confirmation.confirm(self.request)
|
||||||
return Response({'message': 'ok'}, status=status.HTTP_200_OK)
|
return Response({'message': 'ok'}, status=status.HTTP_200_OK)
|
||||||
|
|
|
@ -20,29 +20,31 @@ 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(self, attrs):
|
def _validate_email(self, email, password):
|
||||||
username = attrs.get('username')
|
user = None
|
||||||
email = attrs.get('email')
|
|
||||||
password = attrs.get('password')
|
|
||||||
|
|
||||||
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:
|
if email and password:
|
||||||
user = authenticate(email=email, password=password)
|
user = authenticate(email=email, password=password)
|
||||||
else:
|
else:
|
||||||
msg = _('Must include "email" and "password".')
|
msg = _('Must include "email" and "password".')
|
||||||
raise exceptions.ValidationError(msg)
|
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:
|
if username and password:
|
||||||
user = authenticate(username=username, password=password)
|
user = authenticate(username=username, password=password)
|
||||||
else:
|
else:
|
||||||
msg = _('Must include "username" and "password".')
|
msg = _('Must include "username" and "password".')
|
||||||
raise exceptions.ValidationError(msg)
|
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:
|
if email and password:
|
||||||
user = authenticate(email=email, password=password)
|
user = authenticate(email=email, password=password)
|
||||||
elif username and password:
|
elif username and password:
|
||||||
|
@ -51,12 +53,40 @@ class LoginSerializer(serializers.Serializer):
|
||||||
msg = _('Must include either "username" or "email" and "password".')
|
msg = _('Must include either "username" or "email" and "password".')
|
||||||
raise exceptions.ValidationError(msg)
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
elif username and password:
|
return user
|
||||||
user = authenticate(username=username, password=password)
|
|
||||||
|
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:
|
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:
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -225,7 +271,7 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
self.post(self.login_url, data=payload, status_code=200)
|
self.post(self.login_url, data=payload, status_code=200)
|
||||||
|
|
||||||
def test_password_reset_with_email_in_different_case(self):
|
def test_password_reset_with_email_in_different_case(self):
|
||||||
user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL.lower(), self.PASS)
|
get_user_model().objects.create_user(self.USERNAME, self.EMAIL.lower(), self.PASS)
|
||||||
|
|
||||||
# call password reset in upper case
|
# call password reset in upper case
|
||||||
mail_count = len(mail.outbox)
|
mail_count = len(mail.outbox)
|
||||||
|
@ -272,6 +318,12 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
self._login()
|
self._login()
|
||||||
self._logout()
|
self._logout()
|
||||||
|
|
||||||
|
def test_registration_with_invalid_password(self):
|
||||||
|
data = self.REGISTRATION_DATA.copy()
|
||||||
|
data['password2'] = 'foobar'
|
||||||
|
|
||||||
|
self.post(self.register_url, data=data, status_code=400)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
ACCOUNT_EMAIL_VERIFICATION='mandatory',
|
ACCOUNT_EMAIL_VERIFICATION='mandatory',
|
||||||
ACCOUNT_EMAIL_REQUIRED=True
|
ACCOUNT_EMAIL_REQUIRED=True
|
||||||
|
|
|
@ -99,7 +99,6 @@ class TestSocialAuth(TestCase, BaseAPITestCase):
|
||||||
|
|
||||||
# test empty payload
|
# test empty payload
|
||||||
self.post(self.register_url, data={}, status_code=400)
|
self.post(self.register_url, data={}, status_code=400)
|
||||||
|
|
||||||
self.post(
|
self.post(
|
||||||
self.register_url,
|
self.register_url,
|
||||||
data=self.REGISTRATION_DATA,
|
data=self.REGISTRATION_DATA,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from django.conf.urls import patterns, url, include
|
from django.conf.urls import url, include
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from . import django_urls
|
from . import django_urls
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@ from rest_auth.registration.views import SocialLoginView
|
||||||
class FacebookLogin(SocialLoginView):
|
class FacebookLogin(SocialLoginView):
|
||||||
adapter_class = FacebookOAuth2Adapter
|
adapter_class = FacebookOAuth2Adapter
|
||||||
|
|
||||||
urlpatterns += patterns(
|
urlpatterns += [
|
||||||
'',
|
|
||||||
url(r'^rest-registration/', include('rest_auth.registration.urls')),
|
url(r'^rest-registration/', include('rest_auth.registration.urls')),
|
||||||
url(r'^test-admin/', include(django_urls)),
|
url(r'^test-admin/', include(django_urls)),
|
||||||
url(r'^account-email-verification-sent/$', TemplateView.as_view(),
|
url(r'^account-email-verification-sent/$', TemplateView.as_view(),
|
||||||
|
@ -21,4 +20,4 @@ urlpatterns += patterns(
|
||||||
name='account_confirm_email'),
|
name='account_confirm_email'),
|
||||||
url(r'^social-login/facebook/$', FacebookLogin.as_view(), name='fb_login'),
|
url(r'^social-login/facebook/$', FacebookLogin.as_view(), name='fb_login'),
|
||||||
url(r'^accounts/', include('allauth.socialaccount.urls'))
|
url(r'^accounts/', include('allauth.socialaccount.urls'))
|
||||||
)
|
]
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from rest_auth.views import (
|
from rest_auth.views import (
|
||||||
LoginView, LogoutView, UserDetailsView, PasswordChangeView,
|
LoginView, LogoutView, UserDetailsView, PasswordChangeView,
|
||||||
PasswordResetView, PasswordResetConfirmView
|
PasswordResetView, PasswordResetConfirmView
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = [
|
||||||
'',
|
|
||||||
# URLs that do not require a session or valid token
|
# URLs that do not require a session or valid token
|
||||||
url(r'^password/reset/$', PasswordResetView.as_view(),
|
url(r'^password/reset/$', PasswordResetView.as_view(),
|
||||||
name='rest_password_reset'),
|
name='rest_password_reset'),
|
||||||
|
@ -18,4 +17,4 @@ urlpatterns = patterns(
|
||||||
url(r'^user/$', UserDetailsView.as_view(), name='rest_user_details'),
|
url(r'^user/$', UserDetailsView.as_view(), name='rest_user_details'),
|
||||||
url(r'^password/change/$', PasswordChangeView.as_view(),
|
url(r'^password/change/$', PasswordChangeView.as_view(),
|
||||||
name='rest_password_change'),
|
name='rest_password_change'),
|
||||||
)
|
]
|
||||||
|
|
|
@ -11,7 +11,6 @@ def import_callable(path_or_callable):
|
||||||
return getattr(import_module(package), attr)
|
return getattr(import_module(package), attr)
|
||||||
|
|
||||||
|
|
||||||
def default_create_token(token_model, serializer):
|
def default_create_token(token_model, user, serializer):
|
||||||
user = serializer.validated_data['user']
|
|
||||||
token, _ = token_model.objects.get_or_create(user=user)
|
token, _ = token_model.objects.get_or_create(user=user)
|
||||||
return token
|
return token
|
||||||
|
|
|
@ -35,7 +35,7 @@ class LoginView(GenericAPIView):
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
self.user = self.serializer.validated_data['user']
|
self.user = self.serializer.validated_data['user']
|
||||||
self.token = create_token(self.token_model, self.serializer)
|
self.token = create_token(self.token_model, self.user, self.serializer)
|
||||||
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
||||||
login(self.request, self.user)
|
login(self.request, self.user)
|
||||||
|
|
||||||
|
|
7
setup.py
7
setup.py
|
@ -32,6 +32,13 @@ setup(
|
||||||
'djangorestframework>=3.1.0',
|
'djangorestframework>=3.1.0',
|
||||||
'six>=1.9.0',
|
'six>=1.9.0',
|
||||||
],
|
],
|
||||||
|
extras_require={
|
||||||
|
'with_social': ['django-allauth>=0.24.1'],
|
||||||
|
},
|
||||||
|
tests_require=[
|
||||||
|
'responses>=0.5.0',
|
||||||
|
'django-allauth>=0.24.1',
|
||||||
|
],
|
||||||
test_suite='runtests.runtests',
|
test_suite='runtests.runtests',
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
# cmdclass={},
|
# cmdclass={},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user