From 3f7035eb686d48efee3e0070c0d55c89023e78b8 Mon Sep 17 00:00:00 2001 From: Antoine d'Otreppe Date: Tue, 14 Feb 2017 13:28:42 +0100 Subject: [PATCH 01/69] Added French translations --- rest_auth/locale/fr/LC_MESSAGES/django.mo | Bin 0 -> 2334 bytes rest_auth/locale/fr/LC_MESSAGES/django.po | 98 ++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 rest_auth/locale/fr/LC_MESSAGES/django.mo create mode 100644 rest_auth/locale/fr/LC_MESSAGES/django.po diff --git a/rest_auth/locale/fr/LC_MESSAGES/django.mo b/rest_auth/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..510118c2e838172b018f6331e0c9a9000d29eb66 GIT binary patch literal 2334 zcma)7OK)366ds_365a&~P(eBvN`dyev0K`ZDymA8K%|6*l2$B=s>!`$dz$MRcOFi{ zs(aQTA%S37BO$S@5Ie8ffy5Rh@(0+l<~wt3*$F~rr15uW=9_cQoR|MNdgyb3@f_w$ zm_K2@jCtb${9yb7JO}(0$md5M6yg~0_y{inpU3(WU=tXDPXX@&UjyC)o&f$1d)llK<0f0d;$0a@Hp^i;7Q?4Rw<1zf=8R7}dXVZ=lPXnLCgt#P+ZH6nv zGnnH66=~qf;&IFwUR|Q-l_Tv*mQKlHmz-*AACyxCZR^mX(7~a~x>A=Ui^3`I>ta#0 zv{6{g9;i3-QhHC?P+zO<@nJ5@a#QA8H=`^6byjL+!hw5Bl@h2kHc($V-O{S4ixrbw z=Tsgbr58h;WS+x{o55}=L)KAl3&l@x>UPvHeELdXmQjhd==pYDMlfrNA5$Y~3aa&B z`L=aMt$u*SelfDE?!!~?5gb^X&|%PjY4|{G(^w&Oq^C`V7kJrco7YE{Ob*~{6~<9e zWTtLU(JR&{LKC6zZ(V#8ldD>>EO)82?KYxn;X<*|Q53fA#2UD|EIbvuFed_aWym{q zam~oh5=6^)Iff}Cdd~KB0ZBQ04K-SpNQrBlM~IA#2CimFo-gBJ*O3&w!%;0#;uNQn zV$y-&1c?Bepmq>*=`>#wc1x@~dkZnoR*LMpa$Z|APcv6l&$^JU`L-^ycVpXU8y4H^ zS2nWCNZ$ZfwkU&|r{-+qT-Io2%_cP(^JmUyvvaevAZAxpU$e9c4`gu>8^v&-xF($J4(|q(1Xp|2HGG{`N@~d%(i^6F2P?CYce#UL zH7#KxKrC9gGIbB9n4P@CmrDyht zk2F9v8)TR@q*^VMa71jXB=cxT!@Fn}s|Zk`;tt!yUzNdV5sEx&D}}cNr#t+vtH4LW zjYR5h&w8)9Ev39=mNqR^P%_X{%SLB3U&51f+r=N${@jOCkoaEaL06uU>~(HZ93xII g_8TV{Xq^74>Q<-$q&oWbxJ!-OR#YWg)|D;s4@F(t%>V!Z literal 0 HcmV?d00001 diff --git a/rest_auth/locale/fr/LC_MESSAGES/django.po b/rest_auth/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..b1e97d3 --- /dev/null +++ b/rest_auth/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# 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: 2016-12-22 11:37-0800\n" +"PO-Revision-Date: 2017-02-14 13:27+0100\n" +"Language: fr\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 1.8.11\n" + +#: registration/serializers.py:53 +msgid "View is not defined, pass it as a context variable" +msgstr "La “View” n’est pas définie, passez la en variable contextuelle" + +#: registration/serializers.py:58 +msgid "Define adapter_class in view" +msgstr "Définissez “adapter_class” dans la vue" + +#: registration/serializers.py:77 +msgid "Define callback_url in view" +msgstr "Définissez “callback_url” dans la vue" + +#: registration/serializers.py:81 +msgid "Define client_class in view" +msgstr "Définissez “client_class” dans la vue" + +#: registration/serializers.py:102 +msgid "Incorrect input. access_token or code is required." +msgstr "Paramètres incorrects. Il faut “access_token” ou “code”." + +#: registration/serializers.py:111 +msgid "Incorrect value" +msgstr "Paramètre incorrect" + +#: registration/serializers.py:140 +msgid "A user is already registered with this e-mail address." +msgstr "Un utilisateur existe déjà avec cette adresse email." + +#: registration/serializers.py:148 +msgid "The two password fields didn't match." +msgstr "Les deux mots de passes ne sont pas les mêmes." + +#: registration/views.py:82 +msgid "ok" +msgstr "Ok" + +#: serializers.py:30 +msgid "Must include \"email\" and \"password\"." +msgstr "Doit inclure “email” et “password”." + +#: serializers.py:41 +msgid "Must include \"username\" and \"password\"." +msgstr "Doit inclure “username” et “password”." + +#: serializers.py:54 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Doit inclure un “username” ou “email”, et un “password”." + +#: serializers.py:95 +msgid "User account is disabled." +msgstr "Le compte utilisateur est désactivé." + +#: serializers.py:98 +msgid "Unable to log in with provided credentials." +msgstr "Connexion impossible avec les informations fournies." + +#: serializers.py:107 +msgid "E-mail is not verified." +msgstr "L’adresse email n’a pas été vérifiée." + +#: views.py:114 +msgid "Successfully logged out." +msgstr "Déconnexion effectuée avec succès." + +#: views.py:162 +msgid "Password reset e-mail has been sent." +msgstr "L’email de réinitialisation du mot de passe a été envoyé." + +#: views.py:184 +msgid "Password has been reset with the new password." +msgstr "Le mot de passe a été réinitialisé." + +#: views.py:202 +msgid "New password has been saved." +msgstr "Le nouveau mot de passe est sauvé." + +#~ msgid "Error" +#~ msgstr "Fehler" From 50325ddb4fd0b1685631cf873987a606290d5d20 Mon Sep 17 00:00:00 2001 From: mpuhacz Date: Sat, 11 Mar 2017 12:10:55 +0100 Subject: [PATCH 02/69] polish translation --- rest_auth/locale/pl/pl.mo | Bin 0 -> 2306 bytes rest_auth/locale/pl/pl.po | 99 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 rest_auth/locale/pl/pl.mo create mode 100644 rest_auth/locale/pl/pl.po diff --git a/rest_auth/locale/pl/pl.mo b/rest_auth/locale/pl/pl.mo new file mode 100644 index 0000000000000000000000000000000000000000..bee2ff6f01bcb23f7c53085c80cf425d27f6b7fc GIT binary patch literal 2306 zcmb7_&u<$=6vr1Rzs&DKp+G?oi>8Ufn%$JN!HGeoNlOGtLrDta5>0j|_QdNMGc%jT zR!@;a?-e~%{S&xyK!`&Rj)b^#;DX@9iNB$IXKdGQphB$l^4amc_vX!eZ(n{pdgMlc z=NRM!qz8Eol0ASwczy@ZfPa8)|M-JJ@G3Yv;3wcqShv6#a36dI{2qK0{0Te-{sq1Z z9($=hWkr7K%&5fx9 zi+o#1jx}pTbu-DBF(f4I3SJC16P9ILENO1$I{U|7Cb+bR?3Vh6;5ex)?Q$))1y3u% zvP_iLJhAZ7&TWNQk|2srtD0Pr(v+x_yDMn^WiAl-xXCWdavrSY##tv>4$U%mmnjpI zDV5uZyihtVR}Lw;yhzsK|Dnf`BP6gqQb$1dJ7JXDx@%2Z*a1O8byOtXQ`o7r1F%d z7PCpC5^PAel|fNCTUSHh5pAt@MG8*|a*bmI%g_=Vu8&X|l}n`Bc{0uz7rWvsnJ_Dq z9CniN;ax$yI9*ro)VEanmJf-9C8UR;w9@jg&<#ur=PppqU`?wXbVInDhH!1*wMwPS zysfkiS4>@`;Rku$gzE}FuU%RX&!e&3+2JCyyh<}sd^U_uhtVv}#MRj|VKf&-Pz*2g zUE#bP(u-q?XR2{D9mUXFSzcKh9UE7o(s>u6wBdTE4eu`6x7!&La-Na~)2Lu=WBo!n zH`3Egnr*JbCG>SFWW7prTf&ysvRtz)yr6W;R7tk|($r4RQ~$L#DQmTu-lvGLeKL;T ztIg2FgnwPAz2jad-OtfN9MRRQ{&%MnO~EFH&CJw%>0>7AIji$U40`B8asRILl^glK9sQ?KQ>%Ou-Q*pmog!n0tHJIW+^&1?>l5eGo%3*@=5%xgOT9OaXs&w zkxRMD6=s99ouunL`&{=^?7R+a1oMh87~~R~AK^1n_a, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-05 21:56-0800\n" +"PO-Revision-Date: 2017-03-11 12:10+0100\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Language-Team: \n" +"X-Generator: Poedit 1.8.11\n" +"Last-Translator: \n" +"Language: pl\n" + +#: registration/serializers.py:53 +msgid "View is not defined, pass it as a context variable" +msgstr "Widok nie został zdefiniowany, przekaż go przez zmienną \"context\"" + +#: registration/serializers.py:58 +msgid "Define adapter_class in view" +msgstr "Zdefiniuj \"adapter_class\" w widoku" + +#: registration/serializers.py:77 +msgid "Define callback_url in view" +msgstr "Zdefiniuj \"callback_url\" w widoku" + +#: registration/serializers.py:81 +msgid "Define client_class in view" +msgstr "Zdefiniuj \"client_class\" w widoku" + +#: registration/serializers.py:102 +msgid "Incorrect input. access_token or code is required." +msgstr "Podano błędne dane. \"access_token\" lub \"code\" są wymagne." + +#: registration/serializers.py:111 +msgid "Incorrect value" +msgstr "Niepoprawna wartość." + +#: registration/serializers.py:140 +msgid "A user is already registered with this e-mail address." +msgstr "Istnieje już użytkownik z takim adresem email." + +#: registration/serializers.py:148 +msgid "The two password fields didn't match." +msgstr "Hasła nie są identyczne." + +#: registration/views.py:44 +msgid "Verification e-mail sent." +msgstr "Email weryfikacyjny został wysłany." + +#: registration/views.py:91 +msgid "ok" +msgstr "ok" + +#: serializers.py:30 +msgid "Must include \"email\" and \"password\"." +msgstr "Musisz podać email i hasło." + +#: serializers.py:41 +msgid "Must include \"username\" and \"password\"." +msgstr "Musisz podać nazwę użytkownika i hasło." + +#: serializers.py:54 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Musisz podać nazwę użytkownika (lub email) i hasło." + +#: serializers.py:95 +msgid "User account is disabled." +msgstr "Konto użytkownika zostało wyłączone." + +#: serializers.py:98 +msgid "Unable to log in with provided credentials." +msgstr "Podane dane do logowania są niepoprawne." + +#: serializers.py:107 +msgid "E-mail is not verified." +msgstr "Email nie został zweryfikowany." + +#: views.py:126 +msgid "Successfully logged out." +msgstr "Wylogowano." + +#: views.py:174 +msgid "Password reset e-mail has been sent." +msgstr "Email z linkiem do resetu hasła został wysłany." + +#: views.py:200 +msgid "Password has been reset with the new password." +msgstr "Hasło zostało zresetowane." + +#: views.py:222 +msgid "New password has been saved." +msgstr "Nowe hasło zostało zapisane." From d0d348bf6b12474f1771b793ec821492ad0db1b6 Mon Sep 17 00:00:00 2001 From: mpuhacz Date: Sat, 11 Mar 2017 12:33:25 +0100 Subject: [PATCH 03/69] polish translation --- rest_auth/locale/pl/{ => LC_MESSAGES}/pl.mo | Bin rest_auth/locale/pl/{ => LC_MESSAGES}/pl.po | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename rest_auth/locale/pl/{ => LC_MESSAGES}/pl.mo (100%) rename rest_auth/locale/pl/{ => LC_MESSAGES}/pl.po (100%) diff --git a/rest_auth/locale/pl/pl.mo b/rest_auth/locale/pl/LC_MESSAGES/pl.mo similarity index 100% rename from rest_auth/locale/pl/pl.mo rename to rest_auth/locale/pl/LC_MESSAGES/pl.mo diff --git a/rest_auth/locale/pl/pl.po b/rest_auth/locale/pl/LC_MESSAGES/pl.po similarity index 100% rename from rest_auth/locale/pl/pl.po rename to rest_auth/locale/pl/LC_MESSAGES/pl.po From bf96f6ab8e397586aba74982c71917357e9765bc Mon Sep 17 00:00:00 2001 From: mpuhacz Date: Sat, 11 Mar 2017 15:50:27 +0100 Subject: [PATCH 04/69] polish translation --- .../locale/pl/LC_MESSAGES/{pl.mo => django.mo} | Bin .../locale/pl/LC_MESSAGES/{pl.po => django.po} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename rest_auth/locale/pl/LC_MESSAGES/{pl.mo => django.mo} (100%) rename rest_auth/locale/pl/LC_MESSAGES/{pl.po => django.po} (100%) diff --git a/rest_auth/locale/pl/LC_MESSAGES/pl.mo b/rest_auth/locale/pl/LC_MESSAGES/django.mo similarity index 100% rename from rest_auth/locale/pl/LC_MESSAGES/pl.mo rename to rest_auth/locale/pl/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/pl/LC_MESSAGES/pl.po b/rest_auth/locale/pl/LC_MESSAGES/django.po similarity index 100% rename from rest_auth/locale/pl/LC_MESSAGES/pl.po rename to rest_auth/locale/pl/LC_MESSAGES/django.po From 052094d43cd42f76aef1c781a9cb4e178361bad7 Mon Sep 17 00:00:00 2001 From: Vladislav Manchev Date: Wed, 26 Apr 2017 23:20:10 +0200 Subject: [PATCH 05/69] Pass context to user defined USER_DETAILS_SERIALIZER --- rest_auth/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/serializers.py b/rest_auth/serializers.py index 723cfca..e592dfc 100644 --- a/rest_auth/serializers.py +++ b/rest_auth/serializers.py @@ -146,7 +146,7 @@ class JWTSerializer(serializers.Serializer): JWTUserDetailsSerializer = import_callable( rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer) ) - user_data = JWTUserDetailsSerializer(obj['user']).data + user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data return user_data From cbda9ee075a3ea916dc26a76215f489919bc51bd Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Mon, 15 May 2017 10:36:19 -0400 Subject: [PATCH 06/69] Add Django 1.11 to Travis CI --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b4f050..ce9529d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,9 @@ python: - "2.7" - "3.5" env: - - DJANGO=1.8.17 - - DJANGO=1.9.12 - - DJANGO=1.10.4 + - DJANGO=1.8.18 + - DJANGO=1.10.7 + - DJANGO=1.11.1 install: - pip install -q Django==$DJANGO - pip install coveralls From 937162bd9709be2ab3aaaadd5a1abb05a77e5e2e Mon Sep 17 00:00:00 2001 From: Nathanael Gordon Date: Wed, 17 May 2017 23:36:09 +1000 Subject: [PATCH 07/69] Fix docs settings typo --- docs/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index 1f5b40f..59b301f 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -36,7 +36,7 @@ Configuration You can define your custom serializers for registration endpoint. Possible key values: - - REGISTER_SERIALIZER - serializer class in ``rest_auth.register.views.RegisterView``, default value ``rest_auth.registration.serializers.RegisterSerializer`` + - REGISTER_SERIALIZER - serializer class in ``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 From 90219295a48bc29393a6232fdd295e47903fd737 Mon Sep 17 00:00:00 2001 From: Jacob Rief Date: Tue, 30 May 2017 09:26:16 +0200 Subject: [PATCH 08/69] return user object from upstream method invocation --- rest_auth/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/serializers.py b/rest_auth/serializers.py index 723cfca..ca34ccd 100644 --- a/rest_auth/serializers.py +++ b/rest_auth/serializers.py @@ -220,7 +220,7 @@ class PasswordResetConfirmSerializer(serializers.Serializer): return attrs def save(self): - self.set_password_form.save() + return self.set_password_form.save() class PasswordChangeSerializer(serializers.Serializer): From 8981317b1c94eb3dc713122959b3469212b3720f Mon Sep 17 00:00:00 2001 From: Daniel Vitiello Date: Sun, 4 Jun 2017 16:54:03 -0500 Subject: [PATCH 09/69] Add step to remind user to migrate their database I didn't do this and spent a while tracking down errors with CSRF and Token Validation. --- docs/installation.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/installation.rst b/docs/installation.rst index 6144011..7508cd0 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -31,7 +31,13 @@ Installation url(r'^rest-auth/', include('rest_auth.urls')) ) +4. Migrate your database +.. code-block:: python + + python manage.py migrate + + You're good to go now! From f0175b4aac31cf47d8d5a5cbf170e0068e74a429 Mon Sep 17 00:00:00 2001 From: David Gunter Date: Thu, 15 Jun 2017 16:30:21 -0700 Subject: [PATCH 10/69] Update JWT Support documentation to explain how the library uses django-rest-framework-jwt to handle token encoding. --- docs/installation.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 7508cd0..d4edbd3 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -157,13 +157,15 @@ If you are using Twitter for your social authentication, it is a bit different s JWT Support (optional) ---------------------- -By default, ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, you need to install the following: +By default ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, follow these steps: -1. Install ``django-rest-framework-jwt`` http://getblimp.github.io/django-rest-framework-jwt/ . Right now this is the only supported JWT library. +1. Install `django-rest-framework-jwt `_ + - ``django-rest-framework-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. -2. Add the following to your settings +3. Add the following configuration value to your settings file to enable JWT authentication. .. code-block:: python - REST_USE_JWT = True - + REST_USE_JWT = True \ No newline at end of file From 98306a35c1fd4648f1eb724530164d55c2282862 Mon Sep 17 00:00:00 2001 From: bIgBV Date: Sat, 24 Jun 2017 18:50:50 +0530 Subject: [PATCH 11/69] Pass request in the context when initializing `LoginSerializer` --- rest_auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/views.py b/rest_auth/views.py index 0493a76..05d5488 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -88,7 +88,7 @@ class LoginView(GenericAPIView): def post(self, request, *args, **kwargs): self.request = request - self.serializer = self.get_serializer(data=self.request.data) + self.serializer = self.get_serializer(data=self.request.data, context={'request': request}) self.serializer.is_valid(raise_exception=True) self.login() From 6da0703b0daefcc1d569027b5d5862bda86c5ee0 Mon Sep 17 00:00:00 2001 From: Grigoriy Beziuk Date: Fri, 30 Jun 2017 13:59:10 +0300 Subject: [PATCH 12/69] LoginView.get_response modified in order to respect rest_framework_jwt.JWT_AUTH_COOKIE setting --- rest_auth/views.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rest_auth/views.py b/rest_auth/views.py index 0493a76..290c837 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -84,7 +84,17 @@ class LoginView(GenericAPIView): serializer = serializer_class(instance=self.token, context={'request': self.request}) - return Response(serializer.data, status=status.HTTP_200_OK) + 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): self.request = request From 46fd16700a9e64fc23d843a9c3ff8c1798d60cd0 Mon Sep 17 00:00:00 2001 From: Grigoriy Beziuk Date: Fri, 30 Jun 2017 14:23:56 +0300 Subject: [PATCH 13/69] also for cookie deletion --- rest_auth/views.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rest_auth/views.py b/rest_auth/views.py index 290c837..20175b0 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -133,8 +133,13 @@ class LogoutView(APIView): django_logout(request) - return Response({"detail": _("Successfully logged out.")}, - status=status.HTTP_200_OK) + 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 class UserDetailsView(RetrieveUpdateAPIView): From 99b68b29145778bdff469f7b73d837c3087d6841 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Mon, 2 Oct 2017 18:46:47 +0300 Subject: [PATCH 14/69] Updates README.rst with svg badges --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 9014187..ac7f19e 100644 --- a/README.rst +++ b/README.rst @@ -1,11 +1,11 @@ Welcome to django-rest-auth =========================== -.. image:: https://travis-ci.org/Tivix/django-rest-auth.png +.. image:: https://travis-ci.org/Tivix/django-rest-auth.svg :target: https://travis-ci.org/Tivix/django-rest-auth -.. image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.png +.. image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.svg :target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master @@ -28,4 +28,4 @@ https://github.com/Tivix/django-rest-auth Stack Overflow ----------- -http://stackoverflow.com/questions/tagged/django-rest-auth \ No newline at end of file +http://stackoverflow.com/questions/tagged/django-rest-auth From 7a0fa017d3ac3a6cabfe8796a4331400592223be Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Mon, 2 Oct 2017 12:31:02 -0400 Subject: [PATCH 15/69] Add MANIFEST.in change from #335 to master branch --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index a24b46a..01a589f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,3 +2,4 @@ include AUTHORS include LICENSE include MANIFEST.in include README.md +graft rest_auth From 30c89b1cc69c846976626d4ac4b08855fd3a372d Mon Sep 17 00:00:00 2001 From: mario Date: Mon, 2 Oct 2017 21:38:06 +0200 Subject: [PATCH 16/69] chore: added new test case for custom permission classes + general test module cleanups --- rest_auth/tests/{test_base.py => mixins.py} | 33 ++++++--------------- rest_auth/tests/test_api.py | 25 ++++++++++++++-- rest_auth/tests/test_social.py | 4 +-- 3 files changed, 33 insertions(+), 29 deletions(-) rename rest_auth/tests/{test_base.py => mixins.py} (78%) diff --git a/rest_auth/tests/test_base.py b/rest_auth/tests/mixins.py similarity index 78% rename from rest_auth/tests/test_base.py rename to rest_auth/tests/mixins.py index 48d94f0..437f458 100644 --- a/rest_auth/tests/test_base.py +++ b/rest_auth/tests/mixins.py @@ -6,6 +6,14 @@ from django.test.client import Client, MULTIPART_CONTENT from django.utils.encoding import force_text from rest_framework import status +from rest_framework import permissions + + +class CustomPermissionClass(permissions.BasePermission): + message = 'You shall not pass!' + + def has_permission(self, request, view): + return False class APIClient(Client): @@ -17,7 +25,7 @@ class APIClient(Client): return self.generic('OPTIONS', path, data, content_type, **extra) -class BaseAPITestCase(object): +class TestsMixin(object): """ base for API tests: @@ -64,29 +72,6 @@ class BaseAPITestCase(object): def patch(self, *args, **kwargs): return self.send_request('patch', *args, **kwargs) - # def put(self, *args, **kwargs): - # return self.send_request('put', *args, **kwargs) - - # def delete(self, *args, **kwargs): - # return self.send_request('delete', *args, **kwargs) - - # def options(self, *args, **kwargs): - # return self.send_request('options', *args, **kwargs) - - # def post_file(self, *args, **kwargs): - # kwargs['content_type'] = MULTIPART_CONTENT - # return self.send_request('post', *args, **kwargs) - - # def get_file(self, *args, **kwargs): - # content_type = None - # if 'content_type' in kwargs: - # content_type = kwargs.pop('content_type') - # response = self.send_request('get', *args, **kwargs) - # if content_type: - # self.assertEqual( - # bool(filter(lambda x: content_type in x, response._headers['content-type'])), True) - # return response - def init(self): settings.DEBUG = True self.client = APIClient() diff --git a/rest_auth/tests/test_api.py b/rest_auth/tests/test_api.py index 0356d19..d33635c 100644 --- a/rest_auth/tests/test_api.py +++ b/rest_auth/tests/test_api.py @@ -5,13 +5,18 @@ from django.core import mail from django.conf import settings from django.utils.encoding import force_text -from rest_framework import status from allauth.account import app_settings as account_app_settings -from .test_base import BaseAPITestCase +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 .mixins import TestsMixin, CustomPermissionClass @override_settings(ROOT_URLCONF="tests.urls") -class APITestCase1(TestCase, BaseAPITestCase): +class APIBasicTests(TestsMixin, TestCase): """ Case #1: - user profile: defined @@ -398,6 +403,20 @@ class APITestCase1(TestCase, BaseAPITestCase): 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() diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index 47ac0bb..dff6438 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -11,11 +11,11 @@ import responses from rest_framework import status -from .test_base import BaseAPITestCase +from .mixins import TestsMixin @override_settings(ROOT_URLCONF="tests.urls") -class TestSocialAuth(TestCase, BaseAPITestCase): +class TestSocialAuth(TestsMixin, TestCase): USERNAME = 'person' PASS = 'person' From 7e708d9ca770f7f135e01277aef7fe313fd034f1 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Mon, 2 Oct 2017 15:52:33 -0400 Subject: [PATCH 17/69] Update configs and changelog for version 0.9.2 --- demo/requirements.pip | 2 +- docs/changelog.rst | 6 ++++++ rest_auth/views.py | 3 ++- setup.py | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 2fd3e39..b6c8a77 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.8.0 -django-rest-auth==0.9.1 +django-rest-auth==0.9.2 djangorestframework==3.5.1 django-allauth>=0.24.1 six==1.9.0 diff --git a/docs/changelog.rst b/docs/changelog.rst index ff2f542..bf88fc8 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,12 @@ Changelog ========= +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 rest_auth serializers diff --git a/rest_auth/views.py b/rest_auth/views.py index 05d5488..58b5b29 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -88,7 +88,8 @@ class LoginView(GenericAPIView): def post(self, request, *args, **kwargs): self.request = request - self.serializer = self.get_serializer(data=self.request.data, context={'request': request}) + self.serializer = self.get_serializer(data=self.request.data, + context={'request': request}) self.serializer.is_valid(raise_exception=True) self.login() diff --git a/setup.py b/setup.py index 84ed034..d78a8b5 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ f.close() setup( name='django-rest-auth', - version='0.9.1', + version='0.9.2', author='Sumit Chachra', author_email='chachra@tivix.com', url='http://github.com/Tivix/django-rest-auth', From 42d039b473bc18080d58656f50f379005cd70499 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Tue, 3 Oct 2017 10:17:48 -0400 Subject: [PATCH 18/69] Fix urlpatterns format in docs --- docs/installation.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index d4edbd3..fd09cd7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -26,10 +26,10 @@ Installation .. code-block:: python - urlpatterns = patterns('', + urlpatterns = [ ..., url(r'^rest-auth/', include('rest_auth.urls')) - ) + ] 4. Migrate your database @@ -66,11 +66,11 @@ Registration (optional) .. code-block:: python - urlpatterns = patterns('', + urlpatterns = [ ..., url(r'^rest-auth/', include('rest_auth.urls')), url(r'^rest-auth/registration/', include('rest_auth.registration.urls')) - ) + ] Social Authentication (optional) @@ -120,10 +120,10 @@ Facebook .. code-block:: python - urlpatterns += patterns('', + urlpatterns += [ ..., url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login') - ) + ] Twitter @@ -147,10 +147,10 @@ If you are using Twitter for your social authentication, it is a bit different s .. code-block:: python - urlpatterns += patterns('', + urlpatterns += [ ..., url(r'^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. From 945008d326bdbed6b85d69a0aaf184157cfd741f Mon Sep 17 00:00:00 2001 From: Philippe Luickx Date: Thu, 5 Oct 2017 12:06:05 +0300 Subject: [PATCH 19/69] Checking for pre-existing accounts from a different flow when using social connect --- rest_auth/registration/serializers.py | 15 +++++++++++++++ rest_auth/tests/requirements.pip | 1 + rest_auth/tests/test_social.py | 8 ++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index c6b5d5b..61f82dc 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,6 +1,7 @@ from django.http import HttpRequest from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth import get_user_model try: from allauth.account import app_settings as allauth_settings @@ -111,6 +112,20 @@ class SocialLoginSerializer(serializers.Serializer): raise serializers.ValidationError(_('Incorrect value')) if not login.is_existing: + # We have an account already signed up in a different flow + # with the same email address: raise an exception. + # This needs to be handled in the frontend. We can not just + # link up the accounts due to security constraints + if(allauth_settings.UNIQUE_EMAIL): + # Do we have an account already with this email address? + existing_account = get_user_model().objects.filter( + email=login.user.email, + ).count() + if(existing_account != 0): + # There is an account already + raise serializers.ValidationError( + _("A user is already registered with this e-mail address.")) + login.lookup() login.save(request, connect=True) attrs['user'] = login.account.user diff --git a/rest_auth/tests/requirements.pip b/rest_auth/tests/requirements.pip index 5a30385..f48ee3c 100644 --- a/rest_auth/tests/requirements.pip +++ b/rest_auth/tests/requirements.pip @@ -2,3 +2,4 @@ django-allauth>=0.25.0 responses>=0.3.0 flake8==2.4.0 djangorestframework-jwt>=1.7.2 +djangorestframework>=3.6.4 diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index dff6438..9b2ae55 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -275,8 +275,12 @@ class TestSocialAuth(TestsMixin, TestCase): 'access_token': 'abc123' } - self.post(self.fb_login_url, data=payload, status_code=200) - self.assertIn('key', self.response.json.keys()) + # You should not have access to an account created through register + # by loging in through FB with an account that has the same + # email address. + self.post(self.fb_login_url, data=payload, status_code=400) + # self.post(self.fb_login_url, data=payload, status_code=200) + # self.assertIn('key', self.response.json.keys()) @responses.activate @override_settings( From 05e5c647faca2aa5d1272ba0a989e578495a351c Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Tue, 24 Oct 2017 19:51:45 -0400 Subject: [PATCH 20/69] Test against Python 3.6 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ce9529d..04b7274 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: python python: - "2.7" - "3.5" + - "3.6" env: - DJANGO=1.8.18 - DJANGO=1.10.7 From b34250ec94fa13bfcac1fc21ff1dcbb3fd84c052 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Tue, 24 Oct 2017 20:14:12 -0400 Subject: [PATCH 21/69] Handle extra args and kwargs in all POST endpoints This fixes compatibility with DRF's versioning --- rest_auth/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rest_auth/views.py b/rest_auth/views.py index 58b5b29..8efcdd5 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -113,7 +113,7 @@ class LogoutView(APIView): return self.finalize_response(request, response, *args, **kwargs) - def post(self, request): + def post(self, request, *args, **kwargs): return self.logout(request) def logout(self, request): @@ -193,7 +193,7 @@ class PasswordResetConfirmView(GenericAPIView): def dispatch(self, *args, **kwargs): return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs) - def post(self, request): + def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() @@ -216,7 +216,7 @@ class PasswordChangeView(GenericAPIView): def dispatch(self, *args, **kwargs): return super(PasswordChangeView, self).dispatch(*args, **kwargs) - def post(self, request): + def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() From be2ac99a342c2676f8ed249097531d01d27a885b Mon Sep 17 00:00:00 2001 From: mario Date: Tue, 31 Oct 2017 16:34:29 +0100 Subject: [PATCH 22/69] fix: changed travis.yml and setup.py configuration --- .travis.yml | 8 ++++---- setup.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index ce9529d..02ab3ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,11 @@ python: - "2.7" - "3.5" env: - - DJANGO=1.8.18 - - DJANGO=1.10.7 - - DJANGO=1.11.1 + - DJANGO=1.8.* DRF=3.6.* + - DJANGO=1.10.* DRF=3.7.* + - DJANGO=1.11.* DRF=3.7.* install: - - pip install -q Django==$DJANGO + - pip install -q Django==$DJANGO djangorestframework==$DRF - pip install coveralls - pip install -r rest_auth/tests/requirements.pip script: diff --git a/setup.py b/setup.py index d78a8b5..c3438cf 100644 --- a/setup.py +++ b/setup.py @@ -28,8 +28,8 @@ setup( keywords='django rest auth registration rest-framework django-registration api', zip_safe=False, install_requires=[ - 'Django>=1.8.0', - 'djangorestframework>=3.1.0', + 'Django==1.8.0', + 'djangorestframework==3.1.3', 'six>=1.9.0', ], extras_require={ From 2c1649daf166b0e9e656fad34048454e4d64a436 Mon Sep 17 00:00:00 2001 From: mario Date: Tue, 31 Oct 2017 17:13:57 +0100 Subject: [PATCH 23/69] fix: revert setup.py changes --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c3438cf..b3aa55b 100644 --- a/setup.py +++ b/setup.py @@ -28,8 +28,8 @@ setup( keywords='django rest auth registration rest-framework django-registration api', zip_safe=False, install_requires=[ - 'Django==1.8.0', - 'djangorestframework==3.1.3', + 'Django>=1.8.0', + 'djangorestframework>=3.1.3', 'six>=1.9.0', ], extras_require={ From f89471f980304b1c66c7a92fded22acbb64919a0 Mon Sep 17 00:00:00 2001 From: mario Date: Sun, 12 Nov 2017 10:32:27 +0100 Subject: [PATCH 24/69] pep8 cleanups --- rest_auth/registration/serializers.py | 13 +++++++------ rest_auth/tests/test_social.py | 11 ++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index 61f82dc..b2e9d51 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -116,18 +116,19 @@ class SocialLoginSerializer(serializers.Serializer): # with the same email address: raise an exception. # This needs to be handled in the frontend. We can not just # link up the accounts due to security constraints - if(allauth_settings.UNIQUE_EMAIL): + if allauth_settings.UNIQUE_EMAIL: # Do we have an account already with this email address? - existing_account = get_user_model().objects.filter( + account_exists = get_user_model().objects.filter( email=login.user.email, - ).count() - if(existing_account != 0): - # There is an account already + ).exists() + if account_exists: raise serializers.ValidationError( - _("A user is already registered with this e-mail address.")) + _("User is already registered with this e-mail address.") + ) login.lookup() login.save(request, connect=True) + attrs['user'] = login.account.user return attrs diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index 9b2ae55..e6eca03 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -225,7 +225,7 @@ class TestSocialAuth(TestsMixin, TestCase): REST_SESSION_LOGIN=False, ACCOUNT_EMAIL_CONFIRMATION_HMAC=False ) - def test_edge_case(self): + def test_email_clash_with_existing_account(self): resp_body = { "id": "123123123123", "first_name": "John", @@ -251,6 +251,8 @@ class TestSocialAuth(TestsMixin, TestCase): # test empty payload self.post(self.register_url, data={}, status_code=400) + + # register user and send email confirmation self.post( self.register_url, data=self.REGISTRATION_DATA, @@ -271,16 +273,11 @@ class TestSocialAuth(TestsMixin, TestCase): self._login() self._logout() + # fb log in with already existing email payload = { 'access_token': 'abc123' } - - # You should not have access to an account created through register - # by loging in through FB with an account that has the same - # email address. self.post(self.fb_login_url, data=payload, status_code=400) - # self.post(self.fb_login_url, data=payload, status_code=200) - # self.assertIn('key', self.response.json.keys()) @responses.activate @override_settings( From 8bd8d604ff886f37e87fcc2f9367a672c92098e0 Mon Sep 17 00:00:00 2001 From: Nic Ducheneaut Date: Sat, 25 Nov 2017 14:10:44 -0800 Subject: [PATCH 25/69] Prevent double-validation in LoginSerializer Modified branching statement to prevent double-validation when using "email" as the authentication method with Allauth. --- rest_auth/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/serializers.py b/rest_auth/serializers.py index c5dad7d..45729b2 100644 --- a/rest_auth/serializers.py +++ b/rest_auth/serializers.py @@ -71,7 +71,7 @@ class LoginSerializer(serializers.Serializer): user = self._validate_email(email, password) # Authentication through username - if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME: + elif app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME: user = self._validate_username(username, password) # Authentication through either username or email From 864aa60f924e168ff726bf7dc628bdaf9e60a5d2 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 4 Dec 2017 13:42:14 +0000 Subject: [PATCH 26/69] Run tests against Django 2.0 https://www.djangoproject.com/weblog/2017/dec/02/django-20-released/ --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index f1156b1..8470da1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ env: - DJANGO=1.8.* DRF=3.6.* - DJANGO=1.10.* DRF=3.7.* - DJANGO=1.11.* DRF=3.7.* + - DJANGO=2.0.* DRF=3.7.* install: - pip install -q Django==$DJANGO djangorestframework==$DRF - pip install coveralls @@ -17,3 +18,7 @@ after_success: - coveralls before_script: - flake8 . --config=flake8 +matrix: + exclude: + - python: "2.7" + env: DJANGO=2.0.* DRF=3.7.* From 3a2a25682114aa6486c8f10f9069a1812c2fb63d Mon Sep 17 00:00:00 2001 From: Michael K Date: Mon, 4 Dec 2017 14:52:58 +0100 Subject: [PATCH 27/69] Fixes import path for django's reverse --- rest_auth/tests/mixins.py | 6 +++++- rest_auth/tests/test_api.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/rest_auth/tests/mixins.py b/rest_auth/tests/mixins.py index 437f458..91f0001 100644 --- a/rest_auth/tests/mixins.py +++ b/rest_auth/tests/mixins.py @@ -1,7 +1,6 @@ import json from django.conf import settings -from django.core.urlresolvers import reverse from django.test.client import Client, MULTIPART_CONTENT from django.utils.encoding import force_text @@ -15,6 +14,11 @@ class CustomPermissionClass(permissions.BasePermission): def has_permission(self, request, view): return False +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse + class APIClient(Client): diff --git a/rest_auth/tests/test_api.py b/rest_auth/tests/test_api.py index d33635c..9c5fd9e 100644 --- a/rest_auth/tests/test_api.py +++ b/rest_auth/tests/test_api.py @@ -1,4 +1,3 @@ -from django.core.urlresolvers import reverse from django.test import TestCase, override_settings from django.contrib.auth import get_user_model from django.core import mail @@ -14,6 +13,11 @@ from rest_auth.registration.app_settings import register_permission_classes from .mixins import TestsMixin, CustomPermissionClass +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse + @override_settings(ROOT_URLCONF="tests.urls") class APIBasicTests(TestsMixin, TestCase): From 7ad440f7a2322ed936478fbbceab7c6afd4d8847 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Tue, 5 Dec 2017 00:23:37 -0500 Subject: [PATCH 28/69] Remove Django 1.10 from tests and move imports to top of the file --- .travis.yml | 1 - rest_auth/tests/mixins.py | 11 +++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8470da1..b05a3f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ python: - "3.6" env: - DJANGO=1.8.* DRF=3.6.* - - DJANGO=1.10.* DRF=3.7.* - DJANGO=1.11.* DRF=3.7.* - DJANGO=2.0.* DRF=3.7.* install: diff --git a/rest_auth/tests/mixins.py b/rest_auth/tests/mixins.py index 91f0001..220a28d 100644 --- a/rest_auth/tests/mixins.py +++ b/rest_auth/tests/mixins.py @@ -7,6 +7,11 @@ from django.utils.encoding import force_text from rest_framework import status from rest_framework import permissions +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse + class CustomPermissionClass(permissions.BasePermission): message = 'You shall not pass!' @@ -14,11 +19,6 @@ class CustomPermissionClass(permissions.BasePermission): def has_permission(self, request, view): return False -try: - from django.urls import reverse -except ImportError: - from django.core.urlresolvers import reverse - class APIClient(Client): @@ -30,7 +30,6 @@ class APIClient(Client): class TestsMixin(object): - """ base for API tests: * easy request calls, f.e.: self.post(url, data), self.get(url) From 98d5ce314f1ba4ab8d8707d0924187223234fea3 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Tue, 5 Dec 2017 00:39:32 -0500 Subject: [PATCH 29/69] Fix unit tests --- rest_auth/tests/settings.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rest_auth/tests/settings.py b/rest_auth/tests/settings.py index 060cc89..e353fb0 100644 --- a/rest_auth/tests/settings.py +++ b/rest_auth/tests/settings.py @@ -25,7 +25,7 @@ DATABASES = { } } -MIDDLEWARE_CLASSES = [ +MIDDLEWARE = [ 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -33,6 +33,9 @@ MIDDLEWARE_CLASSES = [ 'django.contrib.messages.middleware.MessageMiddleware' ] +# Adding for backwards compatibility for Django 1.8 tests +MIDDLEWARE_CLASSES = MIDDLEWARE + TEMPLATE_CONTEXT_PROCESSORS = [ 'django.contrib.auth.context_processors.auth', 'django.core.context_processors.debug', From 5e6c5a75ea5367d1d97bdaffe6942f6f54f9aabb Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Tue, 5 Dec 2017 12:39:57 -0500 Subject: [PATCH 30/69] Changes in demo project settings for Django 2.0 compatibility --- demo/demo/settings.py | 6 ++++-- demo/demo/urls.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/demo/demo/settings.py b/demo/demo/settings.py index 7d6399d..514a8fb 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -47,16 +47,18 @@ INSTALLED_APPS = ( 'rest_framework_swagger', ) -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) +# For backwards compatibility for Django 1.8 +MIDDLEWARE_CLASSES = MIDDLEWARE + ROOT_URLCONF = 'demo.urls' WSGI_APPLICATION = 'demo.wsgi.application' diff --git a/demo/demo/urls.py b/demo/demo/urls.py index e66bc9d..af7d38b 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -38,7 +38,7 @@ urlpatterns = [ url(r'^rest-auth/', include('rest_auth.urls')), url(r'^rest-auth/registration/', include('rest_auth.registration.urls')), url(r'^account/', include('allauth.urls')), - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'), url(r'^docs/$', get_swagger_view(title='API Docs'), name='api_docs') ] From a892ca3fa5dadf5e66d07544712a12afee6717ad Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Sat, 16 Dec 2017 16:48:34 -0500 Subject: [PATCH 31/69] Upgrade requirements for demo project --- demo/requirements.pip | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index b6c8a77..7818a9c 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,6 +1,6 @@ -django>=1.8.0 +django>=1.9.0 django-rest-auth==0.9.2 -djangorestframework==3.5.1 +djangorestframework>=3.7.0 django-allauth>=0.24.1 six==1.9.0 django-rest-swagger==2.0.7 From 8a4afe746c1ed2d7159deb7f2ed340c5d1f68473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksi=20H=C3=A4kli?= Date: Sat, 2 Dec 2017 16:00:16 +0200 Subject: [PATCH 32/69] Implement connect social accounts functionality Add serializers and views for connecting accounts with minimal specialization of the existing django-rest-auth interfaces. Also add viewset which enables listing social account infmration via the REST API for social authentication driven client applications. Resolves #347 in GitHub. --- docs/installation.rst | 20 ++++- rest_auth/registration/serializers.py | 45 +++++++++- rest_auth/registration/views.py | 120 ++++++++++++++++++++------ rest_auth/social_serializers.py | 113 ++++++++++++------------ 4 files changed, 212 insertions(+), 86 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index fd09cd7..b694ccc 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -111,11 +111,15 @@ Facebook .. code-block:: python from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - from rest_auth.registration.views import SocialLoginView + from rest_auth.registration.views import SocialLoginView, SocialConnectView class FacebookLogin(SocialLoginView): adapter_class = FacebookOAuth2Adapter + # Add a connect view if you want to allow connecting existing accounts + class FacebookConnect(SocialConnectView): + adapter_class = FacebookOAuth2Adapter + 4. Create url for FacebookLogin view: .. code-block:: python @@ -123,6 +127,7 @@ Facebook urlpatterns += [ ..., url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login') + url(r'^rest-auth/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect') ] @@ -136,13 +141,19 @@ If you are using Twitter for your social authentication, it is a bit different s .. code-block:: python from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter - from rest_auth.views import LoginView - from rest_auth.social_serializers import TwitterLoginSerializer + from rest_auth.registration.views import SocialLoginView + from rest_auth.social_serializers import TwitterLoginSerializer, TwitterConnectSerializer - class TwitterLogin(LoginView): + class TwitterLogin(SocialLoginView): serializer_class = TwitterLoginSerializer adapter_class = TwitterOAuthAdapter + # Add a connect view if you want to allow connecting existing accounts + class TwitterConnect(SocialConnectView): + serializer_class = TwitterConnectSerializer + adapter_class = TwitterOAuthAdapter + + 4. Create url for TwitterLogin view: .. code-block:: python @@ -150,6 +161,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'^rest-auth/twitter/connect/$', TwitterConnect.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. diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index b2e9d51..160b4d6 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -14,10 +14,6 @@ except ImportError: from rest_framework import serializers from requests.exceptions import HTTPError -# 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: - from allauth.socialaccount.helpers import complete_social_login class SocialLoginSerializer(serializers.Serializer): @@ -186,3 +182,44 @@ class RegisterSerializer(serializers.Serializer): class VerifyEmailSerializer(serializers.Serializer): key = serializers.CharField() + + +# 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: + from allauth.socialaccount.helpers import complete_social_login + from allauth.socialaccount.models import SocialAccount + from allauth.socialaccount.providers.base import AuthProcess + + class SocialAccountSerializer(serializers.ModelSerializer): + """ + serialize allauth SocialAccounts for use with a REST API + """ + class Meta: + model = SocialAccount + fields = ( + 'id', + 'provider', + 'uid', + 'last_login', + 'date_joined', + 'extra_data', + ) + + + class SocialConnectMixin(object): + def get_social_login(self, *args, **kwargs): + """ + set the social login process state to connect rather than login + + Refer to the implementation of get_social_login in base class and to the + allauth.socialaccount.helpers module complete_social_login function. + """ + + social_login = super(SocialConnectMixin, self).get_social_login(*args, **kwargs) + social_login.state['process'] = AuthProcess.CONNECT + return social_login + + + class SocialConnectSerializer(SocialConnectMixin, SocialLoginSerializer): + pass diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index d6638b6..9343e72 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -5,11 +5,13 @@ 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 +from rest_framework.permissions import (AllowAny, + IsAuthenticated) +from rest_framework.decorators import detail_route +from rest_framework.viewsets import GenericViewSet from rest_framework.generics import CreateAPIView from rest_framework import status -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 @@ -19,7 +21,8 @@ from rest_auth.app_settings import (TokenSerializer, create_token) from rest_auth.models import TokenModel from rest_auth.registration.serializers import (SocialLoginSerializer, - VerifyEmailSerializer) + VerifyEmailSerializer, + SocialConnectSerializer) from rest_auth.utils import jwt_encode from rest_auth.views import LoginView from .app_settings import RegisterSerializer, register_permission_classes @@ -91,31 +94,98 @@ class VerifyEmailView(APIView, ConfirmEmailView): return Response({'detail': _('ok')}, status=status.HTTP_200_OK) -class SocialLoginView(LoginView): - """ - class used for social authentications - example usage for facebook with access_token - ------------- - from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter +if 'allauth.socialaccount' in settings.INSTALLED_APPS: + from allauth.socialaccount import signals + from allauth.socialaccount.models import SocialAccount + from allauth.socialaccount.adapter import get_adapter - class FacebookLogin(SocialLoginView): - adapter_class = FacebookOAuth2Adapter - ------------- + from rest_auth.registration.serializers import SocialAccountSerializer - example usage for facebook with code - ------------- - from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - from allauth.socialaccount.providers.oauth2.client import OAuth2Client + class SocialLoginView(LoginView): + """ + class used for social authentications + example usage for facebook with access_token + ------------- + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - class FacebookLogin(SocialLoginView): - adapter_class = FacebookOAuth2Adapter - client_class = OAuth2Client - callback_url = 'localhost:8000' - ------------- - """ + class FacebookLogin(SocialLoginView): + adapter_class = FacebookOAuth2Adapter + ------------- - serializer_class = SocialLoginSerializer + example usage for facebook with code - def process_login(self): - get_adapter(self.request).login(self.request, self.user) + ------------- + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + from allauth.socialaccount.providers.oauth2.client import OAuth2Client + + class FacebookLogin(SocialLoginView): + adapter_class = FacebookOAuth2Adapter + client_class = OAuth2Client + callback_url = 'localhost:8000' + ------------- + """ + + serializer_class = SocialLoginSerializer + + def process_login(self): + get_adapter(self.request).login(self.request, self.user) + + + class SocialConnectView(SocialLoginView): + """ + class used for social account linking + + example usage for facebook with access_token + ------------- + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + + class FacebookConnect(SocialConnectView): + adapter_class = FacebookOAuth2Adapter + ------------- + """ + + serializer_class = SocialConnectSerializer + permission_classes = (IsAuthenticated,) + + + class SocialAccountViewSet(GenericViewSet): + """ + allauth SocialAccount REST API read and disconnect views for logged in users + + Refer to the django-allauth package implementation of the models and + account handling logic for more details, this viewset emulates the allauth web UI. + """ + + serializer_class = SocialAccountSerializer + permission_classes = (IsAuthenticated,) + queryset = SocialAccount.objects.none() + + def get_queryset(self): + return SocialAccount.objects.filter(user=self.request.user) + + def list(self, request): + """ + list SocialAccounts for the currently logged in user + """ + + return Response(self.get_serializer(self.get_queryset(), many=True).data) + + @detail_route(methods=['POST']) + def disconnect(self, request, pk): + """ + disconnect SocialAccount from remote service for the currently logged in user + """ + + accounts = self.get_queryset() + account = accounts.get(pk=pk) + get_adapter(self.request).validate_disconnect(account, accounts) + + account.delete() + signals.social_account_removed.send( + sender=SocialAccount, + request=self.request, + socialaccount=account + ) + + return Response(self.get_serializer(account).data) diff --git a/rest_auth/social_serializers.py b/rest_auth/social_serializers.py index 665b98d..6161d1a 100644 --- a/rest_auth/social_serializers.py +++ b/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: @@ -8,68 +9,74 @@ 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 -class TwitterLoginSerializer(serializers.Serializer): - access_token = serializers.CharField() - token_secret = serializers.CharField() - def _get_request(self): - request = self.context.get('request') - if not isinstance(request, HttpRequest): - request = request._request - return request + class TwitterLoginSerializer(serializers.Serializer): + access_token = serializers.CharField() + token_secret = serializers.CharField() - def get_social_login(self, adapter, app, token, response): - """ - :param adapter: allauth.socialaccount Adapter subclass. - Usually OAuthAdapter or Auth2Adapter - :param app: `allauth.socialaccount.SocialApp` instance - :param token: `allauth.socialaccount.SocialToken` instance - :param response: Provider's response for OAuth1. Not used in the - :returns: A populated instance of the - `allauth.socialaccount.SocialLoginView` instance - """ - request = self._get_request() - social_login = adapter.complete_login(request, app, token, - response=response) - social_login.token = token - return social_login + def _get_request(self): + request = self.context.get('request') + if not isinstance(request, HttpRequest): + request = request._request + return request - def validate(self, attrs): - view = self.context.get('view') - request = self._get_request() + def get_social_login(self, adapter, app, token, response): + """ + :param adapter: allauth.socialaccount Adapter subclass. + Usually OAuthAdapter or Auth2Adapter + :param app: `allauth.socialaccount.SocialApp` instance + :param token: `allauth.socialaccount.SocialToken` instance + :param response: Provider's response for OAuth1. Not used in the + :returns: A populated instance of the + `allauth.socialaccount.SocialLoginView` instance + """ + request = self._get_request() + social_login = adapter.complete_login(request, app, token, + response=response) + social_login.token = token + return social_login - if not view: - raise serializers.ValidationError( - "View is not defined, pass it as a context variable" - ) + def validate(self, attrs): + view = self.context.get('view') + request = self._get_request() - adapter_class = getattr(view, 'adapter_class', None) - if not adapter_class: - raise serializers.ValidationError("Define adapter_class in view") + if not view: + raise serializers.ValidationError( + "View is not defined, pass it as a context variable" + ) - adapter = adapter_class(request) - app = adapter.get_provider().get_app(request) + adapter_class = getattr(view, 'adapter_class', None) + if not adapter_class: + raise serializers.ValidationError("Define adapter_class in view") - access_token = attrs.get('access_token') - token_secret = attrs.get('token_secret') + adapter = adapter_class(request) + app = adapter.get_provider().get_app(request) - request.session['oauth_api.twitter.com_access_token'] = { - 'oauth_token': access_token, - 'oauth_token_secret': token_secret, - } - token = SocialToken(token=access_token, token_secret=token_secret) - token.app = app + access_token = attrs.get('access_token') + token_secret = attrs.get('token_secret') - try: - login = self.get_social_login(adapter, app, token, access_token) - complete_social_login(request, login) - except OAuthError as e: - raise serializers.ValidationError(str(e)) + request.session['oauth_api.twitter.com_access_token'] = { + 'oauth_token': access_token, + 'oauth_token_secret': token_secret, + } + token = SocialToken(token=access_token, token_secret=token_secret) + token.app = app - if not login.is_existing: - login.lookup() - login.save(request, connect=True) - attrs['user'] = login.account.user + try: + login = self.get_social_login(adapter, app, token, access_token) + complete_social_login(request, login) + except OAuthError as e: + raise serializers.ValidationError(str(e)) - return attrs + if not login.is_existing: + login.lookup() + login.save(request, connect=True) + attrs['user'] = login.account.user + + return attrs + + + class TwitterConnectSerializer(SocialConnectMixin, TwitterLoginSerializer): + pass From fed6b9840c46eefd99cb695687de307e2855cc4a Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Thu, 18 Jan 2018 21:08:41 -0500 Subject: [PATCH 33/69] Refactor social connect views and serializers # 347 --- rest_auth/registration/serializers.py | 78 ++++++------ rest_auth/registration/views.py | 163 +++++++++++++------------- rest_auth/social_serializers.py | 111 +++++++++--------- 3 files changed, 169 insertions(+), 183 deletions(-) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index 160b4d6..4f99c18 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,5 +1,4 @@ from django.http import HttpRequest -from django.conf import settings from django.utils.translation import ugettext_lazy as _ from django.contrib.auth import get_user_model @@ -9,6 +8,9 @@ try: get_username_max_length) from allauth.account.adapter import get_adapter from allauth.account.utils import setup_user_email + from allauth.socialaccount.helpers import complete_social_login + from allauth.socialaccount.models import SocialAccount + from allauth.socialaccount.providers.base import AuthProcess except ImportError: raise ImportError("allauth needs to be added to INSTALLED_APPS.") @@ -16,6 +18,21 @@ from rest_framework import serializers from requests.exceptions import HTTPError +class SocialAccountSerializer(serializers.ModelSerializer): + """ + serialize allauth SocialAccounts for use with a REST API + """ + class Meta: + model = SocialAccount + fields = ( + 'id', + 'provider', + 'uid', + 'last_login', + 'date_joined', + ) + + class SocialLoginSerializer(serializers.Serializer): access_token = serializers.CharField(required=False, allow_blank=True) code = serializers.CharField(required=False, allow_blank=True) @@ -105,7 +122,7 @@ class SocialLoginSerializer(serializers.Serializer): login = self.get_social_login(adapter, app, social_token, access_token) complete_social_login(request, login) except HTTPError: - raise serializers.ValidationError(_('Incorrect value')) + raise serializers.ValidationError(_("Incorrect value")) if not login.is_existing: # We have an account already signed up in a different flow @@ -130,6 +147,22 @@ class SocialLoginSerializer(serializers.Serializer): return attrs +class SocialConnectMixin(object): + def get_social_login(self, *args, **kwargs): + """ + Set the social login process state to connect rather than login + Refer to the implementation of get_social_login in base class and to the + allauth.socialaccount.helpers module complete_social_login function. + """ + social_login = super(SocialConnectMixin, self).get_social_login(*args, **kwargs) + social_login.state['process'] = AuthProcess.CONNECT + return social_login + + +class SocialConnectSerializer(SocialConnectMixin, SocialLoginSerializer): + pass + + class RegisterSerializer(serializers.Serializer): username = serializers.CharField( max_length=get_username_max_length(), @@ -182,44 +215,3 @@ class RegisterSerializer(serializers.Serializer): class VerifyEmailSerializer(serializers.Serializer): key = serializers.CharField() - - -# 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: - from allauth.socialaccount.helpers import complete_social_login - from allauth.socialaccount.models import SocialAccount - from allauth.socialaccount.providers.base import AuthProcess - - class SocialAccountSerializer(serializers.ModelSerializer): - """ - serialize allauth SocialAccounts for use with a REST API - """ - class Meta: - model = SocialAccount - fields = ( - 'id', - 'provider', - 'uid', - 'last_login', - 'date_joined', - 'extra_data', - ) - - - class SocialConnectMixin(object): - def get_social_login(self, *args, **kwargs): - """ - set the social login process state to connect rather than login - - Refer to the implementation of get_social_login in base class and to the - allauth.socialaccount.helpers module complete_social_login function. - """ - - social_login = super(SocialConnectMixin, self).get_social_login(*args, **kwargs) - social_login.state['process'] = AuthProcess.CONNECT - return social_login - - - class SocialConnectSerializer(SocialConnectMixin, SocialLoginSerializer): - pass diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index 9343e72..0e0ab0d 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -7,21 +7,25 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import (AllowAny, IsAuthenticated) -from rest_framework.decorators import detail_route -from rest_framework.viewsets import GenericViewSet -from rest_framework.generics import CreateAPIView +from rest_framework.generics import CreateAPIView, ListAPIView, GenericAPIView +from rest_framework.exceptions import NotFound from rest_framework import status +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 rest_auth.app_settings import (TokenSerializer, JWTSerializer, create_token) from rest_auth.models import TokenModel -from rest_auth.registration.serializers import (SocialLoginSerializer, - VerifyEmailSerializer, +from rest_auth.registration.serializers import (VerifyEmailSerializer, + SocialLoginSerializer, + SocialAccountSerializer, SocialConnectSerializer) from rest_auth.utils import jwt_encode from rest_auth.views import LoginView @@ -94,98 +98,89 @@ class VerifyEmailView(APIView, ConfirmEmailView): return Response({'detail': _('ok')}, status=status.HTTP_200_OK) -if 'allauth.socialaccount' in settings.INSTALLED_APPS: - from allauth.socialaccount import signals - from allauth.socialaccount.models import SocialAccount - from allauth.socialaccount.adapter import get_adapter +class SocialLoginView(LoginView): + """ + class used for social authentications + example usage for facebook with access_token + ------------- + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - from rest_auth.registration.serializers import SocialAccountSerializer + class FacebookLogin(SocialLoginView): + adapter_class = FacebookOAuth2Adapter + ------------- + + example usage for facebook with code + + ------------- + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + from allauth.socialaccount.providers.oauth2.client import OAuth2Client + + class FacebookLogin(SocialLoginView): + adapter_class = FacebookOAuth2Adapter + client_class = OAuth2Client + callback_url = 'localhost:8000' + ------------- + """ + serializer_class = SocialLoginSerializer + + def process_login(self): + get_adapter(self.request).login(self.request, self.user) - class SocialLoginView(LoginView): - """ - class used for social authentications - example usage for facebook with access_token - ------------- - from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter +class SocialConnectView(LoginView): + """ + class used for social account linking - class FacebookLogin(SocialLoginView): - adapter_class = FacebookOAuth2Adapter - ------------- + example usage for facebook with access_token + ------------- + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - example usage for facebook with code + class FacebookConnect(SocialConnectView): + adapter_class = FacebookOAuth2Adapter + ------------- + """ + serializer_class = SocialConnectSerializer + permission_classes = (IsAuthenticated,) - ------------- - from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - from allauth.socialaccount.providers.oauth2.client import OAuth2Client - - class FacebookLogin(SocialLoginView): - adapter_class = FacebookOAuth2Adapter - client_class = OAuth2Client - callback_url = 'localhost:8000' - ------------- - """ - - serializer_class = SocialLoginSerializer - - def process_login(self): - get_adapter(self.request).login(self.request, self.user) + def process_login(self): + get_adapter(self.request).login(self.request, self.user) - class SocialConnectView(SocialLoginView): - """ - class used for social account linking +class SocialAccountListView(ListAPIView): + """ + List SocialAccounts for the currently logged in user + """ + serializer_class = SocialAccountSerializer + permission_classes = (IsAuthenticated,) - example usage for facebook with access_token - ------------- - from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - - class FacebookConnect(SocialConnectView): - adapter_class = FacebookOAuth2Adapter - ------------- - """ - - serializer_class = SocialConnectSerializer - permission_classes = (IsAuthenticated,) + def get_queryset(self): + return SocialAccount.objects.filter(user=self.request.user) - class SocialAccountViewSet(GenericViewSet): - """ - allauth SocialAccount REST API read and disconnect views for logged in users +class SocialAccountDisconnectView(GenericAPIView): + """ + Disconnect SocialAccount from remote service for + the currently logged in user + """ + serializer_class = SocialConnectSerializer + permission_classes = (IsAuthenticated,) - Refer to the django-allauth package implementation of the models and - account handling logic for more details, this viewset emulates the allauth web UI. - """ + def get_queryset(self): + return SocialAccount.objects.filter(user=self.request.user) - serializer_class = SocialAccountSerializer - permission_classes = (IsAuthenticated,) - queryset = SocialAccount.objects.none() + def post(self, request, *args, **kwargs): + accounts = self.get_queryset() + account = accounts.filter(pk=kwargs['pk']).first() + if not account: + raise NotFound - def get_queryset(self): - return SocialAccount.objects.filter(user=self.request.user) + get_social_adapter(self.request).validate_disconnect(account, accounts) - def list(self, request): - """ - list SocialAccounts for the currently logged in user - """ + account.delete() + signals.social_account_removed.send( + sender=SocialAccount, + request=self.request, + socialaccount=account + ) - return Response(self.get_serializer(self.get_queryset(), many=True).data) - - @detail_route(methods=['POST']) - def disconnect(self, request, pk): - """ - disconnect SocialAccount from remote service for the currently logged in user - """ - - accounts = self.get_queryset() - account = accounts.get(pk=pk) - get_adapter(self.request).validate_disconnect(account, accounts) - - account.delete() - signals.social_account_removed.send( - sender=SocialAccount, - request=self.request, - socialaccount=account - ) - - return Response(self.get_serializer(account).data) + return Response(self.get_serializer(account).data) diff --git a/rest_auth/social_serializers.py b/rest_auth/social_serializers.py index 6161d1a..1621813 100644 --- a/rest_auth/social_serializers.py +++ b/rest_auth/social_serializers.py @@ -1,7 +1,6 @@ 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: @@ -12,71 +11,71 @@ if 'allauth.socialaccount' in settings.INSTALLED_APPS: from rest_auth.registration.serializers import SocialConnectMixin - class TwitterLoginSerializer(serializers.Serializer): - access_token = serializers.CharField() - token_secret = serializers.CharField() +class TwitterLoginSerializer(serializers.Serializer): + access_token = serializers.CharField() + token_secret = serializers.CharField() - def _get_request(self): - request = self.context.get('request') - if not isinstance(request, HttpRequest): - request = request._request - return request + def _get_request(self): + request = self.context.get('request') + if not isinstance(request, HttpRequest): + request = request._request + return request - def get_social_login(self, adapter, app, token, response): - """ - :param adapter: allauth.socialaccount Adapter subclass. - Usually OAuthAdapter or Auth2Adapter - :param app: `allauth.socialaccount.SocialApp` instance - :param token: `allauth.socialaccount.SocialToken` instance - :param response: Provider's response for OAuth1. Not used in the - :returns: A populated instance of the - `allauth.socialaccount.SocialLoginView` instance - """ - request = self._get_request() - social_login = adapter.complete_login(request, app, token, - response=response) - social_login.token = token - return social_login + def get_social_login(self, adapter, app, token, response): + """ + :param adapter: allauth.socialaccount Adapter subclass. + Usually OAuthAdapter or Auth2Adapter + :param app: `allauth.socialaccount.SocialApp` instance + :param token: `allauth.socialaccount.SocialToken` instance + :param response: Provider's response for OAuth1. Not used in the + :returns: A populated instance of the + `allauth.socialaccount.SocialLoginView` instance + """ + request = self._get_request() + social_login = adapter.complete_login(request, app, token, + response=response) + social_login.token = token + return social_login - def validate(self, attrs): - view = self.context.get('view') - request = self._get_request() + def validate(self, attrs): + view = self.context.get('view') + request = self._get_request() - if not view: - raise serializers.ValidationError( - "View is not defined, pass it as a context variable" - ) + if not view: + raise serializers.ValidationError( + "View is not defined, pass it as a context variable" + ) - adapter_class = getattr(view, 'adapter_class', None) - if not adapter_class: - raise serializers.ValidationError("Define adapter_class in view") + adapter_class = getattr(view, 'adapter_class', None) + if not adapter_class: + raise serializers.ValidationError("Define adapter_class in view") - adapter = adapter_class(request) - app = adapter.get_provider().get_app(request) + adapter = adapter_class(request) + app = adapter.get_provider().get_app(request) - access_token = attrs.get('access_token') - token_secret = attrs.get('token_secret') + access_token = attrs.get('access_token') + token_secret = attrs.get('token_secret') - request.session['oauth_api.twitter.com_access_token'] = { - 'oauth_token': access_token, - 'oauth_token_secret': token_secret, - } - token = SocialToken(token=access_token, token_secret=token_secret) - token.app = app + request.session['oauth_api.twitter.com_access_token'] = { + 'oauth_token': access_token, + 'oauth_token_secret': token_secret, + } + token = SocialToken(token=access_token, token_secret=token_secret) + token.app = app - try: - login = self.get_social_login(adapter, app, token, access_token) - complete_social_login(request, login) - except OAuthError as e: - raise serializers.ValidationError(str(e)) + try: + login = self.get_social_login(adapter, app, token, access_token) + complete_social_login(request, login) + except OAuthError as e: + raise serializers.ValidationError(str(e)) - if not login.is_existing: - login.lookup() - login.save(request, connect=True) - attrs['user'] = login.account.user + if not login.is_existing: + login.lookup() + login.save(request, connect=True) + attrs['user'] = login.account.user - return attrs + return attrs - class TwitterConnectSerializer(SocialConnectMixin, TwitterLoginSerializer): - pass +class TwitterConnectSerializer(SocialConnectMixin, TwitterLoginSerializer): + pass From 3eb546f63354382a127d902aff312157b82b171f Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Thu, 18 Jan 2018 21:11:36 -0500 Subject: [PATCH 34/69] Add extra info to docs for social connect #347 --- docs/installation.rst | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index b694ccc..b85cc17 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -161,10 +161,35 @@ 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'^rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_login') + url(r'^rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect') ] .. 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. +Additional Social Connect Views +############################### + +If you are using social connect views, you can also use additional views to check all social accounts attached to the current authenticated user and disconnect selected social accounts. + +.. code-block:: python + + from rest_auth.registration.views import ( + SocialAccountListView, SocialAccountDisconnectView + ) + + urlpatterns += [ + ..., + url( + r'^socialaccounts/$', + SocialAccountListView.as_view(), + name='social_account_list' + ), + url( + r'^socialaccounts/(?P\d+)/disconnect/$', + SocialAccountDisconnectView.as_view(), + name='social_account_disconnect' + ) + ] + JWT Support (optional) ---------------------- @@ -180,4 +205,4 @@ By default ``django-rest-auth`` uses Django's Token-based authentication. If you .. code-block:: python - REST_USE_JWT = True \ No newline at end of file + REST_USE_JWT = True From 6a84d85d9180954c7be47c940a6373e752b0a8d0 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Fri, 19 Jan 2018 18:29:38 -0500 Subject: [PATCH 35/69] Add change in documentation and tests for social connect --- docs/installation.rst | 42 ++++++---- rest_auth/tests/mixins.py | 3 + rest_auth/tests/test_social.py | 149 +++++++++++++++++++++++++++++++++ rest_auth/tests/urls.py | 23 ++++- 4 files changed, 201 insertions(+), 16 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index b85cc17..8a2d3b6 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -111,15 +111,11 @@ Facebook .. code-block:: python from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter - from rest_auth.registration.views import SocialLoginView, SocialConnectView + from rest_auth.registration.views import SocialLoginView class FacebookLogin(SocialLoginView): adapter_class = FacebookOAuth2Adapter - # Add a connect view if you want to allow connecting existing accounts - class FacebookConnect(SocialConnectView): - adapter_class = FacebookOAuth2Adapter - 4. Create url for FacebookLogin view: .. code-block:: python @@ -127,7 +123,6 @@ Facebook urlpatterns += [ ..., url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login') - url(r'^rest-auth/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect') ] @@ -142,18 +137,12 @@ If you are using Twitter for your social authentication, it is a bit different s from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter from rest_auth.registration.views import SocialLoginView - from rest_auth.social_serializers import TwitterLoginSerializer, TwitterConnectSerializer + from rest_auth.social_serializers import TwitterLoginSerializer class TwitterLogin(SocialLoginView): serializer_class = TwitterLoginSerializer adapter_class = TwitterOAuthAdapter - # Add a connect view if you want to allow connecting existing accounts - class TwitterConnect(SocialConnectView): - serializer_class = TwitterConnectSerializer - adapter_class = TwitterOAuthAdapter - - 4. Create url for TwitterLogin view: .. code-block:: python @@ -168,7 +157,32 @@ If you are using Twitter for your social authentication, it is a bit different s Additional Social Connect Views ############################### -If you are using social connect views, you can also use additional views to check all social accounts attached to the current authenticated user and disconnect selected social accounts. +If you want to allow connecting existing accounts in addition to just login, you can use connect views: + +.. code-block:: python + + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + from rest_auth.registration.views import SocialConnectView + from rest_auth.social_serializers import TwitterConnectSerializer + + class FacebookConnect(SocialConnectView): + adapter_class = FacebookOAuth2Adapter + + class TwitterConnect(SocialConnectView): + serializer_class = TwitterConnectSerializer + adapter_class = TwitterOAuthAdapter + +In urls.py: + +.. code-block:: python + + 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') + ] + +You can also use additional views to check all social accounts attached to the current authenticated user and disconnect selected social accounts. .. code-block:: python diff --git a/rest_auth/tests/mixins.py b/rest_auth/tests/mixins.py index 220a28d..30b3d58 100644 --- a/rest_auth/tests/mixins.py +++ b/rest_auth/tests/mixins.py @@ -90,6 +90,9 @@ class TestsMixin(object): self.tw_login_url = reverse('tw_login') self.tw_login_no_view_url = reverse('tw_login_no_view') self.tw_login_no_adapter_url = reverse('tw_login_no_adapter') + self.fb_connect_url = reverse('fb_connect') + self.tw_connect_url = reverse('tw_connect') + self.social_account_list_url = reverse('social_account_list') def _login(self): payload = { diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index e6eca03..6e7a495 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -5,6 +5,11 @@ from django.contrib.auth import get_user_model from django.test.utils import override_settings from django.contrib.sites.models import Site +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 @@ -303,3 +308,147 @@ class TestSocialAuth(TestsMixin, TestCase): self.assertIn('user', self.response.json.keys()) self.assertEqual(get_user_model().objects.all().count(), users_count + 1) + + +@override_settings(ROOT_URLCONF="tests.urls") +class TestSocialConnectAuth(TestsMixin, TestCase): + + USERNAME = 'person' + PASS = 'person' + EMAIL = "person1@world.com" + REGISTRATION_DATA = { + "username": USERNAME, + "password1": PASS, + "password2": PASS, + "email": EMAIL + } + LOGIN_DATA = { + "username": USERNAME, + "password": PASS, + } + + def setUp(self): + self.init() + + facebook_social_app = SocialApp.objects.create( + provider='facebook', + name='Facebook', + client_id='123123123', + secret='321321321', + ) + + twitter_social_app = SocialApp.objects.create( + provider='twitter', + name='Twitter', + client_id='11223344', + secret='55667788', + ) + + site = Site.objects.get_current() + facebook_social_app.sites.add(site) + twitter_social_app.sites.add(site) + self.graph_api_url = GRAPH_API_URL + '/me' + self.twitter_url = 'https://api.twitter.com/1.1/account/verify_credentials.json' + + @responses.activate + def test_social_connect_no_auth(self): + responses.add( + responses.GET, + self.graph_api_url, + body='', + status=200, + content_type='application/json' + ) + + payload = { + 'access_token': 'abc123' + } + self.post(self.fb_connect_url, data=payload, status_code=403) + self.post(self.tw_connect_url, data=payload, status_code=403) + + @responses.activate + def test_social_connect(self): + # register user + self.post( + self.register_url, + data=self.REGISTRATION_DATA, + status_code=201 + ) + + # Test Facebook + resp_body = { + "id": "123123123123", + "first_name": "John", + "gender": "male", + "last_name": "Smith", + "link": "https://www.facebook.com/john.smith", + "locale": "en_US", + "name": "John Smith", + "timezone": 2, + "updated_time": "2014-08-13T10:14:38+0000", + "username": "john.smith", + "verified": True + } + + responses.add( + responses.GET, + self.graph_api_url, + body=json.dumps(resp_body), + status=200, + content_type='application/json' + ) + + payload = { + 'access_token': 'abc123' + } + self.post(self.fb_connect_url, data=payload, status_code=200) + self.assertIn('key', self.response.json.keys()) + + # Test Twitter + self.post(self.logout_url) + self.post(self.login_url, data=self.LOGIN_DATA) + + resp_body = { + "id": "123123123123", + } + + responses.add( + responses.GET, + self.twitter_url, + body=json.dumps(resp_body), + status=200, + content_type='application/json' + ) + + payload = { + 'access_token': 'abc123', + 'token_secret': '1111222233334444' + } + + self.post(self.tw_connect_url, data=payload) + + self.assertIn('key', self.response.json.keys()) + + # Check current social accounts + self.get(self.social_account_list_url) + self.assertEqual(len(self.response.json), 2) + self.assertEqual(self.response.json[0]['provider'], 'facebook') + self.assertEqual(self.response.json[1]['provider'], 'twitter') + + facebook_social_account_id = self.response.json[0]['id'] + + # Try disconnecting accounts + self.incorrect_disconnect_url = reverse( + 'social_account_disconnect', args=[999] + ) + self.post(self.incorrect_disconnect_url, status_code=404) + + self.disconnect_url = reverse( + 'social_account_disconnect', args=[facebook_social_account_id] + ) + self.post(self.disconnect_url, status_code=200) + + # Check social accounts after disconnecting + self.get(self.social_account_list_url) + self.assertEqual(len(self.response.json), 1) + self.assertEqual(self.response.json[0]['provider'], 'twitter') diff --git a/rest_auth/tests/urls.py b/rest_auth/tests/urls.py index 6371218..401f23a 100644 --- a/rest_auth/tests/urls.py +++ b/rest_auth/tests/urls.py @@ -8,8 +8,13 @@ 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 SocialLoginView -from rest_auth.social_serializers import TwitterLoginSerializer +from rest_auth.registration.views import ( + SocialLoginView, SocialConnectView, SocialAccountListView, + SocialAccountDisconnectView +) +from rest_auth.social_serializers import ( + TwitterLoginSerializer, TwitterConnectSerializer +) class FacebookLogin(SocialLoginView): @@ -21,6 +26,15 @@ class TwitterLogin(SocialLoginView): serializer_class = TwitterLoginSerializer +class FacebookConnect(SocialConnectView): + adapter_class = FacebookOAuth2Adapter + + +class TwitterConnect(SocialConnectView): + adapter_class = TwitterOAuthAdapter + serializer_class = TwitterConnectSerializer + + class TwitterLoginSerializerFoo(TwitterLoginSerializer): pass @@ -49,5 +63,10 @@ urlpatterns += [ url(r'^social-login/twitter/$', TwitterLogin.as_view(), name='tw_login'), url(r'^social-login/twitter-no-view/$', twitter_login_view, name='tw_login_no_view'), url(r'^social-login/twitter-no-adapter/$', TwitterLoginNoAdapter.as_view(), name='tw_login_no_adapter'), + 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'^socialaccounts/(?P\d+)/disconnect/$', SocialAccountDisconnectView.as_view(), + name='social_account_disconnect'), url(r'^accounts/', include('allauth.socialaccount.urls')) ] From bcd6ab4401d382cffd09deaa5a6bd0c18ab9692a Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Fri, 19 Jan 2018 19:31:49 -0500 Subject: [PATCH 36/69] Update configs and changelog for version 0.9.3 + additional fixes --- demo/requirements.pip | 2 +- docs/changelog.rst | 7 +++++++ docs/installation.rst | 6 +++--- rest_auth/registration/serializers.py | 11 ++++++++--- rest_auth/tests/test_social.py | 9 +-------- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 7818a9c..7480482 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.9.0 -django-rest-auth==0.9.2 +django-rest-auth==0.9.3 djangorestframework>=3.7.0 django-allauth>=0.24.1 six==1.9.0 diff --git a/docs/changelog.rst b/docs/changelog.rst index bf88fc8..fa79dbc 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,13 @@ Changelog ========= +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 diff --git a/docs/installation.rst b/docs/installation.rst index 8a2d3b6..fa512c5 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -150,14 +150,14 @@ 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'^rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect') ] + .. 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. Additional Social Connect Views ############################### -If you want to allow connecting existing accounts in addition to just login, you can use connect views: +If you want to allow connecting existing accounts in addition to login, you can use connect views: .. code-block:: python @@ -182,7 +182,7 @@ In urls.py: url(r'^rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect') ] -You can also use additional views to check all social accounts attached to the current authenticated user and disconnect selected social accounts. +You can also use the following views to check all social accounts attached to the current authenticated user and disconnect selected social accounts: .. code-block:: python diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index 4f99c18..a82dc6c 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,4 +1,5 @@ from django.http import HttpRequest +from django.conf import settings from django.utils.translation import ugettext_lazy as _ from django.contrib.auth import get_user_model @@ -8,15 +9,19 @@ try: get_username_max_length) from allauth.account.adapter import get_adapter from allauth.account.utils import setup_user_email - from allauth.socialaccount.helpers import complete_social_login - from allauth.socialaccount.models import SocialAccount - from allauth.socialaccount.providers.base import AuthProcess except ImportError: raise ImportError("allauth needs to be added to INSTALLED_APPS.") from rest_framework import serializers from requests.exceptions import HTTPError +# 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: + from allauth.socialaccount.helpers import complete_social_login + from allauth.socialaccount.models import SocialAccount + from allauth.socialaccount.providers.base import AuthProcess + class SocialAccountSerializer(serializers.ModelSerializer): """ diff --git a/rest_auth/tests/test_social.py b/rest_auth/tests/test_social.py index 6e7a495..830e631 100644 --- a/rest_auth/tests/test_social.py +++ b/rest_auth/tests/test_social.py @@ -322,10 +322,6 @@ class TestSocialConnectAuth(TestsMixin, TestCase): "password2": PASS, "email": EMAIL } - LOGIN_DATA = { - "username": USERNAME, - "password": PASS, - } def setUp(self): self.init() @@ -405,9 +401,6 @@ class TestSocialConnectAuth(TestsMixin, TestCase): self.assertIn('key', self.response.json.keys()) # Test Twitter - self.post(self.logout_url) - self.post(self.login_url, data=self.LOGIN_DATA) - resp_body = { "id": "123123123123", } @@ -439,7 +432,7 @@ class TestSocialConnectAuth(TestsMixin, TestCase): # Try disconnecting accounts self.incorrect_disconnect_url = reverse( - 'social_account_disconnect', args=[999] + 'social_account_disconnect', args=[999999999] ) self.post(self.incorrect_disconnect_url, status_code=404) From c009bb997509fed2d7a544d54b25322efbee57d9 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Sat, 20 Jan 2018 20:01:42 -0500 Subject: [PATCH 37/69] Change conditional import from allauth.socialaccount --- rest_auth/registration/serializers.py | 10 +++------- setup.py | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index a82dc6c..db946b7 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -9,19 +9,15 @@ try: get_username_max_length) from allauth.account.adapter import get_adapter from allauth.account.utils import setup_user_email + from allauth.socialaccount.helpers import complete_social_login + from allauth.socialaccount.models import SocialAccount + from allauth.socialaccount.providers.base import AuthProcess except ImportError: raise ImportError("allauth needs to be added to INSTALLED_APPS.") from rest_framework import serializers from requests.exceptions import HTTPError -# 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: - from allauth.socialaccount.helpers import complete_social_login - from allauth.socialaccount.models import SocialAccount - from allauth.socialaccount.providers.base import AuthProcess - class SocialAccountSerializer(serializers.ModelSerializer): """ diff --git a/setup.py b/setup.py index b3aa55b..2c9dad4 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ f.close() setup( name='django-rest-auth', - version='0.9.2', + version='0.9.3', author='Sumit Chachra', author_email='chachra@tivix.com', url='http://github.com/Tivix/django-rest-auth', From a3057b7aa1963da834ffc33edaf188b0e0e4556d Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Sat, 20 Jan 2018 20:25:58 -0500 Subject: [PATCH 38/69] Flake8 fix - unused import --- rest_auth/registration/serializers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index db946b7..4f99c18 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -1,5 +1,4 @@ from django.http import HttpRequest -from django.conf import settings from django.utils.translation import ugettext_lazy as _ from django.contrib.auth import get_user_model From 801bad7c6134e84016d4d1d6ade85c416ce442a5 Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Wed, 6 Jun 2018 15:01:22 -0400 Subject: [PATCH 39/69] Update copyright and version number in Docs config --- docs/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index faba401..c8ecb3b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,16 +44,16 @@ master_doc = 'index' # General information about the project. project = u'django-rest-auth' -copyright = u'2014, Tivix Inc.' +copyright = u'2018, Tivix 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 # built documents. # # The short X.Y version. -version = '0.3.0' +version = '0.9.3' # The full version, including alpha/beta/rc tags. -release = '0.3.0' +release = '0.9.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 95fafe5e0f6716296a1c664c2b870876a6b4e0cc Mon Sep 17 00:00:00 2001 From: Maxim Kukhtenkov Date: Wed, 6 Jun 2018 17:10:43 -0400 Subject: [PATCH 40/69] Remove Django 1.8 from Travis config --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b05a3f7..c296c2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ python: - "3.5" - "3.6" env: - - DJANGO=1.8.* DRF=3.6.* - DJANGO=1.11.* DRF=3.7.* - DJANGO=2.0.* DRF=3.7.* install: From 90760548f6905c5f251a3df6c9f00057b954bac3 Mon Sep 17 00:00:00 2001 From: Daniel <33256939+dgilge@users.noreply.github.com> Date: Mon, 11 Jun 2018 08:46:59 +0200 Subject: [PATCH 41/69] Add DRF 3.8 to Travis config --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index c296c2b..5ca0bf6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,9 @@ python: - "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 @@ -20,3 +22,4 @@ matrix: exclude: - python: "2.7" env: DJANGO=2.0.* DRF=3.7.* + env: DJANGO=2.0.* DRF=3.8.* From db60e433974018d30baf72e224c94463822c387f Mon Sep 17 00:00:00 2001 From: Daniel <33256939+dgilge@users.noreply.github.com> Date: Mon, 11 Jun 2018 09:02:02 +0200 Subject: [PATCH 42/69] Exclude Python 2.7 for Django 2.0 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5ca0bf6..b059c1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,4 +22,5 @@ matrix: exclude: - python: "2.7" env: DJANGO=2.0.* DRF=3.7.* + - python: "2.7" env: DJANGO=2.0.* DRF=3.8.* From a1845aef434c788561b88616bb151abaa7e9c67b Mon Sep 17 00:00:00 2001 From: Daniel <33256939+dgilge@users.noreply.github.com> Date: Thu, 14 Jun 2018 00:06:20 +0200 Subject: [PATCH 43/69] Pass request to authenticate --- rest_auth/serializers.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/rest_auth/serializers.py b/rest_auth/serializers.py index 45729b2..2ea6550 100644 --- a/rest_auth/serializers.py +++ b/rest_auth/serializers.py @@ -21,11 +21,14 @@ class LoginSerializer(serializers.Serializer): email = serializers.EmailField(required=False, allow_blank=True) password = serializers.CharField(style={'input_type': 'password'}) + def authenticate(self, **kwargs): + return authenticate(self.context['request'], **kwargs) + def _validate_email(self, email, password): user = None if email and password: - user = authenticate(email=email, password=password) + user = self.authenticate(email=email, password=password) else: msg = _('Must include "email" and "password".') raise exceptions.ValidationError(msg) @@ -36,7 +39,7 @@ class LoginSerializer(serializers.Serializer): user = None if username and password: - user = authenticate(username=username, password=password) + user = self.authenticate(username=username, password=password) else: msg = _('Must include "username" and "password".') raise exceptions.ValidationError(msg) @@ -47,9 +50,9 @@ class LoginSerializer(serializers.Serializer): user = None if email and password: - user = authenticate(email=email, password=password) + user = self.authenticate(email=email, password=password) elif username and password: - user = authenticate(username=username, password=password) + user = self.authenticate(username=username, password=password) else: msg = _('Must include either "username" or "email" and "password".') raise exceptions.ValidationError(msg) From b9fd4aba96a99f329c71dfe9a68ccf289d7d020a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Dohnal?= Date: Wed, 27 Jun 2018 23:06:34 +0200 Subject: [PATCH 44/69] add czech (cs) translations stub --- rest_auth/locale/cs/LC_MESSAGES/django.po | 103 ++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 rest_auth/locale/cs/LC_MESSAGES/django.po diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/rest_auth/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..3ac6d98 --- /dev/null +++ b/rest_auth/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,103 @@ +# 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. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-27 23:05+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: .\registration\serializers.py:67 +msgid "View is not defined, pass it as a context variable" +msgstr "" + +#: .\registration\serializers.py:72 +msgid "Define adapter_class in view" +msgstr "" + +#: .\registration\serializers.py:91 +msgid "Define callback_url in view" +msgstr "" + +#: .\registration\serializers.py:95 +msgid "Define client_class in view" +msgstr "" + +#: .\registration\serializers.py:116 +msgid "Incorrect input. access_token or code is required." +msgstr "" + +#: .\registration\serializers.py:125 +msgid "Incorrect value" +msgstr "" + +#: .\registration\serializers.py:139 +msgid "User is already registered with this e-mail address." +msgstr "" + +#: .\registration\serializers.py:185 +msgid "A user is already registered with this e-mail address." +msgstr "" + +#: .\registration\serializers.py:193 +msgid "The two password fields didn't match." +msgstr "" + +#: .\registration\views.py:51 +msgid "Verification e-mail sent." +msgstr "" + +#: .\registration\views.py:98 +msgid "ok" +msgstr "" + +#: .\serializers.py:30 +msgid "Must include \"email\" and \"password\"." +msgstr "" + +#: .\serializers.py:41 +msgid "Must include \"username\" and \"password\"." +msgstr "" + +#: .\serializers.py:54 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "" + +#: .\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 "" + +#: .\views.py:127 +msgid "Successfully logged out." +msgstr "" + +#: .\views.py:175 +msgid "Password reset e-mail has been sent." +msgstr "" + +#: .\views.py:201 +msgid "Password has been reset with the new password." +msgstr "" + +#: .\views.py:223 +msgid "New password has been saved." +msgstr "" From fa3000e8bd5b1c7c3622056d25badb953fbc5cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Dohnal?= Date: Wed, 27 Jun 2018 23:18:39 +0200 Subject: [PATCH 45/69] add cs translations --- rest_auth/locale/cs/LC_MESSAGES/django.mo | Bin 0 -> 2376 bytes rest_auth/locale/cs/LC_MESSAGES/django.po | 63 +++++++++++----------- 2 files changed, 31 insertions(+), 32 deletions(-) create mode 100644 rest_auth/locale/cs/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.mo b/rest_auth/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..38857f9a881619301ecd04a57fd1aa8bd0febe2f GIT binary patch literal 2376 zcmbW2O>7%Q6vqcB1of%MvC{bG*?IHcoBupN z|GanCb%y6@j2AJ!!*~hf+CBKd^DB4~{0;Q$Blj})0yvqIgU?|80aymFgL}Yl!TsP* z;34o2@D1?5eSJR*V2JrO(A#|mJ`4T;9sqvod0iFQo^Z7@hkM}7E*X&1d z5joxhk70ghH)F4WSHYLTPjY?<`Z(W%N5R|RliZc!5Fyx87!PCM zSnN@ZeHcF9$1xtmfZOc+{{A2tdjezdAVl`ukIzRi3VwEmQYS1)M_gIK<7KjV z>2Q?_Hk~@ZJ5nhui^3nKNLd&{`yeTM(qT?A~JDx5{s5=oI>f?42}|YB5!6nUty3aH|Fq zvbnmTWXTM(fz&E?6w6p2N~pz?s2;L;&8rHA#_#oam{mmEnvRU&DT3ArBe_CJ%={D?uV*jK1?TW<@UesQ zJQ3qmE{%=_rISJVbt)epFTHl8R4$cZ7+e+|>Ame}H=5gBfE9RD)Vy}g0Z2U<=QO@8%*Mt5ldYgr?IL`3bQJ; zTm=`5ZMkvM?QH5Q$0w-&wKAeBmC?g=no2ZIBl=XOOa~8=ezS7IzZ}KO@M#e8%3_S8Lv{^#Hc&&dxdvdb-ZqHUi{*-=7nZK#kz3H^!v%(Ht9ed z*X*uQqt#v0=Kt)_qH1=GI0IGJD2q?kWo0N;rne!q3E36iTNPWEvbK@k0#2t|#1hv% literal 0 HcmV?d00001 diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/rest_auth/locale/cs/LC_MESSAGES/django.po index 3ac6d98..43ab5e5 100644 --- a/rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/rest_auth/locale/cs/LC_MESSAGES/django.po @@ -1,103 +1,102 @@ -# 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. +# Czech translations of django-rest-auth +# +# This file is distributed under the same license as the django-model-utils package. # -#, fuzzy msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" +"Project-Id-Version: django-rest-auth\n" +"Report-Msgid-Bugs-To: https://github.com/Tivix/django-rest-auth/issues\n" "POT-Creation-Date: 2018-06-27 23:05+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" +"PO-Revision-Date: 2018-06-27 23:15+0200\n" +"Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"Last-Translator: Václav Dohnal \n" +"Language-Team: N/A\n" +"X-Generator: Poedit 2.0.8\n" #: .\registration\serializers.py:67 msgid "View is not defined, pass it as a context variable" -msgstr "" +msgstr "View není definováno, předejte jej jako proměnnou kontextu" #: .\registration\serializers.py:72 msgid "Define adapter_class in view" -msgstr "" +msgstr "Definujte adapter_class ve view" #: .\registration\serializers.py:91 msgid "Define callback_url in view" -msgstr "" +msgstr "Definujte callback_url ve view" #: .\registration\serializers.py:95 msgid "Define client_class in view" -msgstr "" +msgstr "Definujte client_class ve view" #: .\registration\serializers.py:116 msgid "Incorrect input. access_token or code is required." -msgstr "" +msgstr "Nesprávný vstup. access_token je povinný." #: .\registration\serializers.py:125 msgid "Incorrect value" -msgstr "" +msgstr "Nesprávná hodnota" #: .\registration\serializers.py:139 msgid "User is already registered with this e-mail address." -msgstr "" +msgstr "Uživatel s touto adresou je již registrován." #: .\registration\serializers.py:185 msgid "A user is already registered with this e-mail address." -msgstr "" +msgstr "Uživatel s touto adresou je již registrován." #: .\registration\serializers.py:193 msgid "The two password fields didn't match." -msgstr "" +msgstr "Zadaná hesla se neshodují." #: .\registration\views.py:51 msgid "Verification e-mail sent." -msgstr "" +msgstr "Ověřovací e-mail odeslán." #: .\registration\views.py:98 msgid "ok" -msgstr "" +msgstr "ok" #: .\serializers.py:30 msgid "Must include \"email\" and \"password\"." -msgstr "" +msgstr "Musí obsahovat \"e-mail\" a \"heslo\"." #: .\serializers.py:41 msgid "Must include \"username\" and \"password\"." -msgstr "" +msgstr "Musí obsahovat \"uživatelské jméno\" a \"heslo\"." #: .\serializers.py:54 msgid "Must include either \"username\" or \"email\" and \"password\"." -msgstr "" +msgstr "Musí obsahovat \"uživatelské jméno\" nebo \"e-mail\" a \"heslo\"." #: .\serializers.py:95 msgid "User account is disabled." -msgstr "" +msgstr "Uživatelský účet je zakázán." #: .\serializers.py:98 msgid "Unable to log in with provided credentials." -msgstr "" +msgstr "Pomocí zadaných údajů se nelze přihlásit." #: .\serializers.py:107 msgid "E-mail is not verified." -msgstr "" +msgstr "E-mail není ověřený." #: .\views.py:127 msgid "Successfully logged out." -msgstr "" +msgstr "Byli jste úspěšně odhlášení." #: .\views.py:175 msgid "Password reset e-mail has been sent." -msgstr "" +msgstr "E-mail pro resetování hesla byl odeslán." #: .\views.py:201 msgid "Password has been reset with the new password." -msgstr "" +msgstr "Vaše heslo bylo resetováno." #: .\views.py:223 msgid "New password has been saved." -msgstr "" +msgstr "Nové heslo bylo uloženo." From 98212a83f5ddacd78b11ea975bbdebc4f15a1fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=C5=A1ek=20Dohnal?= Date: Wed, 27 Jun 2018 23:19:48 +0200 Subject: [PATCH 46/69] fix typo --- rest_auth/locale/cs/LC_MESSAGES/django.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/rest_auth/locale/cs/LC_MESSAGES/django.po index 43ab5e5..d09df89 100644 --- a/rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/rest_auth/locale/cs/LC_MESSAGES/django.po @@ -1,10 +1,10 @@ # Czech translations of django-rest-auth # -# This file is distributed under the same license as the django-model-utils package. +# This file is distributed under the same license as the Tivix/django-rest-auth package. # msgid "" msgstr "" -"Project-Id-Version: django-rest-auth\n" +"Project-Id-Version: Tivix/django-rest-auth\n" "Report-Msgid-Bugs-To: https://github.com/Tivix/django-rest-auth/issues\n" "POT-Creation-Date: 2018-06-27 23:05+0200\n" "PO-Revision-Date: 2018-06-27 23:15+0200\n" From b778a5085b5086527edf706e110ea03f980e77d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=C5=A1ek=20Dohnal?= Date: Wed, 27 Jun 2018 23:20:10 +0200 Subject: [PATCH 47/69] add full project name --- rest_auth/locale/cs/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/rest_auth/locale/cs/LC_MESSAGES/django.po index d09df89..57291c7 100644 --- a/rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/rest_auth/locale/cs/LC_MESSAGES/django.po @@ -1,4 +1,4 @@ -# Czech translations of django-rest-auth +# Czech translations of Tivix/django-rest-auth # # This file is distributed under the same license as the Tivix/django-rest-auth package. # From 3af4f1a3438bd7add61c549669c8bd35a68b68db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=C5=A1ek=20Dohnal?= Date: Wed, 27 Jun 2018 23:21:56 +0200 Subject: [PATCH 48/69] fix typo --- rest_auth/locale/cs/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/rest_auth/locale/cs/LC_MESSAGES/django.po index 57291c7..7a7b25f 100644 --- a/rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/rest_auth/locale/cs/LC_MESSAGES/django.po @@ -87,7 +87,7 @@ msgstr "E-mail není ověřený." #: .\views.py:127 msgid "Successfully logged out." -msgstr "Byli jste úspěšně odhlášení." +msgstr "Byli jste úspěšně odhlášeni." #: .\views.py:175 msgid "Password reset e-mail has been sent." From 53f901b3c887d4f12219aca64bb6b5ea633b0681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Dohnal?= Date: Wed, 27 Jun 2018 23:22:38 +0200 Subject: [PATCH 49/69] refresh .mo file --- rest_auth/locale/cs/LC_MESSAGES/django.mo | Bin 2376 -> 2488 bytes rest_auth/locale/cs/LC_MESSAGES/django.po | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.mo b/rest_auth/locale/cs/LC_MESSAGES/django.mo index 38857f9a881619301ecd04a57fd1aa8bd0febe2f..3dd71df01d655839aef82270b73b43c1d635de87 100644 GIT binary patch delta 345 zcmX>hv_p8pnfmLD3=Fqe7#Q>!7#KFOF)+vj=|@0X4oEYxLuf@HEdk^^0BIc{9SNj` zfpi;?RtD0ufV3fy-Up=Zf%FF;Ed`_vI2agYfwVV})&|ma(=EpcGdcs#l@wm#gkcCy_k%QCI_+}u?{=DFgYi& zOu;2TBQG&W!KN$`#MMgya~;xi6Ekx_2HJ7?04**}Oi$GfNlnbPQt;Dv+^otb&%~Iy J*^PsV5dbjTOX2_k delta 251 zcmdlXd_ri#nff$F28LTK3=H}V3=EEJ3=Hx>x)4aq0qKcQdIOM_0P@cRX&oT_0!Rx3 zX;F3t24x_v38W2yv@ejh2h#OGS_(+-2hy@Y`WBGZ2GT!(G)TP)2Lpo)koMqU&;whX z3KUQR3QPskAcyP#(jbj5fV3TuX5(aFU;@&vn=2VhnZ>z+QVa5nN_2gT(=$_aol4V- zbwl#46efGKdNCQAPM*$sM1adDF)zI|F+Ei`BsDSDN@4RfHhCtd!)rHh<6vS007B|1 Ap8x;= diff --git a/rest_auth/locale/cs/LC_MESSAGES/django.po b/rest_auth/locale/cs/LC_MESSAGES/django.po index 7a7b25f..eb8c60c 100644 --- a/rest_auth/locale/cs/LC_MESSAGES/django.po +++ b/rest_auth/locale/cs/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: Tivix/django-rest-auth\n" "Report-Msgid-Bugs-To: https://github.com/Tivix/django-rest-auth/issues\n" "POT-Creation-Date: 2018-06-27 23:05+0200\n" -"PO-Revision-Date: 2018-06-27 23:15+0200\n" +"PO-Revision-Date: 2018-06-27 23:22+0200\n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" From 033ee8f483e7c552ed5382120dbd00481fe80ac1 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 21 Aug 2018 21:12:28 -0700 Subject: [PATCH 50/69] Remove deprecated EZ setup --- setup.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 2c9dad4..66c4c04 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,8 @@ #!/usr/bin/env python -try: - from setuptools import setup, find_packages -except ImportError: - from ez_setup import use_setuptools - use_setuptools() - from setuptools import setup, find_packages - - import os +from setuptools import setup, find_packages + here = os.path.dirname(os.path.abspath(__file__)) f = open(os.path.join(here, 'README.rst')) From f0941b4cc2d23e81c75660a9b032dbab785456ff Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 21 Aug 2018 21:16:52 -0700 Subject: [PATCH 51/69] Merge tools configs into setup.cfg --- flake8 | 4 ---- .coveragerc => setup.cfg | 15 ++++++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) delete mode 100644 flake8 rename .coveragerc => setup.cfg (77%) diff --git a/flake8 b/flake8 deleted file mode 100644 index 401fdf4..0000000 --- a/flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length = 120 -exclude = docs/*,demo/* -ignore = F403 \ No newline at end of file diff --git a/.coveragerc b/setup.cfg similarity index 77% rename from .coveragerc rename to setup.cfg index 70d6d0d..3ba7986 100644 --- a/.coveragerc +++ b/setup.cfg @@ -1,8 +1,13 @@ -# .coveragerc to control coverage.py -[run] +[flake8] +max-line-length = 120 +exclude = docs/*,demo/* +ignore = F403 + + +[coverage:run] omit=*site-packages*,*distutils*,*migrations* -[report] +[coverage:report] # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma @@ -22,5 +27,5 @@ exclude_lines = ignore_errors = True -[html] -directory = coverage_html \ No newline at end of file +[coverage:html] +directory = coverage_html From 691c73d5569834d82c7e1df03e74bbdbc089ade3 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 21 Aug 2018 21:18:41 -0700 Subject: [PATCH 52/69] Update .gitignore from GH --- .gitignore | 77 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 7d8d699..894a44c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,35 @@ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] +*$py.class # C extensions *.so # Distribution / packaging .Python -env/ -bin/ build/ develop-eggs/ dist/ +downloads/ eggs/ +.eggs/ lib/ lib64/ parts/ sdist/ var/ +wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec # Installer logs pip-log.txt @@ -30,28 +39,66 @@ pip-delete-this-directory.txt htmlcov/ .tox/ .coverage +.coverage.* .cache nosetests.xml coverage.xml -coverage_html +*.cover +.hypothesis/ +.pytest_cache/ -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Rope -.ropeproject +# Translations +*.mo +*.pot # Django stuff: *.log -*.pot +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy # Sphinx documentation docs/_build/ -.DS_Store -db.sqlite3 +# PyBuilder +target/ -# IntelliJ IDE files -.idea +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ From 4b07c3ca92d64927d0b8ea454bc44ef0d9691000 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 21 Aug 2018 21:29:15 -0700 Subject: [PATCH 53/69] Add wheel & metdata config --- setup.cfg | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/setup.cfg b/setup.cfg index 3ba7986..8d915a7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,11 @@ +[bdist_wheel] +universal = 1 + + +[metadata] +license_file = LICENSE + + [flake8] max-line-length = 120 exclude = docs/*,demo/* From 5d318b3a4ba3572755a631a272594f2342ab04ae Mon Sep 17 00:00:00 2001 From: erdtsksn Date: Sat, 13 Oct 2018 20:15:09 +0300 Subject: [PATCH 54/69] feat: Add Turkish(tr) translation oth: There is no .mo file because there is a .gitignore entry for that. --- rest_auth/locale/tr/LC_MESSAGES/django.po | 95 +++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 rest_auth/locale/tr/LC_MESSAGES/django.po diff --git a/rest_auth/locale/tr/LC_MESSAGES/django.po b/rest_auth/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..f02af80 --- /dev/null +++ b/rest_auth/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# 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: 2017-03-05 21:56-0800\n" +"PO-Revision-Date: 2018-10-13 19:37+0300\n" +"Language: tr\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\n" + +#: registration/serializers.py:67 +msgid "View is not defined, pass it as a context variable" +msgstr "“View” tanımlanmadı, “context” değişkeni olarak tanımla" + +#: registration/serializers.py:72 +msgid "Define adapter_class in view" +msgstr "“view” içerisinde “adapter_class” tanımla" + +#: registration/serializers.py:91 +msgid "Define callback_url in view" +msgstr "“view” içerisinde “callback_url” tanımla" + +#: registration/serializers.py:95 +msgid "Define client_class in view" +msgstr "“view” içerisinde “client_class” tanımla" + +#: registration/serializers.py:116 +msgid "Incorrect input. access_token or code is required." +msgstr "Geçersiz girdi. “access_token” veya “code” gerekli." + +#: registration/serializers.py:125 +msgid "Incorrect value" +msgstr "Geçersiz değer" + +#: registration/serializers.py:185 +msgid "A user is already registered with this e-mail address." +msgstr "Bu e-posta adresi ile bir kullanıcı zaten kayıt olmuştu." + +#: registration/serializers.py:193 +msgid "The two password fields didn't match." +msgstr "İki şifre alanı eşleşmiyor." + +#: registration/views.py:98 +msgid "ok" +msgstr "tamam" + +#: serializers.py:33 +msgid "Must include \"email\" and \"password\"." +msgstr "\"email\" ve \"password\" içermelidir." + +#: serializers.py:44 +msgid "Must include \"username\" and \"password\"." +msgstr "“username\" und \"password\" içermelidir." + +#: serializers.py:57 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Ya ”username\" yada \"email\" ve \"password\" içermelidir." + +#: serializers.py:98 +msgid "User account is disabled." +msgstr "Kullanıcı hesap pasiftir." + +#: serializers.py:101 +msgid "Unable to log in with provided credentials." +msgstr "Sağlanan kimlik bilgileri ile giriş yapılamıyor." + +#: serializers.py:110 +msgid "E-mail is not verified." +msgstr "E-posta adresi doğrulanmadı." + +#: views.py:127 +msgid "Successfully logged out." +msgstr "Başarılı bir şekilde çıkış yapıldı." + +#: views.py:175 +msgid "Password reset e-mail has been sent." +msgstr "Şifre sıfırlama e-postası gönderildi." + +#: views.py:201 +msgid "Password has been reset with the new password." +msgstr "Yeni şifre ile şifre sıfırlandı." + +#: views.py:223 +msgid "New password has been saved." +msgstr "Yeni şifre kaydedildi." From f5fe62ce913f52a41fec7c0aef1b50a2d422e523 Mon Sep 17 00:00:00 2001 From: Kurt Neufeld Date: Thu, 25 Oct 2018 11:28:24 -0600 Subject: [PATCH 55/69] expand JWT acronym in docs --- docs/installation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index fa512c5..647a131 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -205,8 +205,8 @@ You can also use the following views to check all social accounts attached to th ] -JWT Support (optional) ----------------------- +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: From ca39ba7ea99c7c6716fc0da9695da2a839808525 Mon Sep 17 00:00:00 2001 From: Magnun Leno Date: Sat, 27 Oct 2018 02:14:25 -0300 Subject: [PATCH 56/69] Adds django-allauth to dev-requirements.txt --- dev-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-requirements.txt b/dev-requirements.txt index b0a8d61..0a2a9e4 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,3 +1,4 @@ --editable . responses>=0.5.0 djangorestframework-jwt +django-allauth From 9913f8eb03ec42bdae16100744b227f3ea52d2a6 Mon Sep 17 00:00:00 2001 From: yihuang Date: Sun, 28 Oct 2018 11:46:19 +0800 Subject: [PATCH 57/69] add translation for Chinese --- .../locale/zh_Hans/LC_MESSAGES/django.mo | Bin 0 -> 2284 bytes .../locale/zh_Hans/LC_MESSAGES/django.po | 104 ++++++++++++++++++ .../locale/zh_Hant/LC_MESSAGES/django.mo | Bin 0 -> 414 bytes .../locale/zh_Hant/LC_MESSAGES/django.po | 103 +++++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo create mode 100644 rest_auth/locale/zh_Hans/LC_MESSAGES/django.po create mode 100644 rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo create mode 100644 rest_auth/locale/zh_Hant/LC_MESSAGES/django.po diff --git a/rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo b/rest_auth/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..2f6f549e1eb09745256ceda6da662ebc745c57fe GIT binary patch literal 2284 zcmb7^TWl0n7{`x_w^c;(9&aZVtO?AzOOTW;AQcK}Y)bRf7r4F=NYUQvA)N832Xm7_`&lBxCZn66GWG)4Sf&7*+&k#6viOb_|1Jk&#kU{7H^f`zi! zVl2wxNvy}Q9>ap0pnf_(w2VE0Re2sR|G6Ke8bc&EaL=L#Xd!Fwk=*UGs@b5`hURch*UVa%Cxol^gjt6vx(pavw3p5>n24lp_39ct zspvJr=)%BAbkH2(WGv4_tI3l?n^9Px!JGdzVLOB4SB0xvW@Y@Gpr)OeF$zFKq6KrP ztqkhmy35g1fq5`pxfdfOY@Kpo)*jYoTe~qrN|UC*wF9p)-qx_`orbNAd}rhK9ZlO> zL)&H2vR$RciR+s3wikDlb}Pn1ZQI(FP53w{6=kzyDdz|5Uyp%cvmgw>x7oj&5e8ahE*%Ep%zAF+!JxB zv`dkQ@#costsRu?y5{DMh90);_=b5KB-zr`(par58jgfEQ5Q@E+LuJe)Q~rlhS1G= zuJ#BUleNC1eT!08wWEZ(rL8pLd((6?9^-Xgx*KXUJX;vb7RydJF>WRU(ODm@=cT{v zBlV$O^W{iQ>2QM0+HO=}DYk`BuHcdIS|r5^>GQ<{Q~9Yc{Zp6x&r<&MSB0~axyu** zgG0Zj4nRHapSnm#oXvdUPmN`-et6R*Q#PP`X5L`oMRQyIg3E@Lg6B?66eorX>HZ+* z^-uhP^Tnel3h6ZDg||!Y&@sAPa>vvD+<-qmSscGgJ4&|su@C&z49lgD`WFuPLj(TE zWckDQKOU-HEVSV!oB6BaKbrkMGgS6V|0?%KjX!V&Ey!k4*~~-`JNWZOa*;`Q1XyJam^q6hWunR=W?Hq7lMXS z`9ZvF=1Bfz#vd7CxlhmJE{|qs=kiA{=7vYI*H6MIJ2#%|Pm_b^$BTo**_ksqXy%`vMOy41 DJlZ(X literal 0 HcmV?d00001 diff --git a/rest_auth/locale/zh_Hans/LC_MESSAGES/django.po b/rest_auth/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..1c7ff82 --- /dev/null +++ b/rest_auth/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,104 @@ +# 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. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-10-28 11:41+0800\n" +"PO-Revision-Date: 2018-10-28 11:45+0806\n" +"Last-Translator: b' '\n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Translated-Using: django-rosetta 0.9.0\n" + +#: registration/serializers.py:67 +msgid "View is not defined, pass it as a context variable" +msgstr "View未定义,请通过context变量传入" + +#: registration/serializers.py:72 +msgid "Define adapter_class in view" +msgstr "请在View中定义adapter_class" + +#: registration/serializers.py:91 +msgid "Define callback_url in view" +msgstr "请在view中定义callback_url" + +#: registration/serializers.py:95 +msgid "Define client_class in view" +msgstr "请在view中定义client_class" + +#: registration/serializers.py:116 +msgid "Incorrect input. access_token or code is required." +msgstr "输入错误。access_token或code是必填项。" + +#: registration/serializers.py:125 +msgid "Incorrect value" +msgstr "错误的值" + +#: registration/serializers.py:139 +msgid "User is already registered with this e-mail address." +msgstr "该邮箱地址已被注册。" + +#: registration/serializers.py:185 +msgid "A user is already registered with this e-mail address." +msgstr "该邮箱地址已被注册。" + +#: registration/serializers.py:193 +msgid "The two password fields didn't match." +msgstr "两次输入的密码不相同" + +#: registration/views.py:51 +msgid "Verification e-mail sent." +msgstr "验证邮件已发送。" + +#: registration/views.py:98 +msgid "ok" +msgstr "好的" + +#: serializers.py:33 +msgid "Must include \"email\" and \"password\"." +msgstr "比如包含\"email\"和\"password\"。" + +#: serializers.py:44 +msgid "Must include \"username\" and \"password\"." +msgstr "比如包含\"username\"和\"password\"。" + +#: serializers.py:57 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "比如包含\"username\",\"email\",\"password\"其中一个。" + +#: serializers.py:98 +msgid "User account is disabled." +msgstr "用户账号已被禁用。" + +#: serializers.py:101 +msgid "Unable to log in with provided credentials." +msgstr "无法使用提供的信息登录。" + +#: serializers.py:110 +msgid "E-mail is not verified." +msgstr "邮箱未验证。" + +#: views.py:127 +msgid "Successfully logged out." +msgstr "已成功登出。" + +#: views.py:175 +msgid "Password reset e-mail has been sent." +msgstr "密码重置邮件已发送。" + +#: views.py:201 +msgid "Password has been reset with the new password." +msgstr "密码重置成功。" + +#: views.py:223 +msgid "New password has been saved." +msgstr "新密码已设置成功。" diff --git a/rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo b/rest_auth/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..20e5d8dbda6a94eed8fbbe7c2b79f0f6fab611c8 GIT binary patch literal 414 zcmYL^Pfx=j9ENA~)T3t)9K6lnY!?reZDzRA+1P*Sx+QwU6>Cig4KSl0#INUPk*aZT z@&pJE@bYzf@;R_MvYc7YEytD%OCR4-+0AP^_RfEDC13g0KvcnoE8R$eQBD^3WJ%G6 z7ON;roq~5#8Ax>9RB*emHIxz~C(lY)D9(&M1OYP~qp|Dx;JGmNk>}wnZ|M52Yegvd zThm|u=RHtTK$1Z~&|QX;X!w|=)QOokP%0*L%ZyYQh3hy*DM=`r(u73uoCHBZSF0PV zih9p#4kc$hjAD{5*L~$_9M9WkBvpNIY}F)6=;43f$aNM{7%uE{AD!)O_`A96TGogO z+P*NQxtXoY5d4GJ*Lvm(sMyM?5j95sQ)8UG-7D5YDAi75B)Xrao_Q1WJDs@`XYdX3 CzjEdP literal 0 HcmV?d00001 diff --git a/rest_auth/locale/zh_Hant/LC_MESSAGES/django.po b/rest_auth/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..b99489a --- /dev/null +++ b/rest_auth/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,103 @@ +# 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. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-10-28 11:41+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: registration/serializers.py:67 +msgid "View is not defined, pass it as a context variable" +msgstr "" + +#: registration/serializers.py:72 +msgid "Define adapter_class in view" +msgstr "" + +#: registration/serializers.py:91 +msgid "Define callback_url in view" +msgstr "" + +#: registration/serializers.py:95 +msgid "Define client_class in view" +msgstr "" + +#: registration/serializers.py:116 +msgid "Incorrect input. access_token or code is required." +msgstr "" + +#: registration/serializers.py:125 +msgid "Incorrect value" +msgstr "" + +#: registration/serializers.py:139 +msgid "User is already registered with this e-mail address." +msgstr "" + +#: registration/serializers.py:185 +msgid "A user is already registered with this e-mail address." +msgstr "" + +#: registration/serializers.py:193 +msgid "The two password fields didn't match." +msgstr "" + +#: registration/views.py:51 +msgid "Verification e-mail sent." +msgstr "" + +#: registration/views.py:98 +msgid "ok" +msgstr "" + +#: serializers.py:33 +msgid "Must include \"email\" and \"password\"." +msgstr "" + +#: serializers.py:44 +msgid "Must include \"username\" and \"password\"." +msgstr "" + +#: serializers.py:57 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "" + +#: serializers.py:98 +msgid "User account is disabled." +msgstr "" + +#: serializers.py:101 +msgid "Unable to log in with provided credentials." +msgstr "" + +#: serializers.py:110 +msgid "E-mail is not verified." +msgstr "" + +#: views.py:127 +msgid "Successfully logged out." +msgstr "" + +#: views.py:175 +msgid "Password reset e-mail has been sent." +msgstr "" + +#: views.py:201 +msgid "Password has been reset with the new password." +msgstr "" + +#: views.py:223 +msgid "New password has been saved." +msgstr "" From c437ca22ff2e37838f78253c5320c89f8282f5ba Mon Sep 17 00:00:00 2001 From: Oskar Persson Date: Fri, 9 Nov 2018 15:58:09 +0100 Subject: [PATCH 58/69] Translate msg when providing incorrect old password --- rest_auth/serializers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rest_auth/serializers.py b/rest_auth/serializers.py index 2ea6550..b645231 100644 --- a/rest_auth/serializers.py +++ b/rest_auth/serializers.py @@ -256,7 +256,8 @@ class PasswordChangeSerializer(serializers.Serializer): ) if all(invalid_password_conditions): - raise serializers.ValidationError('Invalid password') + err_msg = _("Your old password was entered incorrectly. Please enter it again.") + raise serializers.ValidationError(err_msg) return value def validate(self, attrs): From 25b94db0cc4022df2bd80240dc10e06c28e09ac1 Mon Sep 17 00:00:00 2001 From: vthorey Date: Mon, 12 Nov 2018 16:49:36 +0100 Subject: [PATCH 59/69] Update installation.rst --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index fa512c5..e1a07bf 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -131,7 +131,7 @@ 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.views.LoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute: +3. Create new view as a subclass of ``rest_auth.registration.views.SocialLoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute: .. code-block:: python From e891a76c3f7426a047afa6e2cb988eeecc699612 Mon Sep 17 00:00:00 2001 From: Valentino Date: Mon, 12 Nov 2018 16:58:07 +0100 Subject: [PATCH 60/69] Add example of github API in installation doc. --- docs/installation.rst | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/installation.rst b/docs/installation.rst index e1a07bf..1bd63ea 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -154,6 +154,34 @@ If you are using Twitter for your social authentication, it is a bit different s .. 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. + +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: + +.. 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 + + class GithubLogin(SocialLoginView): + adapter_class = GitHubOAuth2Adapter + callback_url = CALLBACK_URL_YOU_SET_ON_GITHUB + client_class = OAuth2Client + +4. Create url for GitHubLogin view: + +.. code-block:: python + + urlpatterns += [ + ..., + url(r'^rest-auth/github/$', GitHubLogin.as_view(), name='github_login') + ] + Additional Social Connect Views ############################### @@ -162,6 +190,9 @@ If you want to allow connecting existing accounts in addition to login, you can .. code-block:: python from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + 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 @@ -172,6 +203,12 @@ If you want to allow connecting existing accounts in addition to login, you can serializer_class = TwitterConnectSerializer adapter_class = TwitterOAuthAdapter + class GithubConnect(SocialConnectView): + adapter_class = GitHubOAuth2Adapter + callback_url = CALLBACK_URL_YOU_SET_ON_GITHUB + client_class = OAuth2Client + + In urls.py: .. code-block:: python @@ -180,6 +217,7 @@ In urls.py: ..., 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') ] You can also use the following views to check all social accounts attached to the current authenticated user and disconnect selected social accounts: From a3d38f4c59a9b9dbe1ca8c3408b103f307d47e81 Mon Sep 17 00:00:00 2001 From: Jasper Wan Date: Sun, 3 Feb 2019 11:42:24 +0800 Subject: [PATCH 61/69] disable django_logout if REST_SESSION_LOGIN is False --- rest_auth/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_auth/views.py b/rest_auth/views.py index 8efcdd5..3c1a164 100644 --- a/rest_auth/views.py +++ b/rest_auth/views.py @@ -121,8 +121,8 @@ class LogoutView(APIView): request.user.auth_token.delete() except (AttributeError, ObjectDoesNotExist): pass - - django_logout(request) + if getattr(settings, 'REST_SESSION_LOGIN', True): + django_logout(request) return Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) From 64b5572172ea664dd2354a78787a06d0a5f39943 Mon Sep 17 00:00:00 2001 From: Jeongsoo Park Date: Wed, 20 Mar 2019 17:44:18 +0900 Subject: [PATCH 62/69] add a korean translation --- rest_auth/locale/ko/LC_MESSAGES/django.po | 99 +++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 rest_auth/locale/ko/LC_MESSAGES/django.po diff --git a/rest_auth/locale/ko/LC_MESSAGES/django.po b/rest_auth/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..8eb3bef --- /dev/null +++ b/rest_auth/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,99 @@ +# 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. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-05 21:56-0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Jeonsgoo Park \n" +"Language-Team: LANGUAGE \n" +"Language: ko\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: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 "view에 adapter_class를 정의하세요" + +#: registration/serializers.py:77 +msgid "Define callback_url in view" +msgstr "view에 callback_url을 정의하세요" + +#: registration/serializers.py:81 +msgid "Define client_class in view" +msgstr "view에 client_class를 정의하세요" + +#: 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 "이미 이 이메일 주소로 등록된 사용자가 있습니다." + +#: registration/serializers.py:148 +msgid "The two password fields didn't match." +msgstr "두 개의 패스워드 필드가 서로 맞지 않습니다." + +#: registration/views.py:44 +msgid "Verification e-mail sent." +msgstr "확인 이메일을 발송했습니다." + +#: registration/views.py:91 +msgid "ok" +msgstr "ok" + +#: serializers.py:30 +msgid "Must include \"email\" and \"password\"." +msgstr "\"email\"과 \"password\"를 반드시 포함해야 합니다." + +#: serializers.py:41 +msgid "Must include \"username\" and \"password\"." +msgstr "\"username\"과 \"password\"를 반드시 포함해야 합니다." + +#: serializers.py:54 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "\"username\"이나 \"email\", 그리고 \"password\"를 반드시 포함해야 합니다." + +#: 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 "이메일 주소가 확인되지 않았습니다." + +#: 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 11e877ba50771892782fb9a2213812a03a259030 Mon Sep 17 00:00:00 2001 From: Jeongsoo Park Date: Wed, 20 Mar 2019 17:51:09 +0900 Subject: [PATCH 63/69] add a korean translation mo file --- rest_auth/locale/ko/LC_MESSAGES/django.mo | Bin 0 -> 2562 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rest_auth/locale/ko/LC_MESSAGES/django.mo diff --git a/rest_auth/locale/ko/LC_MESSAGES/django.mo b/rest_auth/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..79c07cf696cab7db9cbcda362aadac3c3580eefc GIT binary patch literal 2562 zcmbu9-)|IE6vszJ(e*b-#Hh)!QNh5hK-Azu36(BbZM(I!B>K|a&fIRt&d#j!qm>5} z0$Xef#tL27!fq{*0yRx2w(1)D;DZmo`rv~vMt$75`#0eC&hB=%w8R)Ex%-*fdw!pD z?;o2sWEDJHu%5&E8S8m0^B(-*`4fBt{0o%(TklnrXTjI2d=GpY-zjhpI0`-v7Qq+6 zU%+i(8GIAma$m(x0*vC@1f|?%a4Yx|_!9U#xC6WmJ_GL9P+=UDe)>R|RL+6zh%E~q z!uQ|zE6R58Eo+DC2J0s3hm3Q&7Ns+ z%ezA_UU33mp>rti6(rm}!ng=Us--{B{G(^$o*+bkS+ab-?xlF;~ANd9X zZ&Vp(rq7iQ-<8^$=|i%K%Ve5}SvobP5&4Mi=uOc(gk)VTmg4^+$5A5`u&FMNfbQm@ zlaEl%Aq_H@`Z+Ri*|3bcs~Smt1GVN}tqYv22JHs%id3~jb)%?nR5|L0r5f-}^EjDy zGKsF*D526b$jKYA>(QXprtXq%=+-umQq0o^qe`#E`b`MhQdjmcoQSkz4;wlxX{a^a z7|g^-^vXFxXKdd>sih@XDkHIDVJ9`_8MalMBsUE27{*1)%6{wNNa;JnkjU@|ZT-ACIJosn*ywjEFHaFd3v zzU3!fwa1Q8q${Cz^I=2ksIAQ7F?v7V(yewR)YcYyI}z(>+wno7GahMYuBY}m%yLcU z*-nh!;kM-_ZJWB7GerCGAJa^JFexV~s@bUnP_dFeOLDb`vs8@QTRM;Q%82&2w;wc( zsO=={GBFymBOPrW@p=Ngqq`!9WU>|S!nLgnGZvh=8dc<} z7Z)d1UkAY~?960EAy>}kM5ZV%O|A$wUJaslrL9oKvb- zKxuKg;f|3x1Pi&~d|sT%Q~C4xa`r|!yCky9)L^oHm;68NYUtHSc2ep4VsLG~v^evh zBNC^^Fbv|-5|z*15aUKDBo9iwP=0uaH|64O)p-#I-{3^{B`%hbk4vg<=@ocVnngFh1MR+?8WQrNvBmK9Ix@netR#WNy{U z0Q;*BSY@W`2UMP!O6KJYjb)ejX{9Uj+{wh(IRhkqyip$g3~elr7b#dgA;!?XiH31R KhL!V*%l03*mkKNZ literal 0 HcmV?d00001 From d2cd31a5603c0a65b05cc9d817542d3349fc0c8d Mon Sep 17 00:00:00 2001 From: Jeongsoo Park Date: Wed, 20 Mar 2019 17:52:51 +0900 Subject: [PATCH 64/69] update revision date --- rest_auth/locale/ko/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_auth/locale/ko/LC_MESSAGES/django.po b/rest_auth/locale/ko/LC_MESSAGES/django.po index 8eb3bef..777a2bf 100644 --- a/rest_auth/locale/ko/LC_MESSAGES/django.po +++ b/rest_auth/locale/ko/LC_MESSAGES/django.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-03-05 21:56-0800\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2018-03-20 17:52+0900\n" "Last-Translator: Jeonsgoo Park \n" "Language-Team: LANGUAGE \n" "Language: ko\n" From f39d93042e89912e28d73c4d9e82f60ff0bfe5f4 Mon Sep 17 00:00:00 2001 From: Gaurav Sheni Date: Tue, 26 Mar 2019 11:07:27 -0400 Subject: [PATCH 65/69] Update installation.rst --- docs/installation.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index fa512c5..b9247fa 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -210,8 +210,8 @@ JWT Support (optional) By default ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, follow these steps: -1. Install `django-rest-framework-jwt `_ - - ``django-rest-framework-jwt`` is currently the only supported JWT library. +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. From c7ff94ced701a9134630682a1ace7a279bddcbc5 Mon Sep 17 00:00:00 2001 From: mario Date: Mon, 1 Apr 2019 07:51:51 +0200 Subject: [PATCH 66/69] feat: prep for new release (0.9.4) --- demo/requirements.pip | 2 +- docs/changelog.rst | 8 ++++++++ docs/conf.py | 4 ++-- setup.py | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index 7480482..a74495b 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.9.0 -django-rest-auth==0.9.3 +django-rest-auth==0.9.4 djangorestframework>=3.7.0 django-allauth>=0.24.1 six==1.9.0 diff --git a/docs/changelog.rst b/docs/changelog.rst index fa79dbc..65fa7b7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,14 @@ Changelog ========= +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 diff --git a/docs/conf.py b/docs/conf.py index c8ecb3b..0e988c8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,9 +51,9 @@ copyright = u'2018, Tivix Inc.' # built documents. # # The short X.Y version. -version = '0.9.3' +version = '0.9.4' # The full version, including alpha/beta/rc tags. -release = '0.9.3' +release = '0.9.4' # 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 66c4c04..f71f293 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() setup( name='django-rest-auth', - version='0.9.3', + version='0.9.4', author='Sumit Chachra', author_email='chachra@tivix.com', url='http://github.com/Tivix/django-rest-auth', From 998b2b1fbc883f929cf23d50b867b68913ed6dfa Mon Sep 17 00:00:00 2001 From: mario Date: Mon, 1 Apr 2019 09:51:08 +0200 Subject: [PATCH 67/69] feat: prep for new release (0.9.5) --- demo/requirements.pip | 2 +- docs/changelog.rst | 4 ++++ docs/conf.py | 4 ++-- setup.py | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/demo/requirements.pip b/demo/requirements.pip index a74495b..40b4820 100644 --- a/demo/requirements.pip +++ b/demo/requirements.pip @@ -1,5 +1,5 @@ django>=1.9.0 -django-rest-auth==0.9.4 +django-rest-auth==0.9.5 djangorestframework>=3.7.0 django-allauth>=0.24.1 six==1.9.0 diff --git a/docs/changelog.rst b/docs/changelog.rst index 65fa7b7..e7beb5d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,10 @@ Changelog ========= +0.9.5 +----- +- fixed package distribution issue + 0.9.4 ----- - Compatibility fixes (#437, #506) diff --git a/docs/conf.py b/docs/conf.py index 0e988c8..1c825cc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,9 +51,9 @@ copyright = u'2018, Tivix Inc.' # built documents. # # The short X.Y version. -version = '0.9.4' +version = '0.9.5' # The full version, including alpha/beta/rc tags. -release = '0.9.4' +release = '0.9.5' # 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 f71f293..675b99d 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ f.close() setup( name='django-rest-auth', - version='0.9.4', + version='0.9.5', author='Sumit Chachra', author_email='chachra@tivix.com', url='http://github.com/Tivix/django-rest-auth', From 07d2bd5c5629e5bfff6ecdd605c29027d7380559 Mon Sep 17 00:00:00 2001 From: Bruno Barreto Freitas Date: Tue, 16 Apr 2019 10:27:43 -0300 Subject: [PATCH 68/69] Brazilian Portuguese Translation - django.po file --- rest_auth/locale/pt_BR/LC_MESSAGES/django.po | 99 ++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 rest_auth/locale/pt_BR/LC_MESSAGES/django.po diff --git a/rest_auth/locale/pt_BR/LC_MESSAGES/django.po b/rest_auth/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..d816a54 --- /dev/null +++ b/rest_auth/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,99 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Bruno Barreto Freitas , 2019. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-04-16 09:48-0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Bruno Barreto Freitas \n" +"Language-Team: LANGUAGE \n" +"Language: \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:53 +msgid "View is not defined, pass it as a context variable" +msgstr "\"View\" não está definida, passe-a como uma variável de contexto" + +#: registration/serializers.py:58 +msgid "Define adapter_class in view" +msgstr "Defina \"adapter_class\" na view" + +#: registration/serializers.py:77 +msgid "Define callback_url in view" +msgstr "Defina \"callback_url\" na view" + +#: registration/serializers.py:81 +msgid "Define client_class in view" +msgstr "Defina \"client_class\" na view" + +#: registration/serializers.py:102 +msgid "Incorrect input. access_token or code is required." +msgstr "Entrada incorreta. \"access_token\" ou \"code\" são obrigatórios." + +#: registration/serializers.py:111 +msgid "Incorrect value" +msgstr "Valor incorreto" + +#: registration/serializers.py:140 +msgid "A user is already registered with this e-mail address." +msgstr "Já existe um usuário cadastrado com este endereço de e-mail." + +#: registration/serializers.py:148 +msgid "The two password fields didn't match." +msgstr "Os dois campos de senha não correspondem." + +#: registration/views.py:44 +msgid "Verification e-mail sent." +msgstr "E-mail de verificação enviado." + +#: registration/views.py:91 +msgid "ok" +msgstr "Ok" + +#: serializers.py:30 +msgid "Must include \"email\" and \"password\"." +msgstr "Deve-se incluir \"email\" e \"password\"." + +#: serializers.py:41 +msgid "Must include \"username\" and \"password\"." +msgstr "Deve-se incluir \"username\" e \"password\"." + +#: serializers.py:54 +msgid "Must include either \"username\" or \"email\" and \"password\"." +msgstr "Deve-se incluir \"username\" ou \"email\" e \"password\"." + +#: serializers.py:95 +msgid "User account is disabled." +msgstr "Conta de usuário está desativada" + +#: serializers.py:98 +msgid "Unable to log in with provided credentials." +msgstr "Não foi possível realizar o login com as credenciais fornecidas." + +#: serializers.py:107 +msgid "E-mail is not verified." +msgstr "E-mail não foi verificado." + +#: views.py:126 +msgid "Successfully logged out." +msgstr "Logout realizado com sucesso." + +#: views.py:174 +msgid "Password reset e-mail has been sent." +msgstr "E-mail de redefinição de senha foi enviado." + +#: views.py:200 +msgid "Password has been reset with the new password." +msgstr "Senha foi redefinida com a nova senha." + +#: views.py:222 +msgid "New password has been saved." +msgstr "Nova senha foi salva com sucesso." From 0ad457cea6323ff79658a2a0eefeb0dfdda3f794 Mon Sep 17 00:00:00 2001 From: Raunaq Singh Date: Tue, 25 Feb 2020 12:20:57 +0530 Subject: [PATCH 69/69] Update ReadMe with state of repo According to this issue: https://github.com/Tivix/django-rest-auth/issues/568. This repository is currently unmaintained. This information should be obvious to new users planning to use this package. Hence making this PR. Thanks. --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index ac7f19e..9b54d48 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,8 @@ Welcome to django-rest-auth =========================== +Repository is unmaintained at the moment (on pause). More info can be found on this issue page: https://github.com/Tivix/django-rest-auth/issues/568 + .. image:: https://travis-ci.org/Tivix/django-rest-auth.svg :target: https://travis-ci.org/Tivix/django-rest-auth