mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-30 13:34:00 +03:00
Updates to login view for TokenAuthentication from feedback from Tom
This commit is contained in:
parent
063c027c7b
commit
8eb37e1f7e
|
@ -1,12 +1,8 @@
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.authtoken.models import Token
|
|
||||||
|
|
||||||
|
|
||||||
class AuthTokenSerializer(serializers.Serializer):
|
class AuthTokenSerializer(serializers.Serializer):
|
||||||
token = serializers.Field(source="key")
|
username = serializers.CharField()
|
||||||
username = serializers.CharField(max_length=30)
|
|
||||||
password = serializers.CharField()
|
password = serializers.CharField()
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
@ -26,12 +22,3 @@ class AuthTokenSerializer(serializers.Serializer):
|
||||||
else:
|
else:
|
||||||
raise serializers.ValidationError('Must include "username" and "password"')
|
raise serializers.ValidationError('Must include "username" and "password"')
|
||||||
|
|
||||||
def convert_object(self, obj):
|
|
||||||
ret = self._dict_class()
|
|
||||||
ret['token'] = obj.key
|
|
||||||
ret['user'] = obj.user.id
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def restore_object(self, attrs, instance=None):
|
|
||||||
token, created = Token.objects.get_or_create(user=attrs['user'])
|
|
||||||
return token
|
|
||||||
|
|
|
@ -13,9 +13,8 @@ your authentication settings include `TokenAuthentication`.
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
from django.conf.urls.defaults import patterns, url
|
from django.conf.urls.defaults import patterns, url
|
||||||
from rest_framework.authtoken.views import AuthTokenLoginView, AuthTokenLogoutView
|
from rest_framework.authtoken.views import AuthTokenView
|
||||||
|
|
||||||
urlpatterns = patterns('rest_framework.authtoken.views',
|
urlpatterns = patterns('rest_framework.authtoken.views',
|
||||||
url(r'^login/$', AuthTokenLoginView.as_view(), name='token_login'),
|
url(r'^login/$', AuthTokenView.as_view(), name='token_login'),
|
||||||
url(r'^logout/$', AuthTokenLogoutView.as_view(), name='token_logout'),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.generics import CreateAPIView
|
from rest_framework import status
|
||||||
|
from rest_framework import parsers
|
||||||
|
from rest_framework import renderers
|
||||||
|
from rest_framework.response import Response
|
||||||
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 django.http import HttpResponse
|
|
||||||
|
|
||||||
class AuthTokenLoginView(CreateAPIView):
|
class AuthTokenView(APIView):
|
||||||
|
throttle_classes = ()
|
||||||
|
permission_classes = ()
|
||||||
|
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
||||||
|
renderer_classes = (renderers.JSONRenderer,)
|
||||||
model = Token
|
model = Token
|
||||||
serializer_class = AuthTokenSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class AuthTokenLogoutView(APIView):
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
if request.user.is_authenticated() and request.auth:
|
serializer = AuthTokenSerializer(data=request.DATA)
|
||||||
request.auth.delete()
|
if serializer.is_valid():
|
||||||
return HttpResponse("logged out")
|
token, created = Token.objects.get_or_create(user=serializer.object['user'])
|
||||||
else:
|
return Response({'token': token.key})
|
||||||
return HttpResponse("not logged in")
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
|
@ -158,41 +158,28 @@ class TokenAuthTests(TestCase):
|
||||||
"""Ensure token login view using JSON POST works."""
|
"""Ensure token login view using JSON POST works."""
|
||||||
client = Client(enforce_csrf_checks=True)
|
client = Client(enforce_csrf_checks=True)
|
||||||
response = client.post('/auth-token/login/',
|
response = client.post('/auth-token/login/',
|
||||||
json.dumps({'username': self.username, 'password': self.password}), 'application/json')
|
json.dumps({'username': self.username, 'password': self.password}), 'application/json')
|
||||||
self.assertEqual(response.status_code, 201)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(json.loads(response.content)['token'], self.key)
|
self.assertEqual(json.loads(response.content)['token'], self.key)
|
||||||
|
|
||||||
def test_token_login_json_bad_creds(self):
|
def test_token_login_json_bad_creds(self):
|
||||||
"""Ensure token login view using JSON POST fails if bad credentials are used."""
|
"""Ensure token login view using JSON POST fails if bad credentials are used."""
|
||||||
client = Client(enforce_csrf_checks=True)
|
client = Client(enforce_csrf_checks=True)
|
||||||
response = client.post('/auth-token/login/',
|
response = client.post('/auth-token/login/',
|
||||||
json.dumps({'username': self.username, 'password': "badpass"}), 'application/json')
|
json.dumps({'username': self.username, 'password': "badpass"}), 'application/json')
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertEqual(response.status_code, 400)
|
||||||
|
|
||||||
def test_token_login_json_missing_fields(self):
|
def test_token_login_json_missing_fields(self):
|
||||||
"""Ensure token login view using JSON POST fails if missing fields."""
|
"""Ensure token login view using JSON POST fails if missing fields."""
|
||||||
client = Client(enforce_csrf_checks=True)
|
client = Client(enforce_csrf_checks=True)
|
||||||
response = client.post('/auth-token/login/',
|
response = client.post('/auth-token/login/',
|
||||||
json.dumps({'username': self.username}), 'application/json')
|
json.dumps({'username': self.username}), 'application/json')
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertEqual(response.status_code, 400)
|
||||||
|
|
||||||
def test_token_login_form(self):
|
def test_token_login_form(self):
|
||||||
"""Ensure token login view using form POST works."""
|
"""Ensure token login view using form POST works."""
|
||||||
client = Client(enforce_csrf_checks=True)
|
client = Client(enforce_csrf_checks=True)
|
||||||
response = client.post('/auth-token/login/',
|
response = client.post('/auth-token/login/',
|
||||||
{'username': self.username, 'password': self.password})
|
{'username': self.username, 'password': self.password})
|
||||||
self.assertEqual(response.status_code, 201)
|
|
||||||
self.assertEqual(json.loads(response.content)['token'], self.key)
|
|
||||||
|
|
||||||
def test_token_logout(self):
|
|
||||||
"""Ensure token logout view using JSON POST works."""
|
|
||||||
# Use different User and Token as to isolate this test's effects on other unittests in class
|
|
||||||
username = "ringo"
|
|
||||||
user = User.objects.create_user(username, "starr@thebeatles.com", "pass")
|
|
||||||
token = Token.objects.create(user=user)
|
|
||||||
auth = "Token " + token.key
|
|
||||||
client = Client(enforce_csrf_checks=True)
|
|
||||||
response = client.post('/auth-token/logout/', HTTP_AUTHORIZATION=auth)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
# Ensure token no longer exists
|
self.assertEqual(json.loads(response.content)['token'], self.key)
|
||||||
self.assertRaises(Token.DoesNotExist, lambda token: Token.objects.get(key=token.key), token)
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user