From 596cbee153b7eeaeebcd66a6a56088d842a4822a Mon Sep 17 00:00:00 2001 From: Steve Recio Date: Fri, 10 Jan 2020 17:47:54 -0500 Subject: [PATCH 001/130] add DRF throttle scopes to relevant rest auth views --- rest_auth/registration/views.py | 1 + rest_auth/views.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index 0e0ab0d0..1c28c169 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -40,6 +40,7 @@ class RegisterView(CreateAPIView): serializer_class = RegisterSerializer permission_classes = register_permission_classes() token_model = TokenModel + throttle_scope = 'rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): diff --git a/rest_auth/views.py b/rest_auth/views.py index 0a0a982e..bbeab8ac 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -43,6 +43,7 @@ class LoginView(GenericAPIView): permission_classes = (AllowAny,) serializer_class = LoginSerializer token_model = TokenModel + throttle_scope = 'rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): @@ -114,6 +115,7 @@ class LogoutView(APIView): Accepts/Returns nothing. """ permission_classes = (AllowAny,) + throttle_scope = 'rest_auth' def get(self, request, *args, **kwargs): if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False): @@ -178,6 +180,7 @@ class PasswordResetView(GenericAPIView): """ serializer_class = PasswordResetSerializer permission_classes = (AllowAny,) + throttle_scope = 'rest_auth' def post(self, request, *args, **kwargs): # Create a serializer with request.data @@ -203,6 +206,7 @@ class PasswordResetConfirmView(GenericAPIView): """ serializer_class = PasswordResetConfirmSerializer permission_classes = (AllowAny,) + throttle_scope = 'rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): @@ -226,6 +230,7 @@ class PasswordChangeView(GenericAPIView): """ serializer_class = PasswordChangeSerializer permission_classes = (IsAuthenticated,) + throttle_scope = 'rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): From 10eb4be9cd4b403d78cebbaed75e8e42a54e5ce9 Mon Sep 17 00:00:00 2001 From: Steve Recio Date: Mon, 10 Feb 2020 13:02:20 -0500 Subject: [PATCH 002/130] dont delete auth token on logout --- rest_auth/views.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rest_auth/views.py b/rest_auth/views.py index bbeab8ac..6e94a4c4 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -129,10 +129,6 @@ def post(self, request, *args, **kwargs): return self.logout(request) def logout(self, request): - try: - request.user.auth_token.delete() - except (AttributeError, ObjectDoesNotExist): - pass if getattr(settings, 'REST_SESSION_LOGIN', True): django_logout(request) From 92cc9c18ecaccdf509ef5ff2917ff64f7f81dd94 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 17:59:38 -0600 Subject: [PATCH 003/130] Renames project to dj-rest-auth --- .travis.yml | 4 +- AUTHORS | 2 +- LICENSE | 4 +- MANIFEST.in | 2 +- README.rst | 22 ++++----- demo/demo/settings.py | 4 +- demo/demo/urls.py | 4 +- demo/requirements.pip | 2 +- demo/templates/base.html | 12 ++--- demo/templates/home.html | 4 +- {rest_auth => dj_rest_auth}/__init__.py | 0 {rest_auth => dj_rest_auth}/admin.py | 0 {rest_auth => dj_rest_auth}/app_settings.py | 2 +- .../locale/cs/LC_MESSAGES/django.mo | Bin .../locale/cs/LC_MESSAGES/django.po | 0 .../locale/de/LC_MESSAGES/django.mo | Bin .../locale/de/LC_MESSAGES/django.po | 0 .../locale/es/LC_MESSAGES/django.mo | Bin .../locale/es/LC_MESSAGES/django.po | 0 .../locale/fr/LC_MESSAGES/django.mo | Bin .../locale/fr/LC_MESSAGES/django.po | 0 .../locale/ko/LC_MESSAGES/django.mo | Bin .../locale/ko/LC_MESSAGES/django.po | 0 .../locale/pl/LC_MESSAGES/django.mo | Bin .../locale/pl/LC_MESSAGES/django.po | 0 .../locale/pt_BR/LC_MESSAGES/django.po | 0 .../locale/ru/LC_MESSAGES/django.mo | Bin .../locale/ru/LC_MESSAGES/django.po | 0 .../locale/tr/LC_MESSAGES/django.po | 0 .../locale/zh_Hans/LC_MESSAGES/django.mo | Bin .../locale/zh_Hans/LC_MESSAGES/django.po | 0 .../locale/zh_Hant/LC_MESSAGES/django.mo | Bin .../locale/zh_Hant/LC_MESSAGES/django.po | 0 {rest_auth => dj_rest_auth}/models.py | 0 .../registration/__init__.py | 0 .../registration/app_settings.py | 0 .../registration/serializers.py | 0 .../registration/urls.py | 0 .../registration/views.py | 0 {rest_auth => dj_rest_auth}/serializers.py | 0 .../social_serializers.py | 0 {rest_auth => dj_rest_auth}/tests/__init__.py | 0 .../tests/django_urls.py | 0 {rest_auth => dj_rest_auth}/tests/mixins.py | 0 .../tests/requirements.pip | 0 {rest_auth => dj_rest_auth}/tests/settings.py | 0 {rest_auth => dj_rest_auth}/tests/test_api.py | 0 .../tests/test_social.py | 0 {rest_auth => dj_rest_auth}/tests/urls.py | 0 {rest_auth => dj_rest_auth}/urls.py | 0 {rest_auth => dj_rest_auth}/utils.py | 0 {rest_auth => dj_rest_auth}/views.py | 0 docs/api_endpoints.rst | 2 +- docs/changelog.rst | 4 +- docs/configuration.rst | 18 ++++---- docs/faq.rst | 6 +-- docs/installation.rst | 42 +++++++++--------- docs/introduction.rst | 4 +- 58 files changed, 69 insertions(+), 69 deletions(-) rename {rest_auth => dj_rest_auth}/__init__.py (100%) rename {rest_auth => dj_rest_auth}/admin.py (100%) rename {rest_auth => dj_rest_auth}/app_settings.py (97%) rename {rest_auth => dj_rest_auth}/locale/cs/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/cs/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/de/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/de/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/es/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/es/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/fr/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/fr/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/ko/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/ko/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/pl/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/pl/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/pt_BR/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/ru/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/ru/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/tr/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/zh_Hans/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/zh_Hans/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/locale/zh_Hant/LC_MESSAGES/django.mo (100%) rename {rest_auth => dj_rest_auth}/locale/zh_Hant/LC_MESSAGES/django.po (100%) rename {rest_auth => dj_rest_auth}/models.py (100%) rename {rest_auth => dj_rest_auth}/registration/__init__.py (100%) rename {rest_auth => dj_rest_auth}/registration/app_settings.py (100%) rename {rest_auth => dj_rest_auth}/registration/serializers.py (100%) rename {rest_auth => dj_rest_auth}/registration/urls.py (100%) rename {rest_auth => dj_rest_auth}/registration/views.py (100%) rename {rest_auth => dj_rest_auth}/serializers.py (100%) rename {rest_auth => dj_rest_auth}/social_serializers.py (100%) rename {rest_auth => dj_rest_auth}/tests/__init__.py (100%) rename {rest_auth => dj_rest_auth}/tests/django_urls.py (100%) rename {rest_auth => dj_rest_auth}/tests/mixins.py (100%) rename {rest_auth => dj_rest_auth}/tests/requirements.pip (100%) rename {rest_auth => dj_rest_auth}/tests/settings.py (100%) rename {rest_auth => dj_rest_auth}/tests/test_api.py (100%) rename {rest_auth => dj_rest_auth}/tests/test_social.py (100%) rename {rest_auth => dj_rest_auth}/tests/urls.py (100%) rename {rest_auth => dj_rest_auth}/urls.py (100%) rename {rest_auth => dj_rest_auth}/utils.py (100%) rename {rest_auth => dj_rest_auth}/views.py (100%) diff --git a/.travis.yml b/.travis.yml index b059c1ed..33f42ad3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,9 @@ env: install: - pip install -q Django==$DJANGO djangorestframework==$DRF - pip install coveralls - - pip install -r rest_auth/tests/requirements.pip + - pip install -r dj_rest_auth/tests/requirements.pip script: - - coverage run --source=rest_auth setup.py test + - coverage run --source=dj_rest_auth setup.py test after_success: - coveralls before_script: diff --git a/AUTHORS b/AUTHORS index 21906daa..c5ba2edd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1 @@ -http://github.com/Tivix/django-rest-auth/contributors +http://github.com/iMerica/dj-rest-auth/contributors diff --git a/LICENSE b/LICENSE index 1e3b8535..f868a2a7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Tivix +Copyright (c) 2014 iMerica Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in index 01a589f4..c2d42087 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,4 +2,4 @@ include AUTHORS include LICENSE include MANIFEST.in include README.md -graft rest_auth +graft dj_rest_auth diff --git a/README.rst b/README.rst index ac7f19eb..f79511f2 100644 --- a/README.rst +++ b/README.rst @@ -1,31 +1,31 @@ -Welcome to django-rest-auth +Welcome to dj-rest-auth =========================== -.. image:: https://travis-ci.org/Tivix/django-rest-auth.svg - :target: https://travis-ci.org/Tivix/django-rest-auth +.. image:: https://travis-ci.org/iMerica/dj-rest-auth.svg + :target: https://travis-ci.org/iMerica/dj-rest-auth -.. image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.svg - :target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master +.. image:: https://coveralls.io/repos/iMerica/dj-rest-auth/badge.svg + :target: https://coveralls.io/r/iMerica/dj-rest-auth?branch=master -.. image:: https://readthedocs.org/projects/django-rest-auth/badge/?version=latest - :target: https://readthedocs.org/projects/django-rest-auth/?badge=latest +.. image:: https://readthedocs.org/projects/dj-rest-auth/badge/?version=latest + :target: https://readthedocs.org/projects/dj-rest-auth/?badge=latest -Django-rest-auth provides a set of REST API endpoints for Authentication and Registration +Django-dj-rest-auth provides a set of REST API endpoints for Authentication and Registration Documentation ------------- -http://django-rest-auth.readthedocs.org/en/latest/ +http://dj-rest-auth.readthedocs.org/en/latest/ Source code ----------- -https://github.com/Tivix/django-rest-auth +https://github.com/iMerica/dj-rest-auth Stack Overflow ----------- -http://stackoverflow.com/questions/tagged/django-rest-auth +http://stackoverflow.com/questions/tagged/dj-rest-auth diff --git a/demo/demo/settings.py b/demo/demo/settings.py index 514a8fb1..df6807ae 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -37,11 +37,11 @@ 'rest_framework', 'rest_framework.authtoken', - 'rest_auth', + 'dj_rest_auth', 'allauth', 'allauth.account', - 'rest_auth.registration', + 'dj_rest_auth.registration', 'allauth.socialaccount', 'allauth.socialaccount.providers.facebook', 'rest_framework_swagger', diff --git a/demo/demo/urls.py b/demo/demo/urls.py index af7d38b2..787c6e94 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -35,8 +35,8 @@ TemplateView.as_view(template_name="password_reset_confirm.html"), name='password_reset_confirm'), - url(r'^rest-auth/', include('rest_auth.urls')), - url(r'^rest-auth/registration/', include('rest_auth.registration.urls')), + url(r'^dj-rest-auth/', include('dj_rest_auth.urls')), + url(r'^dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')), url(r'^account/', include('allauth.urls')), url(r'^admin/', admin.site.urls), url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'), diff --git a/demo/requirements.pip b/demo/requirements.pip index 40b4820a..c6f5f42f 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.9.0 -django-rest-auth==0.9.5 +dj-rest-auth==0.9.5 djangorestframework>=3.7.0 django-allauth>=0.24.1 six==1.9.0 diff --git a/demo/templates/base.html b/demo/templates/base.html index cbf02b6d..47e4e649 100644 --- a/demo/templates/base.html +++ b/demo/templates/base.html @@ -4,10 +4,10 @@ - - + + - django-rest-auth demo + dj-rest-auth demo @@ -53,13 +53,13 @@ - django-rest-auth demo + dj-rest-auth demo diff --git a/demo/templates/home.html b/demo/templates/home.html index 134198a4..ecc6f7c6 100644 --- a/demo/templates/home.html +++ b/demo/templates/home.html @@ -3,7 +3,7 @@ {% block content %}
-

django-rest-auth demo

-

Welcome in django-rest-auth demo project!

+

dj-rest-auth demo

+

Welcome in dj-rest-auth demo project!

{% endblock %} diff --git a/rest_auth/__init__.py b/dj_rest_auth/__init__.py similarity index 100% rename from rest_auth/__init__.py rename to dj_rest_auth/__init__.py diff --git a/rest_auth/admin.py b/dj_rest_auth/admin.py similarity index 100% rename from rest_auth/admin.py rename to dj_rest_auth/admin.py diff --git a/rest_auth/app_settings.py b/dj_rest_auth/app_settings.py similarity index 97% rename from rest_auth/app_settings.py rename to dj_rest_auth/app_settings.py index 1b75fe6a..9974c2d7 100644 --- a/rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -1,6 +1,6 @@ from django.conf import settings -from rest_auth.serializers import ( +from dj_rest_auth.serializers import ( TokenSerializer as DefaultTokenSerializer, JWTSerializer as DefaultJWTSerializer, UserDetailsSerializer as DefaultUserDetailsSerializer, diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.mo b/dj_rest_auth/locale/cs/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/cs/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/cs/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/dj_rest_auth/locale/cs/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/cs/LC_MESSAGES/django.po rename to dj_rest_auth/locale/cs/LC_MESSAGES/django.po diff --git a/rest_auth/locale/de/LC_MESSAGES/django.mo b/dj_rest_auth/locale/de/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/de/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/de/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/de/LC_MESSAGES/django.po b/dj_rest_auth/locale/de/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/de/LC_MESSAGES/django.po rename to dj_rest_auth/locale/de/LC_MESSAGES/django.po diff --git a/rest_auth/locale/es/LC_MESSAGES/django.mo b/dj_rest_auth/locale/es/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/es/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/es/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/es/LC_MESSAGES/django.po b/dj_rest_auth/locale/es/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/es/LC_MESSAGES/django.po rename to dj_rest_auth/locale/es/LC_MESSAGES/django.po diff --git a/rest_auth/locale/fr/LC_MESSAGES/django.mo b/dj_rest_auth/locale/fr/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/fr/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/fr/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/fr/LC_MESSAGES/django.po b/dj_rest_auth/locale/fr/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/fr/LC_MESSAGES/django.po rename to dj_rest_auth/locale/fr/LC_MESSAGES/django.po diff --git a/rest_auth/locale/ko/LC_MESSAGES/django.mo b/dj_rest_auth/locale/ko/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/ko/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/ko/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/ko/LC_MESSAGES/django.po b/dj_rest_auth/locale/ko/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/ko/LC_MESSAGES/django.po rename to dj_rest_auth/locale/ko/LC_MESSAGES/django.po diff --git a/rest_auth/locale/pl/LC_MESSAGES/django.mo b/dj_rest_auth/locale/pl/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/pl/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/pl/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/pl/LC_MESSAGES/django.po b/dj_rest_auth/locale/pl/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/pl/LC_MESSAGES/django.po rename to dj_rest_auth/locale/pl/LC_MESSAGES/django.po diff --git a/rest_auth/locale/pt_BR/LC_MESSAGES/django.po b/dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/pt_BR/LC_MESSAGES/django.po rename to dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.po diff --git a/rest_auth/locale/ru/LC_MESSAGES/django.mo b/dj_rest_auth/locale/ru/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/ru/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/ru/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/ru/LC_MESSAGES/django.po b/dj_rest_auth/locale/ru/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/ru/LC_MESSAGES/django.po rename to dj_rest_auth/locale/ru/LC_MESSAGES/django.po diff --git a/rest_auth/locale/tr/LC_MESSAGES/django.po b/dj_rest_auth/locale/tr/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/tr/LC_MESSAGES/django.po rename to dj_rest_auth/locale/tr/LC_MESSAGES/django.po diff --git a/rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo b/dj_rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/zh_Hans/LC_MESSAGES/django.po b/dj_rest_auth/locale/zh_Hans/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/zh_Hans/LC_MESSAGES/django.po rename to dj_rest_auth/locale/zh_Hans/LC_MESSAGES/django.po diff --git a/rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo b/dj_rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo rename to dj_rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/zh_Hant/LC_MESSAGES/django.po b/dj_rest_auth/locale/zh_Hant/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/zh_Hant/LC_MESSAGES/django.po rename to dj_rest_auth/locale/zh_Hant/LC_MESSAGES/django.po diff --git a/rest_auth/models.py b/dj_rest_auth/models.py similarity index 100% rename from rest_auth/models.py rename to dj_rest_auth/models.py diff --git a/rest_auth/registration/__init__.py b/dj_rest_auth/registration/__init__.py similarity index 100% rename from rest_auth/registration/__init__.py rename to dj_rest_auth/registration/__init__.py diff --git a/rest_auth/registration/app_settings.py b/dj_rest_auth/registration/app_settings.py similarity index 100% rename from rest_auth/registration/app_settings.py rename to dj_rest_auth/registration/app_settings.py diff --git a/rest_auth/registration/serializers.py b/dj_rest_auth/registration/serializers.py similarity index 100% rename from rest_auth/registration/serializers.py rename to dj_rest_auth/registration/serializers.py diff --git a/rest_auth/registration/urls.py b/dj_rest_auth/registration/urls.py similarity index 100% rename from rest_auth/registration/urls.py rename to dj_rest_auth/registration/urls.py diff --git a/rest_auth/registration/views.py b/dj_rest_auth/registration/views.py similarity index 100% rename from rest_auth/registration/views.py rename to dj_rest_auth/registration/views.py diff --git a/rest_auth/serializers.py b/dj_rest_auth/serializers.py similarity index 100% rename from rest_auth/serializers.py rename to dj_rest_auth/serializers.py diff --git a/rest_auth/social_serializers.py b/dj_rest_auth/social_serializers.py similarity index 100% rename from rest_auth/social_serializers.py rename to dj_rest_auth/social_serializers.py diff --git a/rest_auth/tests/__init__.py b/dj_rest_auth/tests/__init__.py similarity index 100% rename from rest_auth/tests/__init__.py rename to dj_rest_auth/tests/__init__.py diff --git a/rest_auth/tests/django_urls.py b/dj_rest_auth/tests/django_urls.py similarity index 100% rename from rest_auth/tests/django_urls.py rename to dj_rest_auth/tests/django_urls.py diff --git a/rest_auth/tests/mixins.py b/dj_rest_auth/tests/mixins.py similarity index 100% rename from rest_auth/tests/mixins.py rename to dj_rest_auth/tests/mixins.py diff --git a/rest_auth/tests/requirements.pip b/dj_rest_auth/tests/requirements.pip similarity index 100% rename from rest_auth/tests/requirements.pip rename to dj_rest_auth/tests/requirements.pip diff --git a/rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py similarity index 100% rename from rest_auth/tests/settings.py rename to dj_rest_auth/tests/settings.py diff --git a/rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py similarity index 100% rename from rest_auth/tests/test_api.py rename to dj_rest_auth/tests/test_api.py diff --git a/rest_auth/tests/test_social.py b/dj_rest_auth/tests/test_social.py similarity index 100% rename from rest_auth/tests/test_social.py rename to dj_rest_auth/tests/test_social.py diff --git a/rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py similarity index 100% rename from rest_auth/tests/urls.py rename to dj_rest_auth/tests/urls.py diff --git a/rest_auth/urls.py b/dj_rest_auth/urls.py similarity index 100% rename from rest_auth/urls.py rename to dj_rest_auth/urls.py diff --git a/rest_auth/utils.py b/dj_rest_auth/utils.py similarity index 100% rename from rest_auth/utils.py rename to dj_rest_auth/utils.py diff --git a/rest_auth/views.py b/dj_rest_auth/views.py similarity index 100% rename from rest_auth/views.py rename to dj_rest_auth/views.py diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index 46d2a050..a2a4c7d7 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -72,7 +72,7 @@ Basing on example from installation section :doc:`Installation ` - access_token - code - .. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/registration/views.py + .. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/Tivix/django-rest-auth/blob/master/dj_rest_auth/registration/views.py - /rest-auth/twitter/ (POST) diff --git a/docs/changelog.rst b/docs/changelog.rst index e7beb5da..2bb3f4ca 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -28,7 +28,7 @@ Changelog 0.9.1 ----- -- fixed import error when extending rest_auth serializers +- fixed import error when extending dj_rest_auth serializers - added sensitive fields decorator - added Spanish translations @@ -109,7 +109,7 @@ Changelog ----- - replaced ``django-registration`` with ``django-allauth`` -- moved registration logic to separated django application (``rest_auth.registration``) +- moved registration logic to separated django application (``dj_rest_auth.registration``) - added serializers customization in django settings - added social media authentication view - changed request method from GET to POST in logout endpoint diff --git a/docs/configuration.rst b/docs/configuration.rst index 59b301fb..b988a765 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -6,19 +6,19 @@ Configuration You can define your custom serializers for each endpoint without overriding urls and views by adding ``REST_AUTH_SERIALIZERS`` dictionary in your django settings. Possible key values: - - LOGIN_SERIALIZER - serializer class in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.LoginSerializer`` + - LOGIN_SERIALIZER - serializer class in ``dj_rest_auth.views.LoginView``, default value ``rest_auth.serializers.LoginSerializer`` - - TOKEN_SERIALIZER - response for successful authentication in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.TokenSerializer`` + - TOKEN_SERIALIZER - response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``rest_auth.serializers.TokenSerializer`` - - JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.JWTSerializer`` + - JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``rest_auth.serializers.JWTSerializer`` - - USER_DETAILS_SERIALIZER - serializer class in ``rest_auth.views.UserDetailsView``, default value ``rest_auth.serializers.UserDetailsSerializer`` + - USER_DETAILS_SERIALIZER - serializer class in ``dj_rest_auth.views.UserDetailsView``, default value ``rest_auth.serializers.UserDetailsSerializer`` - - PASSWORD_RESET_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetView``, default value ``rest_auth.serializers.PasswordResetSerializer`` + - PASSWORD_RESET_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetView``, default value ``rest_auth.serializers.PasswordResetSerializer`` - - PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetConfirmView``, default value ``rest_auth.serializers.PasswordResetConfirmSerializer`` + - PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetConfirmView``, default value ``rest_auth.serializers.PasswordResetConfirmSerializer`` - - PASSWORD_CHANGE_SERIALIZER - serializer class in ``rest_auth.views.PasswordChangeView``, default value ``rest_auth.serializers.PasswordChangeSerializer`` + - PASSWORD_CHANGE_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordChangeView``, default value ``rest_auth.serializers.PasswordChangeSerializer`` Example configuration: @@ -36,13 +36,13 @@ Configuration You can define your custom serializers for registration endpoint. Possible key values: - - REGISTER_SERIALIZER - serializer class in ``rest_auth.registration.views.RegisterView``, default value ``rest_auth.registration.serializers.RegisterSerializer`` + - REGISTER_SERIALIZER - serializer class in ``dj_rest_auth.registration.views.RegisterView``, default value ``rest_auth.registration.serializers.RegisterSerializer`` .. note:: The custom REGISTER_SERIALIZER must define a ``def save(self, request)`` method that returns a user model instance - **REST_AUTH_TOKEN_MODEL** - model class for tokens, default value ``rest_framework.authtoken.models`` -- **REST_AUTH_TOKEN_CREATOR** - callable to create tokens, default value ``rest_auth.utils.default_create_token``. +- **REST_AUTH_TOKEN_CREATOR** - callable to create tokens, default value ``dj_rest_auth.utils.default_create_token``. - **REST_SESSION_LOGIN** - Enable session login in Login API view (default: True) diff --git a/docs/faq.rst b/docs/faq.rst index d15566ae..4a382114 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -3,7 +3,7 @@ FAQ 1. Why account_confirm_email url is defined but it is not usable? - In /rest_auth/registration/urls.py we can find something like this: + In /dj_rest_auth/registration/urls.py we can find something like this: .. code-block:: python @@ -36,12 +36,12 @@ FAQ # custom fields for user company_name = models.CharField(max_length=100) - To allow update user details within one request send to rest_auth.views.UserDetailsView view, create serializer like this: + To allow update user details within one request send to dj_rest_auth.views.UserDetailsView view, create serializer like this: .. code-block:: python from rest_framework import serializers - from rest_auth.serializers import UserDetailsSerializer + from dj_rest_auth.serializers import UserDetailsSerializer class UserSerializer(UserDetailsSerializer): diff --git a/docs/installation.rst b/docs/installation.rst index b382d43f..d506727e 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -7,7 +7,7 @@ Installation pip install django-rest-auth -2. Add ``rest_auth`` app to INSTALLED_APPS in your django settings.py: +2. Add ``dj_rest_auth`` app to INSTALLED_APPS in your django settings.py: .. code-block:: python @@ -16,19 +16,19 @@ Installation 'rest_framework', 'rest_framework.authtoken', ..., - 'rest_auth' + 'dj_rest_auth' ) .. note:: This project depends on ``django-rest-framework`` library, so install it if you haven't done yet. Make sure also you have installed ``rest_framework`` and ``rest_framework.authtoken`` apps -3. Add rest_auth urls: +3. Add dj_rest_auth urls: .. code-block:: python urlpatterns = [ ..., - url(r'^rest-auth/', include('rest_auth.urls')) + url(r'^rest-auth/', include('dj_rest_auth.urls')) ] 4. Migrate your database @@ -46,7 +46,7 @@ Registration (optional) 1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install django-rest-auth[with_social]``. -2. Add ``django.contrib.sites``, ``allauth``, ``allauth.account`` and ``rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py: +2. Add ``django.contrib.sites``, ``allauth``, ``allauth.account`` and ``dj_rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py: 3. Add ``SITE_ID = 1`` to your django settings.py @@ -57,19 +57,19 @@ Registration (optional) 'django.contrib.sites', 'allauth', 'allauth.account', - 'rest_auth.registration', + 'dj_rest_auth.registration', ) SITE_ID = 1 -3. Add rest_auth.registration urls: +3. Add dj_rest_auth.registration urls: .. code-block:: python urlpatterns = [ ..., - url(r'^rest-auth/', include('rest_auth.urls')), - url(r'^rest-auth/registration/', include('rest_auth.registration.urls')) + url(r'^rest-auth/', include('dj_rest_auth.urls')), + url(r'^rest-auth/registration/', include('dj_rest_auth.registration.urls')) ] @@ -88,12 +88,12 @@ Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creati ..., 'rest_framework', 'rest_framework.authtoken', - 'rest_auth' + 'dj_rest_auth' ..., 'django.contrib.sites', 'allauth', 'allauth.account', - 'rest_auth.registration', + 'dj_rest_auth.registration', ..., 'allauth.socialaccount', 'allauth.socialaccount.providers.facebook', @@ -106,12 +106,12 @@ Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creati Facebook ######## -3. Create new view as a subclass of ``rest_auth.registration.views.SocialLoginView`` with ``FacebookOAuth2Adapter`` adapter as an attribute: +3. Create new view as a subclass of ``dj_rest_auth.registration.views.SocialLoginView`` with ``FacebookOAuth2Adapter`` adapter as an attribute: .. code-block:: python from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - from rest_auth.registration.views import SocialLoginView + from dj_rest_auth.registration.views import SocialLoginView class FacebookLogin(SocialLoginView): adapter_class = FacebookOAuth2Adapter @@ -131,13 +131,13 @@ Twitter If you are using Twitter for your social authentication, it is a bit different since Twitter uses OAuth 1.0. -3. Create new view as a subclass of ``rest_auth.registration.views.SocialLoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute: +3. Create new view as a subclass of ``dj_rest_auth.registration.views.SocialLoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute: .. code-block:: python from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter - from rest_auth.registration.views import SocialLoginView - from rest_auth.social_serializers import TwitterLoginSerializer + from dj_rest_auth.registration.views import SocialLoginView + from dj_rest_auth.social_serializers import TwitterLoginSerializer class TwitterLogin(SocialLoginView): serializer_class = TwitterLoginSerializer @@ -160,13 +160,13 @@ GitHub If you are using GitHub for your social authentication, it uses code and not AccessToken directly. -3. Create new view as a subclass of ``rest_auth.views.SocialLoginView`` with ``GitHubOAuth2Adapter`` adapter, an ``OAuth2Client`` and a callback_url as attributes: +3. Create new view as a subclass of ``dj_rest_auth.views.SocialLoginView`` with ``GitHubOAuth2Adapter`` adapter, an ``OAuth2Client`` and a callback_url as attributes: .. code-block:: python from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter from allauth.socialaccount.providers.oauth2.client import OAuth2Client - from rest_auth.registration.views import SocialLoginView + from dj_rest_auth.registration.views import SocialLoginView class GithubLogin(SocialLoginView): adapter_class = GitHubOAuth2Adapter @@ -193,8 +193,8 @@ If you want to allow connecting existing accounts in addition to login, you can from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter from allauth.socialaccount.providers.oauth2.client import OAuth2Client - from rest_auth.registration.views import SocialConnectView - from rest_auth.social_serializers import TwitterConnectSerializer + from dj_rest_auth.registration.views import SocialConnectView + from dj_rest_auth.social_serializers import TwitterConnectSerializer class FacebookConnect(SocialConnectView): adapter_class = FacebookOAuth2Adapter @@ -224,7 +224,7 @@ You can also use the following views to check all social accounts attached to th .. code-block:: python - from rest_auth.registration.views import ( + from dj_rest_auth.registration.views import ( SocialAccountListView, SocialAccountDisconnectView ) diff --git a/docs/introduction.rst b/docs/introduction.rst index 191abb50..25cc9148 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -18,8 +18,8 @@ Features Apps structure -------------- -* ``rest_auth`` has basic auth functionality like login, logout, password reset and password change -* ``rest_auth.registration`` has logic related with registration and social media authentication +* ``dj_rest_auth`` has basic auth functionality like login, logout, password reset and password change +* ``dj_rest_auth.registration`` has logic related with registration and social media authentication Angular app From f7da276bd2277576625f111d6732e70670b9a7c8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 18:10:25 -0600 Subject: [PATCH 004/130] Updates names --- README.rst | 31 -------------------- dj_rest_auth/locale/cs/LC_MESSAGES/django.po | 8 ++--- dj_rest_auth/views.py | 2 +- docs/Makefile | 8 ++--- docs/api_endpoints.rst | 24 +++++++-------- docs/conf.py | 20 ++++++------- docs/demo.rst | 6 ++-- docs/index.rst | 24 +++++++-------- docs/installation.rst | 8 ++--- docs/introduction.rst | 4 +-- docs/make.bat | 4 +-- setup.py | 4 +-- 12 files changed, 56 insertions(+), 87 deletions(-) delete mode 100644 README.rst diff --git a/README.rst b/README.rst deleted file mode 100644 index f79511f2..00000000 --- a/README.rst +++ /dev/null @@ -1,31 +0,0 @@ -Welcome to dj-rest-auth -=========================== - -.. image:: https://travis-ci.org/iMerica/dj-rest-auth.svg - :target: https://travis-ci.org/iMerica/dj-rest-auth - - -.. image:: https://coveralls.io/repos/iMerica/dj-rest-auth/badge.svg - :target: https://coveralls.io/r/iMerica/dj-rest-auth?branch=master - - -.. image:: https://readthedocs.org/projects/dj-rest-auth/badge/?version=latest - :target: https://readthedocs.org/projects/dj-rest-auth/?badge=latest - - -Django-dj-rest-auth provides a set of REST API endpoints for Authentication and Registration - - -Documentation -------------- -http://dj-rest-auth.readthedocs.org/en/latest/ - - -Source code ------------ -https://github.com/iMerica/dj-rest-auth - - -Stack Overflow ------------ -http://stackoverflow.com/questions/tagged/dj-rest-auth diff --git a/dj_rest_auth/locale/cs/LC_MESSAGES/django.po b/dj_rest_auth/locale/cs/LC_MESSAGES/django.po index eb8c60c0..e6acf92f 100644 --- a/dj_rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/dj_rest_auth/locale/cs/LC_MESSAGES/django.po @@ -1,11 +1,11 @@ -# Czech translations of Tivix/django-rest-auth +# Czech translations of iMerica/dj-rest-auth # -# This file is distributed under the same license as the Tivix/django-rest-auth package. +# This file is distributed under the same license as the iMerica/dj-rest-auth package. # msgid "" msgstr "" -"Project-Id-Version: Tivix/django-rest-auth\n" -"Report-Msgid-Bugs-To: https://github.com/Tivix/django-rest-auth/issues\n" +"Project-Id-Version: iMerica/dj-rest-auth\n" +"Report-Msgid-Bugs-To: https://github.com/iMerica/dj-rest-auth/issues\n" "POT-Creation-Date: 2018-06-27 23:05+0200\n" "PO-Revision-Date: 2018-06-27 23:22+0200\n" "Language: cs\n" diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 0a0a982e..0a27f8e6 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -164,7 +164,7 @@ def get_queryset(self): """ Adding this method since it is sometimes called when using django-rest-swagger - https://github.com/Tivix/django-rest-auth/issues/275 + https://github.com/iMerica/dj-rest-auth/issues/275 """ return get_user_model().objects.none() diff --git a/docs/Makefile b/docs/Makefile index cf092886..e71af70c 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -85,17 +85,17 @@ qthelp: @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-rest-auth.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/dj-rest-auth.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-rest-auth.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/dj-rest-auth.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/django-rest-auth" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-rest-auth" + @echo "# mkdir -p $$HOME/.local/share/devhelp/dj-rest-auth" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/dj-rest-auth" @echo "# devhelp" epub: diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index a2a4c7d7..f23dabdb 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -4,7 +4,7 @@ API endpoints Basic ----- -- /rest-auth/login/ (POST) +- /dj-rest-auth/login/ (POST) - username - email @@ -12,24 +12,24 @@ Basic Returns Token key -- /rest-auth/logout/ (POST) +- /dj-rest-auth/logout/ (POST) .. note:: ``ACCOUNT_LOGOUT_ON_GET = True`` to allow logout using GET - this is the exact same configuration from allauth. NOT recommended, see: http://django-allauth.readthedocs.io/en/latest/views.html#logout -- /rest-auth/password/reset/ (POST) +- /dj-rest-auth/password/reset/ (POST) - email -- /rest-auth/password/reset/confirm/ (POST) +- /dj-rest-auth/password/reset/confirm/ (POST) - uid - token - new_password1 - new_password2 - .. note:: uid and token are sent in email after calling /rest-auth/password/reset/ + .. note:: uid and token are sent in email after calling /dj-rest-auth/password/reset/ -- /rest-auth/password/change/ (POST) +- /dj-rest-auth/password/change/ (POST) - new_password1 - new_password2 @@ -38,7 +38,7 @@ Basic .. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password. .. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change -- /rest-auth/user/ (GET, PUT, PATCH) +- /dj-rest-auth/user/ (GET, PUT, PATCH) - username - first_name @@ -50,14 +50,14 @@ Basic Registration ------------ -- /rest-auth/registration/ (POST) +- /dj-rest-auth/registration/ (POST) - username - password1 - password2 - email -- /rest-auth/registration/verify-email/ (POST) +- /dj-rest-auth/registration/verify-email/ (POST) - key @@ -67,14 +67,14 @@ Social Media Authentication Basing on example from installation section :doc:`Installation ` -- /rest-auth/facebook/ (POST) +- /dj-rest-auth/facebook/ (POST) - access_token - code - .. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/Tivix/django-rest-auth/blob/master/dj_rest_auth/registration/views.py + .. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/iMerica/dj-rest-auth/blob/master/dj_rest_auth/registration/views.py -- /rest-auth/twitter/ (POST) +- /dj-rest-auth/twitter/ (POST) - access_token - token_secret diff --git a/docs/conf.py b/docs/conf.py index 1c825cc2..dd54bb68 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# django-rest-auth documentation build configuration file, created by +# dj-rest-auth documentation build configuration file, created by # sphinx-quickstart on Wed Oct 8 15:59:37 2014. # # This file is execfile()d with the current directory set to its @@ -43,8 +43,8 @@ master_doc = 'index' # General information about the project. -project = u'django-rest-auth' -copyright = u'2018, Tivix Inc.' +project = u'dj-rest-auth' +copyright = u'2018, iMerica Inc.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -176,7 +176,7 @@ #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'django-rest-authdoc' +htmlhelp_basename = 'dj-rest-authdoc' # -- Options for LaTeX output --------------------------------------------- @@ -196,8 +196,8 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'django-rest-auth.tex', u'django-rest-auth Documentation', - u'Tivix Inc.', 'manual'), + ('index', 'dj-rest-auth.tex', u'dj-rest-auth Documentation', + u'iMerica Inc.', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -226,8 +226,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'django-rest-auth', u'django-rest-auth Documentation', - [u'Tivix Inc.'], 1) + ('index', 'dj-rest-auth', u'dj-rest-auth Documentation', + [u'iMerica Inc.'], 1) ] # If true, show URL addresses after external links. @@ -240,8 +240,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'django-rest-auth', u'django-rest-auth Documentation', - u'Tivix Inc.', 'django-rest-auth', 'One line description of project.', + ('index', 'dj-rest-auth', u'dj-rest-auth Documentation', + u'iMerica Inc.', 'dj-rest-auth', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/demo.rst b/docs/demo.rst index 877ca334..22620f87 100644 --- a/docs/demo.rst +++ b/docs/demo.rst @@ -2,14 +2,14 @@ Demo project ============ The idea of creating demo project was to show how you can potentially use -django-rest-auth app with jQuery on frontend. +dj-rest-auth app with jQuery on frontend. Do these steps to make it running (ideally in virtualenv). .. code-block:: python cd /tmp - git clone https://github.com/Tivix/django-rest-auth.git - cd django-rest-auth/demo/ + git clone https://github.com/iMerica/dj-rest-auth.git + cd dj-rest-auth/demo/ pip install -r requirements.pip python manage.py migrate --settings=demo.settings --noinput python manage.py runserver --settings=demo.settings diff --git a/docs/index.rst b/docs/index.rst index dc25e83c..8be210a6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,14 +1,14 @@ -.. django-rest-auth documentation master file, created by +.. dj-rest-auth documentation master file, created by sphinx-quickstart on Wed Oct 8 15:59:37 2014. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to django-rest-auth's documentation! +Welcome to dj-rest-auth's documentation! ============================================ -.. warning:: Updating django-rest-auth from version **0.3.3** is highly recommended because of a security issue in PasswordResetConfirmation validation method. +.. warning:: Updating dj-rest-auth from version **0.3.3** is highly recommended because of a security issue in PasswordResetConfirmation validation method. -.. note:: django-rest-auth from v0.3.3 supports django-rest-framework v3.0 +.. note:: dj-rest-auth from v0.3.3 supports django-rest-framework v3.0 |build-status| |coverage-status| |requirements-status| |docs| @@ -28,25 +28,25 @@ Contents Changelog -.. |build-status| image:: https://travis-ci.org/Tivix/django-rest-auth.svg?branch=master +.. |build-status| image:: https://travis-ci.org/iMerica/dj-rest-auth.svg?branch=master :alt: build status :scale: 100% - :target: https://travis-ci.org/Tivix/django-rest-auth + :target: https://travis-ci.org/iMerica/dj-rest-auth -.. |coverage-status| image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.png?branch=master +.. |coverage-status| image:: https://coveralls.io/repos/iMerica/dj-rest-auth/badge.png?branch=master :alt: coverage status :scale: 100% - :target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master + :target: https://coveralls.io/r/iMerica/dj-rest-auth?branch=master -.. |requirements-status| image:: https://requires.io/github/Tivix/django-rest-auth/requirements.png?branch=master +.. |requirements-status| image:: https://requires.io/github/iMerica/dj-rest-auth/requirements.png?branch=master :alt: requirements status :scale: 100% - :target: https://requires.io/github/Tivix/django-rest-auth/requirements/?branch=master + :target: https://requires.io/github/iMerica/dj-rest-auth/requirements/?branch=master -.. |docs| image:: https://readthedocs.org/projects/django-rest-auth/badge/?version=latest +.. |docs| image:: https://readthedocs.org/projects/dj-rest-auth/badge/?version=latest :scale: 100% - :target: https://readthedocs.org/projects/django-rest-auth/?badge=latest + :target: https://readthedocs.org/projects/dj-rest-auth/?badge=latest :alt: Documentation Status diff --git a/docs/installation.rst b/docs/installation.rst index d506727e..395299a9 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -5,7 +5,7 @@ Installation .. code-block:: python - pip install django-rest-auth + pip install dj-rest-auth 2. Add ``dj_rest_auth`` app to INSTALLED_APPS in your django settings.py: @@ -44,7 +44,7 @@ You're good to go now! Registration (optional) ----------------------- -1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install django-rest-auth[with_social]``. +1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install dj-rest-auth[with_social]``. 2. Add ``django.contrib.sites``, ``allauth``, ``allauth.account`` and ``dj_rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py: @@ -76,7 +76,7 @@ Registration (optional) Social Authentication (optional) -------------------------------- -Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creating social media authentication view. +Using ``django-allauth``, ``dj-rest-auth`` provides helpful class for creating social media authentication view. .. note:: Points 1 and 2 are related to ``django-allauth`` configuration, so if you have already configured social authentication, then please go to step 3. See ``django-allauth`` documentation for more details. @@ -246,7 +246,7 @@ You can also use the following views to check all social accounts attached to th JSON Web Token (JWT) Support (optional) --------------------------------------- -By default ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, follow these steps: +By default ``dj-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, follow these steps: 1. Install `djangorestframework-jwt `_ - ``djangorestframework-jwt`` is currently the only supported JWT library. diff --git a/docs/introduction.rst b/docs/introduction.rst index 25cc9148..6f4d354c 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -2,7 +2,7 @@ Introduction ============ -Since the introduction of django-rest-framework, Django apps have been able to serve up app-level REST API endpoints. As a result, we saw a lot of instances where developers implemented their own REST registration API endpoints here and there, snippets, and so on. We aim to solve this demand by providing django-rest-auth, a set of REST API endpoints to handle User Registration and Authentication tasks. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for User Management. Of course, we'll add more API endpoints as we see the demand. +Since the introduction of django-rest-framework, Django apps have been able to serve up app-level REST API endpoints. As a result, we saw a lot of instances where developers implemented their own REST registration API endpoints here and there, snippets, and so on. We aim to solve this demand by providing dj-rest-auth, a set of REST API endpoints to handle User Registration and Authentication tasks. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for User Management. Of course, we'll add more API endpoints as we see the demand. Features -------- @@ -25,7 +25,7 @@ Apps structure Angular app ----------- -- Tivix has also created angular module which uses API endpoints from this app - `angular-django-registration-auth `_ +- iMerica has also created angular module which uses API endpoints from this app - `angular-django-registration-auth `_ Demo project diff --git a/docs/make.bat b/docs/make.bat index db1383db..3aff4bbe 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -115,9 +115,9 @@ if "%1" == "qthelp" ( echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\django-rest-auth.qhcp + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\dj-rest-auth.qhcp echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-rest-auth.ghc + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\dj-rest-auth.ghc goto end ) diff --git a/setup.py b/setup.py index 675b99d6..30ee6819 100644 --- a/setup.py +++ b/setup.py @@ -11,11 +11,11 @@ setup( - name='django-rest-auth', + name='dj-rest-auth', version='0.9.5', author='Sumit Chachra', author_email='chachra@tivix.com', - url='http://github.com/Tivix/django-rest-auth', + url='http://github.com/iMerica/dj-rest-auth', description='Create a set of REST API endpoints for Authentication and Registration', packages=find_packages(), long_description=long_description, From 082497429255c2d752e8ca0b797fb8a62141e267 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 18:58:59 -0600 Subject: [PATCH 005/130] Adds circle CI --- LICENSE | 2 +- config.yml | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 config.yml diff --git a/LICENSE b/LICENSE index f868a2a7..42a02920 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 iMerica +Copyright (c) 2014 iMerica https://github.com/iMerica/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/config.yml b/config.yml new file mode 100644 index 00000000..3210e8c3 --- /dev/null +++ b/config.yml @@ -0,0 +1,32 @@ +version: 2.1 +orbs: + python: circleci/python@0.2.1 + +jobs: + build-latest: &template + environment: + DJANGO_VERSION: 3.0.* + DRF: 3.9.* + executor: python/default + steps: + - checkout + - python/load-cache + - run: + - echo -n $DJANGO_VERSION > requirements.txt + - echo -n $DRF >> requirements.txt + - pip install -r requirements.txt + - python/save-cache + - run: + command: ./manage.py test + name: Test + build-django-2: + <<: *template + environment: + DJANGO_VERSION: 2.0.* + DRF: 3.9.* + +workflows: + main: + jobs: + - build-latest + - build-django-2 \ No newline at end of file From 2e5df3b3e70c32ad1286bf3b97c30e704b44d9a9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:00:25 -0600 Subject: [PATCH 006/130] Fixes Circle location --- config.yml => .circleci/config.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config.yml => .circleci/config.yml (100%) diff --git a/config.yml b/.circleci/config.yml similarity index 100% rename from config.yml rename to .circleci/config.yml From 5c50d0cb7f8f007f032f36a7fec712f0ccf2e8fc Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:03:43 -0600 Subject: [PATCH 007/130] Fixes YAML schema --- .circleci/config.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3210e8c3..f270c2ea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,10 +11,9 @@ jobs: steps: - checkout - python/load-cache - - run: - - echo -n $DJANGO_VERSION > requirements.txt - - echo -n $DRF >> requirements.txt - - pip install -r requirements.txt + - run: echo -n $DJANGO_VERSION > requirements.txt + - run: echo -n $DRF >> requirements.txt + - run: pip install -r requirements.txt - python/save-cache - run: command: ./manage.py test From 0797ce257f72d8f8c11eb20dc01356cc9c42793f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:06:43 -0600 Subject: [PATCH 008/130] Remove cache --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f270c2ea..68175a15 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,11 +10,9 @@ jobs: executor: python/default steps: - checkout - - python/load-cache - run: echo -n $DJANGO_VERSION > requirements.txt - run: echo -n $DRF >> requirements.txt - run: pip install -r requirements.txt - - python/save-cache - run: command: ./manage.py test name: Test From 03925f46e40eae7585f390a3d39ff481523e54bf Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:07:45 -0600 Subject: [PATCH 009/130] Removes echo flag --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 68175a15..a3da36ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,8 +10,8 @@ jobs: executor: python/default steps: - checkout - - run: echo -n $DJANGO_VERSION > requirements.txt - - run: echo -n $DRF >> requirements.txt + - run: echo $DJANGO_VERSION > requirements.txt + - run: echo $DRF >> requirements.txt - run: pip install -r requirements.txt - run: command: ./manage.py test From 5faeda0c3a95a7ebfe7a6532bb341b00e3936625 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:11:49 -0600 Subject: [PATCH 010/130] Updates yaml --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a3da36ba..7aca92f2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,13 +5,13 @@ orbs: jobs: build-latest: &template environment: - DJANGO_VERSION: 3.0.* - DRF: 3.9.* + DJANGO_VERSION: 3.0 + DRF: 3.9 executor: python/default steps: - checkout - - run: echo $DJANGO_VERSION > requirements.txt - - run: echo $DRF >> requirements.txt + - run: echo "Django==$DJANGO_VERSION" > requirements.txt + - run: echo "djangorestframework==$DRF" >> requirements.txt - run: pip install -r requirements.txt - run: command: ./manage.py test @@ -19,8 +19,8 @@ jobs: build-django-2: <<: *template environment: - DJANGO_VERSION: 2.0.* - DRF: 3.9.* + DJANGO_VERSION: 2.0 + DRF: 3.9 workflows: main: From a7025c1146424ef48eba3e89bf36d3c686746462 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:13:28 -0600 Subject: [PATCH 011/130] Runs tests --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7aca92f2..0ab50c56 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ jobs: - run: echo "djangorestframework==$DRF" >> requirements.txt - run: pip install -r requirements.txt - run: - command: ./manage.py test + command: ./runtest.py name: Test build-django-2: <<: *template From b2300a4981c711906584ef80dd5323a96250388f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:15:56 -0600 Subject: [PATCH 012/130] Fixes test command --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ab50c56..771be203 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,9 +12,10 @@ jobs: - checkout - run: echo "Django==$DJANGO_VERSION" > requirements.txt - run: echo "djangorestframework==$DRF" >> requirements.txt + - run: pip install coveralls - run: pip install -r requirements.txt - run: - command: ./runtest.py + command: coverage run --source=dj_rest_auth setup.py test name: Test build-django-2: <<: *template From 41dce8885a3b010ba95b4f732ed12d7003814763 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:46:32 -0600 Subject: [PATCH 013/130] Fixes tests --- README.md | 0 dj_rest_auth/tests/django_urls.py | 45 ++++++++++++++++++++----------- dj_rest_auth/tests/settings.py | 4 ++- runtests.py | 4 +-- setup.py | 7 ++--- 5 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..e69de29b diff --git a/dj_rest_auth/tests/django_urls.py b/dj_rest_auth/tests/django_urls.py index c1fb050e..57f9d7d2 100644 --- a/dj_rest_auth/tests/django_urls.py +++ b/dj_rest_auth/tests/django_urls.py @@ -1,30 +1,45 @@ # Moved in Django 1.8 from django to tests/auth_tests/urls.py from django.conf.urls import url -from django.contrib.auth import views from django.contrib.auth.decorators import login_required from django.contrib.auth.urls import urlpatterns +try: + from django.contrib.auth.views import ( + logout, login, password_reset, + password_change, password_reset_confirm + ) +except ImportError: + from django.contrib.auth.views import ( + LoginView, LogoutView, PasswordResetView, + PasswordChangeView, PasswordResetConfirmView + ) + logout = LogoutView.as_view() + login = LoginView.as_view() + password_reset = PasswordResetView.as_view() + password_change = PasswordChangeView.as_view() + password_reset_confirm = PasswordResetConfirmView.as_view() + # special urls for auth test cases urlpatterns += [ - url(r'^logout/custom_query/$', views.logout, dict(redirect_field_name='follow')), - url(r'^logout/next_page/$', views.logout, dict(next_page='/somewhere/')), - url(r'^logout/next_page/named/$', views.logout, dict(next_page='password_reset')), - url(r'^password_reset_from_email/$', views.password_reset, dict(from_email='staffmember@example.com')), - url(r'^password_reset/custom_redirect/$', views.password_reset, dict(post_reset_redirect='/custom/')), - url(r'^password_reset/custom_redirect/named/$', views.password_reset, dict(post_reset_redirect='password_reset')), - url(r'^password_reset/html_email_template/$', views.password_reset, + url(r'^logout/custom_query/$', logout, dict(redirect_field_name='follow')), + url(r'^logout/next_page/$', logout, dict(next_page='/somewhere/')), + url(r'^logout/next_page/named/$', logout, dict(next_page='password_reset')), + url(r'^password_reset_from_email/$', password_reset, dict(from_email='staffmember@example.com')), + url(r'^password_reset/custom_redirect/$', password_reset, dict(post_reset_redirect='/custom/')), + url(r'^password_reset/custom_redirect/named/$', password_reset, dict(post_reset_redirect='password_reset')), + url(r'^password_reset/html_email_template/$', password_reset, dict(html_email_template_name='registration/html_password_reset_email.html')), url(r'^reset/custom/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', - views.password_reset_confirm, + password_reset_confirm, dict(post_reset_redirect='/custom/')), url(r'^reset/custom/named/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', - views.password_reset_confirm, + password_reset_confirm, dict(post_reset_redirect='password_reset')), - url(r'^password_change/custom/$', views.password_change, dict(post_change_redirect='/custom/')), - url(r'^password_change/custom/named/$', views.password_change, dict(post_change_redirect='password_reset')), - url(r'^admin_password_reset/$', views.password_reset, dict(is_admin_site=True)), - url(r'^login_required/$', login_required(views.password_reset)), - url(r'^login_required_login_url/$', login_required(views.password_reset, login_url='/somewhere/')), + url(r'^password_change/custom/$', password_change, dict(post_change_redirect='/custom/')), + url(r'^password_change/custom/named/$', password_change, dict(post_change_redirect='password_reset')), + url(r'^admin_password_reset/$', password_reset, dict(is_admin_site=True)), + url(r'^login_required/$', login_required(password_reset)), + url(r'^login_required_login_url/$', login_required(password_reset, login_url='/somewhere/')), ] diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index e353fb01..16ba4b52 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -1,8 +1,11 @@ import os import sys +import logging PROJECT_ROOT = os.path.abspath(os.path.split(os.path.split(__file__)[0])[0]) + +logging.disable(logging.CRITICAL) ROOT_URLCONF = 'urls' STATIC_URL = '/static/' STATIC_ROOT = '%s/staticserve' % PROJECT_ROOT @@ -70,7 +73,6 @@ } INSTALLED_APPS = [ - 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.humanize', 'django.contrib.contenttypes', diff --git a/runtests.py b/runtests.py index 8b7ede27..cabaf9c4 100644 --- a/runtests.py +++ b/runtests.py @@ -3,8 +3,8 @@ import os import sys -os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings' -test_dir = os.path.join(os.path.dirname(__file__), 'rest_auth') +os.environ['DJANGO_SETTINGS_MODULE'] = 'dj_rest_auth.tests.settings' +test_dir = os.path.join(os.path.dirname(__file__), 'dj_rest_auth') sys.path.insert(0, test_dir) import django diff --git a/setup.py b/setup.py index 30ee6819..472ce6b1 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ here = os.path.dirname(os.path.abspath(__file__)) -f = open(os.path.join(here, 'README.rst')) +f = open(os.path.join(here, 'README.md')) long_description = f.read().strip() f.close() @@ -13,12 +13,13 @@ setup( name='dj-rest-auth', version='0.9.5', - author='Sumit Chachra', - author_email='chachra@tivix.com', + author='iMerica', + author_email='imichael@pm.me', url='http://github.com/iMerica/dj-rest-auth', description='Create a set of REST API endpoints for Authentication and Registration', packages=find_packages(), long_description=long_description, + long_description_content_type='text/markdown', keywords='django rest auth registration rest-framework django-registration api', zip_safe=False, install_requires=[ From 331094b6a7b74681f97db43b587e899bec2d8420 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:54:53 -0600 Subject: [PATCH 014/130] Fixes Imports --- .travis.yml | 26 -------------------------- dj_rest_auth/registration/views.py | 10 +++++----- dj_rest_auth/tests/settings.py | 4 ++-- dj_rest_auth/tests/test_api.py | 4 ++-- dj_rest_auth/tests/urls.py | 6 +++--- dj_rest_auth/urls.py | 2 +- runtests.py | 2 +- 7 files changed, 14 insertions(+), 40 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 33f42ad3..00000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: python -python: - - "2.7" - - "3.5" - - "3.6" -env: - - DJANGO=1.11.* DRF=3.7.* - - DJANGO=1.11.* DRF=3.8.* - - DJANGO=2.0.* DRF=3.7.* - - DJANGO=2.0.* DRF=3.8.* -install: - - pip install -q Django==$DJANGO djangorestframework==$DRF - - pip install coveralls - - pip install -r dj_rest_auth/tests/requirements.pip -script: - - coverage run --source=dj_rest_auth setup.py test -after_success: - - coveralls -before_script: - - flake8 . --config=flake8 -matrix: - exclude: - - python: "2.7" - env: DJANGO=2.0.* DRF=3.7.* - - python: "2.7" - env: DJANGO=2.0.* DRF=3.8.* diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index 0e0ab0d0..f8d11204 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -19,16 +19,16 @@ from allauth.socialaccount.adapter import get_adapter as get_social_adapter from allauth.socialaccount.models import SocialAccount -from rest_auth.app_settings import (TokenSerializer, +from dj_rest_auth.app_settings import (TokenSerializer, JWTSerializer, create_token) -from rest_auth.models import TokenModel -from rest_auth.registration.serializers import (VerifyEmailSerializer, +from dj_rest_auth.models import TokenModel +from dj_rest_auth.registration.serializers import (VerifyEmailSerializer, SocialLoginSerializer, SocialAccountSerializer, SocialConnectSerializer) -from rest_auth.utils import jwt_encode -from rest_auth.views import LoginView +from dj_rest_auth.utils import jwt_encode +from dj_rest_auth.views import LoginView from .app_settings import RegisterSerializer, register_permission_classes sensitive_post_parameters_m = method_decorator( diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index 16ba4b52..c86bfc17 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -90,8 +90,8 @@ 'rest_framework', 'rest_framework.authtoken', - 'rest_auth', - 'rest_auth.registration', + 'dj_rest_auth', + 'dj_rest_auth.registration', 'rest_framework_jwt' ] diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 9c5fd9ea..b6d84f21 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -8,8 +8,8 @@ from rest_framework import status from rest_framework.test import APIRequestFactory -from rest_auth.registration.views import RegisterView -from rest_auth.registration.app_settings import register_permission_classes +from dj_rest_auth.registration.views import RegisterView +from dj_rest_auth.registration.app_settings import register_permission_classes from .mixins import TestsMixin, CustomPermissionClass diff --git a/dj_rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py index 401f23a6..ef900b95 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -7,12 +7,12 @@ from rest_framework.decorators import api_view -from rest_auth.urls import urlpatterns -from rest_auth.registration.views import ( +from dj_rest_auth.urls import urlpatterns +from dj_rest_auth.registration.views import ( SocialLoginView, SocialConnectView, SocialAccountListView, SocialAccountDisconnectView ) -from rest_auth.social_serializers import ( +from dj_rest_auth.social_serializers import ( TwitterLoginSerializer, TwitterConnectSerializer ) diff --git a/dj_rest_auth/urls.py b/dj_rest_auth/urls.py index 7a35e9b5..66647226 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -from rest_auth.views import ( +from dj_rest_auth.views import ( LoginView, LogoutView, UserDetailsView, PasswordChangeView, PasswordResetView, PasswordResetConfirmView ) diff --git a/runtests.py b/runtests.py index cabaf9c4..6fab5085 100644 --- a/runtests.py +++ b/runtests.py @@ -17,7 +17,7 @@ def runtests(): test_runner = TestRunner(verbosity=1, interactive=True) if hasattr(django, 'setup'): django.setup() - failures = test_runner.run_tests(['rest_auth']) + failures = test_runner.run_tests(['dj_rest_auth']) sys.exit(bool(failures)) if __name__ == '__main__': From 6ece00f6e9267ef83b1608cf00d0ca2d45fb8c5d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 19:59:44 -0600 Subject: [PATCH 015/130] Adds Docker runtime --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 771be203..2918fd5b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,6 +4,8 @@ orbs: jobs: build-latest: &template + docker: + - image: circleci/python:3.8.0 environment: DJANGO_VERSION: 3.0 DRF: 3.9 From c43965b55f3d3fdd33c61b351cdf6a66e446bacc Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 20:03:34 -0600 Subject: [PATCH 016/130] Removes Orb --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2918fd5b..16565f15 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,4 @@ version: 2.1 -orbs: - python: circleci/python@0.2.1 jobs: build-latest: &template From 8e7982e52b1cdb1a2a265925bf7240d75a66afbf Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 20:04:34 -0600 Subject: [PATCH 017/130] Uses Docker Orb --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 16565f15..17dbf105 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,6 @@ version: 2.1 +orbs: + docker: circleci/docker@0.6.0 jobs: build-latest: &template From 12883f8efce4fccf93b4c38f10d21f9a1e76f767 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 20:05:46 -0600 Subject: [PATCH 018/130] Uses Docker Executor --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 17dbf105..a5bfacb9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ jobs: environment: DJANGO_VERSION: 3.0 DRF: 3.9 - executor: python/default + executor: docker/docker steps: - checkout - run: echo "Django==$DJANGO_VERSION" > requirements.txt From 3402d1f2cd9e4b4cc74e31dffaacccfc70d445b0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 20:10:13 -0600 Subject: [PATCH 019/130] Uses pip install with user --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a5bfacb9..0fd7227e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,8 +14,8 @@ jobs: - checkout - run: echo "Django==$DJANGO_VERSION" > requirements.txt - run: echo "djangorestframework==$DRF" >> requirements.txt - - run: pip install coveralls - - run: pip install -r requirements.txt + - run: pip install --user coveralls + - run: pip install --user -r requirements.txt - run: command: coverage run --source=dj_rest_auth setup.py test name: Test From a87a458ccfefd279ba585d4080be3f3aa4a5c1c0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 20:30:21 -0600 Subject: [PATCH 020/130] Removes six --- demo/requirements.pip | 1 - dj_rest_auth/app_settings.py | 37 ++++++----------------- dj_rest_auth/models.py | 4 +-- dj_rest_auth/registration/app_settings.py | 9 +++--- dj_rest_auth/serializers.py | 5 +-- dj_rest_auth/utils.py | 12 -------- setup.py | 1 - 7 files changed, 16 insertions(+), 53 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index c6f5f42f..ab0a814e 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -2,5 +2,4 @@ django>=1.9.0 dj-rest-auth==0.9.5 djangorestframework>=3.7.0 django-allauth>=0.24.1 -six==1.9.0 django-rest-swagger==2.0.7 diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 9974c2d7..7f8094fa 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -8,44 +8,27 @@ PasswordResetSerializer as DefaultPasswordResetSerializer, PasswordResetConfirmSerializer as DefaultPasswordResetConfirmSerializer, PasswordChangeSerializer as DefaultPasswordChangeSerializer) -from .utils import import_callable, default_create_token +from .utils import default_create_token -create_token = import_callable( - getattr(settings, 'REST_AUTH_TOKEN_CREATOR', default_create_token)) +create_token = getattr(settings, 'REST_AUTH_TOKEN_CREATOR', default_create_token) serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {}) -TokenSerializer = import_callable( - serializers.get('TOKEN_SERIALIZER', DefaultTokenSerializer)) +TokenSerializer = serializers.get('TOKEN_SERIALIZER', DefaultTokenSerializer) -JWTSerializer = import_callable( - serializers.get('JWT_SERIALIZER', DefaultJWTSerializer)) +JWTSerializer = serializers.get('JWT_SERIALIZER', DefaultJWTSerializer) -UserDetailsSerializer = import_callable( - serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer) -) +UserDetailsSerializer = serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer) -LoginSerializer = import_callable( - serializers.get('LOGIN_SERIALIZER', DefaultLoginSerializer) -) +LoginSerializer = serializers.get('LOGIN_SERIALIZER', DefaultLoginSerializer) -PasswordResetSerializer = import_callable( - serializers.get( +PasswordResetSerializer = serializers.get( 'PASSWORD_RESET_SERIALIZER', DefaultPasswordResetSerializer ) -) -PasswordResetConfirmSerializer = import_callable( - serializers.get( - 'PASSWORD_RESET_CONFIRM_SERIALIZER', - DefaultPasswordResetConfirmSerializer - ) +PasswordResetConfirmSerializer = serializers.get( + 'PASSWORD_RESET_CONFIRM_SERIALIZER', DefaultPasswordResetConfirmSerializer ) -PasswordChangeSerializer = import_callable( - serializers.get( - 'PASSWORD_CHANGE_SERIALIZER', - DefaultPasswordChangeSerializer - ) -) +PasswordChangeSerializer = serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer) diff --git a/dj_rest_auth/models.py b/dj_rest_auth/models.py index a132f9c0..5f690daf 100644 --- a/dj_rest_auth/models.py +++ b/dj_rest_auth/models.py @@ -2,9 +2,7 @@ from rest_framework.authtoken.models import Token as DefaultTokenModel -from .utils import import_callable # Register your models here. -TokenModel = import_callable( - getattr(settings, 'REST_AUTH_TOKEN_MODEL', DefaultTokenModel)) +TokenModel = getattr(settings, 'REST_AUTH_TOKEN_MODEL', DefaultTokenModel) diff --git a/dj_rest_auth/registration/app_settings.py b/dj_rest_auth/registration/app_settings.py index c8cd25ae..3e6db53b 100644 --- a/dj_rest_auth/registration/app_settings.py +++ b/dj_rest_auth/registration/app_settings.py @@ -2,18 +2,17 @@ from rest_framework.permissions import AllowAny from rest_auth.registration.serializers import ( - RegisterSerializer as DefaultRegisterSerializer) -from ..utils import import_callable + RegisterSerializer as DefaultRegisterSerializer +) serializers = getattr(settings, 'REST_AUTH_REGISTER_SERIALIZERS', {}) -RegisterSerializer = import_callable( - serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer)) +RegisterSerializer = serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer) def register_permission_classes(): permission_classes = [AllowAny, ] for klass in getattr(settings, 'REST_AUTH_REGISTER_PERMISSION_CLASSES', tuple()): - permission_classes.append(import_callable(klass)) + permission_classes.append(klass) return tuple(permission_classes) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index b6452317..da8fef79 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -10,7 +10,6 @@ from rest_framework.exceptions import ValidationError from .models import TokenModel -from .utils import import_callable # Get the UserModel UserModel = get_user_model() @@ -146,9 +145,7 @@ def get_user(self, obj): JWTSerializer. Defining it here to avoid circular imports """ rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {}) - JWTUserDetailsSerializer = import_callable( - rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer) - ) + JWTUserDetailsSerializer = rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer) user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data return user_data diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index 800f184c..b69dae0e 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -1,15 +1,3 @@ -from six import string_types -from importlib import import_module - - -def import_callable(path_or_callable): - if hasattr(path_or_callable, '__call__'): - return path_or_callable - else: - assert isinstance(path_or_callable, string_types) - package, attr = path_or_callable.rsplit('.', 1) - return getattr(import_module(package), attr) - def default_create_token(token_model, user, serializer): token, _ = token_model.objects.get_or_create(user=user) diff --git a/setup.py b/setup.py index 472ce6b1..a57994e6 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,6 @@ install_requires=[ 'Django>=1.8.0', 'djangorestframework>=3.1.3', - 'six>=1.9.0', ], extras_require={ 'with_social': ['django-allauth>=0.25.0'], From 7331e63201342342b3b7c6b3a31ff219813546e3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 20:41:51 -0600 Subject: [PATCH 021/130] Fixes min reqs --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index a57994e6..db77e402 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='0.9.5', + version='0.1.0', author='iMerica', author_email='imichael@pm.me', url='http://github.com/iMerica/dj-rest-auth', @@ -23,7 +23,7 @@ keywords='django rest auth registration rest-framework django-registration api', zip_safe=False, install_requires=[ - 'Django>=1.8.0', + 'Django>=1.11', 'djangorestframework>=3.1.3', ], extras_require={ From 4c3a1216767cace2e6dcccaed151850e3ba8256f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:22:37 -0600 Subject: [PATCH 022/130] WIP --- .circleci/config.yml | 2 +- dj_rest_auth/registration/app_settings.py | 2 +- dj_rest_auth/social_serializers.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0fd7227e..138d8adf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: - image: circleci/python:3.8.0 environment: DJANGO_VERSION: 3.0 - DRF: 3.9 + DRF: 3.11 executor: docker/docker steps: - checkout diff --git a/dj_rest_auth/registration/app_settings.py b/dj_rest_auth/registration/app_settings.py index 3e6db53b..fdeae833 100644 --- a/dj_rest_auth/registration/app_settings.py +++ b/dj_rest_auth/registration/app_settings.py @@ -1,7 +1,7 @@ from django.conf import settings from rest_framework.permissions import AllowAny -from rest_auth.registration.serializers import ( +from dj_rest_auth.registration.serializers import ( RegisterSerializer as DefaultRegisterSerializer ) diff --git a/dj_rest_auth/social_serializers.py b/dj_rest_auth/social_serializers.py index 1621813b..6f8a4494 100644 --- a/dj_rest_auth/social_serializers.py +++ b/dj_rest_auth/social_serializers.py @@ -8,7 +8,7 @@ from allauth.socialaccount.models import SocialToken from allauth.socialaccount.providers.oauth.client import OAuthError - from rest_auth.registration.serializers import SocialConnectMixin + from dj_rest_auth.registration.serializers import SocialConnectMixin class TwitterLoginSerializer(serializers.Serializer): From cd2328cfde07f8ae5edcf75aafdf16c612993373 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:25:20 -0600 Subject: [PATCH 023/130] WIP --- dj_rest_auth/tests/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py index ef900b95..5aa37c16 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -53,7 +53,7 @@ class TwitterLoginNoAdapter(SocialLoginView): urlpatterns += [ - url(r'^rest-registration/', include('rest_auth.registration.urls')), + url(r'^rest-registration/', include('dj_rest_auth.registration.urls')), url(r'^test-admin/', include(django_urls)), url(r'^account-email-verification-sent/$', TemplateView.as_view(), name='account_email_verification_sent'), From 3e89a8d32f047098e09336a5e27edc52973d3ecc Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:28:48 -0600 Subject: [PATCH 024/130] Adds dev reqs --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 138d8adf..7bdbc4ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,6 +16,7 @@ jobs: - run: echo "djangorestframework==$DRF" >> requirements.txt - run: pip install --user coveralls - run: pip install --user -r requirements.txt + - run: pip install --user -r dev-requirements.txt - run: command: coverage run --source=dj_rest_auth setup.py test name: Test From 60c1a4ad5f2097f32c83cae08c6720858f9546bf Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:34:24 -0600 Subject: [PATCH 025/130] Adds more tests coverage --- .circleci/config.yml | 5 +++++ setup.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7bdbc4ba..a8c0ea15 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,11 @@ jobs: environment: DJANGO_VERSION: 2.0 DRF: 3.9 + build-django-11: + <<: *template + environment: + DJANGO_VERSION: 1.11 + DRF: 3.9 workflows: main: diff --git a/setup.py b/setup.py index db77e402..09ffe1c1 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ author='iMerica', author_email='imichael@pm.me', url='http://github.com/iMerica/dj-rest-auth', - description='Create a set of REST API endpoints for Authentication and Registration', + description='Authentication and Registration in Django Rest Framework', packages=find_packages(), long_description=long_description, long_description_content_type='text/markdown', From 60cdae15709d2e049cb5d500049a9ae24996629d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:35:00 -0600 Subject: [PATCH 026/130] Runs 1.11 tests --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a8c0ea15..2e9a3d4f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -35,4 +35,5 @@ workflows: main: jobs: - build-latest - - build-django-2 \ No newline at end of file + - build-django-2 + - build-django-11 \ No newline at end of file From c99caac86a3309ce8e7732dc18646b2af233285a Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:35:43 -0600 Subject: [PATCH 027/130] Adds tests --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2e9a3d4f..ee7f31d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ orbs: docker: circleci/docker@0.6.0 jobs: - build-latest: &template + test-latest: &template docker: - image: circleci/python:3.8.0 environment: @@ -20,12 +20,12 @@ jobs: - run: command: coverage run --source=dj_rest_auth setup.py test name: Test - build-django-2: + test-django-2: <<: *template environment: DJANGO_VERSION: 2.0 DRF: 3.9 - build-django-11: + test-django-11: <<: *template environment: DJANGO_VERSION: 1.11 @@ -34,6 +34,6 @@ jobs: workflows: main: jobs: - - build-latest - - build-django-2 - - build-django-11 \ No newline at end of file + - test-latest + - test-django-2 + - test-django-11 \ No newline at end of file From a757eeaf536aeb3ab4453fa69b639251c3964bbe Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:54:55 -0600 Subject: [PATCH 028/130] Install tests reqs --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index ee7f31d8..d05084d0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,7 @@ jobs: - run: pip install --user coveralls - run: pip install --user -r requirements.txt - run: pip install --user -r dev-requirements.txt + - run: pip install --user -r dj_rest_auth/tests/requirements.pip - run: command: coverage run --source=dj_rest_auth setup.py test name: Test From cb1e2b61b8be464f0d017c8f5d1c05bc8d34121b Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 21:58:44 -0600 Subject: [PATCH 029/130] Bumps Django --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d05084d0..34b5db8a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: docker: - image: circleci/python:3.8.0 environment: - DJANGO_VERSION: 3.0 + DJANGO_VERSION: 3.0.3 DRF: 3.11 executor: docker/docker steps: @@ -24,7 +24,7 @@ jobs: test-django-2: <<: *template environment: - DJANGO_VERSION: 2.0 + DJANGO_VERSION: 2.2.10 DRF: 3.9 test-django-11: <<: *template From 93ed2a15282829945dbf93d262e55eca1f5894c8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 22:02:36 -0600 Subject: [PATCH 030/130] DRY's up config --- .circleci/config.yml | 9 +++------ runtests.py | 1 + 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 34b5db8a..869f98be 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,12 +12,9 @@ jobs: executor: docker/docker steps: - checkout - - run: echo "Django==$DJANGO_VERSION" > requirements.txt - - run: echo "djangorestframework==$DRF" >> requirements.txt - - run: pip install --user coveralls - - run: pip install --user -r requirements.txt - - run: pip install --user -r dev-requirements.txt - - run: pip install --user -r dj_rest_auth/tests/requirements.pip + - run: pip install -q --user coveralls djangorestframework==$DRF "Django==$DJANGO_VERSION + - run: pip install -q --user -r dev-requirements.txt + - run: pip install -q --user -r dj_rest_auth/tests/requirements.pip - run: command: coverage run --source=dj_rest_auth setup.py test name: Test diff --git a/runtests.py b/runtests.py index 6fab5085..04dfa7ca 100644 --- a/runtests.py +++ b/runtests.py @@ -20,5 +20,6 @@ def runtests(): failures = test_runner.run_tests(['dj_rest_auth']) sys.exit(bool(failures)) + if __name__ == '__main__': runtests() From 6b27267758561048e47d67f0d28cc5f9b7451db2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 22:03:34 -0600 Subject: [PATCH 031/130] Updates Django version --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 869f98be..2f2b4a51 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,9 +12,9 @@ jobs: executor: docker/docker steps: - checkout - - run: pip install -q --user coveralls djangorestframework==$DRF "Django==$DJANGO_VERSION - - run: pip install -q --user -r dev-requirements.txt - - run: pip install -q --user -r dj_rest_auth/tests/requirements.pip + - run: pip install -q --user coveralls djangorestframework==$DRF Django==$DJANGO_VERSION + - run: pip install --user -r dev-requirements.txt + - run: pip install --user -r dj_rest_auth/tests/requirements.pip - run: command: coverage run --source=dj_rest_auth setup.py test name: Test From 455b88ed573c77de0eb1302055fbd4c47efcc84d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 22:06:53 -0600 Subject: [PATCH 032/130] Removes Django 11 --- .circleci/config.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2f2b4a51..75c5e48b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ orbs: docker: circleci/docker@0.6.0 jobs: - test-latest: &template + test-django-3: &template docker: - image: circleci/python:3.8.0 environment: @@ -23,15 +23,9 @@ jobs: environment: DJANGO_VERSION: 2.2.10 DRF: 3.9 - test-django-11: - <<: *template - environment: - DJANGO_VERSION: 1.11 - DRF: 3.9 workflows: main: jobs: - - test-latest - - test-django-2 - - test-django-11 \ No newline at end of file + - test-django-3 + - test-django-2 \ No newline at end of file From a639fc6ace6436f0a60a5c50e43efffdf431efe8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 22:47:06 -0600 Subject: [PATCH 033/130] Fixes broken tests --- dj_rest_auth/tests/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index c86bfc17..f683ce0c 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -73,6 +73,8 @@ } INSTALLED_APPS = [ + 'django.contrib.messages', + 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.humanize', 'django.contrib.contenttypes', From 39fbc15571e73f28c572d670f9419d2c272254ad Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 22:51:56 -0600 Subject: [PATCH 034/130] Adds README badge --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e69de29b..58f10923 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,4 @@ +# Dj-Rest-Auth +[![](https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg)]() + + From 7f17e18e3e06c842b0bbd0a94d151a5e39dfbfee Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 22:53:34 -0600 Subject: [PATCH 035/130] Updates badge URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58f10923..076cce29 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # Dj-Rest-Auth -[![](https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg)]() +[![](https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/iMerica/dj-rest-auth/pipelines) From aafd10fccee96a545f0b711f8dbaa52bba49c99c Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:02:01 -0600 Subject: [PATCH 036/130] Updates README --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 076cce29..79125b25 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,32 @@ [![](https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/iMerica/dj-rest-auth/pipelines) +Drop-in API endpoints for authentication in Django Rest Framework. + +### Requirements +- Django 2 or 3. +- Python 3 + +### Setup + +Install package + + pip install dj-rest-auth + +Add `dj_rest_auth` app to INSTALLED_APPS in your django settings.py: + + INSTALLED_APPS = ( + ..., + 'rest_framework', + 'rest_framework.authtoken', + ..., + 'rest_auth' + ) + +Add URL patterns + + + urlpatterns = [ + url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) + ] + From 8b3915e1191ca527bde1ce1f6ca5fa2b168e292d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:03:58 -0600 Subject: [PATCH 037/130] Fixes README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79125b25..6a1faa84 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Add `dj_rest_auth` app to INSTALLED_APPS in your django settings.py: 'rest_framework', 'rest_framework.authtoken', ..., - 'rest_auth' + 'dj_rest_auth' ) Add URL patterns From 7d63b53a43bfa48fdc2c34c57be14050c21423b2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:06:12 -0600 Subject: [PATCH 038/130] Updats README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6a1faa84..09a0f5a4 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,7 @@ Add URL patterns url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) ] + +### Acknowledgements + +This project began as a fork of `django-rest-auth`. Big thanks to everyone who contributed to that repo! \ No newline at end of file From 9298014b3a466d8febb4e33b5e2a2359804ec4b4 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:18:19 -0600 Subject: [PATCH 039/130] Fixes docs --- docs/index.rst | 3 +-- docs/installation.rst | 18 +++++++++--------- setup.py | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 8be210a6..04795613 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,9 +6,8 @@ Welcome to dj-rest-auth's documentation! ============================================ -.. warning:: Updating dj-rest-auth from version **0.3.3** is highly recommended because of a security issue in PasswordResetConfirmation validation method. -.. note:: dj-rest-auth from v0.3.3 supports django-rest-framework v3.0 +.. note:: dj-rest-auth from v0.3.3 supports django-rest-framework >= v3.0 |build-status| |coverage-status| |requirements-status| |docs| diff --git a/docs/installation.rst b/docs/installation.rst index 395299a9..cba551e5 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -28,7 +28,7 @@ Installation urlpatterns = [ ..., - url(r'^rest-auth/', include('dj_rest_auth.urls')) + url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) ] 4. Migrate your database @@ -68,8 +68,8 @@ Registration (optional) urlpatterns = [ ..., - url(r'^rest-auth/', include('dj_rest_auth.urls')), - url(r'^rest-auth/registration/', include('dj_rest_auth.registration.urls')) + url(r'^dj-rest-auth/', include('dj_rest_auth.urls')), + url(r'^dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')) ] @@ -122,7 +122,7 @@ Facebook urlpatterns += [ ..., - url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login') + url(r'^dj-rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login') ] @@ -149,7 +149,7 @@ If you are using Twitter for your social authentication, it is a bit different s urlpatterns += [ ..., - url(r'^rest-auth/twitter/$', TwitterLogin.as_view(), name='twitter_login') + url(r'^dj-rest-auth/twitter/$', TwitterLogin.as_view(), name='twitter_login') ] .. note:: Starting from v0.21.0, django-allauth has dropped support for context processors. Check out http://django-allauth.readthedocs.org/en/latest/changelog.html#from-0-21-0 for more details. @@ -179,7 +179,7 @@ If you are using GitHub for your social authentication, it uses code and not Acc urlpatterns += [ ..., - url(r'^rest-auth/github/$', GitHubLogin.as_view(), name='github_login') + url(r'^dj-rest-auth/github/$', GitHubLogin.as_view(), name='github_login') ] Additional Social Connect Views @@ -215,9 +215,9 @@ In urls.py: urlpatterns += [ ..., - url(r'^rest-auth/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect') - url(r'^rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect') - url(r'^rest-auth/github/connect/$', GithubConnect.as_view(), name='github_connect') + url(r'^dj-rest-auth/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect') + url(r'^dj-rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect') + url(r'^dj-rest-auth/github/connect/$', GithubConnect.as_view(), name='github_connect') ] You can also use the following views to check all social accounts attached to the current authenticated user and disconnect selected social accounts: diff --git a/setup.py b/setup.py index 09ffe1c1..9d2b7756 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='0.1.0', + version='0.1.1', author='iMerica', author_email='imichael@pm.me', url='http://github.com/iMerica/dj-rest-auth', From 25d0ebbfd410329231db4ffb2b17ae5b33d7ae3e Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:20:56 -0600 Subject: [PATCH 040/130] Specifies Python version --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9d2b7756..b00ff9e4 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='0.1.1', + version='0.1.2', author='iMerica', author_email='imichael@pm.me', url='http://github.com/iMerica/dj-rest-auth', @@ -36,6 +36,7 @@ ], test_suite='runtests.runtests', include_package_data=True, + python_requires='>=3.5', classifiers=[ 'Framework :: Django', 'Intended Audience :: Developers', From 34d5706b78e6ad7aaa229367169b4827f95ac2f1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:23:47 -0600 Subject: [PATCH 041/130] Updates README --- README.md | 8 ++++++-- docs/index.rst | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 09a0f5a4..268c56a2 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Drop-in API endpoints for authentication in Django Rest Framework. -### Requirements +## Requirements - Django 2 or 3. - Python 3 -### Setup +## Quick Setup Install package @@ -31,6 +31,10 @@ Add URL patterns url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) ] +### Documentation + +View the full documentation here: https://dj-rest-auth.readthedocs.io/en/latest/index.html + ### Acknowledgements diff --git a/docs/index.rst b/docs/index.rst index 04795613..8deb4453 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ Welcome to dj-rest-auth's documentation! ============================================ -.. note:: dj-rest-auth from v0.3.3 supports django-rest-framework >= v3.0 +.. note:: dj-rest-auth supports django-rest-framework >= v3.0 |build-status| |coverage-status| |requirements-status| |docs| From 60e0ca468da09773023ab3489631303f729bcc9a Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:27:00 -0600 Subject: [PATCH 042/130] Updates Docs --- docs/index.rst | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 8deb4453..c3de8ce5 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,7 +10,8 @@ Welcome to dj-rest-auth's documentation! .. note:: dj-rest-auth supports django-rest-framework >= v3.0 -|build-status| |coverage-status| |requirements-status| |docs| +.. image:: https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg + :target: https://circleci.com/gh/iMerica/dj-rest-auth Contents -------- @@ -25,27 +26,3 @@ Contents Demo project FAQ Changelog - - -.. |build-status| image:: https://travis-ci.org/iMerica/dj-rest-auth.svg?branch=master - :alt: build status - :scale: 100% - :target: https://travis-ci.org/iMerica/dj-rest-auth - - -.. |coverage-status| image:: https://coveralls.io/repos/iMerica/dj-rest-auth/badge.png?branch=master - :alt: coverage status - :scale: 100% - :target: https://coveralls.io/r/iMerica/dj-rest-auth?branch=master - - -.. |requirements-status| image:: https://requires.io/github/iMerica/dj-rest-auth/requirements.png?branch=master - :alt: requirements status - :scale: 100% - :target: https://requires.io/github/iMerica/dj-rest-auth/requirements/?branch=master - - -.. |docs| image:: https://readthedocs.org/projects/dj-rest-auth/badge/?version=latest - :scale: 100% - :target: https://readthedocs.org/projects/dj-rest-auth/?badge=latest - :alt: Documentation Status From 9b78f0e3be37a9147890a2f1fe43b9fc11e055e6 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:40:44 -0600 Subject: [PATCH 043/130] Updates change log --- docs/changelog.rst | 118 +-------------------------------------------- 1 file changed, 2 insertions(+), 116 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 2bb3f4ca..42d36bcb 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,120 +1,6 @@ Changelog ========= -0.9.5 +0.1.2 ----- -- fixed package distribution issue - -0.9.4 ------ -- Compatibility fixes (#437, #506) -- JWT auth cookie fix (#345) -- config & packaging fixes -- updated docs -- added new translations (Czech, Chinese, Turkish, Korean) - -0.9.3 ------ -- added social connect views -- added check for pre-existing accounts in social login -- prevent double-validation in LoginSerializer -- unit tests and demo project changes for Django 2.0 - -0.9.2 ------ -- added permission classes configuration for registration -- added more info to JWT docs -- added Polish translations - -0.9.1 ------ -- fixed import error when extending dj_rest_auth serializers -- added sensitive fields decorator -- added Spanish translations - -0.9.0 ------ -- allowed using custom UserDetailsSerializer with JWTSerializer -- fixed error with logout on GET -- updated api endpoints and configuration docs -- bugfixes -- minor text fixes - -0.8.2 ------ -- fixed allauth import error -- added swagger docs to demo project - -0.8.1 ------ -- added support for django-allauth hmac email confirmation pattern - -0.8.0 ------ -- added support for django-rest-framework-jwt -- bugfixes - -0.7.0 ------ -- Wrapped API returned strings in ugettext_lazy -- Fixed not using ``get_username`` which caused issues when using custom user model without username field -- Django 1.9 support -- Added ``TwitterLoginSerializer`` - -0.6.0 ------ -- dropped support for Python 2.6 -- dropped support for Django 1.6 -- fixed demo code -- added better validation support for serializers -- added optional logout after password change -- compatibility fixes -- bugfixes - -0.5.0 ------ -- replaced request.DATA with request.data for compatibility with DRF 3.2 -- authorization codes for social login -- view classes rename (appended "View" to all of them) -- bugfixes - -0.4.0 ------ -- Django 1.8 compatiblity fixes - -0.3.4 ------ -- fixed bug in PasswordResetConfirmation serializer (token field wasn't validated) -- fixed bug in Register view - -0.3.3 ------ - -- support django-rest-framework v3.0 - -0.3.2 ------ - -- fixed few minor bugs - -0.3.1 ------ - -- added old_password field in PasswordChangeSerializer -- make all endpoints browsable -- removed LoggedInRESTAPIView, LoggedOutRESTAPIView -- fixed minor bugs - -0.3.0 ------ - -- replaced ``django-registration`` with ``django-allauth`` -- moved registration logic to separated django application (``dj_rest_auth.registration``) -- added serializers customization in django settings -- added social media authentication view -- changed request method from GET to POST in logout endpoint -- changed request method from POST to PUT/PATCH for user details edition -- changed password reset confim url - uid and token should be sent in POST -- increase test coverage -- made compatibile with django 1.7 -- removed user profile support +Welcome Dj-Rest-Auth \ No newline at end of file From 8bc9ba8c8aa968fd04c4d67b46c0e8c40f46101c Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 23:56:21 -0600 Subject: [PATCH 044/130] Fixes references to serializers + isort --- demo/demo/urls.py | 3 +- demo/demo/wsgi.py | 4 ++- dj_rest_auth/app_settings.py | 40 +++++++++++---------- dj_rest_auth/models.py | 2 -- dj_rest_auth/registration/app_settings.py | 9 +++-- dj_rest_auth/registration/serializers.py | 6 ++-- dj_rest_auth/registration/urls.py | 2 +- dj_rest_auth/registration/views.py | 42 ++++++++++------------- dj_rest_auth/serializers.py | 7 ++-- dj_rest_auth/social_serializers.py | 1 + dj_rest_auth/tests/mixins.py | 6 ++-- dj_rest_auth/tests/settings.py | 2 +- dj_rest_auth/tests/test_api.py | 14 ++++---- dj_rest_auth/tests/test_social.py | 15 ++++---- dj_rest_auth/tests/urls.py | 26 +++++++------- dj_rest_auth/urls.py | 8 ++--- dj_rest_auth/utils.py | 11 ++++++ dj_rest_auth/views.py | 23 ++++++------- docs/conf.py | 2 +- runtests.py | 7 ++-- setup.py | 4 +-- 21 files changed, 116 insertions(+), 118 deletions(-) diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 787c6e94..4f63ba13 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -1,7 +1,6 @@ from django.conf.urls import include, url from django.contrib import admin -from django.views.generic import TemplateView, RedirectView - +from django.views.generic import RedirectView, TemplateView from rest_framework_swagger.views import get_swagger_view urlpatterns = [ diff --git a/demo/demo/wsgi.py b/demo/demo/wsgi.py index ef487544..863501d6 100644 --- a/demo/demo/wsgi.py +++ b/demo/demo/wsgi.py @@ -8,7 +8,9 @@ """ import os -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") + application = get_wsgi_application() diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 7f8094fa..d89202de 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -1,34 +1,36 @@ +from dj_rest_auth.serializers import JWTSerializer as DefaultJWTSerializer +from dj_rest_auth.serializers import LoginSerializer as DefaultLoginSerializer +from dj_rest_auth.serializers import \ + PasswordChangeSerializer as DefaultPasswordChangeSerializer +from dj_rest_auth.serializers import \ + PasswordResetConfirmSerializer as DefaultPasswordResetConfirmSerializer +from dj_rest_auth.serializers import \ + PasswordResetSerializer as DefaultPasswordResetSerializer +from dj_rest_auth.serializers import TokenSerializer as DefaultTokenSerializer +from dj_rest_auth.serializers import \ + UserDetailsSerializer as DefaultUserDetailsSerializer from django.conf import settings -from dj_rest_auth.serializers import ( - TokenSerializer as DefaultTokenSerializer, - JWTSerializer as DefaultJWTSerializer, - UserDetailsSerializer as DefaultUserDetailsSerializer, - LoginSerializer as DefaultLoginSerializer, - PasswordResetSerializer as DefaultPasswordResetSerializer, - PasswordResetConfirmSerializer as DefaultPasswordResetConfirmSerializer, - PasswordChangeSerializer as DefaultPasswordChangeSerializer) -from .utils import default_create_token +from .utils import default_create_token, import_callable -create_token = getattr(settings, 'REST_AUTH_TOKEN_CREATOR', default_create_token) +create_token = import_callable(getattr(settings, 'REST_AUTH_TOKEN_CREATOR', default_create_token)) serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {}) -TokenSerializer = serializers.get('TOKEN_SERIALIZER', DefaultTokenSerializer) +TokenSerializer = import_callable(serializers.get('TOKEN_SERIALIZER', DefaultTokenSerializer)) -JWTSerializer = serializers.get('JWT_SERIALIZER', DefaultJWTSerializer) +JWTSerializer = import_callable(serializers.get('JWT_SERIALIZER', DefaultJWTSerializer)) -UserDetailsSerializer = serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer) +UserDetailsSerializer = import_callable(serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer)) -LoginSerializer = serializers.get('LOGIN_SERIALIZER', DefaultLoginSerializer) +LoginSerializer = import_callable(serializers.get('LOGIN_SERIALIZER', DefaultLoginSerializer)) -PasswordResetSerializer = serializers.get( - 'PASSWORD_RESET_SERIALIZER', - DefaultPasswordResetSerializer - ) +PasswordResetSerializer = import_callable(serializers.get( + 'PASSWORD_RESET_SERIALIZER', DefaultPasswordResetSerializer +)) PasswordResetConfirmSerializer = serializers.get( 'PASSWORD_RESET_CONFIRM_SERIALIZER', DefaultPasswordResetConfirmSerializer ) -PasswordChangeSerializer = serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer) +PasswordChangeSerializer = import_callable(serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer)) diff --git a/dj_rest_auth/models.py b/dj_rest_auth/models.py index 5f690daf..654c0aed 100644 --- a/dj_rest_auth/models.py +++ b/dj_rest_auth/models.py @@ -1,8 +1,6 @@ from django.conf import settings - from rest_framework.authtoken.models import Token as DefaultTokenModel - # Register your models here. TokenModel = getattr(settings, 'REST_AUTH_TOKEN_MODEL', DefaultTokenModel) diff --git a/dj_rest_auth/registration/app_settings.py b/dj_rest_auth/registration/app_settings.py index fdeae833..bbc70754 100644 --- a/dj_rest_auth/registration/app_settings.py +++ b/dj_rest_auth/registration/app_settings.py @@ -1,14 +1,13 @@ +from dj_rest_auth.registration.serializers import \ + RegisterSerializer as DefaultRegisterSerializer from django.conf import settings - from rest_framework.permissions import AllowAny -from dj_rest_auth.registration.serializers import ( - RegisterSerializer as DefaultRegisterSerializer -) +from ..utils import import_callable serializers = getattr(settings, 'REST_AUTH_REGISTER_SERIALIZERS', {}) -RegisterSerializer = serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer) +RegisterSerializer = import_callable(serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer)) def register_permission_classes(): diff --git a/dj_rest_auth/registration/serializers.py b/dj_rest_auth/registration/serializers.py index 4f99c182..fc7c92bb 100644 --- a/dj_rest_auth/registration/serializers.py +++ b/dj_rest_auth/registration/serializers.py @@ -1,6 +1,8 @@ +from django.contrib.auth import get_user_model from django.http import HttpRequest from django.utils.translation import ugettext_lazy as _ -from django.contrib.auth import get_user_model +from requests.exceptions import HTTPError +from rest_framework import serializers try: from allauth.account import app_settings as allauth_settings @@ -14,8 +16,6 @@ except ImportError: raise ImportError("allauth needs to be added to INSTALLED_APPS.") -from rest_framework import serializers -from requests.exceptions import HTTPError class SocialAccountSerializer(serializers.ModelSerializer): diff --git a/dj_rest_auth/registration/urls.py b/dj_rest_auth/registration/urls.py index 1004695e..c42cec6c 100644 --- a/dj_rest_auth/registration/urls.py +++ b/dj_rest_auth/registration/urls.py @@ -1,5 +1,5 @@ -from django.views.generic import TemplateView from django.conf.urls import url +from django.views.generic import TemplateView from .views import RegisterView, VerifyEmailView diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index f8d11204..81ed1eac 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -1,34 +1,30 @@ -from django.conf import settings -from django.utils.decorators import method_decorator -from django.utils.translation import ugettext_lazy as _ -from django.views.decorators.debug import sensitive_post_parameters - -from rest_framework.views import APIView -from rest_framework.response import Response -from rest_framework.permissions import (AllowAny, - IsAuthenticated) -from rest_framework.generics import CreateAPIView, ListAPIView, GenericAPIView -from rest_framework.exceptions import NotFound -from rest_framework import status - +from allauth.account import app_settings as allauth_settings from allauth.account.adapter import get_adapter -from allauth.account.views import ConfirmEmailView from allauth.account.utils import complete_signup -from allauth.account import app_settings as allauth_settings +from allauth.account.views import ConfirmEmailView from allauth.socialaccount import signals from allauth.socialaccount.adapter import get_adapter as get_social_adapter from allauth.socialaccount.models import SocialAccount - -from dj_rest_auth.app_settings import (TokenSerializer, - JWTSerializer, - create_token) +from dj_rest_auth.app_settings import (JWTSerializer, TokenSerializer, + create_token) from dj_rest_auth.models import TokenModel -from dj_rest_auth.registration.serializers import (VerifyEmailSerializer, - SocialLoginSerializer, - SocialAccountSerializer, - SocialConnectSerializer) +from dj_rest_auth.registration.serializers import (SocialAccountSerializer, + SocialConnectSerializer, + SocialLoginSerializer, + VerifyEmailSerializer) from dj_rest_auth.utils import jwt_encode from dj_rest_auth.views import LoginView +from django.conf import settings +from django.utils.decorators import method_decorator +from django.utils.translation import ugettext_lazy as _ +from django.views.decorators.debug import sensitive_post_parameters +from rest_framework import status +from rest_framework.exceptions import NotFound +from rest_framework.generics import CreateAPIView, GenericAPIView, ListAPIView +from rest_framework.permissions import AllowAny, IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView + from .app_settings import RegisterSerializer, register_permission_classes sensitive_post_parameters_m = method_decorator( diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index da8fef79..07783da6 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -1,12 +1,11 @@ -from django.contrib.auth import get_user_model, authenticate from django.conf import settings +from django.contrib.auth import authenticate, get_user_model from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm from django.contrib.auth.tokens import default_token_generator +from django.utils.encoding import force_text from django.utils.http import urlsafe_base64_decode as uid_decoder from django.utils.translation import ugettext_lazy as _ -from django.utils.encoding import force_text - -from rest_framework import serializers, exceptions +from rest_framework import exceptions, serializers from rest_framework.exceptions import ValidationError from .models import TokenModel diff --git a/dj_rest_auth/social_serializers.py b/dj_rest_auth/social_serializers.py index 6f8a4494..60b0c2c3 100644 --- a/dj_rest_auth/social_serializers.py +++ b/dj_rest_auth/social_serializers.py @@ -1,6 +1,7 @@ from django.conf import settings from django.http import HttpRequest from rest_framework import serializers + # Import is needed only if we are using social login, in which # case the allauth.socialaccount will be declared if 'allauth.socialaccount' in settings.INSTALLED_APPS: diff --git a/dj_rest_auth/tests/mixins.py b/dj_rest_auth/tests/mixins.py index 30b3d586..06d776d5 100644 --- a/dj_rest_auth/tests/mixins.py +++ b/dj_rest_auth/tests/mixins.py @@ -1,11 +1,9 @@ import json from django.conf import settings -from django.test.client import Client, MULTIPART_CONTENT +from django.test.client import MULTIPART_CONTENT, Client from django.utils.encoding import force_text - -from rest_framework import status -from rest_framework import permissions +from rest_framework import permissions, status try: from django.urls import reverse diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index f683ce0c..d18f41ec 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -1,6 +1,6 @@ +import logging import os import sys -import logging PROJECT_ROOT = os.path.abspath(os.path.split(os.path.split(__file__)[0])[0]) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index b6d84f21..585b38d2 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -1,17 +1,15 @@ -from django.test import TestCase, override_settings +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 -from django.conf import settings +from django.test import TestCase, override_settings from django.utils.encoding import force_text - -from allauth.account import app_settings as account_app_settings from rest_framework import status from rest_framework.test import APIRequestFactory -from dj_rest_auth.registration.views import RegisterView -from dj_rest_auth.registration.app_settings import register_permission_classes - -from .mixins import TestsMixin, CustomPermissionClass +from .mixins import CustomPermissionClass, TestsMixin try: from django.urls import reverse diff --git a/dj_rest_auth/tests/test_social.py b/dj_rest_auth/tests/test_social.py index 830e6315..47c8d939 100644 --- a/dj_rest_auth/tests/test_social.py +++ b/dj_rest_auth/tests/test_social.py @@ -1,22 +1,23 @@ import json -from django.test import TestCase +import responses +from allauth.socialaccount.models import SocialApp +from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL from django.contrib.auth import get_user_model -from django.test.utils import override_settings from django.contrib.sites.models import Site +from django.test import TestCase +from django.test.utils import override_settings +from rest_framework import status + +from .mixins import TestsMixin try: from django.urls import reverse except ImportError: from django.core.urlresolvers import reverse -from allauth.socialaccount.models import SocialApp -from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL -import responses -from rest_framework import status -from .mixins import TestsMixin @override_settings(ROOT_URLCONF="tests.urls") diff --git a/dj_rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py index 5aa37c16..be199a50 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -1,20 +1,18 @@ -from django.conf.urls import url, include -from django.views.generic import TemplateView -from . import django_urls - -from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter +from allauth.socialaccount.providers.facebook.views import \ + FacebookOAuth2Adapter from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter - +from dj_rest_auth.registration.views import (SocialAccountDisconnectView, + SocialAccountListView, + SocialConnectView, + SocialLoginView) +from dj_rest_auth.social_serializers import (TwitterConnectSerializer, + TwitterLoginSerializer) +from dj_rest_auth.urls import urlpatterns +from django.conf.urls import include, url +from django.views.generic import TemplateView from rest_framework.decorators import api_view -from dj_rest_auth.urls import urlpatterns -from dj_rest_auth.registration.views import ( - SocialLoginView, SocialConnectView, SocialAccountListView, - SocialAccountDisconnectView -) -from dj_rest_auth.social_serializers import ( - TwitterLoginSerializer, TwitterConnectSerializer -) +from . import django_urls class FacebookLogin(SocialLoginView): diff --git a/dj_rest_auth/urls.py b/dj_rest_auth/urls.py index 66647226..d3bfc420 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -1,10 +1,8 @@ +from dj_rest_auth.views import (LoginView, LogoutView, PasswordChangeView, + PasswordResetConfirmView, PasswordResetView, + UserDetailsView) from django.conf.urls import url -from dj_rest_auth.views import ( - LoginView, LogoutView, UserDetailsView, PasswordChangeView, - PasswordResetView, PasswordResetConfirmView -) - urlpatterns = [ # URLs that do not require a session or valid token url(r'^password/reset/$', PasswordResetView.as_view(), diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index b69dae0e..b4858c84 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -1,3 +1,14 @@ +from importlib import import_module + + +def import_callable(path_or_callable): + if hasattr(path_or_callable, '__call__'): + return path_or_callable + else: + assert isinstance(path_or_callable, str) + package, attr = path_or_callable.rsplit('.', 1) + return getattr(import_module(package), attr) + def default_create_token(token_model, user, serializer): token, _ = token_model.objects.get_or_create(user=user) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 0a27f8e6..b3b8f22f 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -1,25 +1,22 @@ -from django.contrib.auth import ( - login as django_login, - logout as django_logout -) from django.conf import settings from django.contrib.auth import get_user_model +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.decorators import method_decorator from django.utils.translation import ugettext_lazy as _ from django.views.decorators.debug import sensitive_post_parameters - from rest_framework import status -from rest_framework.views import APIView -from rest_framework.response import Response from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView -from rest_framework.permissions import IsAuthenticated, AllowAny +from rest_framework.permissions import AllowAny, IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView -from .app_settings import ( - TokenSerializer, UserDetailsSerializer, LoginSerializer, - PasswordResetSerializer, PasswordResetConfirmSerializer, - PasswordChangeSerializer, JWTSerializer, create_token -) +from .app_settings import (JWTSerializer, LoginSerializer, + PasswordChangeSerializer, + PasswordResetConfirmSerializer, + PasswordResetSerializer, TokenSerializer, + UserDetailsSerializer, create_token) from .models import TokenModel from .utils import jwt_encode diff --git a/docs/conf.py b/docs/conf.py index dd54bb68..77305620 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,8 +12,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/runtests.py b/runtests.py index 04dfa7ca..3cb605bf 100644 --- a/runtests.py +++ b/runtests.py @@ -3,13 +3,14 @@ import os import sys +import django +from django.conf import settings +from django.test.utils import get_runner + os.environ['DJANGO_SETTINGS_MODULE'] = 'dj_rest_auth.tests.settings' test_dir = os.path.join(os.path.dirname(__file__), 'dj_rest_auth') sys.path.insert(0, test_dir) -import django -from django.test.utils import get_runner -from django.conf import settings def runtests(): diff --git a/setup.py b/setup.py index b00ff9e4..4bbfac8f 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,8 @@ #!/usr/bin/env python import os -from setuptools import setup, find_packages +from setuptools import find_packages, setup here = os.path.dirname(os.path.abspath(__file__)) f = open(os.path.join(here, 'README.md')) @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='0.1.2', + version='0.1.3', author='iMerica', author_email='imichael@pm.me', url='http://github.com/iMerica/dj-rest-auth', From 38945e871c5844cae71e444ede35f58af85866c3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Mar 2020 00:06:45 -0600 Subject: [PATCH 045/130] Updates README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 268c56a2..e6b1e404 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ [![](https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/iMerica/dj-rest-auth/pipelines) -Drop-in API endpoints for authentication in Django Rest Framework. +Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well +with with SPAs (e.g React, Vue, Angular), and Mobile applications. ## Requirements - Django 2 or 3. From 3c30c399da43e54ce3ff8b320158d07cb83b1b81 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Mar 2020 00:07:36 -0600 Subject: [PATCH 046/130] Corrects grammar --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6b1e404..56d43152 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well -with with SPAs (e.g React, Vue, Angular), and Mobile applications. +with SPAs (e.g React, Vue, Angular), and Mobile applications. ## Requirements - Django 2 or 3. From d90e3db7eb4a3471ab853818bedce75798096cd3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Mar 2020 16:42:28 -0600 Subject: [PATCH 047/130] Uses new org --- AUTHORS | 2 +- demo/templates/base.html | 2 +- dj_rest_auth/locale/cs/LC_MESSAGES/django.po | 8 ++++---- dj_rest_auth/views.py | 1 - docs/api_endpoints.rst | 2 +- docs/demo.rst | 2 +- setup.py | 4 ++-- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/AUTHORS b/AUTHORS index c5ba2edd..e41efa7b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1 @@ -http://github.com/iMerica/dj-rest-auth/contributors +http://github.com/jazzband/dj-rest-auth/contributors diff --git a/demo/templates/base.html b/demo/templates/base.html index 47e4e649..d57ece35 100644 --- a/demo/templates/base.html +++ b/demo/templates/base.html @@ -59,7 +59,7 @@ diff --git a/dj_rest_auth/locale/cs/LC_MESSAGES/django.po b/dj_rest_auth/locale/cs/LC_MESSAGES/django.po index e6acf92f..90e6f71f 100644 --- a/dj_rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/dj_rest_auth/locale/cs/LC_MESSAGES/django.po @@ -1,11 +1,11 @@ -# Czech translations of iMerica/dj-rest-auth +# Czech translations of jazzband/dj-rest-auth # -# This file is distributed under the same license as the iMerica/dj-rest-auth package. +# This file is distributed under the same license as the jazzband/dj-rest-auth package. # msgid "" msgstr "" -"Project-Id-Version: iMerica/dj-rest-auth\n" -"Report-Msgid-Bugs-To: https://github.com/iMerica/dj-rest-auth/issues\n" +"Project-Id-Version: jazzband/dj-rest-auth\n" +"Report-Msgid-Bugs-To: https://github.com/jazzband/dj-rest-auth/issues\n" "POT-Creation-Date: 2018-06-27 23:05+0200\n" "PO-Revision-Date: 2018-06-27 23:22+0200\n" "Language: cs\n" diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index b3b8f22f..c5bcb1ad 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -161,7 +161,6 @@ def get_queryset(self): """ Adding this method since it is sometimes called when using django-rest-swagger - https://github.com/iMerica/dj-rest-auth/issues/275 """ return get_user_model().objects.none() diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index f23dabdb..a4e602aa 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -72,7 +72,7 @@ Basing on example from installation section :doc:`Installation ` - access_token - code - .. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/iMerica/dj-rest-auth/blob/master/dj_rest_auth/registration/views.py + .. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/jazzband/dj-rest-auth/blob/master/dj_rest_auth/registration/views.py - /dj-rest-auth/twitter/ (POST) diff --git a/docs/demo.rst b/docs/demo.rst index 22620f87..ecceddd1 100644 --- a/docs/demo.rst +++ b/docs/demo.rst @@ -8,7 +8,7 @@ Do these steps to make it running (ideally in virtualenv). .. code-block:: python cd /tmp - git clone https://github.com/iMerica/dj-rest-auth.git + git clone https://github.com/jazzband/dj-rest-auth.git cd dj-rest-auth/demo/ pip install -r requirements.pip python manage.py migrate --settings=demo.settings --noinput diff --git a/setup.py b/setup.py index 4bbfac8f..e4f3ec91 100644 --- a/setup.py +++ b/setup.py @@ -12,10 +12,10 @@ setup( name='dj-rest-auth', - version='0.1.3', + version='0.1.4', author='iMerica', author_email='imichael@pm.me', - url='http://github.com/iMerica/dj-rest-auth', + url='http://github.com/jazzband/dj-rest-auth', description='Authentication and Registration in Django Rest Framework', packages=find_packages(), long_description=long_description, From 238b92b472c5473d0a4fc01b993359525f4ded9d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Mar 2020 16:46:47 -0600 Subject: [PATCH 048/130] Updates Circle CI badge --- README.md | 2 +- docs/index.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 56d43152..ec7ae1d7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Dj-Rest-Auth -[![](https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/iMerica/dj-rest-auth/pipelines) +[![](https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/jazzband/dj-rest-auth/pipelines) Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well diff --git a/docs/index.rst b/docs/index.rst index c3de8ce5..82118ccb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,8 +10,8 @@ Welcome to dj-rest-auth's documentation! .. note:: dj-rest-auth supports django-rest-framework >= v3.0 -.. image:: https://circleci.com/gh/iMerica/dj-rest-auth.svg?style=svg - :target: https://circleci.com/gh/iMerica/dj-rest-auth +.. image:: https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg + :target: https://circleci.com/gh/jazzband/dj-rest-auth Contents -------- From c35773d786b7cecc6d1d8ed6763d94bec85db36c Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Mar 2020 17:47:44 -0600 Subject: [PATCH 049/130] Adds Jazzband badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ec7ae1d7..46af4d8e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Dj-Rest-Auth [![](https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/jazzband/dj-rest-auth/pipelines) +[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well From b5914dbb4597624dca62ada0351dd99d69249907 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Mar 2020 17:48:57 -0600 Subject: [PATCH 050/130] Adds contributing file --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..10d79191 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co/) + +This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct) and follow the [guidelines](https://jazzband.co/about/guidelines). \ No newline at end of file From fe01ba02314a66bbe684ec52b88acc8278e33721 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Mar 2020 17:56:32 -0600 Subject: [PATCH 051/130] Adds coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46af4d8e..3ec4ef7f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Dj-Rest-Auth [![](https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/jazzband/dj-rest-auth/pipelines) [![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) - +[![Coverage Status](https://coveralls.io/repos/github/jazzband/dj-rest-auth/badge.svg?branch=master)](https://coveralls.io/github/jazzband/dj-rest-auth?branch=master) Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well with SPAs (e.g React, Vue, Angular), and Mobile applications. From 3b830790f7ddf2aa16780fd54887524cdc4a5c02 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Mar 2020 18:01:31 -0600 Subject: [PATCH 052/130] Adds coveralls dep and tests --- .circleci/config.yml | 3 +++ dev-requirements.txt | 1 + setup.py | 1 + 3 files changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 75c5e48b..5830b0b8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,6 +18,9 @@ jobs: - run: command: coverage run --source=dj_rest_auth setup.py test name: Test + - run: + command: coveralls + name: Coverage test-django-2: <<: *template environment: diff --git a/dev-requirements.txt b/dev-requirements.txt index 0a2a9e4a..9d2af205 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,3 +2,4 @@ responses>=0.5.0 djangorestframework-jwt django-allauth +coveralls>=1.11.1 \ No newline at end of file diff --git a/setup.py b/setup.py index e4f3ec91..94aad460 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,7 @@ 'responses>=0.5.0', 'django-allauth>=0.25.0', 'djangorestframework-jwt>=1.9.0', + 'coveralls>=1.11.1' ], test_suite='runtests.runtests', include_package_data=True, From a4915a1ea8d92ad6baea35c55a84164767c65607 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Mar 2020 18:04:47 -0600 Subject: [PATCH 053/130] Adds coverage repo token --- .circleci/config.yml | 2 +- .coveralls.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .coveralls.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 5830b0b8..d1248695 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,7 +19,7 @@ jobs: command: coverage run --source=dj_rest_auth setup.py test name: Test - run: - command: coveralls + command: COVERALLS_REPO_TOKEN=Q58WdUuZOi89XHyDeDsGE2lxUGQ2IfqP3 coveralls name: Coverage test-django-2: <<: *template diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 00000000..16eb397b --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,2 @@ +service_name: travis-pro +repo_token: Q58WdUuZOi89XHyDeDsGE2lxUGQ2IfqP3 \ No newline at end of file From 229b75543e1454331649c098f7ebd4e3f2e5d8bd Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 10 Mar 2020 22:44:21 -0500 Subject: [PATCH 054/130] Updates version in demo project --- demo/requirements.pip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index ab0a814e..74422291 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.9.0 -dj-rest-auth==0.9.5 +dj-rest-auth==0.1.4 djangorestframework>=3.7.0 django-allauth>=0.24.1 django-rest-swagger==2.0.7 From 9bbc4a3014df5d1da3771bbd1c7170a976f66842 Mon Sep 17 00:00:00 2001 From: alichass Date: Wed, 11 Mar 2020 06:01:03 -0400 Subject: [PATCH 055/130] change standard auth stuff to work with simplejwt --- dj_rest_auth/serializers.py | 3 ++- dj_rest_auth/utils.py | 12 +++++------- dj_rest_auth/views.py | 18 +++--------------- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index 07783da6..b34c9cc6 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -135,7 +135,8 @@ class JWTSerializer(serializers.Serializer): """ Serializer for JWT authentication. """ - token = serializers.CharField() + access_token = serializers.CharField() + refresh_token = serializers.CharField() user = serializers.SerializerMethodField() def get_user(self, obj): diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index b4858c84..165963d9 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -17,12 +17,10 @@ def default_create_token(token_model, user, serializer): def jwt_encode(user): try: - from rest_framework_jwt.settings import api_settings + from rest_framework_simplejwt.serializers import TokenObtainPairSerializer + from rest_framework_simplejwt.views import TokenObtainPairView except ImportError: - raise ImportError("djangorestframework_jwt needs to be installed") + raise ImportError("rest-framework-simplejwt needs to be installed") - jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER - jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER - - payload = jwt_payload_handler(user) - return jwt_encode_handler(payload) + refresh = TokenObtainPairSerializer.get_token(user) + return refresh.access_token, refresh diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index c5bcb1ad..f30980c7 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -59,7 +59,7 @@ def login(self): self.user = self.serializer.validated_data['user'] if getattr(settings, 'REST_USE_JWT', False): - self.token = jwt_encode(self.user) + self.access_token, self.refresh_token = jwt_encode(self.user) else: self.token = create_token(self.token_model, self.user, self.serializer) @@ -73,7 +73,8 @@ def get_response(self): if getattr(settings, 'REST_USE_JWT', False): data = { 'user': self.user, - 'token': self.token + 'access_token': self.access_token, + 'refresh_token': self.refresh_token } serializer = serializer_class(instance=data, context={'request': self.request}) @@ -82,15 +83,6 @@ def get_response(self): context={'request': self.request}) response = Response(serializer.data, status=status.HTTP_200_OK) - if getattr(settings, 'REST_USE_JWT', False): - from rest_framework_jwt.settings import api_settings as jwt_settings - if jwt_settings.JWT_AUTH_COOKIE: - from datetime import datetime - expiration = (datetime.utcnow() + jwt_settings.JWT_EXPIRATION_DELTA) - response.set_cookie(jwt_settings.JWT_AUTH_COOKIE, - self.token, - expires=expiration, - httponly=True) return response def post(self, request, *args, **kwargs): @@ -133,10 +125,6 @@ def logout(self, request): response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) - if getattr(settings, 'REST_USE_JWT', False): - from rest_framework_jwt.settings import api_settings as jwt_settings - if jwt_settings.JWT_AUTH_COOKIE: - response.delete_cookie(jwt_settings.JWT_AUTH_COOKIE) return response From 4fb746e6455bdb78ca1421f53c2d4c86006fbcd3 Mon Sep 17 00:00:00 2001 From: alichass Date: Wed, 11 Mar 2020 06:03:59 -0400 Subject: [PATCH 056/130] updated tests --- dj_rest_auth/tests/settings.py | 4 +--- dj_rest_auth/tests/test_api.py | 8 ++++---- dj_rest_auth/tests/test_social.py | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index d18f41ec..7279c212 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -68,7 +68,7 @@ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', - 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', + 'rest_framework_simplejwt.authentication.JWTAuthentication', ) } @@ -94,8 +94,6 @@ 'dj_rest_auth', 'dj_rest_auth.registration', - - 'rest_framework_jwt' ] 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 585b38d2..5d06fac6 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -152,8 +152,8 @@ def test_login_jwt(self): get_user_model().objects.create_user(self.USERNAME, '', self.PASS) self.post(self.login_url, data=payload, status_code=200) - self.assertEqual('token' in self.response.json.keys(), True) - self.token = self.response.json['token'] + self.assertEqual('access_token' in self.response.json.keys(), True) + self.token = self.response.json['access_token'] def test_login_by_email(self): # starting test without allauth app @@ -382,7 +382,7 @@ def test_user_details_using_jwt(self): "password": self.PASS } self.post(self.login_url, data=payload, status_code=200) - self.token = self.response.json['token'] + self.token = self.response.json['access_token'] self.get(self.user_url, status_code=200) self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200) @@ -426,7 +426,7 @@ def test_registration_with_jwt(self): self.post(self.register_url, data={}, status_code=400) result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201) - self.assertIn('token', result.data) + self.assertIn('access_token', result.data) self.assertEqual(get_user_model().objects.all().count(), user_count + 1) self._login() diff --git a/dj_rest_auth/tests/test_social.py b/dj_rest_auth/tests/test_social.py index 47c8d939..cceba3f7 100644 --- a/dj_rest_auth/tests/test_social.py +++ b/dj_rest_auth/tests/test_social.py @@ -305,7 +305,7 @@ def test_jwt(self): } self.post(self.fb_login_url, data=payload, status_code=200) - self.assertIn('token', self.response.json.keys()) + self.assertIn('access_token', self.response.json.keys()) self.assertIn('user', self.response.json.keys()) self.assertEqual(get_user_model().objects.all().count(), users_count + 1) From 23e88f9838f421b6f85471b51d9fafcf1fc7c7c0 Mon Sep 17 00:00:00 2001 From: alichass Date: Wed, 11 Mar 2020 06:05:11 -0400 Subject: [PATCH 057/130] update registration views to work with simplejwt --- dj_rest_auth/registration/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index 81ed1eac..e9577a16 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -49,7 +49,8 @@ def get_response_data(self, user): if getattr(settings, 'REST_USE_JWT', False): data = { 'user': user, - 'token': self.token + 'access_token': self.access_token, + 'refresh_token': self.refresh_token } return JWTSerializer(data).data else: @@ -68,7 +69,7 @@ def create(self, request, *args, **kwargs): def perform_create(self, serializer): user = serializer.save(self.request) if getattr(settings, 'REST_USE_JWT', False): - self.token = jwt_encode(user) + self.access_token, self.refresh_token = jwt_encode(user) else: create_token(self.token_model, user, serializer) From 231ccc04a38eb1fc4a21545f75d6b0c4c70760b6 Mon Sep 17 00:00:00 2001 From: alichass Date: Wed, 11 Mar 2020 06:15:32 -0400 Subject: [PATCH 058/130] updated docs --- docs/configuration.rst | 2 +- docs/installation.rst | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index b988a765..af858c0f 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -46,7 +46,7 @@ Configuration - **REST_SESSION_LOGIN** - Enable session login in Login API view (default: True) -- **REST_USE_JWT** - Enable JWT Authentication instead of Token/Session based. This is built on top of django-rest-framework-jwt http://getblimp.github.io/django-rest-framework-jwt/, which must also be installed. (default: False) +- **REST_USE_JWT** - Enable JWT Authentication instead of Token/Session based. This is built on top of djangorestframework-simplejwt https://github.com/SimpleJWT/django-rest-framework-simplejwt, which must also be installed. (default: False) - **OLD_PASSWORD_FIELD_ENABLED** - set it to True if you want to have old password verification on password change enpoint (default: False) diff --git a/docs/installation.rst b/docs/installation.rst index cba551e5..50047525 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -248,12 +248,23 @@ JSON Web Token (JWT) Support (optional) By default ``dj-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, follow these steps: -1. Install `djangorestframework-jwt `_ - - ``djangorestframework-jwt`` is currently the only supported JWT library. -2. The ``JWT_PAYLOAD_HANDLER`` and ``JWT_ENCODE_HANDLER`` settings are imported from the ``django-rest-framework-jwt`` settings object. - - Refer to `the library's documentation `_ for information on using different encoders. +1. Install `djangorestframework-simplejwt `_ + - ``djangorestframework-simplejwt`` is currently the only supported JWT library. -3. Add the following configuration value to your settings file to enable JWT authentication. +2. Add a simple_jwt auth configuration to the list of authentication classes. + +.. code-block:: python + + REST_FRAMEWORK = { + ... + 'DEFAULT_AUTHENTICATION_CLASSES': ( + ... + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ) + ... + } + +3. Add the following configuration value to your settings file to enable JWT authentication in dj-rest-auth. .. code-block:: python From 6dd2aea624482cc527b0e10391a56a2dd95d3423 Mon Sep 17 00:00:00 2001 From: alichass Date: Wed, 11 Mar 2020 06:22:52 -0400 Subject: [PATCH 059/130] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 94aad460..8872a565 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ tests_require=[ 'responses>=0.5.0', 'django-allauth>=0.25.0', - 'djangorestframework-jwt>=1.9.0', + 'djangorestframework-simplejwt>=4.4.0 ', 'coveralls>=1.11.1' ], test_suite='runtests.runtests', From e198f8dddb9d54fd445a4bba105152ab6e5c7efe Mon Sep 17 00:00:00 2001 From: Mathias Lantean Date: Wed, 11 Mar 2020 15:23:22 -0300 Subject: [PATCH 060/130] Fix if condition in LoginSerializer As there is no reference to 'rest_auth.registration' this condition always validates to False. We should check if 'dj_rest_auth.registration' is in INSTALLED_APPS. --- dj_rest_auth/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index 07783da6..91c7b8af 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -100,7 +100,7 @@ def validate(self, attrs): raise exceptions.ValidationError(msg) # If required, is the email verified? - if 'rest_auth.registration' in settings.INSTALLED_APPS: + if 'dj_rest_auth.registration' in settings.INSTALLED_APPS: from allauth.account import app_settings if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY: email_address = user.emailaddress_set.get(email=user.email) From 597d17e6ff0f84d26d42808c6dd96427b64136c0 Mon Sep 17 00:00:00 2001 From: Mahmoud Adel Date: Thu, 12 Mar 2020 17:22:46 +0200 Subject: [PATCH 061/130] Uncomment 'django.contrib.messages' When run 'python manage.py migrate --settings=demo.settings --noinput' I get this on console SystemCheckError: System check identified some issues: ERRORS: ?: (admin.E406) 'django.contrib.messages' must be in INSTALLED_APPS in order to use the admin application. So uncomment it to solve the issue. --- demo/demo/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/demo/settings.py b/demo/demo/settings.py index df6807ae..50f5afbd 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -31,7 +31,7 @@ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', - # 'django.contrib.messages', + 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.sites', From 654eb22b7bee4a2a44252af3c14ebbd96ea18dc6 Mon Sep 17 00:00:00 2001 From: Mahmoud Adel Date: Thu, 12 Mar 2020 17:42:09 +0200 Subject: [PATCH 062/130] Fix AttributeError at /docs/ Using this solution https://github.com/encode/django-rest-framework/issues/6809#issuecomment-546302742 To fix: AttributeError at /docs/ 'AutoSchema' object has no attribute 'get_link' --- demo/demo/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demo/demo/settings.py b/demo/demo/settings.py index df6807ae..1cf35f5c 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -120,7 +120,8 @@ 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', - ) + ), + 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } SWAGGER_SETTINGS = { From 12e79aa33ebf835579492a1dd9db970aaef4fbdc Mon Sep 17 00:00:00 2001 From: alichass Date: Thu, 19 Mar 2020 14:37:35 -0400 Subject: [PATCH 063/130] changed for use w/ cookies --- dj_rest_auth/utils.py | 1 - dj_rest_auth/views.py | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index 165963d9..85912a6c 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -18,7 +18,6 @@ def default_create_token(token_model, user, serializer): def jwt_encode(user): try: from rest_framework_simplejwt.serializers import TokenObtainPairSerializer - from rest_framework_simplejwt.views import TokenObtainPairView except ImportError: raise ImportError("rest-framework-simplejwt needs to be installed") diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index f30980c7..37e4880c 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -83,6 +83,15 @@ def get_response(self): context={'request': self.request}) response = Response(serializer.data, status=status.HTTP_200_OK) + if getattr(settings, 'REST_USE_JWT', False): + from rest_framework_simplejwt.settings import api_settings as jwt_settings + #if jwt_settings.JWT_AUTH_COOKIE #this needs to be added to simplejwt + from datetime import datetime + expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) + response.set_cookie('somestring', #replace with jwt_settings.JWT_AUTH_COOKIE + self.access_token, + expires=expiration, + httponly=True) return response def post(self, request, *args, **kwargs): @@ -125,6 +134,10 @@ def logout(self, request): response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) + if getattr(settings, 'REST_USE_JWT', False): + from rest_framework_simplejwt.settings import api_settings as jwt_settings + #if jwt_settings.JWT_AUTH_COOKIE #this needs to be added to simplejwt + response.delete_cookie('somestring') #replace with jwt_settings.JWT_AUTH_COOKIE return response From f73f3af1d3698336d0ad15dceb0add289cb2188c Mon Sep 17 00:00:00 2001 From: alichass Date: Thu, 19 Mar 2020 17:09:20 -0400 Subject: [PATCH 064/130] hopefully this should work? --- dj_rest_auth/app_settings.py | 3 +++ dj_rest_auth/tests/settings.py | 2 +- dj_rest_auth/utils.py | 30 +++++++++++++++++++++++++++++- dj_rest_auth/views.py | 22 +++++++++++----------- docs/installation.rst | 2 +- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index d89202de..39e44ef3 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -34,3 +34,6 @@ ) PasswordChangeSerializer = import_callable(serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer)) + +JWT_AUTH_COOKIE = getattr(settings, 'JWT_AUTH_COOKIE', None) + diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index 7279c212..3d023096 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -68,7 +68,7 @@ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', - 'rest_framework_simplejwt.authentication.JWTAuthentication', + 'dj_rest_auth.utils.JWTCookieAuthentication', ) } diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index 85912a6c..2b8094ab 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -1,5 +1,5 @@ from importlib import import_module - +from .app_settings import JWT_AUTH_COOKIE def import_callable(path_or_callable): if hasattr(path_or_callable, '__call__'): @@ -23,3 +23,31 @@ def jwt_encode(user): refresh = TokenObtainPairSerializer.get_token(user) return refresh.access_token, refresh + + +try: + from rest_framework_simplejwt.authentication import JWTAuthentication + + class JWTCookieAuthentication(JWTAuthentication): + """ + An authentication plugin that hopefully authenticates requests through a JSON web + token provided in a request cookie (and through the header as normal, with a preference to the header). + """ + def authenticate(self, request): + header = self.get_header(request) + if header is None: + if JWT_AUTH_COOKIE: # or settings.JWT_AUTH_COOKIE + raw_token = request.COOKIES.get(JWT_AUTH_COOKIE) # or settings.jwt_auth_cookie + else: + return None + else: + raw_token = self.get_raw_token(header) + + if raw_token is None: + return None + + validated_token = self.get_validated_token(raw_token) + + return self.get_user(validated_token), validated_token +except ImportError as I: + pass diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 37e4880c..28962095 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -16,7 +16,7 @@ PasswordChangeSerializer, PasswordResetConfirmSerializer, PasswordResetSerializer, TokenSerializer, - UserDetailsSerializer, create_token) + UserDetailsSerializer, create_token, JWT_AUTH_COOKIE) from .models import TokenModel from .utils import jwt_encode @@ -85,13 +85,13 @@ def get_response(self): response = Response(serializer.data, status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): from rest_framework_simplejwt.settings import api_settings as jwt_settings - #if jwt_settings.JWT_AUTH_COOKIE #this needs to be added to simplejwt - from datetime import datetime - expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) - response.set_cookie('somestring', #replace with jwt_settings.JWT_AUTH_COOKIE - self.access_token, - expires=expiration, - httponly=True) + if JWT_AUTH_COOKIE: #this needs to be added to simplejwt + from datetime import datetime + expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) + response.set_cookie(JWT_AUTH_COOKIE, #this needs to be added to simplejwt + self.access_token, + expires=expiration, + httponly=True) return response def post(self, request, *args, **kwargs): @@ -135,9 +135,9 @@ def logout(self, request): response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): - from rest_framework_simplejwt.settings import api_settings as jwt_settings - #if jwt_settings.JWT_AUTH_COOKIE #this needs to be added to simplejwt - response.delete_cookie('somestring') #replace with jwt_settings.JWT_AUTH_COOKIE + # from rest_framework_simplejwt.settings import api_settings as jwt_settings + if JWT_AUTH_COOKIE: #this needs to be added to simplejwt + response.delete_cookie(JWT_AUTH_COOKIE) #this needs to be added to simplejwt return response diff --git a/docs/installation.rst b/docs/installation.rst index 50047525..fa4345da 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -259,7 +259,7 @@ By default ``dj-rest-auth`` uses Django's Token-based authentication. If you wan ... 'DEFAULT_AUTHENTICATION_CLASSES': ( ... - 'rest_framework_simplejwt.authentication.JWTAuthentication', + 'dj_rest_auth.utils.JWTCookieAuthentication', ) ... } From dbb3ff2b81d0eb3ba897243995f967be8c50aa76 Mon Sep 17 00:00:00 2001 From: David De Sousa Date: Sat, 21 Mar 2020 11:10:51 +0100 Subject: [PATCH 065/130] Fix typos in the registration serializer documentation --- docs/configuration.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index b988a765..5abaf4b5 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -6,19 +6,19 @@ Configuration You can define your custom serializers for each endpoint without overriding urls and views by adding ``REST_AUTH_SERIALIZERS`` dictionary in your django settings. Possible key values: - - LOGIN_SERIALIZER - serializer class in ``dj_rest_auth.views.LoginView``, default value ``rest_auth.serializers.LoginSerializer`` + - LOGIN_SERIALIZER - serializer class in ``dj_rest_auth.views.LoginView``, default value ``dj_rest_auth.serializers.LoginSerializer`` - - TOKEN_SERIALIZER - response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``rest_auth.serializers.TokenSerializer`` + - TOKEN_SERIALIZER - response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``dj_rest_auth.serializers.TokenSerializer`` - - JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``rest_auth.serializers.JWTSerializer`` + - JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``dj_rest_auth.serializers.JWTSerializer`` - - USER_DETAILS_SERIALIZER - serializer class in ``dj_rest_auth.views.UserDetailsView``, default value ``rest_auth.serializers.UserDetailsSerializer`` + - USER_DETAILS_SERIALIZER - serializer class in ``dj_rest_auth.views.UserDetailsView``, default value ``dj_rest_auth.serializers.UserDetailsSerializer`` - - PASSWORD_RESET_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetView``, default value ``rest_auth.serializers.PasswordResetSerializer`` + - PASSWORD_RESET_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetView``, default value ``dj_rest_auth.serializers.PasswordResetSerializer`` - - PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetConfirmView``, default value ``rest_auth.serializers.PasswordResetConfirmSerializer`` + - PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetConfirmView``, default value ``dj_rest_auth.serializers.PasswordResetConfirmSerializer`` - - PASSWORD_CHANGE_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordChangeView``, default value ``rest_auth.serializers.PasswordChangeSerializer`` + - PASSWORD_CHANGE_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordChangeView``, default value ``dj_rest_auth.serializers.PasswordChangeSerializer`` Example configuration: @@ -36,7 +36,7 @@ Configuration You can define your custom serializers for registration endpoint. Possible key values: - - REGISTER_SERIALIZER - serializer class in ``dj_rest_auth.registration.views.RegisterView``, default value ``rest_auth.registration.serializers.RegisterSerializer`` + - REGISTER_SERIALIZER - serializer class in ``dj_rest_auth.registration.views.RegisterView``, default value ``dj_rest_auth.registration.serializers.RegisterSerializer`` .. note:: The custom REGISTER_SERIALIZER must define a ``def save(self, request)`` method that returns a user model instance From 475e0b94c2cb00e9c260cd944e91d850627fd211 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 05:41:16 -0500 Subject: [PATCH 066/130] Support for Http-Only JWT Cookies --- demo/requirements.pip | 1 + dev-requirements.txt | 2 +- dj_rest_auth/tests/requirements.pip | 3 +- dj_rest_auth/tests/test_api.py | 291 +++------------------------- dj_rest_auth/tests/test_social.py | 3 - dj_rest_auth/tests/urls.py | 12 ++ dj_rest_auth/utils.py | 15 +- dj_rest_auth/views.py | 21 +- docs/configuration.rst | 2 +- 9 files changed, 60 insertions(+), 290 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 74422291..6d249675 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,6 @@ django>=1.9.0 dj-rest-auth==0.1.4 djangorestframework>=3.7.0 +djangorestframework-simplejwt==4.4.0 django-allauth>=0.24.1 django-rest-swagger==2.0.7 diff --git a/dev-requirements.txt b/dev-requirements.txt index 9d2af205..cee8ea6f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ --editable . responses>=0.5.0 -djangorestframework-jwt +djangorestframework-simplejwt==4.4.0 django-allauth coveralls>=1.11.1 \ No newline at end of file diff --git a/dj_rest_auth/tests/requirements.pip b/dj_rest_auth/tests/requirements.pip index f48ee3cf..4ff9b2d6 100644 --- a/dj_rest_auth/tests/requirements.pip +++ b/dj_rest_auth/tests/requirements.pip @@ -1,5 +1,6 @@ django-allauth>=0.25.0 responses>=0.3.0 flake8==2.4.0 -djangorestframework-jwt>=1.7.2 +Django==3.0.4 +djangorestframework-simplejwt==4.4.0 djangorestframework>=3.6.4 diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 5d06fac6..45191860 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -144,293 +144,46 @@ def test_allauth_login_with_email(self): self.post(self.login_url, data=payload, status_code=200) @override_settings(REST_USE_JWT=True) - def test_login_jwt(self): + @override_settings(JWT_AUTH_COOKIE='jwt-auth') + def test_login_jwt_sets_cookie(self): 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) + self.assertTrue('jwt-auth' in resp.cookies.keys()) - self.post(self.login_url, data=payload, status_code=200) - self.assertEqual('access_token' in self.response.json.keys(), True) - self.token = self.response.json['access_token'] - - def test_login_by_email(self): - # starting test without allauth app - settings.INSTALLED_APPS.remove('allauth') - - payload = { - "email": self.EMAIL.lower(), - "password": self.PASS - } - # there is no users in db so it should throw error (400) - self.post(self.login_url, data=payload, status_code=400) - - self.post(self.password_change_url, status_code=403) - - # create user - user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) - - # test auth by email - self.post(self.login_url, data=payload, status_code=200) - self.assertEqual('key' in self.response.json.keys(), True) - self.token = self.response.json['key'] - - # test auth by email in different case - payload = { - "email": self.EMAIL.upper(), - "password": self.PASS - } - self.post(self.login_url, data=payload, status_code=200) - self.assertEqual('key' in self.response.json.keys(), True) - self.token = self.response.json['key'] - - # test inactive user - user.is_active = False - user.save() - self.post(self.login_url, data=payload, status_code=400) - - # test wrong email/password + @override_settings(REST_USE_JWT=True) + @override_settings(JWT_AUTH_COOKIE='jwt-auth') + def test_logout_jwt_deletes_cookie(self): payload = { - "email": 't' + self.EMAIL, - "password": self.PASS - } - self.post(self.login_url, data=payload, status_code=400) - - # test empty payload - self.post(self.login_url, data={}, status_code=400) - - # bring back allauth - settings.INSTALLED_APPS.append('allauth') - - def test_password_change(self): - login_payload = { "username": self.USERNAME, "password": self.PASS } get_user_model().objects.create_user(self.USERNAME, '', self.PASS) - self.post(self.login_url, data=login_payload, status_code=200) - self.token = self.response.json['key'] - - new_password_payload = { - "new_password1": "new_person", - "new_password2": "new_person" - } - self.post( - self.password_change_url, - data=new_password_payload, - status_code=200 - ) - - # user should not be able to login using old password - self.post(self.login_url, data=login_payload, status_code=400) - - # new password should work - login_payload['password'] = new_password_payload['new_password1'] - self.post(self.login_url, data=login_payload, status_code=200) - - # pass1 and pass2 are not equal - new_password_payload = { - "new_password1": "new_person1", - "new_password2": "new_person" - } - self.post( - self.password_change_url, - data=new_password_payload, - status_code=400 - ) - - # send empty payload - self.post(self.password_change_url, data={}, status_code=400) - - @override_settings(OLD_PASSWORD_FIELD_ENABLED=True) - def test_password_change_with_old_password(self): - login_payload = { - "username": self.USERNAME, - "password": self.PASS - } - get_user_model().objects.create_user(self.USERNAME, '', self.PASS) - self.post(self.login_url, data=login_payload, status_code=200) - self.token = self.response.json['key'] - - new_password_payload = { - "old_password": "%s!" % self.PASS, # wrong password - "new_password1": "new_person", - "new_password2": "new_person" - } - self.post( - self.password_change_url, - data=new_password_payload, - status_code=400 - ) - - new_password_payload = { - "old_password": self.PASS, - "new_password1": "new_person", - "new_password2": "new_person" - } - self.post( - self.password_change_url, - data=new_password_payload, - status_code=200 - ) - - # user should not be able to login using old password - self.post(self.login_url, data=login_payload, status_code=400) - - # new password should work - login_payload['password'] = new_password_payload['new_password1'] - self.post(self.login_url, data=login_payload, status_code=200) - - def test_password_reset(self): - user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) - - # call password reset - mail_count = len(mail.outbox) - payload = {'email': self.EMAIL} - self.post(self.password_reset_url, data=payload, status_code=200) - self.assertEqual(len(mail.outbox), mail_count + 1) - - url_kwargs = self._generate_uid_and_token(user) - url = reverse('rest_password_reset_confirm') - - # wrong token - data = { - 'new_password1': self.NEW_PASS, - 'new_password2': self.NEW_PASS, - 'uid': force_text(url_kwargs['uid']), - 'token': '-wrong-token-' - } - self.post(url, data=data, status_code=400) - - # wrong uid - data = { - 'new_password1': self.NEW_PASS, - 'new_password2': self.NEW_PASS, - 'uid': '-wrong-uid-', - 'token': url_kwargs['token'] - } - self.post(url, data=data, status_code=400) - - # wrong token and uid - data = { - 'new_password1': self.NEW_PASS, - 'new_password2': self.NEW_PASS, - 'uid': '-wrong-uid-', - 'token': '-wrong-token-' - } - self.post(url, data=data, status_code=400) - - # valid payload - data = { - 'new_password1': self.NEW_PASS, - 'new_password2': self.NEW_PASS, - 'uid': force_text(url_kwargs['uid']), - 'token': url_kwargs['token'] - } - url = reverse('rest_password_reset_confirm') - self.post(url, data=data, status_code=200) - - payload = { - "username": self.USERNAME, - "password": self.NEW_PASS - } self.post(self.login_url, data=payload, status_code=200) - - def test_password_reset_with_email_in_different_case(self): - get_user_model().objects.create_user(self.USERNAME, self.EMAIL.lower(), self.PASS) - - # call password reset in upper case - mail_count = len(mail.outbox) - payload = {'email': self.EMAIL.upper()} - self.post(self.password_reset_url, data=payload, status_code=200) - self.assertEqual(len(mail.outbox), mail_count + 1) - - def test_password_reset_with_invalid_email(self): - """ - Invalid email should not raise error, as this would leak users - """ - get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) - - # call password reset - mail_count = len(mail.outbox) - payload = {'email': 'nonexisting@email.com'} - self.post(self.password_reset_url, data=payload, status_code=200) - self.assertEqual(len(mail.outbox), mail_count) - - def test_user_details(self): - user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) - payload = { - "username": self.USERNAME, - "password": self.PASS - } - self.post(self.login_url, data=payload, status_code=200) - self.token = self.response.json['key'] - self.get(self.user_url, status_code=200) - - self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200) - user = get_user_model().objects.get(pk=user.pk) - self.assertEqual(user.first_name, self.response.json['first_name']) - self.assertEqual(user.last_name, self.response.json['last_name']) - self.assertEqual(user.email, self.response.json['email']) + resp = self.post(self.logout_url, status=200) + self.assertEqual('', resp.cookies.get('jwt-auth').value) @override_settings(REST_USE_JWT=True) - def test_user_details_using_jwt(self): - user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) + @override_settings(JWT_AUTH_COOKIE='jwt-auth') + @override_settings(REST_FRAMEWORK=dict( + DEFAULT_AUTHENTICATION_CLASSES=[ + 'dj_rest_auth.utils.JWTCookieAuthentication' + ] + )) + @override_settings(REST_SESSION_LOGIN=False) + def test_cookie_authentication(self): payload = { "username": self.USERNAME, "password": self.PASS } - self.post(self.login_url, data=payload, status_code=200) - self.token = self.response.json['access_token'] - self.get(self.user_url, status_code=200) - - self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200) - user = get_user_model().objects.get(pk=user.pk) - self.assertEqual(user.email, self.response.json['email']) - - def test_registration(self): - user_count = get_user_model().objects.all().count() - - # test empty payload - self.post(self.register_url, data={}, status_code=400) - - result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201) - self.assertIn('key', result.data) - self.assertEqual(get_user_model().objects.all().count(), user_count + 1) - - new_user = get_user_model().objects.latest('id') - self.assertEqual(new_user.username, self.REGISTRATION_DATA['username']) - - self._login() - self._logout() - - @override_settings(REST_AUTH_REGISTER_PERMISSION_CLASSES=(CustomPermissionClass,)) - def test_registration_with_custom_permission_class(self): - - class CustomRegisterView(RegisterView): - permission_classes = register_permission_classes() - authentication_classes = () - - factory = APIRequestFactory() - request = factory.post('/customer/details', self.REGISTRATION_DATA, format='json') - - response = CustomRegisterView.as_view()(request) - self.assertEqual(response.data['detail'], CustomPermissionClass.message) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - - @override_settings(REST_USE_JWT=True) - def test_registration_with_jwt(self): - user_count = get_user_model().objects.all().count() - - self.post(self.register_url, data={}, status_code=400) - - result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201) - self.assertIn('access_token', result.data) - self.assertEqual(get_user_model().objects.all().count(), user_count + 1) - - self._login() - self._logout() + get_user_model().objects.create_user(self.USERNAME, '', self.PASS) + resp = self.post(self.login_url, data=payload, status_code=200) + self.assertEqual(['jwt-auth'], list(resp.cookies.keys())) + resp = self.get('/protected-view/') + self.assertEquals(resp.status_code, 200) def test_registration_with_invalid_password(self): data = self.REGISTRATION_DATA.copy() diff --git a/dj_rest_auth/tests/test_social.py b/dj_rest_auth/tests/test_social.py index cceba3f7..819b1534 100644 --- a/dj_rest_auth/tests/test_social.py +++ b/dj_rest_auth/tests/test_social.py @@ -17,9 +17,6 @@ from django.core.urlresolvers import reverse - - - @override_settings(ROOT_URLCONF="tests.urls") class TestSocialAuth(TestsMixin, TestCase): diff --git a/dj_rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py index be199a50..7579e838 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -11,10 +11,21 @@ from django.conf.urls import include, url from django.views.generic import TemplateView from rest_framework.decorators import api_view +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import permissions from . import django_urls +class ExampleProtectedView(APIView): + permission_classes = [permissions.IsAuthenticated] + + + def get(self, *args, **kwargs): + return Response(dict(success=True)) + + class FacebookLogin(SocialLoginView): adapter_class = FacebookOAuth2Adapter @@ -64,6 +75,7 @@ class TwitterLoginNoAdapter(SocialLoginView): url(r'^social-login/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect'), url(r'^social-login/twitter/connect/$', TwitterConnect.as_view(), name='tw_connect'), url(r'^socialaccounts/$', SocialAccountListView.as_view(), name='social_account_list'), + url(r'^protected-view/$', ExampleProtectedView.as_view()), url(r'^socialaccounts/(?P\d+)/disconnect/$', SocialAccountDisconnectView.as_view(), name='social_account_disconnect'), url(r'^accounts/', include('allauth.socialaccount.urls')) diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index 2b8094ab..7cbf3ad1 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -1,5 +1,5 @@ from importlib import import_module -from .app_settings import JWT_AUTH_COOKIE + def import_callable(path_or_callable): if hasattr(path_or_callable, '__call__'): @@ -31,13 +31,16 @@ def jwt_encode(user): class JWTCookieAuthentication(JWTAuthentication): """ An authentication plugin that hopefully authenticates requests through a JSON web - token provided in a request cookie (and through the header as normal, with a preference to the header). + token provided in a request cookie (and through the header as normal, with a + preference to the header). """ def authenticate(self, request): + from django.conf import settings + cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) header = self.get_header(request) if header is None: - if JWT_AUTH_COOKIE: # or settings.JWT_AUTH_COOKIE - raw_token = request.COOKIES.get(JWT_AUTH_COOKIE) # or settings.jwt_auth_cookie + if cookie_name: + raw_token = request.COOKIES.get(cookie_name) else: return None else: @@ -47,7 +50,7 @@ def authenticate(self, request): return None validated_token = self.get_validated_token(raw_token) - return self.get_user(validated_token), validated_token -except ImportError as I: + +except ImportError: pass diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 28962095..a31e8798 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -16,7 +16,7 @@ PasswordChangeSerializer, PasswordResetConfirmSerializer, PasswordResetSerializer, TokenSerializer, - UserDetailsSerializer, create_token, JWT_AUTH_COOKIE) + UserDetailsSerializer, create_token) from .models import TokenModel from .utils import jwt_encode @@ -84,14 +84,17 @@ def get_response(self): response = Response(serializer.data, status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): + cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) from rest_framework_simplejwt.settings import api_settings as jwt_settings - if JWT_AUTH_COOKIE: #this needs to be added to simplejwt + if cookie_name: from datetime import datetime expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME) - response.set_cookie(JWT_AUTH_COOKIE, #this needs to be added to simplejwt - self.access_token, - expires=expiration, - httponly=True) + response.set_cookie( + cookie_name, + self.access_token, + expires=expiration, + httponly=True + ) return response def post(self, request, *args, **kwargs): @@ -135,9 +138,9 @@ def logout(self, request): response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): - # from rest_framework_simplejwt.settings import api_settings as jwt_settings - if JWT_AUTH_COOKIE: #this needs to be added to simplejwt - response.delete_cookie(JWT_AUTH_COOKIE) #this needs to be added to simplejwt + cookie_name = getattr(settings, 'JWT_AUTH_COOKIE') + if cookie_name: + response.delete_cookie(cookie_name) return response diff --git a/docs/configuration.rst b/docs/configuration.rst index af858c0f..d4d67cc4 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -47,7 +47,7 @@ Configuration - **REST_SESSION_LOGIN** - Enable session login in Login API view (default: True) - **REST_USE_JWT** - Enable JWT Authentication instead of Token/Session based. This is built on top of djangorestframework-simplejwt https://github.com/SimpleJWT/django-rest-framework-simplejwt, which must also be installed. (default: False) - +- **JWT_AUTH_COOKIE** - The cookie name/key. - **OLD_PASSWORD_FIELD_ENABLED** - set it to True if you want to have old password verification on password change enpoint (default: False) - **LOGOUT_ON_PASSWORD_CHANGE** - set to False if you want to keep the current user logged in after a password change From ce3b90dea6e2bd5b691d6f2c84fd9e85b07a5952 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 05:52:26 -0500 Subject: [PATCH 067/130] Re-adds previous tests --- dj_rest_auth/tests/test_api.py | 335 ++++++++++++++++++++++++++++++--- dj_rest_auth/views.py | 2 +- 2 files changed, 314 insertions(+), 23 deletions(-) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 45191860..f0607b54 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -144,46 +144,293 @@ def test_allauth_login_with_email(self): self.post(self.login_url, data=payload, status_code=200) @override_settings(REST_USE_JWT=True) - @override_settings(JWT_AUTH_COOKIE='jwt-auth') - def test_login_jwt_sets_cookie(self): + def test_login_jwt(self): 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) - self.assertTrue('jwt-auth' in resp.cookies.keys()) - @override_settings(REST_USE_JWT=True) - @override_settings(JWT_AUTH_COOKIE='jwt-auth') - def test_logout_jwt_deletes_cookie(self): + self.post(self.login_url, data=payload, status_code=200) + self.assertEqual('access_token' in self.response.json.keys(), True) + self.token = self.response.json['access_token'] + + def test_login_by_email(self): + # starting test without allauth app + settings.INSTALLED_APPS.remove('allauth') + + payload = { + "email": self.EMAIL.lower(), + "password": self.PASS + } + # there is no users in db so it should throw error (400) + self.post(self.login_url, data=payload, status_code=400) + + self.post(self.password_change_url, status_code=403) + + # create user + user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) + + # test auth by email + self.post(self.login_url, data=payload, status_code=200) + self.assertEqual('key' in self.response.json.keys(), True) + self.token = self.response.json['key'] + + # test auth by email in different case payload = { + "email": self.EMAIL.upper(), + "password": self.PASS + } + self.post(self.login_url, data=payload, status_code=200) + self.assertEqual('key' in self.response.json.keys(), True) + self.token = self.response.json['key'] + + # test inactive user + user.is_active = False + user.save() + self.post(self.login_url, data=payload, status_code=400) + + # test wrong email/password + payload = { + "email": 't' + self.EMAIL, + "password": self.PASS + } + self.post(self.login_url, data=payload, status_code=400) + + # test empty payload + self.post(self.login_url, data={}, status_code=400) + + # bring back allauth + settings.INSTALLED_APPS.append('allauth') + + def test_password_change(self): + login_payload = { "username": self.USERNAME, "password": self.PASS } get_user_model().objects.create_user(self.USERNAME, '', self.PASS) + self.post(self.login_url, data=login_payload, status_code=200) + self.token = self.response.json['key'] + + new_password_payload = { + "new_password1": "new_person", + "new_password2": "new_person" + } + self.post( + self.password_change_url, + data=new_password_payload, + status_code=200 + ) + + # user should not be able to login using old password + self.post(self.login_url, data=login_payload, status_code=400) + + # new password should work + login_payload['password'] = new_password_payload['new_password1'] + self.post(self.login_url, data=login_payload, status_code=200) + + # pass1 and pass2 are not equal + new_password_payload = { + "new_password1": "new_person1", + "new_password2": "new_person" + } + self.post( + self.password_change_url, + data=new_password_payload, + status_code=400 + ) + + # send empty payload + self.post(self.password_change_url, data={}, status_code=400) + + @override_settings(OLD_PASSWORD_FIELD_ENABLED=True) + def test_password_change_with_old_password(self): + login_payload = { + "username": self.USERNAME, + "password": self.PASS + } + get_user_model().objects.create_user(self.USERNAME, '', self.PASS) + self.post(self.login_url, data=login_payload, status_code=200) + self.token = self.response.json['key'] + + new_password_payload = { + "old_password": "%s!" % self.PASS, # wrong password + "new_password1": "new_person", + "new_password2": "new_person" + } + self.post( + self.password_change_url, + data=new_password_payload, + status_code=400 + ) + + new_password_payload = { + "old_password": self.PASS, + "new_password1": "new_person", + "new_password2": "new_person" + } + self.post( + self.password_change_url, + data=new_password_payload, + status_code=200 + ) + + # user should not be able to login using old password + self.post(self.login_url, data=login_payload, status_code=400) + + # new password should work + login_payload['password'] = new_password_payload['new_password1'] + self.post(self.login_url, data=login_payload, status_code=200) + + def test_password_reset(self): + user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) + + # call password reset + mail_count = len(mail.outbox) + payload = {'email': self.EMAIL} + self.post(self.password_reset_url, data=payload, status_code=200) + self.assertEqual(len(mail.outbox), mail_count + 1) + + url_kwargs = self._generate_uid_and_token(user) + url = reverse('rest_password_reset_confirm') + + # wrong token + data = { + 'new_password1': self.NEW_PASS, + 'new_password2': self.NEW_PASS, + 'uid': force_text(url_kwargs['uid']), + 'token': '-wrong-token-' + } + self.post(url, data=data, status_code=400) + + # wrong uid + data = { + 'new_password1': self.NEW_PASS, + 'new_password2': self.NEW_PASS, + 'uid': '-wrong-uid-', + 'token': url_kwargs['token'] + } + self.post(url, data=data, status_code=400) + + # wrong token and uid + data = { + 'new_password1': self.NEW_PASS, + 'new_password2': self.NEW_PASS, + 'uid': '-wrong-uid-', + 'token': '-wrong-token-' + } + self.post(url, data=data, status_code=400) + + # valid payload + data = { + 'new_password1': self.NEW_PASS, + 'new_password2': self.NEW_PASS, + 'uid': force_text(url_kwargs['uid']), + 'token': url_kwargs['token'] + } + url = reverse('rest_password_reset_confirm') + self.post(url, data=data, status_code=200) + + payload = { + "username": self.USERNAME, + "password": self.NEW_PASS + } self.post(self.login_url, data=payload, status_code=200) - resp = self.post(self.logout_url, status=200) - self.assertEqual('', resp.cookies.get('jwt-auth').value) + + def test_password_reset_with_email_in_different_case(self): + get_user_model().objects.create_user(self.USERNAME, self.EMAIL.lower(), self.PASS) + + # call password reset in upper case + mail_count = len(mail.outbox) + payload = {'email': self.EMAIL.upper()} + self.post(self.password_reset_url, data=payload, status_code=200) + self.assertEqual(len(mail.outbox), mail_count + 1) + + def test_password_reset_with_invalid_email(self): + """ + Invalid email should not raise error, as this would leak users + """ + get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) + + # call password reset + mail_count = len(mail.outbox) + payload = {'email': 'nonexisting@email.com'} + self.post(self.password_reset_url, data=payload, status_code=200) + self.assertEqual(len(mail.outbox), mail_count) + + def test_user_details(self): + user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) + payload = { + "username": self.USERNAME, + "password": self.PASS + } + self.post(self.login_url, data=payload, status_code=200) + self.token = self.response.json['key'] + self.get(self.user_url, status_code=200) + + self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200) + user = get_user_model().objects.get(pk=user.pk) + self.assertEqual(user.first_name, self.response.json['first_name']) + self.assertEqual(user.last_name, self.response.json['last_name']) + self.assertEqual(user.email, self.response.json['email']) @override_settings(REST_USE_JWT=True) - @override_settings(JWT_AUTH_COOKIE='jwt-auth') - @override_settings(REST_FRAMEWORK=dict( - DEFAULT_AUTHENTICATION_CLASSES=[ - 'dj_rest_auth.utils.JWTCookieAuthentication' - ] - )) - @override_settings(REST_SESSION_LOGIN=False) - def test_cookie_authentication(self): + def test_user_details_using_jwt(self): + user = get_user_model().objects.create_user(self.USERNAME, self.EMAIL, self.PASS) 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) - self.assertEqual(['jwt-auth'], list(resp.cookies.keys())) - resp = self.get('/protected-view/') - self.assertEquals(resp.status_code, 200) + self.post(self.login_url, data=payload, status_code=200) + self.token = self.response.json['access_token'] + self.get(self.user_url, status_code=200) + + self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200) + user = get_user_model().objects.get(pk=user.pk) + self.assertEqual(user.email, self.response.json['email']) + + def test_registration(self): + user_count = get_user_model().objects.all().count() + + # test empty payload + self.post(self.register_url, data={}, status_code=400) + + result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201) + self.assertIn('key', result.data) + self.assertEqual(get_user_model().objects.all().count(), user_count + 1) + + new_user = get_user_model().objects.latest('id') + self.assertEqual(new_user.username, self.REGISTRATION_DATA['username']) + + self._login() + self._logout() + + @override_settings(REST_AUTH_REGISTER_PERMISSION_CLASSES=(CustomPermissionClass,)) + def test_registration_with_custom_permission_class(self): + + class CustomRegisterView(RegisterView): + permission_classes = register_permission_classes() + authentication_classes = () + + factory = APIRequestFactory() + request = factory.post('/customer/details', self.REGISTRATION_DATA, format='json') + + response = CustomRegisterView.as_view()(request) + self.assertEqual(response.data['detail'], CustomPermissionClass.message) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + @override_settings(REST_USE_JWT=True) + def test_registration_with_jwt(self): + user_count = get_user_model().objects.all().count() + + self.post(self.register_url, data={}, status_code=400) + + result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201) + self.assertIn('access_token', result.data) + self.assertEqual(get_user_model().objects.all().count(), user_count + 1) + + self._login() + self._logout() def test_registration_with_invalid_password(self): data = self.REGISTRATION_DATA.copy() @@ -267,3 +514,47 @@ def test_logout_on_post_only(self): self.post(self.login_url, data=payload, status_code=status.HTTP_200_OK) self.get(self.logout_url, status_code=status.HTTP_405_METHOD_NOT_ALLOWED) + + @override_settings(REST_USE_JWT=True) + @override_settings(JWT_AUTH_COOKIE='jwt-auth') + def test_login_jwt_sets_cookie(self): + 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) + self.assertTrue('jwt-auth' in resp.cookies.keys()) + + + @override_settings(REST_USE_JWT=True) + @override_settings(JWT_AUTH_COOKIE='jwt-auth') + def test_logout_jwt_deletes_cookie(self): + payload = { + "username": self.USERNAME, + "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.logout_url, status=200) + self.assertEqual('', resp.cookies.get('jwt-auth').value) + + + @override_settings(REST_USE_JWT=True) + @override_settings(JWT_AUTH_COOKIE='jwt-auth') + @override_settings(REST_FRAMEWORK=dict( + DEFAULT_AUTHENTICATION_CLASSES=[ + 'dj_rest_auth.utils.JWTCookieAuthentication' + ] + )) + @override_settings(REST_SESSION_LOGIN=False) + def test_cookie_authentication(self): + 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) + self.assertEqual(['jwt-auth'], list(resp.cookies.keys())) + resp = self.get('/protected-view/') + self.assertEquals(resp.status_code, 200) \ No newline at end of file diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index a31e8798..c5ba7fcd 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -138,7 +138,7 @@ def logout(self, request): response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): - cookie_name = getattr(settings, 'JWT_AUTH_COOKIE') + cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) if cookie_name: response.delete_cookie(cookie_name) return response From 4070bce94bda8d3c3d04839f0f2952d88f95490f Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 06:20:44 -0500 Subject: [PATCH 068/130] Attempts to fix tests --- .circleci/config.yml | 2 +- dev-requirements.txt | 2 +- dj_rest_auth/tests/requirements.pip | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d1248695..efcf7920 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,9 +12,9 @@ jobs: executor: docker/docker steps: - checkout - - run: pip install -q --user coveralls djangorestframework==$DRF Django==$DJANGO_VERSION - run: pip install --user -r dev-requirements.txt - run: pip install --user -r dj_rest_auth/tests/requirements.pip + - run: pip install -q --user coveralls djangorestframework==$DRF Django==$DJANGO_VERSION - run: command: coverage run --source=dj_rest_auth setup.py test name: Test diff --git a/dev-requirements.txt b/dev-requirements.txt index cee8ea6f..9cb5377a 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,4 +2,4 @@ responses>=0.5.0 djangorestframework-simplejwt==4.4.0 django-allauth -coveralls>=1.11.1 \ No newline at end of file +coveralls>=1.11. \ No newline at end of file diff --git a/dj_rest_auth/tests/requirements.pip b/dj_rest_auth/tests/requirements.pip index 4ff9b2d6..9f28d704 100644 --- a/dj_rest_auth/tests/requirements.pip +++ b/dj_rest_auth/tests/requirements.pip @@ -1,6 +1,4 @@ django-allauth>=0.25.0 responses>=0.3.0 flake8==2.4.0 -Django==3.0.4 djangorestframework-simplejwt==4.4.0 -djangorestframework>=3.6.4 From 27815933f52ab393477abaa94bcae0d86fee6fcf Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 06:23:13 -0500 Subject: [PATCH 069/130] Bumps minor version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8872a565..46f5d5fb 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='0.1.4', + version='0.2.0', author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From bfd67501048a519b6e07f9ef55e04f21a4695353 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 06:25:43 -0500 Subject: [PATCH 070/130] Removes coveralls patch edit --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 9cb5377a..cee8ea6f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,4 +2,4 @@ responses>=0.5.0 djangorestframework-simplejwt==4.4.0 django-allauth -coveralls>=1.11. \ No newline at end of file +coveralls>=1.11.1 \ No newline at end of file From fe06053abe2859e5a5c4887590c3546f71b6d332 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 06:38:54 -0500 Subject: [PATCH 071/130] Adds JWT example to Readme --- README.md | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3ec4ef7f..a106d5e3 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,35 @@ Install package Add `dj_rest_auth` app to INSTALLED_APPS in your django settings.py: - INSTALLED_APPS = ( - ..., - 'rest_framework', - 'rest_framework.authtoken', - ..., - 'dj_rest_auth' - ) +```python +INSTALLED_APPS = ( + ..., + 'rest_framework', + 'rest_framework.authtoken', + ..., + 'dj_rest_auth' +) +``` Add URL patterns +```python +urlpatterns = [ + url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) +] +``` + +(Optional) + +Use Http-Only cookies + +```python +REST_USE_JWT = True +JWT_AUTH_COOKIE = 'jwt-auth' +``` + + - urlpatterns = [ - url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) - ] ### Documentation From 1eaa8edd0ef1718d612b037c2f1e367a28aea23f Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Mar 2020 06:40:01 -0500 Subject: [PATCH 072/130] README tweak --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a106d5e3..b87ba309 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,8 @@ urlpatterns = [ ] ``` -(Optional) -Use Http-Only cookies +(Optional) Use Http-Only cookies ```python REST_USE_JWT = True From c933513438d8fb53cf55f2dd3a8ea8ab2bdad00f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 11:09:07 -0500 Subject: [PATCH 073/130] Bumps version, fixes import ordering --- dj_rest_auth/app_settings.py | 1 - dj_rest_auth/tests/test_api.py | 7 ++----- dj_rest_auth/tests/urls.py | 4 ++-- setup.py | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 39e44ef3..16c3888f 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -36,4 +36,3 @@ PasswordChangeSerializer = import_callable(serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer)) JWT_AUTH_COOKIE = getattr(settings, 'JWT_AUTH_COOKIE', None) - diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index f0607b54..0134560d 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -407,7 +407,6 @@ def test_registration(self): @override_settings(REST_AUTH_REGISTER_PERMISSION_CLASSES=(CustomPermissionClass,)) def test_registration_with_custom_permission_class(self): - class CustomRegisterView(RegisterView): permission_classes = register_permission_classes() authentication_classes = () @@ -477,7 +476,7 @@ def test_registration_with_email_verification(self): ) # verify email - email_confirmation = new_user.emailaddress_set.get(email=self.EMAIL)\ + email_confirmation = new_user.emailaddress_set.get(email=self.EMAIL) \ .emailconfirmation_set.order_by('-created')[0] self.post( self.verify_email_url, @@ -526,7 +525,6 @@ def test_login_jwt_sets_cookie(self): resp = self.post(self.login_url, data=payload, status_code=200) self.assertTrue('jwt-auth' in resp.cookies.keys()) - @override_settings(REST_USE_JWT=True) @override_settings(JWT_AUTH_COOKIE='jwt-auth') def test_logout_jwt_deletes_cookie(self): @@ -539,7 +537,6 @@ def test_logout_jwt_deletes_cookie(self): resp = self.post(self.logout_url, status=200) self.assertEqual('', resp.cookies.get('jwt-auth').value) - @override_settings(REST_USE_JWT=True) @override_settings(JWT_AUTH_COOKIE='jwt-auth') @override_settings(REST_FRAMEWORK=dict( @@ -557,4 +554,4 @@ def test_cookie_authentication(self): resp = self.post(self.login_url, data=payload, status_code=200) self.assertEqual(['jwt-auth'], list(resp.cookies.keys())) resp = self.get('/protected-view/') - self.assertEquals(resp.status_code, 200) \ No newline at end of file + self.assertEquals(resp.status_code, 200) diff --git a/dj_rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py index 7579e838..e2c786e4 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -10,10 +10,10 @@ from dj_rest_auth.urls import urlpatterns from django.conf.urls import include, url from django.views.generic import TemplateView +from rest_framework import permissions from rest_framework.decorators import api_view -from rest_framework.views import APIView from rest_framework.response import Response -from rest_framework import permissions +from rest_framework.views import APIView from . import django_urls diff --git a/setup.py b/setup.py index 46f5d5fb..da113374 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='0.2.0', + version='1.0.0', author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From 9d24b4ffe00c83e5279b4c4a2dfca4bc36d5bfa6 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 11:36:03 -0500 Subject: [PATCH 074/130] Updates docs and demo --- demo/demo/settings.py | 2 -- demo/requirements.pip | 3 ++- docs/changelog.rst | 13 ++++++++++++- docs/index.rst | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/demo/demo/settings.py b/demo/demo/settings.py index 31056dea..9394428a 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -34,11 +34,9 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.sites', - 'rest_framework', 'rest_framework.authtoken', 'dj_rest_auth', - 'allauth', 'allauth.account', 'dj_rest_auth.registration', diff --git a/demo/requirements.pip b/demo/requirements.pip index 6d249675..04b962d1 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,6 +1,7 @@ django>=1.9.0 dj-rest-auth==0.1.4 -djangorestframework>=3.7.0 +djangorestframework>=3.11.0 djangorestframework-simplejwt==4.4.0 django-allauth>=0.24.1 django-rest-swagger==2.0.7 +coreapi==2.3.3 \ No newline at end of file diff --git a/docs/changelog.rst b/docs/changelog.rst index 42d36bcb..405df481 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -3,4 +3,15 @@ Changelog 0.1.2 ----- -Welcome Dj-Rest-Auth \ No newline at end of file +Welcome Dj-Rest-Auth + +1.0.0 +----- +Replaces `rest_framework_jwt` with `djangorestframework-simplejwt`. + + +- rest_framework_jwt is now unmaintained so we've switched to simplewjt, +which is a strong jwt library with a large community. +- This change means you may need to change your client code if you're upgrading + from the previous version. Example: token -> access_token. Please see demo + for more information. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 82118ccb..10eb7cb3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ Welcome to dj-rest-auth's documentation! ============================================ -.. note:: dj-rest-auth supports django-rest-framework >= v3.0 +.. note:: dj-rest-auth version 1.0.0 now uses Django Simple JWT. Please see changelog. .. image:: https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg From ff7d9728bb9baad2fbea3135bc93892375831ae2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 11:39:21 -0500 Subject: [PATCH 075/130] Use master in demo --- demo/requirements.pip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 04b962d1..64a3488d 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.9.0 -dj-rest-auth==0.1.4 +git+https://github.com/jazzband/dj-rest-auth.git@master djangorestframework>=3.11.0 djangorestframework-simplejwt==4.4.0 django-allauth>=0.24.1 From ac3cbcb613f78e385a3a94c4339cc2c5394949ec Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 12:15:02 -0500 Subject: [PATCH 076/130] Adds React SPA --- .gitignore | 2 + demo/demo/settings.py | 5 + demo/react-spa/.gitignore | 23 +++++ demo/react-spa/README.md | 68 ++++++++++++++ demo/react-spa/package.json | 34 +++++++ demo/react-spa/public/favicon.ico | Bin 0 -> 3150 bytes demo/react-spa/public/index.html | 43 +++++++++ demo/react-spa/public/logo192.png | Bin 0 -> 5347 bytes demo/react-spa/public/logo512.png | Bin 0 -> 9664 bytes demo/react-spa/public/manifest.json | 25 +++++ demo/react-spa/public/robots.txt | 3 + demo/react-spa/src/App.css | 38 ++++++++ demo/react-spa/src/App.js | 58 ++++++++++++ demo/react-spa/src/App.test.js | 9 ++ demo/react-spa/src/index.css | 13 +++ demo/react-spa/src/index.js | 17 ++++ demo/react-spa/src/logo.svg | 7 ++ demo/react-spa/src/serviceWorker.js | 141 ++++++++++++++++++++++++++++ demo/react-spa/src/setupTests.js | 5 + demo/requirements.pip | 3 +- 20 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 demo/react-spa/.gitignore create mode 100644 demo/react-spa/README.md create mode 100644 demo/react-spa/package.json create mode 100644 demo/react-spa/public/favicon.ico create mode 100644 demo/react-spa/public/index.html create mode 100644 demo/react-spa/public/logo192.png create mode 100644 demo/react-spa/public/logo512.png create mode 100644 demo/react-spa/public/manifest.json create mode 100644 demo/react-spa/public/robots.txt create mode 100644 demo/react-spa/src/App.css create mode 100644 demo/react-spa/src/App.js create mode 100644 demo/react-spa/src/App.test.js create mode 100644 demo/react-spa/src/index.css create mode 100644 demo/react-spa/src/index.js create mode 100644 demo/react-spa/src/logo.svg create mode 100644 demo/react-spa/src/serviceWorker.js create mode 100644 demo/react-spa/src/setupTests.js diff --git a/.gitignore b/.gitignore index 894a44cc..84cc2dea 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ venv.bak/ # mypy .mypy_cache/ +demo/react-spa/node_modules/ +demo/react-spa/yarn.lock \ No newline at end of file diff --git a/demo/demo/settings.py b/demo/demo/settings.py index 9394428a..c0013990 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -43,9 +43,11 @@ 'allauth.socialaccount', 'allauth.socialaccount.providers.facebook', 'rest_framework_swagger', + 'corsheaders' ) MIDDLEWARE = ( + 'corsheaders.middleware.CorsMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -126,3 +128,6 @@ 'LOGIN_URL': 'login', 'LOGOUT_URL': 'logout', } + + +CORS_ORIGIN_ALLOW_ALL = True # For demo purposes only. Use a white list in the real world. \ No newline at end of file diff --git a/demo/react-spa/.gitignore b/demo/react-spa/.gitignore new file mode 100644 index 00000000..4d29575d --- /dev/null +++ b/demo/react-spa/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/demo/react-spa/README.md b/demo/react-spa/README.md new file mode 100644 index 00000000..9c40dcdc --- /dev/null +++ b/demo/react-spa/README.md @@ -0,0 +1,68 @@ +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `yarn start` + +Runs the app in the development mode.
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.
+You will also see any lint errors in the console. + +### `yarn test` + +Launches the test runner in the interactive watch mode.
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `yarn build` + +Builds the app for production to the `build` folder.
+It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
+Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `yarn eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). + +### Code Splitting + +This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting + +### Analyzing the Bundle Size + +This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size + +### Making a Progressive Web App + +This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app + +### Advanced Configuration + +This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration + +### Deployment + +This section has moved here: https://facebook.github.io/create-react-app/docs/deployment + +### `yarn build` fails to minify + +This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify diff --git a/demo/react-spa/package.json b/demo/react-spa/package.json new file mode 100644 index 00000000..62f42268 --- /dev/null +++ b/demo/react-spa/package.json @@ -0,0 +1,34 @@ +{ + "name": "react-spa", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^4.2.4", + "@testing-library/react": "^9.3.2", + "@testing-library/user-event": "^7.1.2", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-scripts": "3.4.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/demo/react-spa/public/favicon.ico b/demo/react-spa/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..bcd5dfd67cd0361b78123e95c2dd96031f27f743 GIT binary patch literal 3150 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 MDeX2GIKR{Qf5okjU;qFB literal 0 HcmV?d00001 diff --git a/demo/react-spa/public/index.html b/demo/react-spa/public/index.html new file mode 100644 index 00000000..aa069f27 --- /dev/null +++ b/demo/react-spa/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/demo/react-spa/public/logo192.png b/demo/react-spa/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..fc44b0a3796c0e0a64c3d858ca038bd4570465d9 GIT binary patch literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/demo/react-spa/public/manifest.json b/demo/react-spa/public/manifest.json new file mode 100644 index 00000000..080d6c77 --- /dev/null +++ b/demo/react-spa/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/demo/react-spa/public/robots.txt b/demo/react-spa/public/robots.txt new file mode 100644 index 00000000..e9e57dc4 --- /dev/null +++ b/demo/react-spa/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/demo/react-spa/src/App.css b/demo/react-spa/src/App.css new file mode 100644 index 00000000..74b5e053 --- /dev/null +++ b/demo/react-spa/src/App.css @@ -0,0 +1,38 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/demo/react-spa/src/App.js b/demo/react-spa/src/App.js new file mode 100644 index 00000000..70fedadd --- /dev/null +++ b/demo/react-spa/src/App.js @@ -0,0 +1,58 @@ +import React, { useState } from 'react'; +import './App.css'; + +function App() { + const [ resp, changeResponse ] = useState(null); + const [ username, changeUsername ] = useState(''); + const [ password, changePassword ] = useState(''); + + function onSubmit(e) { + e.preventDefault(); + return fetch('http://localhost:8000/dj-rest-auth/login/', { + method: 'POST', + credentials: 'omit', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify({username, password}) + }).then(resp => resp.json()).then(data => { + changeResponse(data) + }) + } + + return ( +
+
+

+ Login +

+

+ + {resp && + Response: {JSON.stringify(resp)} + } +

+
+
+ changeUsername(e.target.value)} + value={username} + type={'input'} + name={'username'}/> +
+
+ changePassword(e.target.value)} + value={password} + type={'password'} + name={'password'}/> +
+ +
+
+
+ ); +} + +export default App; diff --git a/demo/react-spa/src/App.test.js b/demo/react-spa/src/App.test.js new file mode 100644 index 00000000..4db7ebc2 --- /dev/null +++ b/demo/react-spa/src/App.test.js @@ -0,0 +1,9 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + const { getByText } = render(); + const linkElement = getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/demo/react-spa/src/index.css b/demo/react-spa/src/index.css new file mode 100644 index 00000000..ec2585e8 --- /dev/null +++ b/demo/react-spa/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/demo/react-spa/src/index.js b/demo/react-spa/src/index.js new file mode 100644 index 00000000..f5185c1e --- /dev/null +++ b/demo/react-spa/src/index.js @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render( + + + , + document.getElementById('root') +); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://bit.ly/CRA-PWA +serviceWorker.unregister(); diff --git a/demo/react-spa/src/logo.svg b/demo/react-spa/src/logo.svg new file mode 100644 index 00000000..6b60c104 --- /dev/null +++ b/demo/react-spa/src/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/demo/react-spa/src/serviceWorker.js b/demo/react-spa/src/serviceWorker.js new file mode 100644 index 00000000..b04b771a --- /dev/null +++ b/demo/react-spa/src/serviceWorker.js @@ -0,0 +1,141 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.0/8 are considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +export function register(config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://bit.ly/CRA-PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: { 'Service-Worker': 'script' }, + }) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready + .then(registration => { + registration.unregister(); + }) + .catch(error => { + console.error(error.message); + }); + } +} diff --git a/demo/react-spa/src/setupTests.js b/demo/react-spa/src/setupTests.js new file mode 100644 index 00000000..74b1a275 --- /dev/null +++ b/demo/react-spa/src/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom/extend-expect'; diff --git a/demo/requirements.pip b/demo/requirements.pip index 64a3488d..e9276aa9 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -4,4 +4,5 @@ djangorestframework>=3.11.0 djangorestframework-simplejwt==4.4.0 django-allauth>=0.24.1 django-rest-swagger==2.0.7 -coreapi==2.3.3 \ No newline at end of file +django-cors-headers==3.2.1 +coreapi==2.3.3 From a7f54991c1fe4ad675d3d74ab33b40d20272ca3f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 13:51:31 -0500 Subject: [PATCH 077/130] Adds POC Login Form in React --- demo/demo/settings.py | 7 ++++++- demo/react-spa/src/App.css | 2 ++ demo/react-spa/src/App.js | 22 +++++++++++++++------- demo/react-spa/src/index.css | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/demo/demo/settings.py b/demo/demo/settings.py index c0013990..4496f0d3 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -116,10 +116,14 @@ ACCOUNT_AUTHENTICATION_METHOD = 'username' ACCOUNT_EMAIL_VERIFICATION = 'optional' +REST_USE_JWT = True +JWT_AUTH_COOKIE = 'auth' + REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', + 'dj_rest_auth.utils.JWTCookieAuthentication' ), 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } @@ -130,4 +134,5 @@ } -CORS_ORIGIN_ALLOW_ALL = True # For demo purposes only. Use a white list in the real world. \ No newline at end of file +# For demo purposes only. Use a white list in the real world. +CORS_ORIGIN_ALLOW_ALL = True diff --git a/demo/react-spa/src/App.css b/demo/react-spa/src/App.css index 74b5e053..92fd3acc 100644 --- a/demo/react-spa/src/App.css +++ b/demo/react-spa/src/App.css @@ -1,5 +1,6 @@ .App { text-align: center; + width: 100%; } .App-logo { @@ -22,6 +23,7 @@ justify-content: center; font-size: calc(10px + 2vmin); color: white; + width: 100%; } .App-link { diff --git a/demo/react-spa/src/App.js b/demo/react-spa/src/App.js index 70fedadd..a8546a43 100644 --- a/demo/react-spa/src/App.js +++ b/demo/react-spa/src/App.js @@ -18,21 +18,28 @@ function App() { body: JSON.stringify({username, password}) }).then(resp => resp.json()).then(data => { changeResponse(data) - }) + }).catch(error => console.log('error ->', error)) } return (
-

+

Login -

-

- +

+
+ Inspect the network requests in your browser to view headers returned by dj-rest-auth. +
+
{resp && - Response: {JSON.stringify(resp)} +
+ + {JSON.stringify(resp)} + +
} -

+
+
+
); diff --git a/demo/react-spa/src/index.css b/demo/react-spa/src/index.css index ec2585e8..379ece5f 100644 --- a/demo/react-spa/src/index.css +++ b/demo/react-spa/src/index.css @@ -1,13 +1,48 @@ body { margin: 0; + width: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + display: flex; + flex-direction: column; +} + +body div { + flex-direction: row; + text-align: center; + display: flex; + justify-content: center; +} + +ul { + width: 240px; + font-size: 11px; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; + word-break: break-all; + height: 200px; + color: #0f0f0f; +} + +.response { + margin: 20px; + background-color: #eee; + width: 80%; + height: 200px; + overflow: scroll; +} + +.help-text { + font-size: 11px; + margin: 20px; +} + +form > div { + margin: 20px; } From c4130d1812159fe1ea8f4f330d1dedaf716c94b4 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 14:00:06 -0500 Subject: [PATCH 078/130] Adds more help to docs --- docs/installation.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/installation.rst b/docs/installation.rst index fa4345da..867286fd 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -269,3 +269,18 @@ By default ``dj-rest-auth`` uses Django's Token-based authentication. If you wan .. code-block:: python REST_USE_JWT = True + +4. Declare what you want the cookie key to be called. + +.. code-block:: python + + JWT_AUTH_COOKIE = 'my-app-auth' + + +This example value above will cause dj-rest-auth to return a `Set-Cookie` header that looks like this: + +.. code-block:: bash + + Set-Cookie: my-app-auth=xxxxxxxxxxxxx; expires=Sat, 28 Mar 2020 18:59:00 GMT; HttpOnly; Max-Age=300; Path=/ + +``JWT_AUTH_COOKIE`` is also used while authenticating each request against protected views. \ No newline at end of file From 66beda5efc9e6354cdbd6f8f9a9f4f1cfdbf673f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 14:05:20 -0500 Subject: [PATCH 079/130] Updates changelog --- docs/changelog.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 405df481..78186af4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,9 +9,5 @@ Welcome Dj-Rest-Auth ----- Replaces `rest_framework_jwt` with `djangorestframework-simplejwt`. - -- rest_framework_jwt is now unmaintained so we've switched to simplewjt, -which is a strong jwt library with a large community. -- This change means you may need to change your client code if you're upgrading - from the previous version. Example: token -> access_token. Please see demo - for more information. \ No newline at end of file +Rest_framework_jwt is now unmaintained so we've switched to simplewjt, which is a strong jwt library with a large community. +This change means you may need to change your client code if you're upgrading from the previous version. \ No newline at end of file From c05903baace80f945be3efa4376b534e6f6bf912 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 14:15:50 -0500 Subject: [PATCH 080/130] Adds note about React SPA --- docs/demo.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/demo.rst b/docs/demo.rst index ecceddd1..6c67fe9f 100644 --- a/docs/demo.rst +++ b/docs/demo.rst @@ -1,9 +1,9 @@ Demo project ============ -The idea of creating demo project was to show how you can potentially use +This demo project shows how you can potentially use dj-rest-auth app with jQuery on frontend. -Do these steps to make it running (ideally in virtualenv). +To run this locally follow the steps below. .. code-block:: python @@ -14,4 +14,14 @@ Do these steps to make it running (ideally in virtualenv). python manage.py migrate --settings=demo.settings --noinput python manage.py runserver --settings=demo.settings -Now, go to ``http://127.0.0.1:8000/`` in your browser. + +Now, go to ``http://127.0.0.1:8000/`` in your browser. There is also a +Single Page Application (SPA) in React within the ``demo/`` directory. To run this do: + +.. code-block:: python + cd react-spa/ + yarn # or npm install + yarn run start + + +Now, go to ``https://localhost:3000`` in your browser to view it. From 53ca547ed2fa925ec9f4d1ae0e451f9bde3d1fca Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 14:19:46 -0500 Subject: [PATCH 081/130] Updates RST Docs --- docs/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 77305620..1f575785 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,7 +44,7 @@ # General information about the project. project = u'dj-rest-auth' -copyright = u'2018, iMerica Inc.' +copyright = u'2020, @iMerica' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -227,7 +227,7 @@ # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'dj-rest-auth', u'dj-rest-auth Documentation', - [u'iMerica Inc.'], 1) + [u'@iMerica'], 1) ] # If true, show URL addresses after external links. @@ -241,7 +241,7 @@ # dir menu entry, description, category) texinfo_documents = [ ('index', 'dj-rest-auth', u'dj-rest-auth Documentation', - u'iMerica Inc.', 'dj-rest-auth', 'One line description of project.', + u'@iMerica', 'dj-rest-auth', 'One line description of project.', 'Miscellaneous'), ] From 68dbdf7e3e4215ba1e8bd1d078a6d9eb0731eb2b Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 28 Mar 2020 14:24:21 -0500 Subject: [PATCH 082/130] Fixes docs code sample --- docs/demo.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/demo.rst b/docs/demo.rst index 6c67fe9f..b8bc2f1c 100644 --- a/docs/demo.rst +++ b/docs/demo.rst @@ -19,6 +19,7 @@ Now, go to ``http://127.0.0.1:8000/`` in your browser. There is also a Single Page Application (SPA) in React within the ``demo/`` directory. To run this do: .. code-block:: python + cd react-spa/ yarn # or npm install yarn run start From de25807805e98db988c6198a7a65bfef2efeb6e9 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Mon, 30 Mar 2020 22:02:12 +0530 Subject: [PATCH 083/130] Note in docs to add allauth urls if account email verification is mandatory Update docs to add `account_email_verification_sent` endpoint while using `registration`. Without this endpoint, if email verification is set to **MANDATORY** , it gives error ``` Reverse for 'account_email_verification_sent' not found. 'account_email_verification_sent' is not a valid view function or pattern name. ``` This is a copy PR of [#577](https://github.com/Tivix/django-rest-auth/pull/577) in in upstream project. --- docs/api_endpoints.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index a4e602aa..be3b0964 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -61,6 +61,11 @@ Registration - key + .. note:: If you set account email verification as mandatory, you have to add the VerifyEmailView with the used `name`. + You need to import the view: ``from rest_auth.registration.views import VerifyEmailView``. Then add the url with the corresponding name: + ``url(r'^rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent')`` to the urlpatterns list. + + Social Media Authentication --------------------------- From 3c896603ade6fbabe3c734688b16bcd3afa02ba0 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Tue, 31 Mar 2020 07:57:14 +0530 Subject: [PATCH 084/130] Update module name Changed module name to `dj_rest_auth` --- docs/api_endpoints.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index be3b0964..c253f7b6 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -62,8 +62,8 @@ Registration - key .. note:: If you set account email verification as mandatory, you have to add the VerifyEmailView with the used `name`. - You need to import the view: ``from rest_auth.registration.views import VerifyEmailView``. Then add the url with the corresponding name: - ``url(r'^rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent')`` to the urlpatterns list. + You need to import the view: ``from dj_rest_auth.registration.views import VerifyEmailView``. Then add the url with the corresponding name: + ``url(r'^dj-rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent')`` to the urlpatterns list. From 1c485bcbce3024d7b2e97e062c90c8371823f2c9 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Tue, 31 Mar 2020 16:24:43 +0530 Subject: [PATCH 085/130] Update documentation Update documentation for `old_password` validation skip. --- docs/api_endpoints.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index c253f7b6..614c21e3 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -35,7 +35,7 @@ Basic - new_password2 - old_password - .. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password. + .. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password. If user has no usable password set (registration using social account), validation will be skipped for `old_password` to allow to set a new password. .. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change - /dj-rest-auth/user/ (GET, PUT, PATCH) From 26b6e220437b3900e96303a9e80e1034f6b3688e Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Wed, 1 Apr 2020 18:54:16 -0400 Subject: [PATCH 086/130] blacklist refresh token on logout if REST_USE_JWT and added .idea to gitignore --- .gitignore | 3 +++ dj_rest_auth/views.py | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 84cc2dea..136132c4 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,9 @@ target/ # Jupyter Notebook .ipynb_checkpoints +# IDE +.idea + # pyenv .python-version diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index c5ba7fcd..7f2e651f 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -11,6 +11,8 @@ from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView +from rest_framework_simplejwt.exceptions import TokenError +from rest_framework_simplejwt.tokens import RefreshToken from .app_settings import (JWTSerializer, LoginSerializer, PasswordChangeSerializer, @@ -134,13 +136,29 @@ def logout(self, request): pass if getattr(settings, 'REST_SESSION_LOGIN', True): django_logout(request) - response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) if cookie_name: response.delete_cookie(cookie_name) + # add refresh token to blacklist + try: + token = RefreshToken(request.data['refresh']) + token.blacklist() + except KeyError: + response = Response({"detail": _("Refresh token was not included.")}, + status=status.HTTP_401_UNAUTHORIZED) + except TokenError as e: + if e.args[0] == 'Token is blacklisted': + response = Response({"detail": _("Token is already blacklisted.")}, + status=status.HTTP_404_NOT_FOUND) + except AttributeError as e: + # warn user blacklist is not enabled if not using JWT_AUTH_COOKIE + if not cookie_name: + if e.args[0] == "'RefreshToken' object has no attribute 'blacklist'": + response = Response({"detail": _("Blacklist is not enabled in INSTALLED_APPS.")}, + status=status.HTTP_501_NOT_IMPLEMENTED) return response From 241011a353e0a3f4b7a62890bda71deb803c78bc Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Wed, 1 Apr 2020 18:56:41 -0400 Subject: [PATCH 087/130] attempt to blacklist token if no JWT_AUTH_COOKIE is found --- dj_rest_auth/views.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 7f2e651f..365545e6 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -142,20 +142,20 @@ def logout(self, request): cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) if cookie_name: response.delete_cookie(cookie_name) - # add refresh token to blacklist - try: - token = RefreshToken(request.data['refresh']) - token.blacklist() - except KeyError: - response = Response({"detail": _("Refresh token was not included.")}, - status=status.HTTP_401_UNAUTHORIZED) - except TokenError as e: - if e.args[0] == 'Token is blacklisted': - response = Response({"detail": _("Token is already blacklisted.")}, - status=status.HTTP_404_NOT_FOUND) - except AttributeError as e: - # warn user blacklist is not enabled if not using JWT_AUTH_COOKIE - if not cookie_name: + else: + # add refresh token to blacklist + try: + token = RefreshToken(request.data['refresh']) + token.blacklist() + except KeyError: + response = Response({"detail": _("Refresh token was not included.")}, + status=status.HTTP_401_UNAUTHORIZED) + except TokenError as e: + if e.args[0] == 'Token is blacklisted': + response = Response({"detail": _("Token is already blacklisted.")}, + status=status.HTTP_404_NOT_FOUND) + except AttributeError as e: + # warn user blacklist is not enabled if e.args[0] == "'RefreshToken' object has no attribute 'blacklist'": response = Response({"detail": _("Blacklist is not enabled in INSTALLED_APPS.")}, status=status.HTTP_501_NOT_IMPLEMENTED) From 9180f3967a17051b6c9d633300a972050ea4d374 Mon Sep 17 00:00:00 2001 From: Michael <487897+iMerica@users.noreply.github.com> Date: Wed, 1 Apr 2020 18:41:23 -0500 Subject: [PATCH 088/130] Revert "Update documentation" This reverts commit 1c485bcbce3024d7b2e97e062c90c8371823f2c9. --- docs/api_endpoints.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index 614c21e3..c253f7b6 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -35,7 +35,7 @@ Basic - new_password2 - old_password - .. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password. If user has no usable password set (registration using social account), validation will be skipped for `old_password` to allow to set a new password. + .. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password. .. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change - /dj-rest-auth/user/ (GET, PUT, PATCH) From aaab91f82bb81c74f8df99c274983f5be27cfefc Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Wed, 1 Apr 2020 21:28:02 -0400 Subject: [PATCH 089/130] updated exceptions to raise error if not not handled --- dj_rest_auth/tests/test_api.py | 11 +++++++++++ dj_rest_auth/views.py | 14 +++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 0134560d..f373dcc8 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -555,3 +555,14 @@ def test_cookie_authentication(self): self.assertEqual(['jwt-auth'], list(resp.cookies.keys())) resp = self.get('/protected-view/') self.assertEquals(resp.status_code, 200) + + @override_settings(REST_USE_JWT=True) + def test_blacklisting(self): + payload = { + "username": self.USERNAME, + "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.logout_url, status=200) + pass diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 365545e6..c79423f8 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -147,18 +147,26 @@ def logout(self, request): try: token = RefreshToken(request.data['refresh']) token.blacklist() + except KeyError: - response = Response({"detail": _("Refresh token was not included.")}, + response = Response({"detail": _("Refresh token was not included in request data.")}, status=status.HTTP_401_UNAUTHORIZED) + except TokenError as e: - if e.args[0] == 'Token is blacklisted': + 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 AttributeError as e: # warn user blacklist is not enabled - if e.args[0] == "'RefreshToken' object has no attribute 'blacklist'": + 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 + return response From 8f97cbc6179675bd14a587c8c471ff574d446710 Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Thu, 2 Apr 2020 10:01:07 -0400 Subject: [PATCH 090/130] added rest_framework_simplejwt.token_blacklist to settings for tests, return 500 if error occurs instead of raising, added unit tests for blacklist --- Makefile | 2 ++ dj_rest_auth/tests/settings.py | 2 ++ dj_rest_auth/tests/test_api.py | 34 ++++++++++++++++++++++++++++++---- dj_rest_auth/views.py | 28 +++++++++++++++------------- 4 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..103ee60f --- /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 3d023096..5f57f916 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -94,6 +94,8 @@ '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 f373dcc8..0e5a3c6e 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 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 @@ def test_cookie_authentication(self): 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 @@ def test_blacklisting(self): "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 c79423f8..f3bb3fec 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -147,25 +147,27 @@ def logout(self, request): 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 From 8b284f8adf86b2ff29c49aa4c66aaa26325d67f9 Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Thu, 2 Apr 2020 10:07:23 -0400 Subject: [PATCH 091/130] fixed typo in 500 response --- dj_rest_auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index f3bb3fec..f3d6c723 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -166,7 +166,7 @@ def logout(self, request): status=status.HTTP_500_INTERNAL_SERVER_ERROR) else: - response = Response({"detail": _("No attr error has occurred.")}, + response = Response({"detail": _("An error has occurred.")}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) return response From 3304a6b3d39b2b02af5806617d1ec0d6b4d4f1f4 Mon Sep 17 00:00:00 2001 From: Jonathan Henrique Maia de Moraes Date: Fri, 3 Apr 2020 14:50:02 -0300 Subject: [PATCH 092/130] Fix JWTSerializer USER_DETAILS_SERIALIZER import Related to #30 --- dj_rest_auth/serializers.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index 3e0132d0..efd455e4 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -4,6 +4,7 @@ from django.contrib.auth.tokens import default_token_generator from django.utils.encoding import force_text from django.utils.http import urlsafe_base64_decode as uid_decoder +from django.utils.module_loading import import_string from django.utils.translation import ugettext_lazy as _ from rest_framework import exceptions, serializers from rest_framework.exceptions import ValidationError @@ -145,7 +146,14 @@ def get_user(self, obj): JWTSerializer. Defining it here to avoid circular imports """ rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {}) - JWTUserDetailsSerializer = rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer) + + JWTUserDetailsSerializer = import_string( + rest_auth_serializers.get( + 'USER_DETAILS_SERIALIZER', + 'dj_rest_auth.serializers.UserDetailsSerializer' + ) + ) + user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data return user_data From 058df2b1ce58bc6b1302e17aa05445c8139a511b Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 6 Apr 2020 20:39:11 -0500 Subject: [PATCH 093/130] Bumps version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index da113374..f3c7f8c2 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='1.0.0', + version='1.0.1', author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From b55fcc2361f0e0ff46933cbed79b0851675d924a Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Tue, 7 Apr 2020 20:24:15 -0400 Subject: [PATCH 094/130] deleted make file and adding testing section to README --- Makefile | 2 -- README.md | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 103ee60f..00000000 --- a/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -test: - coverage run --source=dj_rest_auth setup.py test diff --git a/README.md b/README.md index b87ba309..deefdb59 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,12 @@ REST_USE_JWT = True JWT_AUTH_COOKIE = 'jwt-auth' ``` +### Testing +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/), +which runs the tests against all supported Django installs. To run the test coverage +within a virtualenv, run `coverage run ./runtests.py` from the repository directory then run `coverage report`. ### Documentation From d5d9c69aa3aaea8c1a5d77d20439bb62f8420a03 Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Thu, 9 Apr 2020 20:53:04 -0400 Subject: [PATCH 095/130] check if blacklist is installed and warn user to delete client side if cookies and blacklist are not enabled --- dj_rest_auth/tests/test_api.py | 11 ++++++----- dj_rest_auth/views.py | 16 +++++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 0e5a3c6e..4c4de9e9 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -1,5 +1,4 @@ import json -from unittest.mock import patch from allauth.account import app_settings as account_app_settings from django.conf import settings @@ -560,9 +559,8 @@ def test_cookie_authentication(self): 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'") + def test_blacklisting_not_installed(self): + settings.INSTALLED_APPS.remove('rest_framework_simplejwt.token_blacklist') payload = { "username": self.USERNAME, "password": self.PASS @@ -571,7 +569,10 @@ def test_blacklisting_not_installed(self, mocked_blacklist): 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) + self.assertEqual(resp.status_code, 200) + self.assertEqual(resp.data["detail"], + "Neither cookies or blacklist are enabled, so the token has not been deleted server side. " + "Please make sure the token is deleted client side.") @override_settings(REST_USE_JWT=True) def test_blacklisting(self): diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index f3d6c723..325466e0 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -134,19 +134,23 @@ def logout(self, request): request.user.auth_token.delete() except (AttributeError, ObjectDoesNotExist): pass + if getattr(settings, 'REST_SESSION_LOGIN', True): django_logout(request) response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) + if getattr(settings, 'REST_USE_JWT', False): cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) if cookie_name: response.delete_cookie(cookie_name) - else: + + elif 'rest_framework_simplejwt.token_blacklist' in settings.INSTALLED_APPS: # add refresh token to blacklist 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) @@ -157,10 +161,6 @@ def logout(self, request): 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) @@ -169,6 +169,12 @@ def logout(self, request): response = Response({"detail": _("An error has occurred.")}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + else: + response = Response({ + "detail": _("Neither cookies or blacklist are enabled, so the token has not been deleted server " + "side. Please make sure the token is deleted client side." + )}, status=status.HTTP_200_OK) + return response From 91c052fe47c1d98579260e6606fb254a5e6c34db Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Thu, 9 Apr 2020 21:00:48 -0400 Subject: [PATCH 096/130] changed invalid or expired and blacklisted errors to 401 --- dj_rest_auth/tests/test_api.py | 9 +++++++-- dj_rest_auth/views.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 4c4de9e9..c53be66a 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -583,13 +583,18 @@ def test_blacklisting(self): 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'] + # test refresh token not included in request data resp = self.post(self.logout_url, status=200) self.assertEqual(resp.status_code, 401) + # test token is invalid or expired resp = self.post(self.logout_url, status=200, data={'refresh': '1'}) - self.assertEqual(resp.status_code, 404) + self.assertEqual(resp.status_code, 401) + # test successful logout resp = self.post(self.logout_url, status=200, data={'refresh': token}) self.assertEqual(resp.status_code, 200) + # test token is blacklisted resp = self.post(self.logout_url, status=200, data={'refresh': token}) - self.assertEqual(resp.status_code, 404) + self.assertEqual(resp.status_code, 401) + # test other TokenError, AttributeError, TypeError (invalid format) 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 325466e0..25ebe316 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -159,7 +159,7 @@ def logout(self, request): 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) + status=status.HTTP_401_UNAUTHORIZED) else: response = Response({"detail": _("An error has occurred.")}, From 1c64c0d398615b3a9590658837a7e7a68ea051ac Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Thu, 9 Apr 2020 21:03:41 -0400 Subject: [PATCH 097/130] changed spacing for better readability --- dj_rest_auth/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 25ebe316..114856b0 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -137,6 +137,7 @@ def logout(self, request): if getattr(settings, 'REST_SESSION_LOGIN', True): django_logout(request) + response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) From 40125b15c44aaa440fa457e4a25b1c99191159d0 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 13 Apr 2020 23:05:06 -0500 Subject: [PATCH 098/130] Bumps version for release --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f3c7f8c2..6e897fc9 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='1.0.1', + version='1.0.2', author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From 40208ea0b63ab6ad7cc454d43cf9eabc09f9f8b6 Mon Sep 17 00:00:00 2001 From: Rami Chowdhury Date: Tue, 14 Apr 2020 13:26:52 -0400 Subject: [PATCH 099/130] Don't _require_ rest_framework_simplejwt Rather than importing it at the top level (which breaks dj-rest-auth entirely if you aren't using JWTs and don't have the library installed), only do the import if the user has the relevant setting enabled. --- dj_rest_auth/views.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 114856b0..674c9b8a 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -11,8 +11,20 @@ from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView -from rest_framework_simplejwt.exceptions import TokenError -from rest_framework_simplejwt.tokens import RefreshToken + +if getattr(settings, 'REST_USE_JWT'): + from rest_framework_simplejwt.exceptions import TokenError + from rest_framework_simplejwt.tokens import RefreshToken +else: + # NOTE: these are not actually used except if `REST_USE_JWT` is True, but + # ensuring they're defined anyway in case + + class TokenError(Exception): + pass + + class RefreshToken: + pass + from .app_settings import (JWTSerializer, LoginSerializer, PasswordChangeSerializer, From 506912f83245ad6844527a5839bec6e34dc2a065 Mon Sep 17 00:00:00 2001 From: Rami Chowdhury Date: Tue, 14 Apr 2020 15:20:43 -0400 Subject: [PATCH 100/130] Move import inside response method This is not idiomatic, but I don't see another neat way to move it out of the top level and still handle testing / other situations where the settings are modified on-the-fly. --- dj_rest_auth/views.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index 674c9b8a..b5fcdb85 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -12,20 +12,6 @@ from rest_framework.response import Response from rest_framework.views import APIView -if getattr(settings, 'REST_USE_JWT'): - from rest_framework_simplejwt.exceptions import TokenError - from rest_framework_simplejwt.tokens import RefreshToken -else: - # NOTE: these are not actually used except if `REST_USE_JWT` is True, but - # ensuring they're defined anyway in case - - class TokenError(Exception): - pass - - class RefreshToken: - pass - - from .app_settings import (JWTSerializer, LoginSerializer, PasswordChangeSerializer, PasswordResetConfirmSerializer, @@ -154,6 +140,13 @@ def logout(self, request): status=status.HTTP_200_OK) if getattr(settings, 'REST_USE_JWT', False): + # NOTE: this import occurs here rather than at the top level + # because JWT support is optional, and if `REST_USE_JWT` isn't + # True we shouldn't need the dependency + from rest_framework_simplejwt.exceptions import TokenError + from rest_framework_simplejwt.tokens import RefreshToken + + cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) if cookie_name: response.delete_cookie(cookie_name) From 8583c5597e4435daaca987bfae363d14032b4f4f Mon Sep 17 00:00:00 2001 From: VolkerSchiewe Date: Wed, 15 Apr 2020 10:44:54 +0200 Subject: [PATCH 101/130] Add token endpoints from rest_framework_simplejwt to url config --- dj_rest_auth/urls.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dj_rest_auth/urls.py b/dj_rest_auth/urls.py index d3bfc420..3ff64c68 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -2,6 +2,7 @@ PasswordResetConfirmView, PasswordResetView, UserDetailsView) from django.conf.urls import url +from django.conf import settings urlpatterns = [ # URLs that do not require a session or valid token @@ -16,3 +17,13 @@ url(r'^password/change/$', PasswordChangeView.as_view(), name='rest_password_change'), ] + +if getattr(settings, 'REST_USE_JWT', True): + from rest_framework_simplejwt.views import ( + TokenRefreshView, TokenVerifyView, + ) + + urlpatterns += [ + url(r'token/verify/$', TokenVerifyView.as_view(), name='token_verify'), + url(r'^token/refresh/$', TokenRefreshView.as_view(), name='token_refresh'), + ] From 5e8cca163374a5006ca650ec9ceb17aab6c1f5d6 Mon Sep 17 00:00:00 2001 From: Serhiy Romanov Date: Wed, 15 Apr 2020 16:26:54 +0300 Subject: [PATCH 102/130] Use import_string for getting TokenModel instead of passing class --- dj_rest_auth/models.py | 6 ++---- docs/configuration.rst | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dj_rest_auth/models.py b/dj_rest_auth/models.py index 654c0aed..84108212 100644 --- a/dj_rest_auth/models.py +++ b/dj_rest_auth/models.py @@ -1,6 +1,4 @@ from django.conf import settings -from rest_framework.authtoken.models import Token as DefaultTokenModel +from django.utils.module_loading import import_string -# Register your models here. - -TokenModel = getattr(settings, 'REST_AUTH_TOKEN_MODEL', DefaultTokenModel) +TokenModel = import_string(getattr(settings, 'REST_AUTH_TOKEN_MODEL', 'rest_framework.authtoken.models.Token')) diff --git a/docs/configuration.rst b/docs/configuration.rst index c841e60e..aac74c2a 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -40,9 +40,9 @@ Configuration .. note:: The custom REGISTER_SERIALIZER must define a ``def save(self, request)`` method that returns a user model instance -- **REST_AUTH_TOKEN_MODEL** - model class for tokens, default value ``rest_framework.authtoken.models`` +- **REST_AUTH_TOKEN_MODEL** - path to model class for tokens, default value ``'rest_framework.authtoken.models.Token'`` -- **REST_AUTH_TOKEN_CREATOR** - callable to create tokens, default value ``dj_rest_auth.utils.default_create_token``. +- **REST_AUTH_TOKEN_CREATOR** - path to callable or callable for creating tokens, default value ``dj_rest_auth.utils.default_create_token``. - **REST_SESSION_LOGIN** - Enable session login in Login API view (default: True) From d882edcf10f2a5c6c537a40b85e1b719a5b015f0 Mon Sep 17 00:00:00 2001 From: Michael <487897+iMerica@users.noreply.github.com> Date: Thu, 16 Apr 2020 00:28:05 -0500 Subject: [PATCH 103/130] Update dj_rest_auth/urls.py Co-Authored-By: Daniele Tricoli --- dj_rest_auth/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/urls.py b/dj_rest_auth/urls.py index 3ff64c68..2fc16948 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -24,6 +24,6 @@ ) urlpatterns += [ - url(r'token/verify/$', TokenVerifyView.as_view(), name='token_verify'), + url(r'^token/verify/$', TokenVerifyView.as_view(), name='token_verify'), url(r'^token/refresh/$', TokenRefreshView.as_view(), name='token_refresh'), ] From 17e92304977c05c1aae6da4a7d31d5ce8bc28231 Mon Sep 17 00:00:00 2001 From: Michael <487897+iMerica@users.noreply.github.com> Date: Thu, 16 Apr 2020 00:28:14 -0500 Subject: [PATCH 104/130] Update dj_rest_auth/urls.py Co-Authored-By: Daniele Tricoli --- dj_rest_auth/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/urls.py b/dj_rest_auth/urls.py index 2fc16948..9c79691d 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -18,7 +18,7 @@ name='rest_password_change'), ] -if getattr(settings, 'REST_USE_JWT', True): +if getattr(settings, 'REST_USE_JWT', False): from rest_framework_simplejwt.views import ( TokenRefreshView, TokenVerifyView, ) From a190e036d2c1b4f6668e4bbe790175f51d4711b5 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 16 Apr 2020 01:59:04 -0500 Subject: [PATCH 105/130] Bug fixes related to Simple JWT integrations --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6e897fc9..5885ea98 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='1.0.2', + version='1.0.3', author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From 4dcca581784571ccb449afad17ff77acfbd9623b Mon Sep 17 00:00:00 2001 From: Francesco Pinzauti Date: Thu, 16 Apr 2020 15:38:03 +0200 Subject: [PATCH 106/130] changed url to path --- docs/api_endpoints.rst | 2 +- docs/installation.rst | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index c253f7b6..dc159ce7 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -63,7 +63,7 @@ Registration .. note:: If you set account email verification as mandatory, you have to add the VerifyEmailView with the used `name`. You need to import the view: ``from dj_rest_auth.registration.views import VerifyEmailView``. Then add the url with the corresponding name: - ``url(r'^dj-rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent')`` to the urlpatterns list. + ``path('dj-rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent')`` to the urlpatterns list. diff --git a/docs/installation.rst b/docs/installation.rst index 867286fd..6a7d83fb 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -28,7 +28,7 @@ Installation urlpatterns = [ ..., - url(r'^dj-rest-auth/', include('dj_rest_auth.urls')) + path('dj-rest-auth/', include('dj_rest_auth.urls')) ] 4. Migrate your database @@ -68,8 +68,8 @@ Registration (optional) urlpatterns = [ ..., - url(r'^dj-rest-auth/', include('dj_rest_auth.urls')), - url(r'^dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')) + path('dj-rest-auth/', include('dj_rest_auth.urls')), + path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')) ] @@ -122,7 +122,7 @@ Facebook urlpatterns += [ ..., - url(r'^dj-rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login') + path('dj-rest-auth/facebook/', FacebookLogin.as_view(), name='fb_login') ] @@ -149,7 +149,7 @@ If you are using Twitter for your social authentication, it is a bit different s urlpatterns += [ ..., - url(r'^dj-rest-auth/twitter/$', TwitterLogin.as_view(), name='twitter_login') + path('dj-rest-auth/twitter/', TwitterLogin.as_view(), name='twitter_login') ] .. note:: Starting from v0.21.0, django-allauth has dropped support for context processors. Check out http://django-allauth.readthedocs.org/en/latest/changelog.html#from-0-21-0 for more details. @@ -179,7 +179,7 @@ If you are using GitHub for your social authentication, it uses code and not Acc urlpatterns += [ ..., - url(r'^dj-rest-auth/github/$', GitHubLogin.as_view(), name='github_login') + path('dj-rest-auth/github/', GitHubLogin.as_view(), name='github_login') ] Additional Social Connect Views @@ -215,9 +215,9 @@ In urls.py: urlpatterns += [ ..., - url(r'^dj-rest-auth/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect') - url(r'^dj-rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect') - url(r'^dj-rest-auth/github/connect/$', GithubConnect.as_view(), name='github_connect') + path('dj-rest-auth/facebook/connect/', FacebookConnect.as_view(), name='fb_connect') + path('dj-rest-auth/twitter/connect/', TwitterConnect.as_view(), name='twitter_connect') + path('dj-rest-auth/github/connect/', GithubConnect.as_view(), name='github_connect') ] You can also use the following views to check all social accounts attached to the current authenticated user and disconnect selected social accounts: @@ -230,13 +230,13 @@ You can also use the following views to check all social accounts attached to th urlpatterns += [ ..., - url( - r'^socialaccounts/$', + path( + 'socialaccounts/', SocialAccountListView.as_view(), name='social_account_list' ), - url( - r'^socialaccounts/(?P\d+)/disconnect/$', + path( + 'socialaccounts//disconnect/', SocialAccountDisconnectView.as_view(), name='social_account_disconnect' ) From 64e07ec755e4ce77b260b64099bf98e645fd550a Mon Sep 17 00:00:00 2001 From: Serhiy Romanov Date: Fri, 17 Apr 2020 11:27:24 +0300 Subject: [PATCH 107/130] Fix missed import_callable --- dj_rest_auth/app_settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 16c3888f..784a6912 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -29,9 +29,9 @@ 'PASSWORD_RESET_SERIALIZER', DefaultPasswordResetSerializer )) -PasswordResetConfirmSerializer = serializers.get( +PasswordResetConfirmSerializer = import_callable(serializers.get( 'PASSWORD_RESET_CONFIRM_SERIALIZER', DefaultPasswordResetConfirmSerializer -) +)) PasswordChangeSerializer = import_callable(serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer)) From 4a46807a1f7a9484c157e545dba983b8d0ce0e8e Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 18 Apr 2020 12:58:50 -0500 Subject: [PATCH 108/130] Bumps version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5885ea98..9c98f605 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='dj-rest-auth', - version='1.0.3', + version='1.0.4', author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From 2602d66fefa5e8e96da25a7bd37e1c7fdba2cd87 Mon Sep 17 00:00:00 2001 From: Ranet P Date: Tue, 21 Apr 2020 18:17:57 +0300 Subject: [PATCH 109/130] Pass context to JWTSerializer and TokenSerializer --- dj_rest_auth/registration/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index e9577a16..937f3274 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -52,9 +52,9 @@ def get_response_data(self, user): 'access_token': self.access_token, 'refresh_token': self.refresh_token } - return JWTSerializer(data).data + return JWTSerializer(data, context=self.get_serializer_context()).data else: - return TokenSerializer(user.auth_token).data + return TokenSerializer(user.auth_token, context=self.get_serializer_context()).data def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) From 23bef47110afdbf7f81ba89f85808121cbf8467c Mon Sep 17 00:00:00 2001 From: Rafael Laranja Date: Sun, 26 Apr 2020 09:52:10 -0300 Subject: [PATCH 110/130] Compile pt_BR language messages --- dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.mo | Bin 0 -> 2358 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.mo diff --git a/dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.mo b/dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..64a4e314ea34fc303d0ee0d01b0cfb45de7c0ebe GIT binary patch literal 2358 zcma)7OK)366uv-tnRlU3#Ou_8wovZHX-k#5O=;4)C6L4+O(MZ28s9s%hm2>;%)L&_ zf*lLCNL|6EVo@Q%iVb3gWEMy)*deh&@B@$#e*nI7AFRj zJPF))M`5Q8jIh^0*82pwANVcs1>n!XBf!6aPXdqZDX;}(KU+YU3_b>agxIbEU&H>n zyMo|ZJ_m9hAC&khkmLRa$a+5kInKxLF8mz?9>#tNcnp{U4*)+09t8dX41s?F*)H7^ z1TO*402hD?SO>08dUk|w?BUaN2dcgChP zl1_D%Orl`X#MU_(r?4{2(uhPHBZ{rmZc9VfQEU^*DLDCFrV#k_m66by43;y`w_}|_ zvo1NAIti0deTc|+tV`PTeZ#fW2G zEhCv6pw=?2x**9+-JVh}w8{=mjH13#a4E}6)y=fNLfZCv=&D5tgY~|objMDjL8*1( zDN%_zl+r+?aX$(+jOb`6TE5FY%qL>#>_{cB6rB);ks>7ZMD4~p2M7TDB*dL$|fCc z%$y7x$HSQu)HvBZJ{vY>8x1IiYjUL6c&YbxYknGgJVdGW|Q?Uhz-N%%Be zcfxorQtO(u;4))rL117}whIpPfkaMs_;aWD+AThwMI*Ge+fi%>XJE+mGSQRax)g&Z zEzPf7+~9;xFD;$bDzdIO(Lo~1i_5J^_A^nVc8)7$5X_Y!vf`q>GSotuQxx}w!ywIV ztX~LcCwd%oSGur;=aneaYtn2-rL|R^IibS~)(w1<%rM{jxud73_&Imj(1AIcdGS;& zcw>Bx zc$!K6;dF{iCZ{EtnDJ+px>l8Rg2-$Xv5jle5drB0p=*p5>@ zk&eGYb{O?dq4CJ8+ZKd3lA#9$F~O+G^9R*buO0Mqi`IlP{RkGKOcUJ635FS-u z3?2qFksj}TgoaNgSNwO0MUmWYK6Pd!3=v0D-7ZR1 c@RAJknpuoHW)z$>zQ&=#X-QNzXm1C912@mNTL1t6 literal 0 HcmV?d00001 From 7b1bfecdd955a2ea37ba087ac55b7f6daac49787 Mon Sep 17 00:00:00 2001 From: Francesco Pinzauti Date: Thu, 7 May 2020 10:26:48 +0200 Subject: [PATCH 111/130] added italian language --- dj_rest_auth/locale/it/LC_MESSAGES/django.po | 123 +++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 dj_rest_auth/locale/it/LC_MESSAGES/django.po diff --git a/dj_rest_auth/locale/it/LC_MESSAGES/django.po b/dj_rest_auth/locale/it/LC_MESSAGES/django.po new file mode 100644 index 00000000..d901fa71 --- /dev/null +++ b/dj_rest_auth/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,123 @@ +# Italian language. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-07 09:46+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Pinzauti \n" +"Language-Team: \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: .\registration\serializers.py:67 +msgid "View is not defined, pass it as a context variable" +msgstr "\"view\" non è definito, passalo come variabile di contesto" + +#: .\registration\serializers.py:72 +msgid "Define adapter_class in view" +msgstr "Definisci \"adapter_class\" in view" + +#: .\registration\serializers.py:91 +msgid "Define callback_url in view" +msgstr "Definisci \"callback_url\" in view" + +#: .\registration\serializers.py:95 +msgid "Define client_class in view" +msgstr "Definisci \"client_class\" in view" + +#: .\registration\serializers.py:116 +msgid "Incorrect input. access_token or code is required." +msgstr "Input errato. È richiesto \"access_token\" o \"code\"." + +#: .\registration\serializers.py:125 +msgid "Incorrect value" +msgstr "Valore errato" + +#: .\registration\serializers.py:139 +msgid "User is already registered with this e-mail address." +msgstr "Un altro utente è già registrato con questo indirizzo e-mail." + +#: .\registration\serializers.py:185 +msgid "A user is already registered with this e-mail address." +msgstr "Un altro utente è già registrato con questo indirizzo e-mail." + +#: .\registration\serializers.py:193 +msgid "The two password fields didn't match." +msgstr "Le password non corrispondono." + +#: .\registration\views.py:47 +msgid "Verification e-mail sent." +msgstr "E-mail di verifica inviata." + +#: .\registration\views.py:95 +msgid "ok" +msgstr "ok" + +#: .\serializers.py:32 +msgid "Must include \"email\" and \"password\"." +msgstr "Deve includere \"email\" e \"password\"." + +#: .\serializers.py:43 +msgid "Must include \"username\" and \"password\"." +msgstr "Deve includere \"email\" e \"password\"." + +#: .\serializers.py:56 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Deve includere o \"username\" o \"email\" e \"password\"." + +#: .\serializers.py:97 +msgid "User account is disabled." +msgstr "L'account è disabilitato." + +#: .\serializers.py:100 +msgid "Unable to log in with provided credentials." +msgstr "Impossibile accedere con le credenziali fornite." + +#: .\serializers.py:109 +msgid "E-mail is not verified." +msgstr "L'e-mail non è verificata." + +#: .\serializers.py:264 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "La tua password precedente non è corretta. Inseriscila nuovamente." + +#: .\views.py:139 +msgid "Successfully logged out." +msgstr "Disconnesso con successo." + +#: .\views.py:161 +msgid "Refresh token was not included in request data." +msgstr "Il \"Refresh token\" non è presente nei dati della richiesta." + +#: .\views.py:171 .\views.py:175 +msgid "An error has occurred." +msgstr "Si è verificato un errore." + +#: .\views.py:180 +msgid "" +"Neither cookies or blacklist are enabled, so the token has not been deleted " +"server side. Please make sure the token is deleted client side." +msgstr "" +"Né i cookies né la blacklist sono abilitati, quindi il token non è stato eliminato " +"lato server. Assicurarsi che il token sia eliminato lato client." + +#: .\views.py:230 +msgid "Password reset e-mail has been sent." +msgstr "L'e-mail per il recupero della password è stata inviata." + +#: .\views.py:256 +msgid "Password has been reset with the new password." +msgstr "Password aggiornata." + +#: .\views.py:278 +msgid "New password has been saved." +msgstr "Nuova password salvata." From 3b0e95cee731e4c0ac0d7810b2a371504faeccff Mon Sep 17 00:00:00 2001 From: Francesco Pinzauti Date: Thu, 7 May 2020 10:35:22 +0200 Subject: [PATCH 112/130] Compile italian language --- dj_rest_auth/locale/it/LC_MESSAGES/django.mo | Bin 0 -> 3001 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dj_rest_auth/locale/it/LC_MESSAGES/django.mo diff --git a/dj_rest_auth/locale/it/LC_MESSAGES/django.mo b/dj_rest_auth/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..e6874866ec7d4849042403c15d01d1b41c9272b9 GIT binary patch literal 3001 zcmbtWOKcoP5N$~KneYqWkSMCGKn5i<`G6p7VuBMp!jeCWaV!N6QG2F$w{dUx(mk`r zzT_H-Lr!o4!4WPTIB*IA#W$`#i!U1Hi)=p9Ss%THuSo zEA{wmAn*Spa2hyqw-5+P%ma@irzPMSj4$6)#s3ZP5XLuv1pK4MgZEbRXMiu@{oB9? zfLDPW-^VpxujhXSeu($`@2hzD68IR#-vK$_Ux259`zETmSAhpH?gNhjuL8LS-vT+l z8$jlF|NTNVfiDBk0X>lO`3i`11k#CP=6VlqzK}w^Ktc3b4+TPuTs|^<0mL@(0?p!a z+?*p{kK*2o`(fN%cZ4rcs(4{*@nHSTHQ>7Q#rcY9DueQ*14-kR%s0uajt+(LDyI!y zbgAfKQYAg94aq$BDuh%_TTgqx_Tk}DW@HGYEe*8V7*1x= zm^GQLUn;%%%bd~57PqXMt@cI~))h2RUbi)GHfJ-3ZLEZ?t3}O{v5}8F+PON?0}&=hz@=b87Sv`G)g(BfZ6l>9Vq?{=rUxI`G;U znIoXv?XXx|XU?r_1wuWo8BkdAFQp@gH+V(>Ctl10|5C1O!+&@lN}-RM2Y0aM~zKOg>7Nse`w8azS5pHq7Qu7sR>fup_ligaY7+E;qr1N;j!OR@BwB3?rq3N`?ZTDKg9;SuLy02oP?Ub^kk`*O;*l;**BIb#O zxrNzLjK|Ys6X%!_i>)^Mh=s{H+BZn-6lGoM(UnsdR?a6UM|K=iTlr)b+~nGJnsjmv zo?E8$(j@1d?}aAWejJ9W6Q`(poO;gEp(#54{HX~v4=P@GMO-*S!1dUG}x(gdYZFUw1EpJ^@iE1hqOE-|CLmH$RL>b$WQrYQf zhffM?+fIG@{7p9KtE|MMW2r_qLmIhs9H<1_107e+8EV|5qz#BktZ|>kmz&ip%@T^A z=xkVCY&(Oda@OMGS@mzIB-SAyHQJQ@v8w3McQyx|=$T&MffKNbk3M8Mhxo)3fN`ay zTToI>Z6v4*H2M7GP)?CTl+&sp@b!PsR{b{tH65O>5jzb&KRb*>h1G?tBo-} Date: Sat, 9 May 2020 17:32:05 -0500 Subject: [PATCH 113/130] Adds centralized version store --- dj_rest_auth/__version__.py | 8 ++++++++ docs/conf.py | 8 ++++++-- setup.py | 6 +++++- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 dj_rest_auth/__version__.py diff --git a/dj_rest_auth/__version__.py b/dj_rest_auth/__version__.py new file mode 100644 index 00000000..dd67bedc --- /dev/null +++ b/dj_rest_auth/__version__.py @@ -0,0 +1,8 @@ +__title__ = 'dj-rest-auth' +__description__ = 'Authentication and Registration in Django Rest Framework.' +__url__ = 'http://github.com/jazzband/dj-rest-auth' +__version__ = '1.0.5' +__author__ = '@iMerica https://github.com/iMerica' +__author_email__ = 'imichael@pm.me' +__license__ = 'MIT' +__copyright__ = 'Copyright 2020 @iMerica https://github.com/iMerica' \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 1f575785..97831a77 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,6 +15,10 @@ import os import sys +about = {} +with open('../dj_rest_auth/__version__.py', 'r', encoding="utf8") as f: + exec(f.read(), about) + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -51,9 +55,9 @@ # built documents. # # The short X.Y version. -version = '0.9.5' +version = about['__version__'] # The full version, including alpha/beta/rc tags. -release = '0.9.5' +release = about['__version__'] # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index 9c98f605..fac004b2 100644 --- a/setup.py +++ b/setup.py @@ -10,9 +10,13 @@ f.close() +about = {} +with open('dj_rest_auth/__version__.py', 'r', encoding="utf8") as f: + exec(f.read(), about) + setup( name='dj-rest-auth', - version='1.0.4', + version=about['__version__'], author='iMerica', author_email='imichael@pm.me', url='http://github.com/jazzband/dj-rest-auth', From b3758c9c267538f717fc63ed6f552abc209ab929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lide=CC=81n?= Date: Sun, 10 May 2020 15:08:00 +0200 Subject: [PATCH 114/130] Added swedish (sv) translations --- rest_auth/locale/sv/LC_MESSAGES/django.mo | Bin 0 -> 2565 bytes rest_auth/locale/sv/LC_MESSAGES/django.po | 107 ++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 rest_auth/locale/sv/LC_MESSAGES/django.mo create mode 100644 rest_auth/locale/sv/LC_MESSAGES/django.po diff --git a/rest_auth/locale/sv/LC_MESSAGES/django.mo b/rest_auth/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..185c73cf39038920d95bde4095978f1c0c02c91f GIT binary patch literal 2565 zcmbVN&5smC6fY1JM)3nhB^rE=8Zgl9?7A3SvI@G3Az@(yyQ>}ysqL=mDW|4-tg7yD zZrt?OQa3H%lK8t@O`G2r2cgm?$I z0AxD@U<|wgWW5pa1>kSM*MWQX32_2=40r^16*vd%jo04++20-DIpFU=xDqoD3(-XE zbHKA$fAokDuL8dYHi37>co)cd?0r;-w}3~1PXVt0TfhX!{%!y-1Ahdv{*nE4Jx-0$ z01sgQd*E^4t?~ZPz@u0ngz#P9Ng&s?3*>r!349Ou1CZn1+d$61$1(9&9K=Kl;xOhj zn5=UMlLtyv4X!iC{6xJJ2yuJB?DlvL|M-p&QZ=5&FVYt%nRpEISxj+`3a=b#PtrIg z(;+#PX&;nRDGhY!Q0PFYqMp=-WSTnVeJmDLTU&*->_hchVx;$^EtOggCc;D-vmul2 zwZfUd$c$Dt+;?uNb^>=c4^%3r+ghcuxL}jqIh6!h=@%g;nIwqfTFAS~Qtl|pQ^hGb z^?9KY_|7AxG=&n&h3C_WDWKU@oJ^CXO{v*O>WZ-4VF|UjxnF>&A6(+Z!$nH43L%r4--_X=3>KluzMOCVHVa$+B zo@Kbz93>R19YtY~PoqJpP3kGtsXZ2`CqvSS#hR5H28ubKI<}xbedxjpX7z3+@#ZV2T+8ys?E_Cb$^**Oe;o7uWDIkFq7KGBJYY7mw$#P zj4q@Rg7b)Lo*GwFKX)No_L)wj_lwL&t2wq;E=N~XsaYvnltInYY-_d^wN6DdEt)ws z-5>iUF&F1O!h7OGtQ#fg&^SSH!d9wX#=@(|tQ2lq|xTRMXXy%PGh{(eq z+c7fa4!KNXj8>KGVf}IRp|Z-=(v@7LDEn+Y8_zYwlEtGcN1Ha4PSI%7;Yp^_jyc8Q zP)a>C4!VXqELKrJ_d!;yqEP0FS2XnK-t}*GvCF;d-;$;}ypkB4AU$NM-(8G~l8Xs7E&n(Y1`}HO_lG1Nq|H!Z*xz}&jv1SO8^ony2xLaL z@zg+ypdv@UFLBvO@#16~q{M>J7T%8!qfKLiAKz;rJCsuc3RE+$bbEAr*AXr&$#SY& zJL~GCTX|ax%vXFJi(sH~v^CZAZTQ5)sA)t&GLFNy~Qe+(0Van6l)=Y=-!^#c=pPTDm4OUN&%LtE1r zw>^JEgE~pR5?AlU=RL3yacp@1HKi#d7B$k#WDjjJy)LAOz^Og%UwkUpk%ZCQ4v;Ar K1UF+<5!#=x2OS^) literal 0 HcmV?d00001 diff --git a/rest_auth/locale/sv/LC_MESSAGES/django.po b/rest_auth/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 00000000..747f5af7 --- /dev/null +++ b/rest_auth/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,107 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-10 12:48+0000\n" +"PO-Revision-Date: 2020-05-10 15:04+0200\n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Last-Translator: \n" +"Language-Team: \n" +"X-Generator: Poedit 2.2.4\n" + +#: rest_auth/rest_auth/registration/serializers.py:67 +msgid "View is not defined, pass it as a context variable" +msgstr "Vyn definieras inte, skicka den som en kontextvariabel" + +#: rest_auth/rest_auth/registration/serializers.py:72 +msgid "Define adapter_class in view" +msgstr "Definiera “adapter_class” i vyn" + +#: rest_auth/rest_auth/registration/serializers.py:91 +msgid "Define callback_url in view" +msgstr "Definiera “callback_url” i vyn" + +#: rest_auth/rest_auth/registration/serializers.py:95 +msgid "Define client_class in view" +msgstr "Definiera “client_class” i vyn" + +#: rest_auth/rest_auth/registration/serializers.py:116 +msgid "Incorrect input. access_token or code is required." +msgstr "Felaktig inmatning. access_token eller code krävs." + +#: rest_auth/rest_auth/registration/serializers.py:125 +msgid "Incorrect value" +msgstr "Felaktigt värde" + +#: rest_auth/rest_auth/registration/serializers.py:139 +msgid "User is already registered with this e-mail address." +msgstr "Användaren är redan registrerad med den här e-postadressen." + +#: rest_auth/rest_auth/registration/serializers.py:185 +msgid "A user is already registered with this e-mail address." +msgstr "En användare är redan registrerad med den här e-postadressen." + +#: rest_auth/rest_auth/registration/serializers.py:193 +msgid "The two password fields didn't match." +msgstr "De två lösenordsfälten matchade inte." + +#: rest_auth/rest_auth/registration/views.py:51 +msgid "Verification e-mail sent." +msgstr "Verifikationsmail har skickats." + +#: rest_auth/rest_auth/registration/views.py:98 +msgid "ok" +msgstr "ok" + +#: rest_auth/rest_auth/serializers.py:33 +msgid "Must include \"email\" and \"password\"." +msgstr "Måste inkludera “email” och “password”." + +#: rest_auth/rest_auth/serializers.py:44 +msgid "Must include \"username\" and \"password\"." +msgstr "Måste innehålla “username” och “password”." + +#: rest_auth/rest_auth/serializers.py:57 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Måste innehålla antingen “username” eller “email” och “password”." + +#: rest_auth/rest_auth/serializers.py:98 +msgid "User account is disabled." +msgstr "Användarkontot är avstängt." + +#: rest_auth/rest_auth/serializers.py:101 +msgid "Unable to log in with provided credentials." +msgstr "Det går inte att logga in med de angivna uppgifterna." + +#: rest_auth/rest_auth/serializers.py:110 +msgid "E-mail is not verified." +msgstr "E-post är inte verifierad." + +#: rest_auth/rest_auth/serializers.py:259 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ditt gamla lösenord angavs felaktigt. Vänligen ange det igen." + +#: rest_auth/rest_auth/views.py:137 +msgid "Successfully logged out." +msgstr "Utloggad." + +#: rest_auth/rest_auth/views.py:190 +msgid "Password reset e-mail has been sent." +msgstr "E-post för återställning av lösenord har skickats." + +#: rest_auth/rest_auth/views.py:216 +msgid "Password has been reset with the new password." +msgstr "Lösenordet har återställts med det nya lösenordet." + +#: rest_auth/rest_auth/views.py:238 +msgid "New password has been saved." +msgstr "Nytt lösenord har sparats." From 5f137da9306d63fb1730119ca739c775bc63faac Mon Sep 17 00:00:00 2001 From: Mahmoud Adel Date: Sun, 10 May 2020 18:05:30 +0200 Subject: [PATCH 115/130] make token validation in PasswordResetConfirmSerializer is the first thing to do in validate() method --- dj_rest_auth/serializers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index efd455e4..f05d1439 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -208,6 +208,9 @@ def custom_validation(self, attrs): def validate(self, attrs): self._errors = {} + if not default_token_generator.check_token(self.user, attrs['token']): + raise ValidationError({'token': ['Invalid value']}) + # Decode the uidb64 to uid to get User object try: uid = force_text(uid_decoder(attrs['uid'])) @@ -222,8 +225,6 @@ def validate(self, attrs): ) if not self.set_password_form.is_valid(): raise serializers.ValidationError(self.set_password_form.errors) - if not default_token_generator.check_token(self.user, attrs['token']): - raise ValidationError({'token': ['Invalid value']}) return attrs From 0be5b2dd156c13dc1cc4cb49c853b48f5606d461 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 11 May 2020 19:39:33 -0500 Subject: [PATCH 116/130] Fixes no-user issue --- dj_rest_auth/serializers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index f05d1439..16ebebcf 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -208,9 +208,6 @@ def custom_validation(self, attrs): def validate(self, attrs): self._errors = {} - if not default_token_generator.check_token(self.user, attrs['token']): - raise ValidationError({'token': ['Invalid value']}) - # Decode the uidb64 to uid to get User object try: uid = force_text(uid_decoder(attrs['uid'])) @@ -218,6 +215,9 @@ def validate(self, attrs): except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist): raise ValidationError({'uid': ['Invalid value']}) + if not default_token_generator.check_token(self.user, attrs['token']): + raise ValidationError({'token': ['Invalid value']}) + self.custom_validation(attrs) # Construct SetPasswordForm instance self.set_password_form = self.set_password_form_class( From 0bc943ff25ce6f0e9eda9295c8c5c629faa870d2 Mon Sep 17 00:00:00 2001 From: Robert Wells Date: Sat, 16 May 2020 13:41:45 -0700 Subject: [PATCH 117/130] Adds a tox.ini file and instructions in the readme for how to use it. --- README.md | 17 ++++++++++- dj_rest_auth/__version__.py | 2 +- dj_rest_auth/app_settings.py | 4 ++- dj_rest_auth/registration/serializers.py | 1 - dj_rest_auth/tests/urls.py | 1 - dj_rest_auth/utils.py | 2 +- dj_rest_auth/views.py | 1 - tox.ini | 37 ++++++++++++++++++++++++ 8 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 tox.ini diff --git a/README.md b/README.md index deefdb59..0430a085 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,21 @@ The easiest way to run test coverage is with [`coverage`](https://pypi.org/proje which runs the tests against all supported Django installs. To run the test coverage within a virtualenv, run `coverage run ./runtests.py` from the repository directory then run `coverage report`. +#### Tox + +Testing may also be done using [`tox`](https://pypi.org/project/tox/), which +will run the tests against all supported combinations of python and django. + +Install tox, either globally or within a virtualenv, and then simply run `tox` +from the repository directory. As there are many combinations, you may run them +in [`parallel`](https://tox.readthedocs.io/en/latest/config.html#cmdoption-tox-p) +using `tox --parallel`. + +The `tox.ini` includes an environment for testing code [`coverage`](https://pypi.org/project/coverage/) +and you can run it and view this report with `tox -e coverage`. + +Linting may also be performed via [`flake8`](https://pypi.org/project/flake8/) +by running `tox -e flake8`. ### Documentation @@ -59,4 +74,4 @@ View the full documentation here: https://dj-rest-auth.readthedocs.io/en/latest/ ### Acknowledgements -This project began as a fork of `django-rest-auth`. Big thanks to everyone who contributed to that repo! \ No newline at end of file +This project began as a fork of `django-rest-auth`. Big thanks to everyone who contributed to that repo! diff --git a/dj_rest_auth/__version__.py b/dj_rest_auth/__version__.py index dd67bedc..5b7a5aa3 100644 --- a/dj_rest_auth/__version__.py +++ b/dj_rest_auth/__version__.py @@ -5,4 +5,4 @@ __author__ = '@iMerica https://github.com/iMerica' __author_email__ = 'imichael@pm.me' __license__ = 'MIT' -__copyright__ = 'Copyright 2020 @iMerica https://github.com/iMerica' \ No newline at end of file +__copyright__ = 'Copyright 2020 @iMerica https://github.com/iMerica' diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 784a6912..fe6e6a26 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -33,6 +33,8 @@ 'PASSWORD_RESET_CONFIRM_SERIALIZER', DefaultPasswordResetConfirmSerializer )) -PasswordChangeSerializer = import_callable(serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer)) +PasswordChangeSerializer = import_callable( + serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer) +) JWT_AUTH_COOKIE = getattr(settings, 'JWT_AUTH_COOKIE', None) diff --git a/dj_rest_auth/registration/serializers.py b/dj_rest_auth/registration/serializers.py index fc7c92bb..7d9d4a0f 100644 --- a/dj_rest_auth/registration/serializers.py +++ b/dj_rest_auth/registration/serializers.py @@ -17,7 +17,6 @@ raise ImportError("allauth needs to be added to INSTALLED_APPS.") - class SocialAccountSerializer(serializers.ModelSerializer): """ serialize allauth SocialAccounts for use with a REST API diff --git a/dj_rest_auth/tests/urls.py b/dj_rest_auth/tests/urls.py index e2c786e4..f1796d67 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -21,7 +21,6 @@ class ExampleProtectedView(APIView): permission_classes = [permissions.IsAuthenticated] - def get(self, *args, **kwargs): return Response(dict(success=True)) diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index 7cbf3ad1..e1ef77ac 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -45,7 +45,7 @@ def authenticate(self, request): return None else: raw_token = self.get_raw_token(header) - + if raw_token is None: return None diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index b5fcdb85..c968334b 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -146,7 +146,6 @@ def logout(self, request): from rest_framework_simplejwt.exceptions import TokenError from rest_framework_simplejwt.tokens import RefreshToken - cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) if cookie_name: response.delete_cookie(cookie_name) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..484802bc --- /dev/null +++ b/tox.ini @@ -0,0 +1,37 @@ +# tox (https://tox.readthedocs.io/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +# Running this tox will test against all supported version +# combinations of python and django as described at the following +# https://docs.djangoproject.com/en/3.0/faq/install/#what-python-version-can-i-use-with-django +# https://endoflife.date/django +[tox] +skipsdist = true +envlist = + python{3.5,3.6,3.7,3.8}-django22 + python{3.6,3.7,3.8}-django30 + +[testenv] +commands = + python ./runtests.py +deps = + -rdev-requirements.txt + django22: Django>=2.2,<2.3 + django30: Django>=3.0,<3.1 + +# Configuration for coverage and flake8 is being set in `./setup.cfg` +[testenv:coverage] +commands = + coverage run ./runtests.py + coverage report +deps = + -rdev-requirements.txt + +[testenv:flake8] +changedir = {toxinidir}/dj_rest_auth +commands = + flake8 . +deps = + flake8==3.8.1 From 860c350ac939256c4b477198df66046e50826e7a Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 16 May 2020 15:58:57 -0500 Subject: [PATCH 118/130] Fixes the Circle CI Link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0430a085..06d9953a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Dj-Rest-Auth -[![](https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg)](https://app.circleci.com/github/jazzband/dj-rest-auth/pipelines) +[![](https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg)](https://app.circleci.com/pipelines/github/jazzband/dj-rest-auth) [![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) [![Coverage Status](https://coveralls.io/repos/github/jazzband/dj-rest-auth/badge.svg?branch=master)](https://coveralls.io/github/jazzband/dj-rest-auth?branch=master) From 2a6fb3a87321ebcf6c0ea4c3b1d0d66285309198 Mon Sep 17 00:00:00 2001 From: Sean Farley Date: Tue, 19 May 2020 19:21:11 -0700 Subject: [PATCH 119/130] serializers: import gettext_lazy; fixes #70 Per Django's warning, ugettext_lazy will be removed in a future version. --- dj_rest_auth/serializers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index 16ebebcf..302be848 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -5,7 +5,10 @@ from django.utils.encoding import force_text from django.utils.http import urlsafe_base64_decode as uid_decoder from django.utils.module_loading import import_string -from django.utils.translation import ugettext_lazy as _ +try: + from django.utils.translation import gettext_lazy as _ +except ImportError: + from django.utils.translation import ugettext_lazy as _ from rest_framework import exceptions, serializers from rest_framework.exceptions import ValidationError From 1fe4ba7d3435e2d74c2ed3e63cf28caed59237fd Mon Sep 17 00:00:00 2001 From: Mahmoud Adel Date: Thu, 28 May 2020 00:13:43 +0200 Subject: [PATCH 120/130] Updated PasswordResetConfirmSerializer docstring --- dj_rest_auth/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dj_rest_auth/serializers.py b/dj_rest_auth/serializers.py index 302be848..a65f7655 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -196,7 +196,7 @@ def save(self): class PasswordResetConfirmSerializer(serializers.Serializer): """ - Serializer for requesting a password reset e-mail. + Serializer for confirming a password reset attempt. """ new_password1 = serializers.CharField(max_length=128) new_password2 = serializers.CharField(max_length=128) From 9a75a153456c7afa826f99eb8556fa540214eb08 Mon Sep 17 00:00:00 2001 From: erdaltsksn Date: Sat, 30 May 2020 04:33:40 +0300 Subject: [PATCH 121/130] docs: Update registration install command for zsh why: The zsh cannot process [] character correctly. iss: https://github.com/Tivix/django-rest-auth/issues/402 --- docs/installation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 6a7d83fb..94579eec 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -44,7 +44,7 @@ You're good to go now! Registration (optional) ----------------------- -1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install dj-rest-auth[with_social]``. +1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install 'dj-rest-auth[with_social]'``. 2. Add ``django.contrib.sites``, ``allauth``, ``allauth.account`` and ``dj_rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py: @@ -283,4 +283,4 @@ This example value above will cause dj-rest-auth to return a `Set-Cookie` header Set-Cookie: my-app-auth=xxxxxxxxxxxxx; expires=Sat, 28 Mar 2020 18:59:00 GMT; HttpOnly; Max-Age=300; Path=/ -``JWT_AUTH_COOKIE`` is also used while authenticating each request against protected views. \ No newline at end of file +``JWT_AUTH_COOKIE`` is also used while authenticating each request against protected views. From 202b5e8d4df459a22e4f618fd353cfa56444ff17 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:16:02 -0500 Subject: [PATCH 122/130] Adds vulnerability disclosure --- docs/disclosure.rst | 17 +++++++++++++++++ docs/index.rst | 1 + 2 files changed, 18 insertions(+) create mode 100644 docs/disclosure.rst diff --git a/docs/disclosure.rst b/docs/disclosure.rst new file mode 100644 index 00000000..c4e2ae5f --- /dev/null +++ b/docs/disclosure.rst @@ -0,0 +1,17 @@ +Vulnerability Disclosure +======================== + +Attn: Developers and Security Researchers. + +Please observe the standard best practices of responsible disclosure, especially considering that this is OSS. +See OWASP's disclosure `cheat sheet `_. + +Some basic rules: + +- Keep it legal. +- Respect everyone's privacy. +- Contact the core maintainer(s) immediately if you discover a security vulnerability (imichael@pm.me for now). + + + + diff --git a/docs/index.rst b/docs/index.rst index 10eb7cb3..2084a267 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,3 +26,4 @@ Contents Demo project FAQ Changelog + Security Disclosure From c18ccf57fd1f02dc15962f61289a09f21e7d9d3e Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:25:20 -0500 Subject: [PATCH 123/130] Improves link in docs --- docs/disclosure.rst | 6 ++---- docs/index.rst | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/disclosure.rst b/docs/disclosure.rst index c4e2ae5f..4e7d4948 100644 --- a/docs/disclosure.rst +++ b/docs/disclosure.rst @@ -1,16 +1,14 @@ Vulnerability Disclosure ======================== -Attn: Developers and Security Researchers. - Please observe the standard best practices of responsible disclosure, especially considering that this is OSS. -See OWASP's disclosure `cheat sheet `_. +See OWASP's disclosure `cheat sheet `_. Some basic rules: - Keep it legal. - Respect everyone's privacy. -- Contact the core maintainer(s) immediately if you discover a security vulnerability (imichael@pm.me for now). +- Contact the core maintainer(s) immediately if you discover a serious security vulnerability (imichael@pm.me for now). diff --git a/docs/index.rst b/docs/index.rst index 2084a267..1d5ac3b4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,4 +26,4 @@ Contents Demo project FAQ Changelog - Security Disclosure + Vulnerability Disclosure From 24413e4a4400aee9744379cc41463a960fa4247b Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:30:16 -0500 Subject: [PATCH 124/130] Removes changelog. Refer to Github instead --- docs/changelog.rst | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 docs/changelog.rst diff --git a/docs/changelog.rst b/docs/changelog.rst deleted file mode 100644 index 78186af4..00000000 --- a/docs/changelog.rst +++ /dev/null @@ -1,13 +0,0 @@ -Changelog -========= - -0.1.2 ------ -Welcome Dj-Rest-Auth - -1.0.0 ------ -Replaces `rest_framework_jwt` with `djangorestframework-simplejwt`. - -Rest_framework_jwt is now unmaintained so we've switched to simplewjt, which is a strong jwt library with a large community. -This change means you may need to change your client code if you're upgrading from the previous version. \ No newline at end of file From 3ac4251233f30a4aa320201b1a79af4b738dff76 Mon Sep 17 00:00:00 2001 From: Dmitriy Kalinin Date: Sat, 30 May 2020 09:30:49 +0300 Subject: [PATCH 125/130] Added ukrainian locale --- dj_rest_auth/locale/uk/django.po | 101 +++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 dj_rest_auth/locale/uk/django.po diff --git a/dj_rest_auth/locale/uk/django.po b/dj_rest_auth/locale/uk/django.po new file mode 100644 index 00000000..519c59fa --- /dev/null +++ b/dj_rest_auth/locale/uk/django.po @@ -0,0 +1,101 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-23 21:56-0800\n" +"PO-Revision-Date: 2020-05-23 00:56+0300\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" +"X-Generator: Poedit 2.3.1\n" + +#: registration/serializers.py:53 +msgid "View is not defined, pass it as a context variable" +msgstr "View невідомий, передайте його як змінну контексту" + +#: registration/serializers.py:58 +msgid "Define adapter_class in view" +msgstr "Встановіть adapter_class у view" + +#: registration/serializers.py:77 +msgid "Define callback_url in view" +msgstr "Встановіть callback_url у view" + +#: registration/serializers.py:81 +msgid "Define client_class in view" +msgstr "Встановіть client_class у view" + +#: registration/serializers.py:102 +msgid "Incorrect input. access_token or code is required." +msgstr "Некоректне введення. Необхідний access_token або code." + +#: registration/serializers.py:111 +msgid "Incorrect value" +msgstr "Некоректне значення" + +#: registration/serializers.py:140 +msgid "A user is already registered with this e-mail address." +msgstr "Користувач з таким e-mail адресою вже зареєстрований." + +#: registration/serializers.py:148 +msgid "The two password fields didn't match." +msgstr "Паролі не збігаються." + +#: registration/views.py:44 +msgid "Verification e-mail sent." +msgstr "Лист з підтвердженням вислано на email." + +#: registration/views.py:91 +msgid "ok" +msgstr "добре" + +#: serializers.py:30 +msgid "Must include \"email\" and \"password\"." +msgstr "Має включати \"email\" и \"пароль\"." + +#: serializers.py:41 +msgid "Must include \"username\" and \"password\"." +msgstr "Має включати \"юзернейм\" и \"пароль\"." + +#: serializers.py:54 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Повинно включати або \"юзернейм\" либо \"email\" и \"пароль\"." + +#: serializers.py:95 +msgid "User account is disabled." +msgstr "Користувач вимкнений." + +#: serializers.py:98 +msgid "Unable to log in with provided credentials." +msgstr "Неможливо увійти в систему з зазначеними обліковими даними." + +#: serializers.py:107 +msgid "E-mail is not verified." +msgstr "E-mail не підтверджено." + +#: views.py:126 +msgid "Successfully logged out." +msgstr "Успішно вийшли." + +#: views.py:174 +msgid "Password reset e-mail has been sent." +msgstr "Лист з інструкціями по відновленню пароля вислано." + +#: views.py:200 +msgid "Password has been reset with the new password." +msgstr "Пароль змінено на новий." + +#: views.py:222 +msgid "New password has been saved." +msgstr "Новий пароль збережений." From 13a241f0b295847b2da81c2aa92326265ad077f7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:34:42 -0500 Subject: [PATCH 126/130] Updates index --- docs/disclosure.rst | 4 ++-- docs/index.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/disclosure.rst b/docs/disclosure.rst index 4e7d4948..5b7619ab 100644 --- a/docs/disclosure.rst +++ b/docs/disclosure.rst @@ -1,5 +1,5 @@ -Vulnerability Disclosure -======================== +Vulnerability Disclosure Policy +=============================== Please observe the standard best practices of responsible disclosure, especially considering that this is OSS. See OWASP's disclosure `cheat sheet `_. diff --git a/docs/index.rst b/docs/index.rst index 1d5ac3b4..00bdad96 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,4 +26,4 @@ Contents Demo project FAQ Changelog - Vulnerability Disclosure + Disclosure Policy From 099e61e5f11887d3424f2fad69e29aa033ef9875 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:37:05 -0500 Subject: [PATCH 127/130] Removes reference tot changelog --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 00bdad96..3a969027 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ Welcome to dj-rest-auth's documentation! ============================================ -.. note:: dj-rest-auth version 1.0.0 now uses Django Simple JWT. Please see changelog. +.. note:: dj-rest-auth version 1.0.0 now uses Django Simple JWT. .. image:: https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg From 62e291ba779641fa7244569fdcc8b42ad60dee9d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:38:03 -0500 Subject: [PATCH 128/130] Fixes docs --- docs/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 3a969027..8569e550 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -25,5 +25,4 @@ Contents Configuration Demo project FAQ - Changelog Disclosure Policy From 073ea5536e1589d3e11c18519aa6fe349d428e84 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 May 2020 01:41:58 -0500 Subject: [PATCH 129/130] Bumps to 1.0.6 --- 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 5b7a5aa3..c61dbebb 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/jazzband/dj-rest-auth' -__version__ = '1.0.5' +__version__ = '1.0.6' __author__ = '@iMerica https://github.com/iMerica' __author_email__ = 'imichael@pm.me' __license__ = 'MIT' From 2daa44e5f416e7d876a52b4fbd82a6ef63b7e4ed Mon Sep 17 00:00:00 2001 From: Steve Recio Date: Wed, 3 Jun 2020 09:17:15 -0400 Subject: [PATCH 130/130] change throttle scope naming (rest_auth -> dj_rest_auth) --- dj_rest_auth/registration/views.py | 2 +- dj_rest_auth/views.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dj_rest_auth/registration/views.py b/dj_rest_auth/registration/views.py index 02c73b91..d3c0de8c 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -36,7 +36,7 @@ class RegisterView(CreateAPIView): serializer_class = RegisterSerializer permission_classes = register_permission_classes() token_model = TokenModel - throttle_scope = 'rest_auth' + throttle_scope = 'dj_rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index e68b2ac0..dc3dea80 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -40,7 +40,7 @@ class LoginView(GenericAPIView): permission_classes = (AllowAny,) serializer_class = LoginSerializer token_model = TokenModel - throttle_scope = 'rest_auth' + throttle_scope = 'dj_rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): @@ -116,7 +116,7 @@ class LogoutView(APIView): Accepts/Returns nothing. """ permission_classes = (AllowAny,) - throttle_scope = 'rest_auth' + throttle_scope = 'dj_rest_auth' def get(self, request, *args, **kwargs): if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False): @@ -219,7 +219,7 @@ class PasswordResetView(GenericAPIView): """ serializer_class = PasswordResetSerializer permission_classes = (AllowAny,) - throttle_scope = 'rest_auth' + throttle_scope = 'dj_rest_auth' def post(self, request, *args, **kwargs): # Create a serializer with request.data @@ -245,7 +245,7 @@ class PasswordResetConfirmView(GenericAPIView): """ serializer_class = PasswordResetConfirmSerializer permission_classes = (AllowAny,) - throttle_scope = 'rest_auth' + throttle_scope = 'dj_rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs): @@ -269,7 +269,7 @@ class PasswordChangeView(GenericAPIView): """ serializer_class = PasswordChangeSerializer permission_classes = (IsAuthenticated,) - throttle_scope = 'rest_auth' + throttle_scope = 'dj_rest_auth' @sensitive_post_parameters_m def dispatch(self, *args, **kwargs):