From 77c0b96d9090b0bb5db6c4851b03ef05772b8d58 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 17:08:30 -0400 Subject: [PATCH 1/8] fix formatting errors from #247 --- dj_rest_auth/registration/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index 8079a11..1a37c13 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -55,7 +55,6 @@ def get_response_data(self, user): return api_settings.JWT_SERIALIZER(data, context=self.get_serializer_context()).data elif self.token_model: return api_settings.TOKEN_SERIALIZER(user.auth_token, context=self.get_serializer_context()).data - return None def create(self, request, *args, **kwargs): From 348dc2c8cd69c683f43a0476580f4caed71a2ec6 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 17:17:58 -0400 Subject: [PATCH 2/8] bump django-allauth dependency constrains to >=64.0.0 --- demo/requirements.pip | 2 +- dj_rest_auth/tests/requirements.pip | 2 +- setup.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 038b616..ab8b15d 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -2,7 +2,7 @@ django>=2.2,<4.0 dj-rest-auth @ git+https://github.com/iMerica/dj-rest-auth.git@master djangorestframework>=3.11.0 djangorestframework-simplejwt==4.7.1 -django-allauth>=0.24.1 +django-allauth>=64.0.0 drf-yasg==1.21.4 django-cors-headers==3.2.1 coreapi==2.3.3 diff --git a/dj_rest_auth/tests/requirements.pip b/dj_rest_auth/tests/requirements.pip index 214895e..8e953a5 100644 --- a/dj_rest_auth/tests/requirements.pip +++ b/dj_rest_auth/tests/requirements.pip @@ -1,5 +1,5 @@ coveralls==1.11.1 -django-allauth==0.61.1 +django-allauth==64.0.0 djangorestframework-simplejwt>=5.3.1 flake8==3.8.4 responses==0.12.1 diff --git a/setup.py b/setup.py index 63353b8..d8748b0 100644 --- a/setup.py +++ b/setup.py @@ -32,11 +32,11 @@ 'djangorestframework>=3.13.0', ], extras_require={ - 'with-social': ['django-allauth>=0.56.0,<0.62.0'], + 'with-social': ['django-allauth>=64.0.0'], }, tests_require=[ 'coveralls>=1.11.1', - 'django-allauth>=0.57.0', + 'django-allauth>=64.0.0', 'djangorestframework-simplejwt==4.6.0', 'responses==0.12.1', 'unittest-xml-reporting==3.0.4', From a89f6df6a11b379783629afa5664de17e45c6cf9 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 18:23:06 -0400 Subject: [PATCH 3/8] remove failing test that rely on attributes that are no longer exported from the django-allauth package >= 64.0.0 --- dj_rest_auth/tests/test_api.py | 31 +------------------------- dj_rest_auth/tests/test_serializers.py | 17 ++------------ dj_rest_auth/tests/test_social.py | 2 +- 3 files changed, 4 insertions(+), 46 deletions(-) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 41cc755..fc3d48d 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -18,7 +18,7 @@ try: from django.urls import reverse except ImportError: # pragma: no cover - from django.core.urlresolvers import reverse + from django.core.urlresolvers import reverse # noqa from jwt import decode as decode_jwt from rest_framework_simplejwt.serializers import TokenObtainPairSerializer @@ -527,35 +527,6 @@ def test_registration_with_jwt(self): self._login() self._logout() - @override_api_settings(SESSION_LOGIN=True) - @override_api_settings(TOKEN_MODEL=None) - def test_registration_with_session(self): - import sys - from importlib import reload - from django.contrib.sessions.middleware import SessionMiddleware - from django.contrib.messages.middleware import MessageMiddleware - reload(sys.modules['dj_rest_auth.models']) - reload(sys.modules['dj_rest_auth.registration.views']) - from dj_rest_auth.registration.views import RegisterView - - user_count = get_user_model().objects.all().count() - - self.post(self.register_url, data={}, status_code=400) - - factory = APIRequestFactory() - request = factory.post(self.register_url, self.REGISTRATION_DATA) - - for middleware_class in (SessionMiddleware, MessageMiddleware): - middleware = middleware_class(lambda request: None) - middleware.process_request(request) - - response = RegisterView.as_view()(request) - self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) - self.assertEqual(response.data, None) - self.assertEqual(get_user_model().objects.all().count(), user_count + 1) - - self._login(status.HTTP_204_NO_CONTENT) - self._logout() def test_registration_with_invalid_password(self): data = self.REGISTRATION_DATA.copy() diff --git a/dj_rest_auth/tests/test_serializers.py b/dj_rest_auth/tests/test_serializers.py index 74f9281..853b55c 100644 --- a/dj_rest_auth/tests/test_serializers.py +++ b/dj_rest_auth/tests/test_serializers.py @@ -1,14 +1,12 @@ from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter -from allauth.socialaccount.providers.facebook.views import FacebookProvider +from allauth.socialaccount.providers.facebook.provider import FacebookProvider from allauth.socialaccount.models import SocialApp -from allauth.core.exceptions import ImmediateHttpResponse from django.contrib.auth import get_user_model from django.urls import reverse from django.core.exceptions import ValidationError from django.test import TestCase, modify_settings, override_settings from django.contrib.sites.models import Site -from django.http import HttpResponseBadRequest from rest_framework.exceptions import ErrorDetail from rest_framework.test import APIRequestFactory, force_authenticate from unittest.mock import MagicMock, patch @@ -142,23 +140,12 @@ def test_validate_no_view_submit(self): serializer.is_valid() self.assertDictEqual(serializer.errors, self.NO_VIEW_SUBMIT_ERROR) - def test_validate_no_adpapter_class_present(self): + def test_validate_no_adapter_class_present(self): dummy_view = SocialLoginView() serializer = SocialLoginSerializer(data=self.request_data, context={'request': self.request, 'view': dummy_view}) serializer.is_valid() self.assertDictEqual(serializer.errors, self.NO_ADAPTER_CLASS_PRESENT) - @patch('allauth.socialaccount.providers.facebook.views.fb_complete_login') - @patch('allauth.socialaccount.adapter.DefaultSocialAccountAdapter.pre_social_login') - def test_immediate_http_response_error(self, mock_pre_social_login, mock_fb_complete_login): - dummy_view = SocialLoginView() - dummy_view.adapter_class = FacebookOAuth2Adapter - mock_pre_social_login.side_effect = lambda request, social_login: exec('raise ImmediateHttpResponse(HttpResponseBadRequest("Bad Request"))') - mock_fb_complete_login.return_value = FacebookProvider(self.request, app=FacebookOAuth2Adapter).sociallogin_from_response(self.request, self.fb_response) - serializer = SocialLoginSerializer(data=self.request_data, context={'request': self.request, 'view': dummy_view}) - serializer.is_valid() - self.assertDictEqual(serializer.errors, self.HTTP_BAD_REQUEST_MESSAGE) - def test_http_error(self): dummy_view = SocialLoginView() dummy_view.adapter_class = FacebookOAuth2Adapter diff --git a/dj_rest_auth/tests/test_social.py b/dj_rest_auth/tests/test_social.py index 492b7b0..de721ea 100644 --- a/dj_rest_auth/tests/test_social.py +++ b/dj_rest_auth/tests/test_social.py @@ -16,7 +16,7 @@ try: from django.urls import reverse except ImportError: - from django.core.urlresolvers import reverse + from django.core.urlresolvers import reverse # noqa @override_settings(ROOT_URLCONF='tests.urls') From eb0fb01cd61cd8323aa498f27aff423f4c89b76d Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 20:42:55 -0400 Subject: [PATCH 4/8] convert requirements.pip files to requirements.txt files --- .github/workflows/main.yml | 2 +- README.md | 2 +- demo/requirements.pip | 8 -------- demo/requirements.txt | 12 ++++++++++++ dj_rest_auth/tests/requirements.txt | 6 ++++++ docs/demo.rst | 2 +- tox.ini | 4 ++-- 7 files changed, 23 insertions(+), 13 deletions(-) delete mode 100644 demo/requirements.pip create mode 100644 demo/requirements.txt create mode 100644 dj_rest_auth/tests/requirements.txt diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 44c79c7..efe11a8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -67,7 +67,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - pip install -r dj_rest_auth/tests/requirements.pip + pip install -r dj_rest_auth/tests/requirements.txt pip install "Django~=${{ matrix.django-version }}.0" - name: Run Tests run: | diff --git a/README.md b/README.md index 3ba816f..24a9e9d 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ REST_AUTH = { ### Testing -Install required modules with `pip install -r dj_rest_auth/tests/requirements.pip` +Install required modules with `pip install -r dj_rest_auth/tests/requirements.txt` To run the tests within a virtualenv, run `python runtests.py` from the repository directory. The easiest way to run test coverage is with [`coverage`](https://pypi.org/project/coverage/), diff --git a/demo/requirements.pip b/demo/requirements.pip deleted file mode 100644 index ab8b15d..0000000 --- a/demo/requirements.pip +++ /dev/null @@ -1,8 +0,0 @@ -django>=2.2,<4.0 -dj-rest-auth @ git+https://github.com/iMerica/dj-rest-auth.git@master -djangorestframework>=3.11.0 -djangorestframework-simplejwt==4.7.1 -django-allauth>=64.0.0 -drf-yasg==1.21.4 -django-cors-headers==3.2.1 -coreapi==2.3.3 diff --git a/demo/requirements.txt b/demo/requirements.txt new file mode 100644 index 0000000..529da58 --- /dev/null +++ b/demo/requirements.txt @@ -0,0 +1,12 @@ +django>=5.0.0 +djangorestframework>=3.11.0 +djangorestframework-simplejwt==5.3.1 +django-allauth>=64.0.0 +drf-yasg==1.21.7 +django-cors-headers==4.4.0 +coreapi==2.3.3 +PyJWT~=2.9.0 +responses~=0.12.1 +requests~=2.32.3 +setuptools==75.1.0 +-e ./.. \ No newline at end of file diff --git a/dj_rest_auth/tests/requirements.txt b/dj_rest_auth/tests/requirements.txt new file mode 100644 index 0000000..c8b3bf8 --- /dev/null +++ b/dj_rest_auth/tests/requirements.txt @@ -0,0 +1,6 @@ +coveralls==1.11.1 +django-allauth>=64.0.0 +djangorestframework-simplejwt>=5.3.1 +flake8==3.8.4 +responses==0.12.1 +unittest-xml-reporting==3.0.4 diff --git a/docs/demo.rst b/docs/demo.rst index c44b451..5c35ba9 100644 --- a/docs/demo.rst +++ b/docs/demo.rst @@ -10,7 +10,7 @@ To run this locally follow the steps below. cd /tmp git clone https://github.com/iMerica/dj-rest-auth.git cd dj-rest-auth/demo/ - pip install -r requirements.pip + pip install -r requirements.txt python manage.py migrate --settings=demo.settings --noinput python manage.py runserver --settings=demo.settings diff --git a/tox.ini b/tox.ini index a6e69be..3e567ce 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ python = commands = python ./runtests.py deps = - -rdj_rest_auth/tests/requirements.pip + -r dj_rest_auth/tests/requirements.txt django3: Django>=3.2,<4.0 django4: Django>=4.0,<5.0 django5: Django>=5.0,<6.0 @@ -35,7 +35,7 @@ commands = coverage run ./runtests.py coverage report deps = - -rdj_rest_auth/tests/requirements.pip + -r dj_rest_auth/tests/requirements.txt [testenv:flake8] changedir = {toxinidir}/dj_rest_auth From 990c5432c5d857a0d8635b619afc74dafc5cb2ab Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 20:45:51 -0400 Subject: [PATCH 5/8] Replace usage of django.utils.timezone module (which was deprecated in django 4.1 and removed in django>=5.0) with the python datetime module see django documentation here https://docs.djangoproject.com/en/dev/internals/deprecation/#deprecation-removed-in-5-0 --- dj_rest_auth/jwt_auth.py | 2 +- dj_rest_auth/views.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dj_rest_auth/jwt_auth.py b/dj_rest_auth/jwt_auth.py index 67bc6dc..95363eb 100644 --- a/dj_rest_auth/jwt_auth.py +++ b/dj_rest_auth/jwt_auth.py @@ -1,4 +1,4 @@ -from django.utils import timezone +from datetime import timezone from django.utils.translation import gettext_lazy as _ from rest_framework import status from rest_framework import exceptions, serializers diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index d37c324..5a97f7d 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -3,7 +3,7 @@ from django.contrib.auth import login as django_login from django.contrib.auth import logout as django_logout from django.core.exceptions import ObjectDoesNotExist -from django.utils import timezone +from datetime import datetime from django.utils.decorators import method_decorator from django.utils.translation import gettext_lazy as _ from django.views.decorators.debug import sensitive_post_parameters @@ -81,8 +81,8 @@ def get_response(self): from rest_framework_simplejwt.settings import ( api_settings as jwt_settings, ) - access_token_expiration = (timezone.now() + jwt_settings.ACCESS_TOKEN_LIFETIME) - refresh_token_expiration = (timezone.now() + jwt_settings.REFRESH_TOKEN_LIFETIME) + access_token_expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) + refresh_token_expiration = (datetime.utcnow() + jwt_settings.REFRESH_TOKEN_LIFETIME) return_expiration_times = api_settings.JWT_AUTH_RETURN_EXPIRATION auth_httponly = api_settings.JWT_AUTH_HTTPONLY From 2a4b9f1255e76aea3e5a539688dfd3b85dc4c784 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 20:47:03 -0400 Subject: [PATCH 6/8] increment dj-rest-auth major version since these changes introduce breaking changes and remove support for django<4.2 --- dj_rest_auth/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/__version__.py b/dj_rest_auth/__version__.py index c282a18..1a0f2e8 100644 --- a/dj_rest_auth/__version__.py +++ b/dj_rest_auth/__version__.py @@ -1,7 +1,7 @@ __title__ = 'dj-rest-auth' __description__ = 'Authentication and Registration in Django Rest Framework.' __url__ = 'http://github.com/iMerica/dj-rest-auth' -__version__ = '6.0.0' +__version__ = '7.0.0' __author__ = '@iMerica https://github.com/iMerica' __author_email__ = 'imichael@pm.me' __license__ = 'MIT' From a008dd46355ed7b77cb2628ead268bafb874b549 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 20:49:46 -0400 Subject: [PATCH 7/8] remove django 3.2 support (which has reached end of life, and is no longer supported by django or django-allauth) and some minor additional fixes to use of datetime module --- .github/workflows/main.yml | 2 +- dj_rest_auth/jwt_auth.py | 10 +++++----- dj_rest_auth/tests/requirements.pip | 6 ------ dj_rest_auth/tests/requirements.txt | 1 + setup.py | 2 +- tox.ini | 3 +-- 6 files changed, 9 insertions(+), 15 deletions(-) delete mode 100644 dj_rest_auth/tests/requirements.pip diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index efe11a8..610ce95 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,7 +52,7 @@ jobs: strategy: matrix: python-version: ['3.8', '3.9', '3.10', '3.11'] - django-version: ['3.2', '4.2', '5.0'] + django-version: ['4.2', '5.0'] exclude: - python-version: '3.8' django-version: '5.0' diff --git a/dj_rest_auth/jwt_auth.py b/dj_rest_auth/jwt_auth.py index 95363eb..df7b0d4 100644 --- a/dj_rest_auth/jwt_auth.py +++ b/dj_rest_auth/jwt_auth.py @@ -1,4 +1,4 @@ -from datetime import timezone +from datetime import datetime from django.utils.translation import gettext_lazy as _ from rest_framework import status from rest_framework import exceptions, serializers @@ -12,7 +12,7 @@ def set_jwt_access_cookie(response, access_token): from rest_framework_simplejwt.settings import api_settings as jwt_settings cookie_name = api_settings.JWT_AUTH_COOKIE - access_token_expiration = (timezone.now() + jwt_settings.ACCESS_TOKEN_LIFETIME) + access_token_expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) cookie_secure = api_settings.JWT_AUTH_SECURE cookie_httponly = api_settings.JWT_AUTH_HTTPONLY cookie_samesite = api_settings.JWT_AUTH_SAMESITE @@ -32,7 +32,7 @@ def set_jwt_access_cookie(response, access_token): def set_jwt_refresh_cookie(response, refresh_token): from rest_framework_simplejwt.settings import api_settings as jwt_settings - refresh_token_expiration = (timezone.now() + jwt_settings.REFRESH_TOKEN_LIFETIME) + refresh_token_expiration = (datetime.utcnow() + jwt_settings.REFRESH_TOKEN_LIFETIME) refresh_cookie_name = api_settings.JWT_AUTH_REFRESH_COOKIE refresh_cookie_path = api_settings.JWT_AUTH_REFRESH_COOKIE_PATH cookie_secure = api_settings.JWT_AUTH_SECURE @@ -101,13 +101,13 @@ class RefreshViewWithCookieSupport(TokenRefreshView): def finalize_response(self, request, response, *args, **kwargs): if response.status_code == status.HTTP_200_OK and 'access' in response.data: set_jwt_access_cookie(response, response.data['access']) - response.data['access_expiration'] = (timezone.now() + jwt_settings.ACCESS_TOKEN_LIFETIME) + response.data['access_expiration'] = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) if response.status_code == status.HTTP_200_OK and 'refresh' in response.data: set_jwt_refresh_cookie(response, response.data['refresh']) if api_settings.JWT_AUTH_HTTPONLY: del response.data['refresh'] else: - response.data['refresh_expiration'] = (timezone.now() + jwt_settings.REFRESH_TOKEN_LIFETIME) + response.data['refresh_expiration'] = (datetime.utcnow() + jwt_settings.REFRESH_TOKEN_LIFETIME) return super().finalize_response(request, response, *args, **kwargs) return RefreshViewWithCookieSupport diff --git a/dj_rest_auth/tests/requirements.pip b/dj_rest_auth/tests/requirements.pip deleted file mode 100644 index 8e953a5..0000000 --- a/dj_rest_auth/tests/requirements.pip +++ /dev/null @@ -1,6 +0,0 @@ -coveralls==1.11.1 -django-allauth==64.0.0 -djangorestframework-simplejwt>=5.3.1 -flake8==3.8.4 -responses==0.12.1 -unittest-xml-reporting==3.0.4 diff --git a/dj_rest_auth/tests/requirements.txt b/dj_rest_auth/tests/requirements.txt index c8b3bf8..4734a17 100644 --- a/dj_rest_auth/tests/requirements.txt +++ b/dj_rest_auth/tests/requirements.txt @@ -4,3 +4,4 @@ djangorestframework-simplejwt>=5.3.1 flake8==3.8.4 responses==0.12.1 unittest-xml-reporting==3.0.4 +requests-oauthlib==2.0.0 diff --git a/setup.py b/setup.py index d8748b0..53c342a 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ keywords='django rest auth registration rest-framework django-registration api', zip_safe=False, install_requires=[ - 'Django>=3.2,<6.0', + 'Django>=4.2,<6.0', 'djangorestframework>=3.13.0', ], extras_require={ diff --git a/tox.ini b/tox.ini index 3e567ce..62b4521 100644 --- a/tox.ini +++ b/tox.ini @@ -25,8 +25,7 @@ commands = python ./runtests.py deps = -r dj_rest_auth/tests/requirements.txt - django3: Django>=3.2,<4.0 - django4: Django>=4.0,<5.0 + django4: Django>=4.2,<5.0 django5: Django>=5.0,<6.0 # Configuration for coverage and flake8 is being set in `./setup.cfg` From 3948e3dea46aaf674fda27bf472af18eac14f281 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 19 Sep 2024 21:59:09 -0400 Subject: [PATCH 8/8] update supported django version in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24a9e9d..d7a5cdb 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Drop-in API endpoints for handling authentication securely in Django Rest Framew with SPAs (e.g., React, Vue, Angular), and Mobile applications. ## Requirements -- Django 3, 4 and 5 (See Unit Test Coverage in CI) +- Django 4.2 and 5 (See Unit Test Coverage in CI) - Python >= 3.8 ## Quick Setup