From 92cc9c18ecaccdf509ef5ff2917ff64f7f81dd94 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Feb 2020 17:59:38 -0600 Subject: [PATCH 001/127] 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 b059c1e..33f42ad 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 21906da..c5ba2ed 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 1e3b853..f868a2a 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 01a589f..c2d4208 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 ac7f19e..f79511f 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 514a8fb..df6807a 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -37,11 +37,11 @@ INSTALLED_APPS = ( '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 af7d38b..787c6e9 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -35,8 +35,8 @@ urlpatterns = [ 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 40b4820..c6f5f42 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 cbf02b6..47e4e64 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 134198a..ecc6f7c 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 1b75fe6..9974c2d 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 46d2a05..a2a4c7d 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 e7beb5d..2bb3f4c 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 59b301f..b988a76 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 d15566a..4a38211 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 b382d43..d506727 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 191abb5..25cc914 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 002/127] 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 f79511f..0000000 --- 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 eb8c60c..e6acf92 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 0a0a982..0a27f8e 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -164,7 +164,7 @@ class UserDetailsView(RetrieveUpdateAPIView): """ 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 cf09288..e71af70 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 a2a4c7d..f23dabd 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 1c825cc..dd54bb6 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 @@ source_suffix = '.rst' 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_static_path = ['_static'] #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 @@ latex_elements = { # (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 @@ latex_documents = [ # 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 @@ man_pages = [ # (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 877ca33..22620f8 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 dc25e83..8be210a 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 d506727..395299a 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 25cc914..6f4d354 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 db1383d..3aff4bb 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 675b99d..30ee681 100644 --- a/setup.py +++ b/setup.py @@ -11,11 +11,11 @@ f.close() 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 003/127] 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 f868a2a..42a0292 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 0000000..3210e8c --- /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 004/127] 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 005/127] 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 3210e8c..f270c2e 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 006/127] Remove cache --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f270c2e..68175a1 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 007/127] 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 68175a1..a3da36b 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 008/127] Updates yaml --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a3da36b..7aca92f 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 009/127] Runs tests --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7aca92f..0ab50c5 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 010/127] 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 0ab50c5..771be20 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 011/127] 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 0000000..e69de29 diff --git a/dj_rest_auth/tests/django_urls.py b/dj_rest_auth/tests/django_urls.py index c1fb050..57f9d7d 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 e353fb0..16ba4b5 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 @@ REST_FRAMEWORK = { } INSTALLED_APPS = [ - 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.humanize', 'django.contrib.contenttypes', diff --git a/runtests.py b/runtests.py index 8b7ede2..cabaf9c 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 30ee681..472ce6b 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup, find_packages 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 @@ f.close() 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 012/127] 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 33f42ad..0000000 --- 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 0e0ab0d..f8d1120 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -19,16 +19,16 @@ from allauth.socialaccount import signals 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 16ba4b5..c86bfc1 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -90,8 +90,8 @@ INSTALLED_APPS = [ '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 9c5fd9e..b6d84f2 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -8,8 +8,8 @@ from allauth.account import app_settings as account_app_settings 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 401f23a..ef900b9 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -7,12 +7,12 @@ from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter 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 7a35e9b..6664722 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 cabaf9c..6fab508 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 013/127] Adds Docker runtime --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 771be20..2918fd5 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 014/127] Removes Orb --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2918fd5..16565f1 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 015/127] Uses Docker Orb --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 16565f1..17dbf10 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 016/127] 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 17dbf10..a5bfacb 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 017/127] 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 a5bfacb..0fd7227 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 018/127] Removes six --- demo/requirements.pip | 1 - dj_rest_auth/app_settings.py | 39 +++++++---------------- 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, 17 insertions(+), 54 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index c6f5f42..ab0a814 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 9974c2d..7f8094f 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -8,44 +8,27 @@ from dj_rest_auth.serializers import ( 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 = serializers.get( + 'PASSWORD_RESET_CONFIRM_SERIALIZER', DefaultPasswordResetConfirmSerializer ) -PasswordResetConfirmSerializer = import_callable( - 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 a132f9c..5f690da 100644 --- a/dj_rest_auth/models.py +++ b/dj_rest_auth/models.py @@ -2,9 +2,7 @@ from django.conf import settings 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 c8cd25a..3e6db53 100644 --- a/dj_rest_auth/registration/app_settings.py +++ b/dj_rest_auth/registration/app_settings.py @@ -2,18 +2,17 @@ from django.conf import settings 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 b645231..da8fef7 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -10,7 +10,6 @@ from rest_framework import serializers, exceptions 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 @@ class JWTSerializer(serializers.Serializer): 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 800f184..b69dae0 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 472ce6b..a57994e 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,6 @@ setup( 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 019/127] Fixes min reqs --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index a57994e..db77e40 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 @@ setup( 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 020/127] 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 0fd7227..138d8ad 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 3e6db53..fdeae83 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 1621813..6f8a449 100644 --- a/dj_rest_auth/social_serializers.py +++ b/dj_rest_auth/social_serializers.py @@ -8,7 +8,7 @@ if 'allauth.socialaccount' in settings.INSTALLED_APPS: 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 021/127] 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 ef900b9..5aa37c1 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 022/127] Adds dev reqs --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 138d8ad..7bdbc4b 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 023/127] 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 7bdbc4b..a8c0ea1 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 db77e40..09ffe1c 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( 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 024/127] 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 a8c0ea1..2e9a3d4 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 025/127] Adds tests --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2e9a3d4..ee7f31d 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 026/127] Install tests reqs --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index ee7f31d..d05084d 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 027/127] Bumps Django --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d05084d..34b5db8 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 028/127] 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 34b5db8..869f98b 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 6fab508..04dfa7c 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 029/127] 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 869f98b..2f2b4a5 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 030/127] 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 2f2b4a5..75c5e48 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 031/127] 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 c86bfc1..f683ce0 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -73,6 +73,8 @@ REST_FRAMEWORK = { } 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 032/127] Adds README badge --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e69de29..58f1092 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 033/127] Updates badge URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58f1092..076cce2 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 034/127] Updates README --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 076cce2..79125b2 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 035/127] Fixes README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79125b2..6a1faa8 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 036/127] Updats README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6a1faa8..09a0f5a 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 037/127] 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 8be210a..0479561 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 395299a..cba551e 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 09ffe1c..9d2b775 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 038/127] Specifies Python version --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9d2b775..b00ff9e 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 @@ setup( ], 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 039/127] 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 09a0f5a..268c56a 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 0479561..8deb445 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 040/127] Updates Docs --- docs/index.rst | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 8deb445..c3de8ce 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 041/127] 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 2bb3f4c..42d36bc 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 042/127] 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 | 11 +++--- dj_rest_auth/registration/serializers.py | 6 +-- dj_rest_auth/registration/urls.py | 2 +- dj_rest_auth/registration/views.py | 46 +++++++++++------------ 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, 119 insertions(+), 121 deletions(-) diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 787c6e9..4f63ba1 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 ef48754..863501d 100644 --- a/demo/demo/wsgi.py +++ b/demo/demo/wsgi.py @@ -8,7 +8,9 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ """ 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 7f8094f..d89202d 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 5f690da..654c0ae 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 fdeae83..bbc7075 100644 --- a/dj_rest_auth/registration/app_settings.py +++ b/dj_rest_auth/registration/app_settings.py @@ -1,14 +1,13 @@ -from django.conf import settings - -from rest_framework.permissions import AllowAny -from dj_rest_auth.registration.serializers import ( +from dj_rest_auth.registration.serializers import \ RegisterSerializer as DefaultRegisterSerializer -) +from django.conf import settings +from rest_framework.permissions import AllowAny +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 4f99c18..fc7c92b 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 @@ try: 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 1004695..c42cec6 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 f8d1120..81ed1ea 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -1,34 +1,30 @@ +from allauth.account import app_settings as allauth_settings +from allauth.account.adapter import get_adapter +from allauth.account.utils import complete_signup +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 (JWTSerializer, TokenSerializer, + create_token) +from dj_rest_auth.models import TokenModel +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.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 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 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.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.models import TokenModel -from dj_rest_auth.registration.serializers import (VerifyEmailSerializer, - SocialLoginSerializer, - SocialAccountSerializer, - SocialConnectSerializer) -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/serializers.py b/dj_rest_auth/serializers.py index da8fef7..07783da 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 6f8a449..60b0c2c 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 30b3d58..06d776d 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 f683ce0..d18f41e 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 b6d84f2..585b38d 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 830e631..47c8d93 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 5aa37c1..be199a5 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 6664722..d3bfc42 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 b69dae0..b4858c8 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 0a27f8e..b3b8f22 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 dd54bb6..7730562 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 04dfa7c..3cb605b 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 b00ff9e..4bbfac8 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 @@ f.close() 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 043/127] Updates README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 268c56a..e6b1e40 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 044/127] Corrects grammar --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6b1e40..56d4315 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 045/127] 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 c5ba2ed..e41efa7 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 47e4e64..d57ece3 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 e6acf92..90e6f71 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 b3b8f22..c5bcb1a 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -161,7 +161,6 @@ class UserDetailsView(RetrieveUpdateAPIView): """ 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 f23dabd..a4e602a 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 22620f8..ecceddd 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 4bbfac8..e4f3ec9 100644 --- a/setup.py +++ b/setup.py @@ -12,10 +12,10 @@ f.close() 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 046/127] 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 56d4315..ec7ae1d 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 c3de8ce..82118cc 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 047/127] Adds Jazzband badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ec7ae1d..46af4d8 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 048/127] 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 0000000..10d7919 --- /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 049/127] Adds coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46af4d8..3ec4ef7 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 050/127] 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 75c5e48..5830b0b 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 0a2a9e4..9d2af20 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 e4f3ec9..94aad46 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,7 @@ setup( '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 051/127] 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 5830b0b..d124869 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 0000000..16eb397 --- /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 052/127] 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 ab0a814..7442229 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 053/127] 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 07783da..b34c9cc 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 b4858c8..165963d 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 c5bcb1a..f30980c 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -59,7 +59,7 @@ class LoginView(GenericAPIView): 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 @@ class LoginView(GenericAPIView): 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 @@ class LoginView(GenericAPIView): 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 @@ class LogoutView(APIView): 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 054/127] 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 d18f41e..7279c21 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -68,7 +68,7 @@ TEMPLATES = [ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', - 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', + 'rest_framework_simplejwt.authentication.JWTAuthentication', ) } @@ -94,8 +94,6 @@ INSTALLED_APPS = [ '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 585b38d..5d06fac 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -152,8 +152,8 @@ class APIBasicTests(TestsMixin, TestCase): 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 @@ class APIBasicTests(TestsMixin, TestCase): "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 @@ class APIBasicTests(TestsMixin, TestCase): 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 47c8d93..cceba3f 100644 --- a/dj_rest_auth/tests/test_social.py +++ b/dj_rest_auth/tests/test_social.py @@ -305,7 +305,7 @@ class TestSocialAuth(TestsMixin, TestCase): } 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 055/127] 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 81ed1ea..e9577a1 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -49,7 +49,8 @@ class RegisterView(CreateAPIView): 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 @@ class RegisterView(CreateAPIView): 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 056/127] 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 b988a76..af858c0 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 cba551e..5004752 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 057/127] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 94aad46..8872a56 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ setup( 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 058/127] 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 07783da..91c7b8a 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -100,7 +100,7 @@ class LoginSerializer(serializers.Serializer): 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 059/127] 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 df6807a..50f5afb 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -31,7 +31,7 @@ INSTALLED_APPS = ( '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 060/127] 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 df6807a..1cf35f5 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -120,7 +120,8 @@ REST_FRAMEWORK = { '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 061/127] 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 165963d..85912a6 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 f30980c..37e4880 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -83,6 +83,15 @@ class LoginView(GenericAPIView): 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 @@ class LogoutView(APIView): 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 062/127] 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 d89202d..39e44ef 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -34,3 +34,6 @@ PasswordResetConfirmSerializer = serializers.get( ) 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 7279c21..3d02309 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -68,7 +68,7 @@ TEMPLATES = [ 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 85912a6..2b8094a 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 37e4880..2896209 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -16,7 +16,7 @@ from .app_settings import (JWTSerializer, LoginSerializer, 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 @@ class LoginView(GenericAPIView): 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 @@ class LogoutView(APIView): 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 5004752..fa4345d 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 063/127] 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 b988a76..5abaf4b 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 064/127] 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 | 299 +++------------------------- 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, 64 insertions(+), 294 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 7442229..6d24967 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 9d2af20..cee8ea6 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 f48ee3c..4ff9b2d 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 5d06fac..4519186 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -144,293 +144,46 @@ class APIBasicTests(TestsMixin, TestCase): 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) - - 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) - - 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.login_url, data=payload, status_code=200) + self.assertTrue('jwt-auth' in resp.cookies.keys()) @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') + 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) - 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) + resp = self.post(self.logout_url, status=200) + self.assertEqual('', resp.cookies.get('jwt-auth').value) @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() + @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) 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 cceba3f..819b153 100644 --- a/dj_rest_auth/tests/test_social.py +++ b/dj_rest_auth/tests/test_social.py @@ -17,9 +17,6 @@ except ImportError: 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 be199a5..7579e83 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -11,10 +11,21 @@ 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 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 @@ urlpatterns += [ 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 2b8094a..7cbf3ad 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 @@ try: 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 @@ try: 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 2896209..a31e879 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -16,7 +16,7 @@ from .app_settings import (JWTSerializer, LoginSerializer, 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 @@ class LoginView(GenericAPIView): 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 @@ class LogoutView(APIView): 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 af858c0..d4d67cc 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 065/127] Re-adds previous tests --- dj_rest_auth/tests/test_api.py | 345 ++++++++++++++++++++++++++++++--- dj_rest_auth/views.py | 2 +- 2 files changed, 319 insertions(+), 28 deletions(-) diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index 4519186..f0607b5 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -144,46 +144,293 @@ class APIBasicTests(TestsMixin, TestCase): 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): - 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) + 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') - @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 = { + "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) - 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=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']) + + @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) + 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() def test_registration_with_invalid_password(self): data = self.REGISTRATION_DATA.copy() @@ -267,3 +514,47 @@ class APIBasicTests(TestsMixin, TestCase): 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 a31e879..c5ba7fc 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -138,7 +138,7 @@ class LogoutView(APIView): 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 066/127] 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 d124869..efcf792 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 cee8ea6..9cb5377 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 4ff9b2d..9f28d70 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 067/127] Bumps minor version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8872a56..46f5d5f 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 068/127] 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 9cb5377..cee8ea6 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 069/127] Adds JWT example to Readme --- README.md | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3ec4ef7..a106d5e 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 070/127] README tweak --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a106d5e..b87ba30 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 071/127] 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 | 6 +++--- setup.py | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/dj_rest_auth/app_settings.py b/dj_rest_auth/app_settings.py index 39e44ef..16c3888 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -36,4 +36,3 @@ PasswordResetConfirmSerializer = serializers.get( 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 f0607b5..0134560 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -407,7 +407,6 @@ class APIBasicTests(TestsMixin, TestCase): @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 @@ class APIBasicTests(TestsMixin, TestCase): ) # 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 @@ class APIBasicTests(TestsMixin, TestCase): 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 @@ class APIBasicTests(TestsMixin, TestCase): 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 @@ class APIBasicTests(TestsMixin, TestCase): 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 7579e83..e2c786e 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -10,10 +10,10 @@ from dj_rest_auth.social_serializers import (TwitterConnectSerializer, 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 rest_framework.views import APIView -from rest_framework.response import Response from rest_framework import permissions +from rest_framework.decorators import api_view +from rest_framework.response import Response +from rest_framework.views import APIView from . import django_urls diff --git a/setup.py b/setup.py index 46f5d5f..da11337 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 072/127] 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 31056de..9394428 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -34,11 +34,9 @@ INSTALLED_APPS = ( '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 6d24967..04b962d 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 42d36bc..405df48 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 82118cc..10eb7cb 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 073/127] 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 04b962d..64a3488 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 074/127] 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 894a44c..84cc2de 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 9394428..c001399 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -43,9 +43,11 @@ INSTALLED_APPS = ( '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 @@ SWAGGER_SETTINGS = { '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 0000000..4d29575 --- /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 0000000..9c40dcd --- /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 0000000..62f4226 --- /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 zcmaKtc{Ei0AIGn;MZ^<@lHD*OV;K7~W1q3jSjJcqNywTkMOhP*k~Oj?GO|6{m(*C2 zC7JA+hN%%Bp7T4;J@?%2_x=5zbI<2~->=X60stMr0B~{wzpi9D0MG|# zyuANt7z6;uz%?PEfAnimLl^)6h5ARwGXemG2>?hqQv-I^Gpyh$JH}Ag92}3{$a#z& zd`il2Sb#$U&e&4#^4R|GTgk!Qs+x*PCL{2+`uB5mqtnqLaaw`*H2oqJ?XF(zUACc2 zSibBrdQzcidqv*TK}rpEv1ie&;Famq2IK5%4c}1Jt2b1x_{y1C!?EU)@`_F)yN*NK z)(u03@%g%uDawwXGAMm%EnP9FgoucUedioDwL~{6RVO@A-Q$+pwVRR%WYR>{K3E&Q zzqzT!EEZ$_NHGYM6&PK#CGUV$pTWsiI5#~m>htoJ!vbc0=gm3H8sz8KzIiVN5xdCT z%;}`UH2Pc8))1VS-unh?v4*H*NIy5On{MRKw7BTmOO9oE2UApwkCl9Z?^dod9M^#w z51tEZhf+#dpTo#GDDy#kuzoIjMjZ?%v*h$ z*vwUMOjGc?R0(FjLWkMD)kca4z6~H45FIzQ!Zzu&-yWyMdCBsDr2`l}Q{8fH$H@O< z$&snNzbqLk?(GIe?!PVh?F~2qk4z^rMcp$P^hw^rUPjyCyoNTRw%;hNOwrCoN?G0E z!wT^=4Loa9@O{t;Wk(Nj=?ms1Z?UN_;21m%sUm?uib=pg&x|u)8pP#l--$;B9l47n zUUnMV0sXLe*@Gvy>XWjRoqc2tOzgYn%?g@Lb8C&WsxV1Kjssh^ZBs*Ysr+E6%tsC_ zCo-)hkYY=Bn?wMB4sqm?WS>{kh<6*DO)vXnQpQ9`-_qF6!#b;3Nf@;#B>e2j$yokl6F|9p1<($2 z=WSr%)Z?^|r6njhgbuMrIN>8JE05u0x5t@_dEfbGn9r0hK4c2vp>(*$GXsjeLL_uz zWpyfUgdv!~-2N;llVzik#s2*XB*%7u8(^sJv&T3pzaR&<9({17Zs~UY>#ugZZkHBs zD+>0_an$?}utGp$dcXtyFHnTQZJ}SF=oZ}X07dz~K>^o(vjTzw8ZQc!Fw1W=&Z?9% zv63|~l}70sJbY?H8ON8j)w5=6OpXuaZ}YT03`2%u8{;B0Vafo_iY7&BiQTbRkdJBYL}?%ATfmc zLG$uXt$@3j#OIjALdT&Ut$=9F8cgV{w_f5eS)PjoVi z&oemp-SKJ~UuGuCP1|iY?J^S&P z)-IG?O-*=z6kfZrX5H*G=aQ{ZaqnOqP@&+_;nq@mA>EcjgxrYX8EK|Iq4&E&rxR?R z8N$QOdRwY zr{P`O)=87>YLHtFfGXW z6P)ucrhj~It_9w<^v5>T6N1U}+BkS))=WX*2JY=}^b2czGhH<`?`(}}qMcpPx_%>M zM|fs(+I1m&_h(zqp-HgP>re$2O^o$q)xu#fl0ivOJE({duU)a*OD(eYgSi^cdTn}pqcPM(;S)2%1By^Wh%-CaC%>d9hi`7J zaxL7@;nhA>PE%s99&;z{8>VFgf{u!(-B-x7Of6ueme+ScryL`h(^qKE)DtieWY>-7 zgB)VJESQS4*1LU(2&@pgLvSt{(((C?K_V(rQk``i&5}ZPG;G^FiPlZ$7|-vEmMWlU z5lQ%iK2nu=h2wd_7>gK@vX=*AG+u~rQP$NwPC`ZA?4nh{3tui1x@bT6-;Rk3yDQ>d z?3qRD#+PeV7#FAa>s`Xwxsx_oRFcN$StW2=CW`=qObsT?SD^#^jM1Yk}PSPxJ zG@-_mnNU_)vM|iLRSI>UMp|hatyS}17R{10IuL0TLlupt>9dRs_SPQbv7BLYyC#qv16E-y@XZ= z-!p7I%#r-BVi$nQq3&ssRc_IC%R6$tA&^s_l46880~Wst3@>(|EO<}T4~ci~#!=e; zD)B>o%1+$ksURD1p7I-<3ehlFyVkqrySf&gg>Bp0Z9?JaG|gyTZ{Cb8SdvAWVmFX7v2ohs!OCc!Udk zUITUpmZ33rKLI#(&lDj}cKA#dpL4Fil=$5pu_wi1XJR!llw` zSItPBDEdMHk2>c7#%lBxZHHvtVUOZ$}v?=?AT~9!Jcqa@IJGuMg(s^7r>pcTrd)pS`{5Cu8WPey` z9)!!OUUY@L%9Q+bZa*S5`3f_|lFCPN6kdp_M2>{le8;cn^XUsPa+TUk47qd6)IBR% zk*&Ip?!Ge_gmmdj)BX}P_5o@VI2*wbZ^>UhFju}0gQZh!pP%4XT9{@w;G#b3XK8sN zF(7i$Jv(IM$8Akys9dhP^^~H2(7BfJp}yDW1#@!CL-!mGcSCnJ599WK9MV@yo_u$v 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 0000000..aa069f2 --- /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 0000000..080d6c7 --- /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 0000000..e9e57dc --- /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 0000000..74b5e05 --- /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 0000000..70fedad --- /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 0000000..4db7ebc --- /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 0000000..ec2585e --- /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 0000000..f5185c1 --- /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 0000000..6b60c10 --- /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 0000000..b04b771 --- /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 0000000..74b1a27 --- /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 64a3488..e9276aa 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 075/127] 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 c001399..4496f0d 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -116,10 +116,14 @@ ACCOUNT_EMAIL_REQUIRED = False 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 @@ SWAGGER_SETTINGS = { } -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 74b5e05..92fd3ac 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 70fedad..a8546a4 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 ec2585e..379ece5 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 076/127] 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 fa4345d..867286f 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 077/127] Updates changelog --- docs/changelog.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 405df48..78186af 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 078/127] 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 ecceddd..6c67fe9 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 079/127] 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 7730562..1f57578 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,7 +44,7 @@ master_doc = 'index' # 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 @@ latex_documents = [ # (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 @@ man_pages = [ # 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 080/127] Fixes docs code sample --- docs/demo.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/demo.rst b/docs/demo.rst index 6c67fe9..b8bc2f1 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 081/127] 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 a4e602a..be3b096 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 082/127] 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 be3b096..c253f7b 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 083/127] 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 c253f7b..614c21e 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 084/127] 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 84cc2de..136132c 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 c5ba7fc..7f2e651 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -11,6 +11,8 @@ from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView 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 @@ class LogoutView(APIView): 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 085/127] 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 7f2e651..365545e 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -142,20 +142,20 @@ class LogoutView(APIView): 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 086/127] 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 614c21e..c253f7b 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 087/127] 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 0134560..f373dcc 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -555,3 +555,14 @@ class APIBasicTests(TestsMixin, TestCase): 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 365545e..c79423f 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -147,18 +147,26 @@ class LogoutView(APIView): 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 088/127] 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 0000000..103ee60 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + coverage run --source=dj_rest_auth setup.py test diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index 3d02309..5f57f91 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -94,6 +94,8 @@ INSTALLED_APPS = [ 'dj_rest_auth', 'dj_rest_auth.registration', + + 'rest_framework_simplejwt.token_blacklist' ] SECRET_KEY = "38dh*skf8sjfhs287dh&^hd8&3hdg*j2&sd" diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index f373dcc..0e5a3c6 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -1,6 +1,7 @@ +import json +from unittest.mock import patch + from allauth.account import app_settings as account_app_settings -from dj_rest_auth.registration.app_settings import register_permission_classes -from dj_rest_auth.registration.views import RegisterView from django.conf import settings from django.contrib.auth import get_user_model from django.core import mail @@ -9,6 +10,8 @@ from django.utils.encoding import force_text from rest_framework import status from rest_framework.test import APIRequestFactory +from dj_rest_auth.registration.app_settings import register_permission_classes +from dj_rest_auth.registration.views import RegisterView from .mixins import CustomPermissionClass, TestsMixin try: @@ -556,6 +559,20 @@ class APIBasicTests(TestsMixin, TestCase): resp = self.get('/protected-view/') self.assertEquals(resp.status_code, 200) + @override_settings(REST_USE_JWT=True) + @patch('rest_framework_simplejwt.tokens.BlacklistMixin.blacklist') + def test_blacklisting_not_installed(self, mocked_blacklist): + mocked_blacklist.side_effect = AttributeError(f"'RefreshToken' object has no attribute 'blacklist'") + payload = { + "username": self.USERNAME, + "password": self.PASS + } + get_user_model().objects.create_user(self.USERNAME, '', self.PASS) + resp = self.post(self.login_url, data=payload, status_code=200) + token = resp.data['refresh_token'] + resp = self.post(self.logout_url, status=200, data={'refresh': token}) + self.assertEqual(resp.status_code, 501) + @override_settings(REST_USE_JWT=True) def test_blacklisting(self): payload = { @@ -563,6 +580,15 @@ class APIBasicTests(TestsMixin, TestCase): "password": self.PASS } get_user_model().objects.create_user(self.USERNAME, '', self.PASS) - self.post(self.login_url, data=payload, status_code=200) + resp = self.post(self.login_url, data=payload, status_code=200) + token = resp.data['refresh_token'] resp = self.post(self.logout_url, status=200) - pass + self.assertEqual(resp.status_code, 401) + resp = self.post(self.logout_url, status=200, data={'refresh': '1'}) + self.assertEqual(resp.status_code, 404) + resp = self.post(self.logout_url, status=200, data={'refresh': token}) + self.assertEqual(resp.status_code, 200) + resp = self.post(self.logout_url, status=200, data={'refresh': token}) + self.assertEqual(resp.status_code, 404) + resp = self.post(self.logout_url, status=200, data=json.dumps({'refresh': token})) + self.assertEqual(resp.status_code, 500) diff --git a/dj_rest_auth/views.py b/dj_rest_auth/views.py index c79423f..f3bb3fe 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -147,25 +147,27 @@ class LogoutView(APIView): try: token = RefreshToken(request.data['refresh']) token.blacklist() - except KeyError: response = Response({"detail": _("Refresh token was not included in request data.")}, status=status.HTTP_401_UNAUTHORIZED) - except TokenError as e: - if hasattr(e, 'args') and 'Token is blacklisted' in e.args: - response = Response({"detail": _("Token is already blacklisted.")}, - status=status.HTTP_404_NOT_FOUND) - else: - raise + except (TokenError, AttributeError, TypeError) as error: + if hasattr(error, 'args'): + if 'Token is blacklisted' in error.args or 'Token is invalid or expired' in error.args: + response = Response({"detail": _(error.args[0])}, + status=status.HTTP_404_NOT_FOUND) + + # warn user blacklist is not enabled + elif "'RefreshToken' object has no attribute 'blacklist'" in error.args: + response = Response({"detail": _("Blacklist is not enabled in INSTALLED_APPS.")}, + status=status.HTTP_501_NOT_IMPLEMENTED) + else: + response = Response({"detail": _("An error has occurred.")}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) - except AttributeError as e: - # warn user blacklist is not enabled - if hasattr(e, 'args') and "'RefreshToken' object has no attribute 'blacklist'" in e.args: - response = Response({"detail": _("Blacklist is not enabled in INSTALLED_APPS.")}, - status=status.HTTP_501_NOT_IMPLEMENTED) else: - raise + response = Response({"detail": _("No attr error has occurred.")}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) return response From 8b284f8adf86b2ff29c49aa4c66aaa26325d67f9 Mon Sep 17 00:00:00 2001 From: Marc LaBelle Date: Thu, 2 Apr 2020 10:07:23 -0400 Subject: [PATCH 089/127] 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 f3bb3fe..f3d6c72 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -166,7 +166,7 @@ class LogoutView(APIView): 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 090/127] 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 3e0132d..efd455e 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -4,6 +4,7 @@ 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.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 @@ class JWTSerializer(serializers.Serializer): 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 091/127] Bumps version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index da11337..f3c7f8c 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 092/127] 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 103ee60..0000000 --- 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 b87ba30..deefdb5 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 093/127] 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 0e5a3c6..4c4de9e 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 @@ class APIBasicTests(TestsMixin, TestCase): 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 @@ class APIBasicTests(TestsMixin, TestCase): 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 f3d6c72..325466e 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -134,19 +134,23 @@ class LogoutView(APIView): 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 @@ class LogoutView(APIView): 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 @@ class LogoutView(APIView): 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 094/127] 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 4c4de9e..c53be66 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -583,13 +583,18 @@ class APIBasicTests(TestsMixin, TestCase): 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 325466e..25ebe31 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -159,7 +159,7 @@ class LogoutView(APIView): 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 095/127] 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 25ebe31..114856b 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -137,6 +137,7 @@ class LogoutView(APIView): 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 096/127] Bumps version for release --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f3c7f8c..6e897fc 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 097/127] 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 114856b..674c9b8 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -11,8 +11,20 @@ from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView 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 098/127] 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 674c9b8..b5fcdb8 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -12,20 +12,6 @@ from rest_framework.permissions import AllowAny, IsAuthenticated 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 @@ class LogoutView(APIView): 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 099/127] 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 d3bfc42..3ff64c6 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -2,6 +2,7 @@ from dj_rest_auth.views import (LoginView, LogoutView, PasswordChangeView, 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 @@ urlpatterns = [ 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 100/127] 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 654c0ae..8410821 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 c841e60..aac74c2 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 101/127] 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 3ff64c6..2fc1694 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -24,6 +24,6 @@ if getattr(settings, 'REST_USE_JWT', True): ) 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 102/127] 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 2fc1694..9c79691 100644 --- a/dj_rest_auth/urls.py +++ b/dj_rest_auth/urls.py @@ -18,7 +18,7 @@ urlpatterns = [ 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 103/127] 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 6e897fc..5885ea9 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 104/127] 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 c253f7b..dc159ce 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 867286f..6a7d83f 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 105/127] 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 16c3888..784a691 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -29,9 +29,9 @@ PasswordResetSerializer = import_callable(serializers.get( '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 106/127] Bumps version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5885ea9..9c98f60 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() 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 107/127] 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 e9577a1..937f327 100644 --- a/dj_rest_auth/registration/views.py +++ b/dj_rest_auth/registration/views.py @@ -52,9 +52,9 @@ class RegisterView(CreateAPIView): '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 108/127] 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 109/127] 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 0000000..d901fa7 --- /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 110/127] 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 111/127] 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 0000000..dd67bed --- /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 1f57578..97831a7 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 @@ copyright = u'2020, @iMerica' # 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 9c98f60..fac004b 100644 --- a/setup.py +++ b/setup.py @@ -10,9 +10,13 @@ long_description = f.read().strip() 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 112/127] 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 0000000..747f5af --- /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 113/127] 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 efd455e..f05d143 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -208,6 +208,9 @@ class PasswordResetConfirmSerializer(serializers.Serializer): 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 @@ class PasswordResetConfirmSerializer(serializers.Serializer): ) 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 114/127] 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 f05d143..16ebebc 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -208,9 +208,6 @@ class PasswordResetConfirmSerializer(serializers.Serializer): 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 @@ class PasswordResetConfirmSerializer(serializers.Serializer): 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 115/127] 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 deefdb5..0430a08 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 dd67bed..5b7a5aa 100644 --- a/dj_rest_auth/__version__.py +++ b/dj_rest_auth/__version__.py @@ -5,4 +5,4 @@ __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 +__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 784a691..fe6e6a2 100644 --- a/dj_rest_auth/app_settings.py +++ b/dj_rest_auth/app_settings.py @@ -33,6 +33,8 @@ PasswordResetConfirmSerializer = import_callable(serializers.get( '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 fc7c92b..7d9d4a0 100644 --- a/dj_rest_auth/registration/serializers.py +++ b/dj_rest_auth/registration/serializers.py @@ -17,7 +17,6 @@ except ImportError: 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 e2c786e..f1796d6 100644 --- a/dj_rest_auth/tests/urls.py +++ b/dj_rest_auth/tests/urls.py @@ -21,7 +21,6 @@ from . import django_urls 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 7cbf3ad..e1ef77a 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -45,7 +45,7 @@ try: 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 b5fcdb8..c968334 100644 --- a/dj_rest_auth/views.py +++ b/dj_rest_auth/views.py @@ -146,7 +146,6 @@ class LogoutView(APIView): 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 0000000..484802b --- /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 116/127] Fixes the Circle CI Link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0430a08..06d9953 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 117/127] 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 16ebebc..302be84 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -5,7 +5,10 @@ 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 _ +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 118/127] 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 302be84..a65f765 100644 --- a/dj_rest_auth/serializers.py +++ b/dj_rest_auth/serializers.py @@ -196,7 +196,7 @@ class PasswordResetSerializer(serializers.Serializer): 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 119/127] 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 6a7d83f..94579ee 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 120/127] 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 0000000..c4e2ae5 --- /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 10eb7cb..2084a26 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 121/127] 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 c4e2ae5..4e7d494 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 2084a26..1d5ac3b 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 122/127] 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 78186af..0000000 --- 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 123/127] 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 0000000..519c59f --- /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 124/127] 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 4e7d494..5b7619a 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 1d5ac3b..00bdad9 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 125/127] 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 00bdad9..3a96902 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 126/127] Fixes docs --- docs/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 3a96902..8569e55 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 127/127] 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 5b7a5aa..c61dbeb 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'