Skip to content

Commit

Permalink
Merge pull request #4672 from kobotoolbox/create-api-token-via-get-re…
Browse files Browse the repository at this point in the history
…quest

Allow GET to `/token/` to create a new API token if none exists
  • Loading branch information
noliveleger committed Oct 3, 2023
2 parents c639e7a + c825783 commit 8cb1ea9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
28 changes: 23 additions & 5 deletions kpi/tests/test_token.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# coding: utf-8
from django.urls import reverse
from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.authtoken.models import Token

Expand All @@ -23,23 +24,40 @@ def test_get_existing_token(self):
)

def test_delete_token(self):
assert Token.objects.filter(user__username=self.username).exists()
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
assert not Token.objects.filter(user__username=self.username).exists()

def test_create_token(self):
def test_create_token_via_get(self):
# Originally, a POST was required to generate a token, but no longer
self.test_delete_token()
response = self.client.get(self.url, format='json')
self.assertEqual(
response.data['token'],
Token.objects.get(user__username=self.username).key
)

def test_create_token_via_post(self):
# Retained for API stability
self.test_delete_token()
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
response = self.client.post(self.url, format='json')
self.assertEqual(
response.data['token'],
Token.objects.get(user__username=self.username).key
)

def test_new_user_has_token_automatically_created(self):
User = get_user_model()
u = User.objects.create_user(
username='token_test', password='token_test'
)
self.client.login(username='token_test', password='token_test')
response = self.client.get(self.url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)

def test_anonymous_access_denied(self):
self.client.logout()
response = self.client.get(self.url)
Expand Down
9 changes: 6 additions & 3 deletions kpi/views/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ def _which_user(self, request):
return user

def get(self, request, *args, **kwargs):
""" Retrieve an existing token only """
""" Retrieve an existing token, or create and retrieve a new one """
user = self._which_user(request)
token = get_object_or_404(Token, user=user)
token, _ = Token.objects.get_or_create(user=user)
return Response({'token': token.key})

def post(self, request, *args, **kwargs):
""" Return a token, creating a new one if none exists """
"""
Return a token, creating a new one if none exists. Unnecessary now that
GET also creates a token, but left here for API stability
"""
user = self._which_user(request)
token, created = Token.objects.get_or_create(user=user)
return Response(
Expand Down

0 comments on commit 8cb1ea9

Please sign in to comment.