Updates to login view for TokenAuthentication from feedback from Tom

This commit is contained in:
Rob Romano 2012-11-12 15:16:53 -08:00
parent 063c027c7b
commit 8eb37e1f7e
4 changed files with 24 additions and 48 deletions

View File

@ -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

View File

@ -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'),
) )

View File

@ -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)

View File

@ -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)