diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..103ee60 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + coverage run --source=dj_rest_auth setup.py test diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index 3d02309..5f57f91 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -94,6 +94,8 @@ INSTALLED_APPS = [ 'dj_rest_auth', 'dj_rest_auth.registration', + + 'rest_framework_simplejwt.token_blacklist' ] SECRET_KEY = "38dh*skf8sjfhs287dh&^hd8&3hdg*j2&sd" diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index f373dcc..0e5a3c6 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -1,6 +1,7 @@ +import json +from unittest.mock import patch + from allauth.account import app_settings as account_app_settings -from dj_rest_auth.registration.app_settings import register_permission_classes -from dj_rest_auth.registration.views import RegisterView from django.conf import settings from django.contrib.auth import get_user_model from django.core import mail @@ -9,6 +10,8 @@ from django.utils.encoding import force_text from rest_framework import status from rest_framework.test import APIRequestFactory +from dj_rest_auth.registration.app_settings import register_permission_classes +from dj_rest_auth.registration.views import RegisterView from .mixins import CustomPermissionClass, TestsMixin try: @@ -556,6 +559,20 @@ class APIBasicTests(TestsMixin, TestCase): resp = self.get('/protected-view/') self.assertEquals(resp.status_code, 200) + @override_settings(REST_USE_JWT=True) + @patch('rest_framework_simplejwt.tokens.BlacklistMixin.blacklist') + def test_blacklisting_not_installed(self, mocked_blacklist): + mocked_blacklist.side_effect = AttributeError(f"'RefreshToken' object has no attribute 'blacklist'") + payload = { + "username": self.USERNAME, + "password": self.PASS + } + get_user_model().objects.create_user(self.USERNAME, '', self.PASS) + resp = self.post(self.login_url, data=payload, status_code=200) + token = resp.data['refresh_token'] + resp = self.post(self.logout_url, status=200, data={'refresh': token}) + self.assertEqual(resp.status_code, 501) + @override_settings(REST_USE_JWT=True) def test_blacklisting(self): payload = { @@ -563,6 +580,15 @@ class APIBasicTests(TestsMixin, TestCase): "password": self.PASS } get_user_model().objects.create_user(self.USERNAME, '', self.PASS) - self.post(self.login_url, data=payload, status_code=200) + resp = self.post(self.login_url, data=payload, status_code=200) + token = resp.data['refresh_token'] resp = self.post(self.logout_url, status=200) - pass + self.assertEqual(resp.status_code, 401) + resp = self.post(self.logout_url, status=200, data={'refresh': '1'}) + self.assertEqual(resp.status_code, 404) + resp = self.post(self.logout_url, status=200, data={'refresh': token}) + self.assertEqual(resp.status_code, 200) + resp = self.post(self.logout_url, status=200, data={'refresh': token}) + self.assertEqual(resp.status_code, 404) + resp = self.post(self.logout_url, status=200, data=json.dumps({'refresh': token})) + self.assertEqual(resp.status_code, 500) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index c79423f..f3bb3fe 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -147,25 +147,27 @@ class LogoutView(APIView): try: token = RefreshToken(request.data['refresh']) token.blacklist() - except KeyError: response = Response({"detail": _("Refresh token was not included in request data.")}, status=status.HTTP_401_UNAUTHORIZED) - except TokenError as e: - if hasattr(e, 'args') and 'Token is blacklisted' in e.args: - response = Response({"detail": _("Token is already blacklisted.")}, - status=status.HTTP_404_NOT_FOUND) - else: - raise + except (TokenError, AttributeError, TypeError) as error: + if hasattr(error, 'args'): + if 'Token is blacklisted' in error.args or 'Token is invalid or expired' in error.args: + response = Response({"detail": _(error.args[0])}, + status=status.HTTP_404_NOT_FOUND) + + # warn user blacklist is not enabled + elif "'RefreshToken' object has no attribute 'blacklist'" in error.args: + response = Response({"detail": _("Blacklist is not enabled in INSTALLED_APPS.")}, + status=status.HTTP_501_NOT_IMPLEMENTED) + else: + response = Response({"detail": _("An error has occurred.")}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) - except AttributeError as e: - # warn user blacklist is not enabled - if hasattr(e, 'args') and "'RefreshToken' object has no attribute 'blacklist'" in e.args: - response = Response({"detail": _("Blacklist is not enabled in INSTALLED_APPS.")}, - status=status.HTTP_501_NOT_IMPLEMENTED) else: - raise + response = Response({"detail": _("No attr error has occurred.")}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) return response