Unit test api
* adds unit test for APIUserToken * enhances handling of token fetching for API
This commit is contained in:
parent
1726eb38ad
commit
b854695399
@ -14,7 +14,7 @@ class APIUserToken(models.Model):
|
|||||||
valid_until = models.DateField(
|
valid_until = models.DateField(
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
help_text="Token is only valid until this date",
|
help_text="Token is only valid until this date. Forever if null/blank.",
|
||||||
)
|
)
|
||||||
is_active = models.BooleanField(
|
is_active = models.BooleanField(
|
||||||
default=False,
|
default=False,
|
||||||
@ -25,12 +25,11 @@ class APIUserToken(models.Model):
|
|||||||
return self.token
|
return self.token
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_user_from_token(token: str, username: str):
|
def get_user_from_token(token: str):
|
||||||
""" Getter for the related user object
|
""" Getter for the related user object
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
token (str): The used token
|
token (str): The used token
|
||||||
username (str): The username
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
user (User): Otherwise None
|
user (User): Otherwise None
|
||||||
@ -39,7 +38,6 @@ class APIUserToken(models.Model):
|
|||||||
try:
|
try:
|
||||||
token_obj = APIUserToken.objects.get(
|
token_obj = APIUserToken.objects.get(
|
||||||
token=token,
|
token=token,
|
||||||
user__username=username
|
|
||||||
)
|
)
|
||||||
if not token_obj.is_active:
|
if not token_obj.is_active:
|
||||||
raise PermissionError("Token unverified")
|
raise PermissionError("Token unverified")
|
||||||
|
7
api/tests/unit/__init__.py
Normal file
7
api/tests/unit/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 17.08.23
|
||||||
|
|
||||||
|
"""
|
71
api/tests/unit/test_token.py
Normal file
71
api/tests/unit/test_token.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 17.08.23
|
||||||
|
|
||||||
|
"""
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
from api.models import APIUserToken
|
||||||
|
from konova.tests.test_views import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class APIUserTokenTestCase(BaseTestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.token = APIUserToken.objects.create()
|
||||||
|
self.superuser.api_token = self.token
|
||||||
|
self.superuser.save()
|
||||||
|
|
||||||
|
def test_str(self):
|
||||||
|
self.assertEqual(str(self.token), self.token.token)
|
||||||
|
|
||||||
|
def test_get_user_from_token(self):
|
||||||
|
a_day = timedelta(days=1)
|
||||||
|
today = now().date()
|
||||||
|
|
||||||
|
self.assertFalse(self.token.is_active)
|
||||||
|
self.assertIsNone(self.token.valid_until)
|
||||||
|
|
||||||
|
try:
|
||||||
|
#Token not existing --> fail
|
||||||
|
token_user = APIUserToken.get_user_from_token(self.token.token[::-1])
|
||||||
|
self.fail("There should not have been any token")
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Token not active --> fail
|
||||||
|
token_user = APIUserToken.get_user_from_token(self.token.token)
|
||||||
|
self.fail("Token is unverified but token user has been fetchable.")
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
self.token.is_active = True
|
||||||
|
self.token.valid_until = today - a_day
|
||||||
|
self.token.save()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Token valid until yesterday --> fail
|
||||||
|
token_user = APIUserToken.get_user_from_token(self.token.token)
|
||||||
|
self.fail("Token reached end of lifetime but token user has been fetchable.")
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Token valid until tomorrow --> success
|
||||||
|
self.token.valid_until = today + a_day
|
||||||
|
self.token.save()
|
||||||
|
|
||||||
|
token_user = APIUserToken.get_user_from_token(self.token.token)
|
||||||
|
self.assertEqual(token_user, self.superuser)
|
||||||
|
del token_user
|
||||||
|
|
||||||
|
# Token valid forever --> success
|
||||||
|
self.token.valid_until = None
|
||||||
|
self.token.save()
|
||||||
|
token_user = APIUserToken.get_user_from_token(self.token.token)
|
||||||
|
self.assertEqual(token_user, self.superuser)
|
||||||
|
|
@ -53,7 +53,13 @@ class AbstractAPIView(View):
|
|||||||
# Fetch the proper user from the given request header token
|
# Fetch the proper user from the given request header token
|
||||||
ksp_token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
|
ksp_token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
|
||||||
ksp_user = request.headers.get(KSP_USER_HEADER_IDENTIFIER, None)
|
ksp_user = request.headers.get(KSP_USER_HEADER_IDENTIFIER, None)
|
||||||
self.user = APIUserToken.get_user_from_token(ksp_token, ksp_user)
|
token_user = APIUserToken.get_user_from_token(ksp_token)
|
||||||
|
|
||||||
|
if ksp_user != token_user.username:
|
||||||
|
raise PermissionError(f"Invalid token for {ksp_user}")
|
||||||
|
else:
|
||||||
|
self.user = token_user
|
||||||
|
|
||||||
request.user = self.user
|
request.user = self.user
|
||||||
if not self.user.is_default_user():
|
if not self.user.is_default_user():
|
||||||
raise PermissionError("Default permissions required")
|
raise PermissionError("Default permissions required")
|
||||||
|
Loading…
Reference in New Issue
Block a user