mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2025-04-21 17:22:06 +03:00
Merge ad61169dfa
into beb073f35f
This commit is contained in:
commit
c5bc4255d7
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -55,3 +55,8 @@ db.sqlite3
|
|||
|
||||
# IntelliJ IDE files
|
||||
.idea
|
||||
|
||||
# Virtual Environments
|
||||
.vagrant/
|
||||
cookbooks/
|
||||
tmp/
|
||||
|
|
|
@ -4,77 +4,139 @@ API endpoints
|
|||
Basic
|
||||
-----
|
||||
|
||||
- /rest-auth/login/ (POST)
|
||||
Typically, auth data is sent in the body, with a header ``Content-Type: application/x-www-form-urlencoded``
|
||||
|
||||
- username
|
||||
- email
|
||||
- password
|
||||
/rest-auth/login/ (POST)
|
||||
************************
|
||||
**Request (standalone):**
|
||||
|
||||
Returns Token key
|
||||
- ``username`` or ``email`` (email will be used to lookup username)
|
||||
- ``password`` (required)
|
||||
|
||||
- /rest-auth/logout/ (POST)
|
||||
**Request (using django-allauth):**
|
||||
|
||||
.. note:: ``ACCOUNT_LOGOUT_ON_GET = True`` to allow logout using GET - this is the exact same configuration from allauth. NOT recommended, see: http://django-allauth.readthedocs.io/en/latest/views.html#logout
|
||||
- ``username`` (required when ``ACCOUNT_AUTHENTICATION_METHOD = 'username'`` or ``'username_email'``)
|
||||
- ``email`` (required when ``ACCOUNT_AUTHENTICATION_METHOD = 'email'`` or ``'username_email'``)
|
||||
- ``password`` (required)
|
||||
|
||||
- /rest-auth/password/reset/ (POST)
|
||||
**Response:**
|
||||
|
||||
- email
|
||||
- ``token``
|
||||
- ``user`` (when using django-rest-framework-jwt or django-rest-knox)
|
||||
|
||||
- /rest-auth/password/reset/confirm/ (POST)
|
||||
/rest-auth/logout/ (POST)
|
||||
*************************
|
||||
|
||||
**Request (standalone):**
|
||||
|
||||
- uid
|
||||
- token
|
||||
- new_password1
|
||||
- new_password2
|
||||
- No values expected
|
||||
|
||||
.. note:: uid and token are sent in email after calling /rest-auth/password/reset/
|
||||
**Request (using django-rest-knox):**
|
||||
|
||||
- /rest-auth/password/change/ (POST)
|
||||
- ``Authorization: Token TOKEN`` *(Header)*
|
||||
|
||||
- new_password1
|
||||
- new_password2
|
||||
- old_password
|
||||
**Response:**
|
||||
|
||||
.. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password.
|
||||
.. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change
|
||||
- No values
|
||||
|
||||
- /rest-auth/user/ (GET, PUT, PATCH)
|
||||
.. note:: ``ACCOUNT_LOGOUT_ON_GET = True`` to allow logout using GET - this is the exact same configuration from allauth. NOT recommended, see: http://django-allauth.readthedocs.io/en/latest/views.html#logout
|
||||
|
||||
- username
|
||||
- first_name
|
||||
- last_name
|
||||
/rest-auth/logoutall/ (POST)
|
||||
****************************
|
||||
|
||||
Returns pk, username, email, first_name, last_name
|
||||
This endpoint deletes all Knox tokens, and will only be loaded when `REST_USE_KNOX = True`.
|
||||
|
||||
| **Request (using django-rest-knox):**
|
||||
|
||||
- `Authorization`: `Token TOKEN` (Header)
|
||||
|
||||
**Response:**
|
||||
|
||||
- No values
|
||||
|
||||
.. note:: ``ACCOUNT_LOGOUT_ON_GET = True`` to allow logout using GET - this is the exact same configuration from allauth. NOT recommended, see: http://django-allauth.readthedocs.io/en/latest/views.html#logout
|
||||
|
||||
/rest-auth/password/reset/ (POST)
|
||||
*********************************
|
||||
|
||||
- email
|
||||
|
||||
/rest-auth/password/reset/confirm/ (POST)
|
||||
*****************************************
|
||||
|
||||
- uid
|
||||
- token
|
||||
- new_password1
|
||||
- new_password2
|
||||
|
||||
.. note:: uid and token are sent in email after calling /rest-auth/password/reset/
|
||||
|
||||
/rest-auth/password/change/ (POST)
|
||||
**********************************
|
||||
- new_password1
|
||||
- new_password2
|
||||
- old_password
|
||||
|
||||
.. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password.
|
||||
.. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change
|
||||
|
||||
/rest-auth/user/ (GET, PUT, PATCH)
|
||||
**********************************
|
||||
- username
|
||||
- first_name
|
||||
- last_name
|
||||
|
||||
Returns pk, username, email, first_name, last_name
|
||||
|
||||
|
||||
Registration
|
||||
------------
|
||||
|
||||
- /rest-auth/registration/ (POST)
|
||||
/rest-auth/registration/ (POST)
|
||||
*******************************
|
||||
|
||||
- username
|
||||
- password1
|
||||
- password2
|
||||
- email
|
||||
**Request (using django-allauth):**
|
||||
|
||||
- /rest-auth/registration/verify-email/ (POST)
|
||||
- ``username`` (required when ``ACCOUNT_AUTHENTICATION_METHOD = 'username'`` or ``'username_email'``, or when ``ACCOUNT_USERNAME_REQUIRED = True``)
|
||||
- ``email`` (required when ``ACCOUNT_AUTHENTICATION_METHOD = 'email'`` or ``'username_email'``, or when ``ACCOUNT_EMAIL_REQUIRED = True``)
|
||||
- ``password1`` (required)
|
||||
- ``password2`` (required)
|
||||
|
||||
- key
|
||||
**Response (using django-allauth):**
|
||||
|
||||
- No values
|
||||
|
||||
**Response (using django-allauth and django-rest-knox)**
|
||||
|
||||
- ``token``
|
||||
- ``user``
|
||||
|
||||
/rest-auth/registration/verify-email/ (POST)
|
||||
********************************************
|
||||
|
||||
**Request (using django-allauth):**
|
||||
|
||||
- ``key``
|
||||
|
||||
**Response (using django-allauth):**
|
||||
|
||||
- No values
|
||||
|
||||
Social Media Authentication
|
||||
---------------------------
|
||||
|
||||
Basing on example from installation section :doc:`Installation </installation>`
|
||||
Based on the example from the installation section :doc:`Installation </installation>`
|
||||
|
||||
- /rest-auth/facebook/ (POST)
|
||||
/rest-auth/facebook/ (POST)
|
||||
***************************
|
||||
|
||||
- access_token
|
||||
- code
|
||||
- ``access_token``
|
||||
- ``code``
|
||||
|
||||
.. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/registration/views.py
|
||||
|
||||
- /rest-auth/twitter/ (POST)
|
||||
/rest-auth/twitter/ (POST)
|
||||
**************************
|
||||
|
||||
- access_token
|
||||
- token_secret
|
||||
- ``access_token``
|
||||
- ``token_secret``
|
||||
|
|
|
@ -12,6 +12,8 @@ Configuration
|
|||
|
||||
- JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.JWTSerializer``
|
||||
|
||||
- KNOX_SERIALIZER - (Using REST_USE_KNOX=True) response for successful authentication in ``rest_auth.views.LoginView`` and successful registration in ``rest_auth.registration.views.RegisterView`` (using ``django-allauth`` and ``ACCOUNT_EMAIL_VERIFICATION = 'optional' or 'none'``), default value ``rest_auth.serializers.KnoxSerializer``
|
||||
|
||||
- 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.PasswordResetView``, default value ``rest_auth.serializers.PasswordResetSerializer``
|
||||
|
@ -48,6 +50,8 @@ Configuration
|
|||
|
||||
- **REST_USE_JWT** - Enable JWT Authentication instead of Token/Session based. This is built on top of django-rest-framework-jwt http://getblimp.github.io/django-rest-framework-jwt/, which must also be installed. (default: False)
|
||||
|
||||
- **REST_USE_KNOX** - Use Knox token authentication instead of the built-in Django-Rest-Framework token authentication. Knox makes some significant security improvements, and supports multiple tokens per user. https://github.com/James1345/django-rest-knox/ must be installed. Not compatible with ``REST_USE_JWT`` (default: False)
|
||||
|
||||
- **OLD_PASSWORD_FIELD_ENABLED** - set it to True if you want to have old password verification on password change enpoint (default: False)
|
||||
|
||||
- **LOGOUT_ON_PASSWORD_CHANGE** - set to False if you want to keep the current user logged in after a password change
|
||||
- **LOGOUT_ON_PASSWORD_CHANGE** - set to False if you want to keep the current user logged in after a password change (default: False)
|
||||
|
|
|
@ -153,7 +153,7 @@ JWT Support (optional)
|
|||
|
||||
By default, ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, you need to install the following:
|
||||
|
||||
1. Install ``django-rest-framework-jwt`` http://getblimp.github.io/django-rest-framework-jwt/ . Right now this is the only supported JWT library.
|
||||
1. Install ``django-rest-framework-jwt`` http://getblimp.github.io/django-rest-framework-jwt/ .
|
||||
|
||||
2. Add the following to your settings
|
||||
|
||||
|
@ -161,3 +161,19 @@ By default, ``django-rest-auth`` uses Django's Token-based authentication. If yo
|
|||
|
||||
REST_USE_JWT = True
|
||||
|
||||
|
||||
Knox (optional)
|
||||
---------------
|
||||
By default, ``django-rest-auth`` uses Django's Token-based authentication. ``django-rest-knox`` provides more secure token authentication with additional features, including multiple tokens per user.
|
||||
|
||||
Knox and JWT cannot currently be used simultaneously.
|
||||
|
||||
1. Install ``django-rest-knox`` https://james1345.github.io/django-rest-knox/installation/ .
|
||||
|
||||
2. Configure ``django-rest-knox`` https://james1345.github.io/django-rest-knox/settings/ . ``REST_KNOX['USER_SERIALIZER']`` will not be used.
|
||||
|
||||
3. Add the following to your settings
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
REST_USE_KNOX = True
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.conf import settings
|
|||
|
||||
from rest_auth.serializers import (
|
||||
TokenSerializer as DefaultTokenSerializer,
|
||||
KnoxSerializer as DefaultKnoxSerializer,
|
||||
JWTSerializer as DefaultJWTSerializer,
|
||||
UserDetailsSerializer as DefaultUserDetailsSerializer,
|
||||
LoginSerializer as DefaultLoginSerializer,
|
||||
|
@ -21,6 +22,9 @@ TokenSerializer = import_callable(
|
|||
JWTSerializer = import_callable(
|
||||
serializers.get('JWT_SERIALIZER', DefaultJWTSerializer))
|
||||
|
||||
KnoxSerializer = import_callable(
|
||||
serializers.get('KNOX_TOKEN_SERIALIZER', DefaultKnoxSerializer))
|
||||
|
||||
UserDetailsSerializer = import_callable(
|
||||
serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer)
|
||||
)
|
||||
|
|
|
@ -16,11 +16,12 @@ from allauth.account import app_settings as allauth_settings
|
|||
|
||||
from rest_auth.app_settings import (TokenSerializer,
|
||||
JWTSerializer,
|
||||
KnoxSerializer,
|
||||
create_token)
|
||||
from rest_auth.models import TokenModel
|
||||
from rest_auth.registration.serializers import (SocialLoginSerializer,
|
||||
VerifyEmailSerializer)
|
||||
from rest_auth.utils import jwt_encode
|
||||
from rest_auth.utils import create_knox_token, jwt_encode
|
||||
from rest_auth.views import LoginView
|
||||
from .app_settings import RegisterSerializer
|
||||
|
||||
|
@ -49,8 +50,14 @@ class RegisterView(CreateAPIView):
|
|||
'token': self.token
|
||||
}
|
||||
return JWTSerializer(data).data
|
||||
elif getattr(settings, 'REST_USE_KNOX', False):
|
||||
data = {
|
||||
'user': user,
|
||||
'token': self.token
|
||||
}
|
||||
return KnoxSerializer(data).data
|
||||
else:
|
||||
return TokenSerializer(user.auth_token).data
|
||||
return TokenSerializer(self.token).data
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
|
@ -65,9 +72,11 @@ class RegisterView(CreateAPIView):
|
|||
def perform_create(self, serializer):
|
||||
user = serializer.save(self.request)
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
self.token = jwt_encode(user)
|
||||
self.token = jwt_encode(user)
|
||||
elif getattr(settings, 'REST_USE_KNOX', False):
|
||||
self.token = create_knox_token(user)
|
||||
else:
|
||||
create_token(self.token_model, user, serializer)
|
||||
self.token = create_token(self.token_model, user, serializer)
|
||||
|
||||
complete_signup(self.request._request, user,
|
||||
allauth_settings.EMAIL_VERIFICATION,
|
||||
|
|
|
@ -114,7 +114,6 @@ class TokenSerializer(serializers.ModelSerializer):
|
|||
"""
|
||||
Serializer for Token model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = TokenModel
|
||||
fields = ('key',)
|
||||
|
@ -133,7 +132,7 @@ class UserDetailsSerializer(serializers.ModelSerializer):
|
|||
# Required to allow using custom USER_DETAILS_SERIALIZER in
|
||||
# JWTSerializer. Defining it here to avoid circular imports
|
||||
rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
|
||||
JWTUserDetailsSerializer = import_callable(
|
||||
CustomUserDetailsSerializer = import_callable(
|
||||
rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer)
|
||||
)
|
||||
|
||||
|
@ -143,7 +142,15 @@ class JWTSerializer(serializers.Serializer):
|
|||
Serializer for JWT authentication.
|
||||
"""
|
||||
token = serializers.CharField()
|
||||
user = JWTUserDetailsSerializer()
|
||||
user = CustomUserDetailsSerializer()
|
||||
|
||||
|
||||
class KnoxSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for Knox authentication.
|
||||
"""
|
||||
token = serializers.CharField()
|
||||
user = CustomUserDetailsSerializer()
|
||||
|
||||
|
||||
class PasswordResetSerializer(serializers.Serializer):
|
||||
|
|
|
@ -2,3 +2,4 @@ django-allauth>=0.19.1
|
|||
responses>=0.3.0
|
||||
flake8==2.4.0
|
||||
djangorestframework-jwt>=1.7.2
|
||||
django-rest-knox>=2.3.0
|
||||
|
|
|
@ -66,6 +66,15 @@ REST_FRAMEWORK = {
|
|||
)
|
||||
}
|
||||
|
||||
REST_FRAMEWORK_KNOX = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'knox.auth.TokenAuthentication',
|
||||
),
|
||||
'DEFAULT_PERMISSION_CLASSES': (
|
||||
'rest_framework.permissions.IsAuthenticated',
|
||||
),
|
||||
}
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
|
@ -88,7 +97,9 @@ INSTALLED_APPS = [
|
|||
'rest_auth',
|
||||
'rest_auth.registration',
|
||||
|
||||
'rest_framework_jwt'
|
||||
'rest_framework_jwt',
|
||||
|
||||
'knox'
|
||||
]
|
||||
|
||||
SECRET_KEY = "38dh*skf8sjfhs287dh&^hd8&3hdg*j2&sd"
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core import mail
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.six.moves import reload_module
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
from rest_framework import views as drf_views
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from allauth.account import app_settings as account_app_settings
|
||||
from knox.models import AuthToken
|
||||
|
||||
from .test_base import BaseAPITestCase
|
||||
from .settings import REST_FRAMEWORK_KNOX
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF="tests.urls")
|
||||
|
@ -148,6 +158,24 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
|||
self.assertEqual('token' in self.response.json.keys(), True)
|
||||
self.token = self.response.json['token']
|
||||
|
||||
@override_settings(REST_USE_KNOX=True, REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication')},)
|
||||
def test_login_knox(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.assertEqual('token' in self.response.json.keys(), True)
|
||||
self.token = self.response.json['token']
|
||||
self.assertEqual('user' in self.response.json.keys(), True)
|
||||
self.user = self.response.json['user']
|
||||
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.assertNotEqual(self.token, self.response.json['token'])
|
||||
|
||||
def test_login_by_email(self):
|
||||
# starting test without allauth app
|
||||
settings.INSTALLED_APPS.remove('allauth')
|
||||
|
@ -382,6 +410,21 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
|||
user = get_user_model().objects.get(pk=user.pk)
|
||||
self.assertEqual(user.email, self.response.json['email'])
|
||||
|
||||
@override_settings(REST_USE_KNOX=True, REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication')},)
|
||||
def test_user_details_using_knox(self):
|
||||
user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS)
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.token = self.response.json['token']
|
||||
self.get(self.user_url, status_code=200)
|
||||
self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200)
|
||||
user = get_user_model().objects.get(pk=user.pk)
|
||||
self.assertEqual(user.email, self.response.json['email'])
|
||||
|
||||
def test_registration(self):
|
||||
user_count = get_user_model().objects.all().count()
|
||||
|
||||
|
@ -411,6 +454,21 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
|||
self._login()
|
||||
self._logout()
|
||||
|
||||
@override_settings(REST_USE_KNOX=True, REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication')},)
|
||||
def test_registration_with_knox(self):
|
||||
user_count = get_user_model().objects.all().count()
|
||||
|
||||
self.post(self.register_url, data={}, status_code=400)
|
||||
|
||||
result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201)
|
||||
self.assertIn('token', result.data)
|
||||
self.assertIn('user', result.data)
|
||||
self.assertEqual(get_user_model().objects.all().count(), user_count + 1)
|
||||
|
||||
self._login()
|
||||
self._logout()
|
||||
|
||||
def test_registration_with_invalid_password(self):
|
||||
data = self.REGISTRATION_DATA.copy()
|
||||
data['password2'] = 'foobar'
|
||||
|
@ -493,3 +551,43 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
|||
|
||||
self.post(self.login_url, data=payload, status_code=status.HTTP_200_OK)
|
||||
self.get(self.logout_url, status_code=status.HTTP_405_METHOD_NOT_ALLOWED)
|
||||
|
||||
# @override_settings(REST_USE_KNOX=True, REST_FRAMEWORK = {
|
||||
# 'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication')},)
|
||||
def test_logout_knox(self):
|
||||
with override_settings(REST_USE_KNOX=True, REST_FRAMEWORK=REST_FRAMEWORK_KNOX):
|
||||
reload_module(drf_views)
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
|
||||
self.client = APIClient()
|
||||
|
||||
response = self.client.post(self.login_url, data=payload, status_code=status.HTTP_200_OK)
|
||||
self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % response.data['token']))
|
||||
self.client.post(self.logout_url, status_code=status.HTTP_200_OK)
|
||||
self.assertEqual(AuthToken.objects.count(), 0)
|
||||
reload_module(drf_views)
|
||||
|
||||
@override_settings(REST_USE_KNOX=True, REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication')},)
|
||||
def test_logout_all_knox(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
|
||||
self.logout_all_url = reverse('rest_logout_all')
|
||||
|
||||
self.client = APIClient()
|
||||
|
||||
self.client.post(self.login_url, data=payload, status_code=status.HTTP_200_OK)
|
||||
response = self.client.post(self.login_url, data=payload, status_code=status.HTTP_200_OK)
|
||||
self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % response.data['token']))
|
||||
self.client.post(self.logout_all_url, status_code=status.HTTP_200_OK)
|
||||
self.assertEqual(AuthToken.objects.count(), 0)
|
||||
|
|
|
@ -8,6 +8,7 @@ from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
|||
from rest_framework.decorators import api_view
|
||||
|
||||
from rest_auth.urls import urlpatterns
|
||||
from rest_auth.views import LogoutAllView
|
||||
from rest_auth.registration.views import SocialLoginView
|
||||
from rest_auth.social_serializers import TwitterLoginSerializer
|
||||
|
||||
|
@ -49,5 +50,6 @@ urlpatterns += [
|
|||
url(r'^social-login/twitter/$', TwitterLogin.as_view(), name='tw_login'),
|
||||
url(r'^social-login/twitter-no-view/$', twitter_login_view, name='tw_login_no_view'),
|
||||
url(r'^social-login/twitter-no-adapter/$', TwitterLoginNoAdapter.as_view(), name='tw_login_no_adapter'),
|
||||
url(r'^accounts/', include('allauth.socialaccount.urls'))
|
||||
url(r'^accounts/', include('allauth.socialaccount.urls')),
|
||||
url(r'^logoutall/$', LogoutAllView.as_view(), name='rest_logout_all'),
|
||||
]
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls import url
|
||||
|
||||
from rest_auth.views import (
|
||||
LoginView, LogoutView, UserDetailsView, PasswordChangeView,
|
||||
PasswordResetView, PasswordResetConfirmView
|
||||
LoginView, LogoutView, LogoutAllView, UserDetailsView,
|
||||
PasswordChangeView, PasswordResetView, PasswordResetConfirmView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -18,3 +19,8 @@ urlpatterns = [
|
|||
url(r'^password/change/$', PasswordChangeView.as_view(),
|
||||
name='rest_password_change'),
|
||||
]
|
||||
|
||||
if getattr(settings, 'REST_USE_KNOX', False):
|
||||
urlpatterns.append(
|
||||
url(r'^logoutall/$', LogoutAllView.as_view(), name='rest_logout_all')
|
||||
)
|
||||
|
|
|
@ -16,6 +16,15 @@ def default_create_token(token_model, user, serializer):
|
|||
return token
|
||||
|
||||
|
||||
def create_knox_token(user):
|
||||
try:
|
||||
from knox.models import AuthToken
|
||||
except ImportError:
|
||||
raise ImportError("django-rest-knox needs to be installed")
|
||||
token = AuthToken.objects.create(user=user)
|
||||
return token
|
||||
|
||||
|
||||
def jwt_encode(user):
|
||||
try:
|
||||
from rest_framework_jwt.settings import api_settings
|
||||
|
|
|
@ -16,12 +16,19 @@ from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
|
|||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
|
||||
from .app_settings import (
|
||||
TokenSerializer, UserDetailsSerializer, LoginSerializer,
|
||||
PasswordResetSerializer, PasswordResetConfirmSerializer,
|
||||
PasswordChangeSerializer, JWTSerializer, create_token
|
||||
TokenSerializer, KnoxSerializer, UserDetailsSerializer,
|
||||
LoginSerializer, PasswordResetSerializer,
|
||||
PasswordResetConfirmSerializer, PasswordChangeSerializer,
|
||||
JWTSerializer, create_token
|
||||
)
|
||||
from .models import TokenModel
|
||||
from .utils import jwt_encode
|
||||
from .utils import create_knox_token, jwt_encode
|
||||
|
||||
if getattr(settings, 'REST_USE_KNOX', False):
|
||||
try:
|
||||
from knox.auth import TokenAuthentication as KnoxTokenAuthentication
|
||||
except ImportError:
|
||||
raise ImportError("Install django-rest-knox to use REST_USE_KNOX = True")
|
||||
|
||||
sensitive_post_parameters_m = method_decorator(
|
||||
sensitive_post_parameters(
|
||||
|
@ -54,6 +61,8 @@ class LoginView(GenericAPIView):
|
|||
def get_response_serializer(self):
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
response_serializer = JWTSerializer
|
||||
elif getattr(settings, 'REST_USE_KNOX', False):
|
||||
response_serializer = KnoxSerializer
|
||||
else:
|
||||
response_serializer = TokenSerializer
|
||||
return response_serializer
|
||||
|
@ -63,6 +72,8 @@ class LoginView(GenericAPIView):
|
|||
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
self.token = jwt_encode(self.user)
|
||||
elif getattr(settings, 'REST_USE_KNOX', False):
|
||||
self.token = create_knox_token(self.user)
|
||||
else:
|
||||
self.token = create_token(self.token_model, self.user,
|
||||
self.serializer)
|
||||
|
@ -80,6 +91,13 @@ class LoginView(GenericAPIView):
|
|||
}
|
||||
serializer = serializer_class(instance=data,
|
||||
context={'request': self.request})
|
||||
elif getattr(settings, 'REST_USE_KNOX', False):
|
||||
data = {
|
||||
'user': self.user,
|
||||
'token': self.token
|
||||
}
|
||||
serializer = serializer_class(instance=data,
|
||||
context={'request': self.request})
|
||||
else:
|
||||
serializer = serializer_class(instance=self.token,
|
||||
context={'request': self.request})
|
||||
|
@ -102,7 +120,11 @@ class LogoutView(APIView):
|
|||
|
||||
Accepts/Returns nothing.
|
||||
"""
|
||||
permission_classes = (AllowAny,)
|
||||
if getattr(settings, 'REST_USE_KNOX', False):
|
||||
authentication_classes = (KnoxTokenAuthentication,)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
else:
|
||||
permission_classes = (AllowAny,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
|
||||
|
@ -117,7 +139,44 @@ class LogoutView(APIView):
|
|||
|
||||
def logout(self, request):
|
||||
try:
|
||||
request.user.auth_token.delete()
|
||||
if getattr(settings, 'REST_USE_KNOX', False):
|
||||
request._auth.delete()
|
||||
else:
|
||||
request.user.auth_token.delete()
|
||||
except (AttributeError, ObjectDoesNotExist):
|
||||
pass
|
||||
|
||||
django_logout(request)
|
||||
|
||||
return Response({"detail": _("Successfully logged out.")},
|
||||
status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class LogoutAllView(APIView):
|
||||
"""
|
||||
Calls Django logout method and deletes all the Knox tokens
|
||||
assigned to the current User object.
|
||||
|
||||
Accepts/Returns nothing.
|
||||
"""
|
||||
if getattr(settings, 'REST_USE_KNOX', False):
|
||||
authentication_classes = (KnoxTokenAuthentication,)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
|
||||
response = self.logout_all(request)
|
||||
else:
|
||||
response = self.http_method_not_allowed(request, *args, **kwargs)
|
||||
|
||||
return self.finalize_response(request, response, *args, **kwargs)
|
||||
|
||||
def post(self, request):
|
||||
return self.logout_all(request)
|
||||
|
||||
def logout_all(self, request):
|
||||
try:
|
||||
request.user.auth_token_set.all().delete()
|
||||
except (AttributeError, ObjectDoesNotExist):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user