mirror of
				https://github.com/Tivix/django-rest-auth.git
				synced 2025-11-04 01:27:36 +03:00 
			
		
		
		
	Merge branch 'development' of https://github.com/philippeluickx/django-rest-auth into philippeluickx-development
This commit is contained in:
		
						commit
						1b667fa4ab
					
				| 
						 | 
					@ -73,3 +73,4 @@ Basing on example from installation section :doc:`Installation </installation>`
 | 
				
			||||||
- /rest-auth/facebook/ (POST)
 | 
					- /rest-auth/facebook/ (POST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - access_token
 | 
					    - access_token
 | 
				
			||||||
 | 
					    - code
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,17 +6,17 @@ Configuration
 | 
				
			||||||
    You can define your custom serializers for each endpoint without overriding urls and views by adding ``REST_AUTH_SERIALIZERS`` dictionary in your django settings.
 | 
					    You can define your custom serializers for each endpoint without overriding urls and views by adding ``REST_AUTH_SERIALIZERS`` dictionary in your django settings.
 | 
				
			||||||
    Possible key values:
 | 
					    Possible key values:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - LOGIN_SERIALIZER - serializer class in ``rest_auth.views.Login``, default value ``rest_auth.serializers.LoginSerializer``
 | 
					        - LOGIN_SERIALIZER - serializer class in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.LoginSerializer``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - TOKEN_SERIALIZER - response for successful authentication in ``rest_auth.views.Login``, default value ``rest_auth.serializers.TokenSerializer``
 | 
					        - TOKEN_SERIALIZER - response for successful authentication in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.TokenSerializer``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - USER_DETAILS_SERIALIZER - serializer class in ``rest_auth.views.UserDetails``, default value ``rest_auth.serializers.UserDetailsSerializer``
 | 
					        - USER_DETAILS_SERIALIZER - serializer class in ``rest_auth.views.UserDetailsView``, default value ``rest_auth.serializers.UserDetailsSerializer``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - PASSWORD_RESET_SERIALIZER - serializer class in ``rest_auth.views.PasswordReset``, default value ``rest_auth.serializers.PasswordResetSerializer``
 | 
					        - PASSWORD_RESET_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetView``, default value ``rest_auth.serializers.PasswordResetSerializer``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetConfirm``, default value ``rest_auth.serializers.PasswordResetConfirmSerializer``
 | 
					        - PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetConfirmView``, default value ``rest_auth.serializers.PasswordResetConfirmSerializer``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - PASSWORD_CHANGE_SERIALIZER - serializer class in ``rest_auth.views.PasswordChange``, default value ``rest_auth.serializers.PasswordChangeSerializer``
 | 
					        - PASSWORD_CHANGE_SERIALIZER - serializer class in ``rest_auth.views.PasswordChangeView``, default value ``rest_auth.serializers.PasswordChangeSerializer``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Example configuration:
 | 
					    Example configuration:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ FAQ
 | 
				
			||||||
            # custom fields for user
 | 
					            # custom fields for user
 | 
				
			||||||
            company_name = models.CharField(max_length=100)
 | 
					            company_name = models.CharField(max_length=100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    To allow update user details within one request send to rest_auth.views.UserDetails view, create serializer like this:
 | 
					    To allow update user details within one request send to rest_auth.views.UserDetailsView view, create serializer like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .. code-block:: python
 | 
					    .. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,14 +91,14 @@ Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creati
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3. Add Social Application in django admin panel
 | 
					3. Add Social Application in django admin panel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4. Create new view as a subclass of ``rest_auth.registration.views.SocialLogin`` with ``FacebookOAuth2Adapter`` adapter as an attribute:
 | 
					4. Create new view as a subclass of ``rest_auth.registration.views.SocialLoginView`` with ``FacebookOAuth2Adapter`` adapter as an attribute:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
					    from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
				
			||||||
    from rest_auth.registration.views import SocialLogin
 | 
					    from rest_auth.registration.views import SocialLoginView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class FacebookLogin(SocialLogin):
 | 
					    class FacebookLogin(SocialLoginView):
 | 
				
			||||||
        adapter_class = FacebookOAuth2Adapter
 | 
					        adapter_class = FacebookOAuth2Adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
5. Create url for FacebookLogin view:
 | 
					5. Create url for FacebookLogin view:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,40 +1,99 @@
 | 
				
			||||||
from django.http import HttpRequest
 | 
					from django.http import HttpRequest
 | 
				
			||||||
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
 | 
				
			||||||
 | 
					# case the allauth.socialaccount will be declared
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
    from allauth.socialaccount.helpers import complete_social_login
 | 
					    from allauth.socialaccount.helpers import complete_social_login
 | 
				
			||||||
 | 
					except ImportError:
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SocialLoginSerializer(serializers.Serializer):
 | 
					class SocialLoginSerializer(serializers.Serializer):
 | 
				
			||||||
 | 
					    access_token = serializers.CharField(required=False)
 | 
				
			||||||
 | 
					    code = serializers.CharField(required=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    access_token = serializers.CharField(required=True)
 | 
					    def _get_request(self):
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def validate(self, attrs):
 | 
					 | 
				
			||||||
        access_token = attrs.get('access_token')
 | 
					 | 
				
			||||||
        view = self.context.get('view')
 | 
					 | 
				
			||||||
        request = self.context.get('request')
 | 
					        request = self.context.get('request')
 | 
				
			||||||
        if not isinstance(request, HttpRequest):
 | 
					        if not isinstance(request, HttpRequest):
 | 
				
			||||||
            request = request._request
 | 
					            request = request._request
 | 
				
			||||||
 | 
					        return request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_social_login(self, adapter, app, token, response):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param adapter: allauth.socialaccount Adapter subclass. Usually OAuthAdapter or Auth2Adapter
 | 
				
			||||||
 | 
					        :param app: `allauth.socialaccount.SocialApp` instance
 | 
				
			||||||
 | 
					        :param token: `allauth.socialaccount.SocialToken` instance
 | 
				
			||||||
 | 
					        :param response: Provider's response for OAuth1. Not used in the
 | 
				
			||||||
 | 
					        :return: :return: A populated instance of the `allauth.socialaccount.SocialLoginView` instance
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        request = self._get_request()
 | 
				
			||||||
 | 
					        social_login = adapter.complete_login(request, app, token, response=response)
 | 
				
			||||||
 | 
					        social_login.token = token
 | 
				
			||||||
 | 
					        return social_login
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def validate(self, attrs):
 | 
				
			||||||
 | 
					        view = self.context.get('view')
 | 
				
			||||||
 | 
					        request = self._get_request()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not view:
 | 
					        if not view:
 | 
				
			||||||
            raise serializers.ValidationError(
 | 
					            raise serializers.ValidationError(
 | 
				
			||||||
                'View is not defined, pass it as a context variable'
 | 
					                'View is not defined, pass it as a context variable'
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.adapter_class = getattr(view, 'adapter_class', None)
 | 
					        adapter_class = getattr(view, 'adapter_class', None)
 | 
				
			||||||
 | 
					        if not adapter_class:
 | 
				
			||||||
        if not self.adapter_class:
 | 
					 | 
				
			||||||
            raise serializers.ValidationError('Define adapter_class in view')
 | 
					            raise serializers.ValidationError('Define adapter_class in view')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.adapter = self.adapter_class()
 | 
					        adapter = adapter_class()
 | 
				
			||||||
        app = self.adapter.get_provider().get_app(request)
 | 
					        app = adapter.get_provider().get_app(request)
 | 
				
			||||||
        token = self.adapter.parse_token({'access_token': access_token})
 | 
					
 | 
				
			||||||
 | 
					        # More info on code vs access_token
 | 
				
			||||||
 | 
					        # http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Case 1: We received the access_token
 | 
				
			||||||
 | 
					        if('access_token' in attrs):
 | 
				
			||||||
 | 
					            access_token = attrs.get('access_token')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Case 2: We received the authorization code
 | 
				
			||||||
 | 
					        elif('code' in attrs):
 | 
				
			||||||
 | 
					            self.callback_url = getattr(view, 'callback_url', None)
 | 
				
			||||||
 | 
					            self.client_class = getattr(view, 'client_class', None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if not self.callback_url:
 | 
				
			||||||
 | 
					                raise serializers.ValidationError(
 | 
				
			||||||
 | 
					                    'Define callback_url in view'
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            if not self.client_class:
 | 
				
			||||||
 | 
					                raise serializers.ValidationError(
 | 
				
			||||||
 | 
					                    'Define client_class in view'
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            code = attrs.get('code')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            provider = adapter.get_provider()
 | 
				
			||||||
 | 
					            scope = provider.get_scope(request)
 | 
				
			||||||
 | 
					            client = self.client_class(
 | 
				
			||||||
 | 
					                request,
 | 
				
			||||||
 | 
					                app.client_id,
 | 
				
			||||||
 | 
					                app.secret,
 | 
				
			||||||
 | 
					                adapter.access_token_method,
 | 
				
			||||||
 | 
					                adapter.access_token_url,
 | 
				
			||||||
 | 
					                self.callback_url,
 | 
				
			||||||
 | 
					                scope
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            token = client.get_access_token(code)
 | 
				
			||||||
 | 
					            access_token = token['access_token']
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            raise serializers.ValidationError('Incorrect input. access_token or code is required.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        token = adapter.parse_token({'access_token': access_token})
 | 
				
			||||||
        token.app = app
 | 
					        token.app = app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            login = self.adapter.complete_login(request, app, token,
 | 
					            login = self.get_social_login(adapter, app, token, access_token)
 | 
				
			||||||
                                                response=access_token)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            login.token = token
 | 
					 | 
				
			||||||
            complete_social_login(request, login)
 | 
					            complete_social_login(request, login)
 | 
				
			||||||
        except HTTPError:
 | 
					        except HTTPError:
 | 
				
			||||||
            raise serializers.ValidationError('Incorrect value')
 | 
					            raise serializers.ValidationError('Incorrect value')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
from django.views.generic import TemplateView
 | 
					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 RegisterView, VerifyEmailView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = patterns(
 | 
					urlpatterns = patterns(
 | 
				
			||||||
    '',
 | 
					    '',
 | 
				
			||||||
    url(r'^$', Register.as_view(), name='rest_register'),
 | 
					    url(r'^$', RegisterView.as_view(), name='rest_register'),
 | 
				
			||||||
    url(r'^verify-email/$', VerifyEmail.as_view(), name='rest_verify_email'),
 | 
					    url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # This url is used by django-allauth and empty TemplateView is
 | 
					    # This url is used by django-allauth and empty TemplateView is
 | 
				
			||||||
    # defined just to allow reverse() call inside app, for example when email
 | 
					    # defined just to allow reverse() call inside app, for example when email
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,21 +3,32 @@ 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 import status
 | 
					from rest_framework import status
 | 
				
			||||||
 | 
					from rest_framework.authtoken.models import Token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from allauth.account.views import SignupView, ConfirmEmailView
 | 
					from allauth.account.views import SignupView, 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from rest_auth.app_settings import UserDetailsSerializer
 | 
					from rest_auth.app_settings import UserDetailsSerializer, TokenSerializer
 | 
				
			||||||
from rest_auth.registration.serializers import SocialLoginSerializer
 | 
					from rest_auth.registration.serializers import SocialLoginSerializer
 | 
				
			||||||
from rest_auth.views import Login
 | 
					from rest_auth.views import LoginView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Register(APIView, SignupView):
 | 
					class RegisterView(APIView, SignupView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    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,)
 | 
				
			||||||
    user_serializer_class = UserDetailsSerializer
 | 
					 | 
				
			||||||
    allowed_methods = ('POST', 'OPTIONS', 'HEAD')
 | 
					    allowed_methods = ('POST', 'OPTIONS', 'HEAD')
 | 
				
			||||||
 | 
					    token_model = Token
 | 
				
			||||||
 | 
					    serializer_class = TokenSerializer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get(self, *args, **kwargs):
 | 
					    def get(self, *args, **kwargs):
 | 
				
			||||||
        return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
					        return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
				
			||||||
| 
						 | 
					@ -27,6 +38,9 @@ class Register(APIView, SignupView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def form_valid(self, form):
 | 
					    def form_valid(self, form):
 | 
				
			||||||
        self.user = form.save(self.request)
 | 
					        self.user = form.save(self.request)
 | 
				
			||||||
 | 
					        self.token, created = self.token_model.objects.get_or_create(
 | 
				
			||||||
 | 
					            user=self.user
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
        if isinstance(self.request, HttpRequest):
 | 
					        if isinstance(self.request, HttpRequest):
 | 
				
			||||||
            request = self.request
 | 
					            request = self.request
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
| 
						 | 
					@ -47,14 +61,15 @@ class Register(APIView, SignupView):
 | 
				
			||||||
            return self.get_response_with_errors()
 | 
					            return self.get_response_with_errors()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_response(self):
 | 
					    def get_response(self):
 | 
				
			||||||
        serializer = self.user_serializer_class(instance=self.user)
 | 
					        # serializer = self.user_serializer_class(instance=self.user)
 | 
				
			||||||
 | 
					        serializer = self.serializer_class(instance=self.token)
 | 
				
			||||||
        return Response(serializer.data, status=status.HTTP_201_CREATED)
 | 
					        return Response(serializer.data, status=status.HTTP_201_CREATED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_response_with_errors(self):
 | 
					    def get_response_with_errors(self):
 | 
				
			||||||
        return Response(self.form.errors, status=status.HTTP_400_BAD_REQUEST)
 | 
					        return Response(self.form.errors, status=status.HTTP_400_BAD_REQUEST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VerifyEmail(APIView, ConfirmEmailView):
 | 
					class VerifyEmailView(APIView, ConfirmEmailView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    permission_classes = (AllowAny,)
 | 
					    permission_classes = (AllowAny,)
 | 
				
			||||||
    allowed_methods = ('POST', 'OPTIONS', 'HEAD')
 | 
					    allowed_methods = ('POST', 'OPTIONS', 'HEAD')
 | 
				
			||||||
| 
						 | 
					@ -69,14 +84,28 @@ class VerifyEmail(APIView, ConfirmEmailView):
 | 
				
			||||||
        return Response({'message': 'ok'}, status=status.HTTP_200_OK)
 | 
					        return Response({'message': 'ok'}, status=status.HTTP_200_OK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SocialLogin(Login):
 | 
					class SocialLoginView(LoginView):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    class used for social authentications
 | 
					    class used for social authentications
 | 
				
			||||||
    example usage for facebook
 | 
					    example usage for facebook with access_token
 | 
				
			||||||
 | 
					    -------------
 | 
				
			||||||
    from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
					    from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
				
			||||||
    class FacebookLogin(SocialLogin):
 | 
					
 | 
				
			||||||
 | 
					    class FacebookLogin(SocialLoginView):
 | 
				
			||||||
        adapter_class = FacebookOAuth2Adapter
 | 
					        adapter_class = FacebookOAuth2Adapter
 | 
				
			||||||
 | 
					    -------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    example usage for facebook with code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    -------------
 | 
				
			||||||
 | 
					    from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
				
			||||||
 | 
					    from allauth.socialaccount.providers.oauth2.client import OAuth2Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class FacebookLogin(SocialLoginView):
 | 
				
			||||||
 | 
					        adapter_class = FacebookOAuth2Adapter
 | 
				
			||||||
 | 
					         client_class = OAuth2Client
 | 
				
			||||||
 | 
					         callback_url = 'localhost:8000'
 | 
				
			||||||
 | 
					    -------------
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serializer_class = SocialLoginSerializer
 | 
					    serializer_class = SocialLoginSerializer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
from django.contrib.auth import get_user_model
 | 
					from django.contrib.auth import get_user_model, authenticate
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm
 | 
					from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
| 
						 | 
					@ -7,24 +7,75 @@ except:
 | 
				
			||||||
    # make compatible with django 1.5
 | 
					    # make compatible with django 1.5
 | 
				
			||||||
    from django.utils.http import base36_to_int as uid_decoder
 | 
					    from django.utils.http import base36_to_int as uid_decoder
 | 
				
			||||||
from django.contrib.auth.tokens import default_token_generator
 | 
					from django.contrib.auth.tokens import default_token_generator
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from rest_framework import serializers
 | 
					from rest_framework import serializers, exceptions
 | 
				
			||||||
from rest_framework.authtoken.models import Token
 | 
					from rest_framework.authtoken.models import Token
 | 
				
			||||||
from rest_framework.authtoken.serializers import AuthTokenSerializer
 | 
					from rest_framework.authtoken.serializers import AuthTokenSerializer
 | 
				
			||||||
from rest_framework.exceptions import ValidationError
 | 
					from rest_framework.exceptions import ValidationError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LoginSerializer(AuthTokenSerializer):
 | 
					class LoginSerializer(serializers.Serializer):
 | 
				
			||||||
 | 
					    username = serializers.CharField(required=False)
 | 
				
			||||||
 | 
					    email = serializers.EmailField(required=False)
 | 
				
			||||||
 | 
					    password = serializers.CharField(style={'input_type': 'password'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def validate(self, attrs):
 | 
					    def validate(self, attrs):
 | 
				
			||||||
        attrs = super(LoginSerializer, self).validate(attrs)
 | 
					        username = attrs.get('username')
 | 
				
			||||||
 | 
					        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:
 | 
				
			||||||
 | 
					                    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:
 | 
				
			||||||
 | 
					                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:
 | 
				
			||||||
 | 
					                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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif username and password:
 | 
				
			||||||
 | 
					            user = authenticate(username=username, password=password)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            msg = _('Must include "username" and "password".')
 | 
				
			||||||
 | 
					            raise exceptions.ValidationError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Did we get back an active user?
 | 
				
			||||||
 | 
					        if user:
 | 
				
			||||||
 | 
					            if not user.is_active:
 | 
				
			||||||
 | 
					                msg = _('User account is disabled.')
 | 
				
			||||||
 | 
					                raise exceptions.ValidationError(msg)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            msg = _('Unable to log in with provided credentials.')
 | 
				
			||||||
 | 
					            raise exceptions.ValidationError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If required, is the email verified?
 | 
				
			||||||
        if 'rest_auth.registration' in settings.INSTALLED_APPS:
 | 
					        if 'rest_auth.registration' in settings.INSTALLED_APPS:
 | 
				
			||||||
            from allauth.account import app_settings
 | 
					            from allauth.account import app_settings
 | 
				
			||||||
            if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY:
 | 
					            if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY:
 | 
				
			||||||
                user = attrs['user']
 | 
					 | 
				
			||||||
                email_address = user.emailaddress_set.get(email=user.email)
 | 
					                email_address = user.emailaddress_set.get(email=user.email)
 | 
				
			||||||
                if not email_address.verified:
 | 
					                if not email_address.verified:
 | 
				
			||||||
                    raise serializers.ValidationError('E-mail is not verified.')
 | 
					                    raise serializers.ValidationError('E-mail is not verified.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        attrs['user'] = user
 | 
				
			||||||
        return attrs
 | 
					        return attrs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,10 +5,10 @@ import rest_auth.django_test_urls
 | 
				
			||||||
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
					from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from rest_auth.urls import urlpatterns
 | 
					from rest_auth.urls import urlpatterns
 | 
				
			||||||
from rest_auth.registration.views import SocialLogin
 | 
					from rest_auth.registration.views import SocialLoginView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FacebookLogin(SocialLogin):
 | 
					class FacebookLogin(SocialLoginView):
 | 
				
			||||||
    adapter_class = FacebookOAuth2Adapter
 | 
					    adapter_class = FacebookOAuth2Adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns += patterns(
 | 
					urlpatterns += patterns(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +1,21 @@
 | 
				
			||||||
from django.conf.urls import patterns, url
 | 
					from django.conf.urls import patterns, url
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from rest_auth.views import (
 | 
					from rest_auth.views import (
 | 
				
			||||||
    Login, Logout, UserDetails, PasswordChange,
 | 
					    LoginView, LogoutView, UserDetailsView, PasswordChangeView,
 | 
				
			||||||
    PasswordReset, PasswordResetConfirm
 | 
					    PasswordResetView, PasswordResetConfirmView
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = patterns(
 | 
					urlpatterns = patterns(
 | 
				
			||||||
    '',
 | 
					    '',
 | 
				
			||||||
    # URLs that do not require a session or valid token
 | 
					    # URLs that do not require a session or valid token
 | 
				
			||||||
    url(r'^password/reset/$', PasswordReset.as_view(),
 | 
					    url(r'^password/reset/$', PasswordResetView.as_view(),
 | 
				
			||||||
        name='rest_password_reset'),
 | 
					        name='rest_password_reset'),
 | 
				
			||||||
    url(r'^password/reset/confirm/$', PasswordResetConfirm.as_view(),
 | 
					    url(r'^password/reset/confirm/$', PasswordResetConfirmView.as_view(),
 | 
				
			||||||
        name='rest_password_reset_confirm'),
 | 
					        name='rest_password_reset_confirm'),
 | 
				
			||||||
    url(r'^login/$', Login.as_view(), name='rest_login'),
 | 
					    url(r'^login/$', LoginView.as_view(), name='rest_login'),
 | 
				
			||||||
    # URLs that require a user to be logged in with a valid session / token.
 | 
					    # URLs that require a user to be logged in with a valid session / token.
 | 
				
			||||||
    url(r'^logout/$', Logout.as_view(), name='rest_logout'),
 | 
					    url(r'^logout/$', LogoutView.as_view(), name='rest_logout'),
 | 
				
			||||||
    url(r'^user/$', UserDetails.as_view(), name='rest_user_details'),
 | 
					    url(r'^user/$', UserDetailsView.as_view(), name='rest_user_details'),
 | 
				
			||||||
    url(r'^password/change/$', PasswordChange.as_view(),
 | 
					    url(r'^password/change/$', PasswordChangeView.as_view(),
 | 
				
			||||||
        name='rest_password_change'),
 | 
					        name='rest_password_change'),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ from .app_settings import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Login(GenericAPIView):
 | 
					class LoginView(GenericAPIView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Check the credentials and return the REST Token
 | 
					    Check the credentials and return the REST Token
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ class Login(GenericAPIView):
 | 
				
			||||||
        return self.get_response()
 | 
					        return self.get_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Logout(APIView):
 | 
					class LogoutView(APIView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Calls Django logout method and delete the Token object
 | 
					    Calls Django logout method and delete the Token object
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ class Logout(APIView):
 | 
				
			||||||
                        status=status.HTTP_200_OK)
 | 
					                        status=status.HTTP_200_OK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UserDetails(RetrieveUpdateAPIView):
 | 
					class UserDetailsView(RetrieveUpdateAPIView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Returns User's details in JSON format.
 | 
					    Returns User's details in JSON format.
 | 
				
			||||||
| 
						 | 
					@ -97,7 +97,7 @@ class UserDetails(RetrieveUpdateAPIView):
 | 
				
			||||||
        return self.request.user
 | 
					        return self.request.user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordReset(GenericAPIView):
 | 
					class PasswordResetView(GenericAPIView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Calls Django Auth PasswordResetForm save method.
 | 
					    Calls Django Auth PasswordResetForm save method.
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,7 @@ class PasswordReset(GenericAPIView):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordResetConfirm(GenericAPIView):
 | 
					class PasswordResetConfirmView(GenericAPIView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Password reset e-mail link is confirmed, therefore this resets the user's password.
 | 
					    Password reset e-mail link is confirmed, therefore this resets the user's password.
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ class PasswordResetConfirm(GenericAPIView):
 | 
				
			||||||
        return Response({"success": "Password has been reset with the new password."})
 | 
					        return Response({"success": "Password has been reset with the new password."})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordChange(GenericAPIView):
 | 
					class PasswordChangeView(GenericAPIView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Calls Django Auth SetPasswordForm save method.
 | 
					    Calls Django Auth SetPasswordForm save method.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user