[Python-modules-commits] [django-allauth] 01/03: New upstream version 0.35.0

Pierre-Elliott Bécue peb-guest at moszumanska.debian.org
Tue Feb 6 08:20:22 UTC 2018


This is an automated email from the git hooks/post-receive script.

peb-guest pushed a commit to branch master
in repository django-allauth.

commit 58ab8f0afaefffb35db2cfa89c02466d0b4729e0
Author: Pierre-Elliott Bécue <becue at crans.org>
Date:   Tue Feb 6 09:09:22 2018 +0100

    New upstream version 0.35.0
---
 AUTHORS                                            |   2 +
 ChangeLog.rst                                      |  18 ++
 PKG-INFO                                           |  12 +-
 README.rst                                         |   6 +-
 allauth/__init__.py                                |   6 +-
 allauth/account/adapter.py                         |  20 +-
 allauth/account/admin.py                           |   6 -
 allauth/account/app_settings.py                    |   6 +-
 allauth/account/auth_backends.py                   |   2 +-
 allauth/account/forms.py                           |  35 ++-
 allauth/account/tests.py                           |  67 +++++-
 allauth/account/utils.py                           |  11 +-
 allauth/account/views.py                           |  20 +-
 allauth/compat.py                                  |  42 ----
 allauth/locale/ar/LC_MESSAGES/django.mo            | Bin 16110 -> 16110 bytes
 allauth/locale/ar/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/cs/LC_MESSAGES/django.mo            | Bin 11211 -> 11707 bytes
 allauth/locale/cs/LC_MESSAGES/django.po            | 120 ++++++-----
 allauth/locale/de/LC_MESSAGES/django.mo            | Bin 13474 -> 16890 bytes
 allauth/locale/de/LC_MESSAGES/django.po            | 237 ++++++++++-----------
 allauth/locale/el/LC_MESSAGES/django.mo            | Bin 18617 -> 18617 bytes
 allauth/locale/el/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/en/LC_MESSAGES/django.mo            | Bin 378 -> 378 bytes
 allauth/locale/en/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/es/LC_MESSAGES/django.mo            | Bin 13890 -> 14037 bytes
 allauth/locale/es/LC_MESSAGES/django.po            | 216 +++++++++----------
 allauth/locale/fa/LC_MESSAGES/django.mo            | Bin 16978 -> 16978 bytes
 allauth/locale/fa/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/fi/LC_MESSAGES/django.mo            | Bin 14484 -> 14484 bytes
 allauth/locale/fi/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/fr/LC_MESSAGES/django.mo            | Bin 15863 -> 15856 bytes
 allauth/locale/fr/LC_MESSAGES/django.po            | 112 +++++-----
 allauth/locale/he/LC_MESSAGES/django.mo            | Bin 15958 -> 15958 bytes
 allauth/locale/he/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/hr/LC_MESSAGES/django.mo            | Bin 13503 -> 13503 bytes
 allauth/locale/hr/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/hu/LC_MESSAGES/django.mo            | Bin 12062 -> 12062 bytes
 allauth/locale/hu/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/it/LC_MESSAGES/django.mo            | Bin 13206 -> 13206 bytes
 allauth/locale/it/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/ja/LC_MESSAGES/django.mo            | Bin 14805 -> 14805 bytes
 allauth/locale/ja/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/ko/LC_MESSAGES/django.mo            | Bin 14092 -> 14092 bytes
 allauth/locale/ko/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/ky/LC_MESSAGES/django.mo            | Bin 18533 -> 18533 bytes
 allauth/locale/ky/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/lt/LC_MESSAGES/django.mo            | Bin 15531 -> 15531 bytes
 allauth/locale/lt/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/lv/LC_MESSAGES/django.mo            | Bin 15188 -> 15188 bytes
 allauth/locale/lv/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/nl/LC_MESSAGES/django.mo            | Bin 13772 -> 13772 bytes
 allauth/locale/nl/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/no/LC_MESSAGES/django.mo            | Bin 16004 -> 16004 bytes
 allauth/locale/no/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/pl/LC_MESSAGES/django.mo            | Bin 15384 -> 15384 bytes
 allauth/locale/pl/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/pt_BR/LC_MESSAGES/django.mo         | Bin 14499 -> 14499 bytes
 allauth/locale/pt_BR/LC_MESSAGES/django.po         | 110 +++++-----
 allauth/locale/pt_PT/LC_MESSAGES/django.mo         | Bin 10642 -> 10642 bytes
 allauth/locale/pt_PT/LC_MESSAGES/django.po         | 110 +++++-----
 allauth/locale/ru/LC_MESSAGES/django.mo            | Bin 19790 -> 19790 bytes
 allauth/locale/ru/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/sk/LC_MESSAGES/django.mo            | Bin 15233 -> 15233 bytes
 allauth/locale/sk/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/sv/LC_MESSAGES/django.mo            | Bin 11050 -> 11050 bytes
 allauth/locale/sv/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/th/LC_MESSAGES/django.mo            | Bin 19727 -> 19727 bytes
 allauth/locale/th/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/tr/LC_MESSAGES/django.mo            | Bin 10605 -> 10605 bytes
 allauth/locale/tr/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/uk/LC_MESSAGES/django.mo            | Bin 19469 -> 19469 bytes
 allauth/locale/uk/LC_MESSAGES/django.po            | 110 +++++-----
 allauth/locale/zh_CN/LC_MESSAGES/django.mo         | Bin 11467 -> 11467 bytes
 allauth/locale/zh_CN/LC_MESSAGES/django.po         | 110 +++++-----
 allauth/locale/zh_Hans/LC_MESSAGES/django.mo       | Bin 11134 -> 11134 bytes
 allauth/locale/zh_Hans/LC_MESSAGES/django.po       | 110 +++++-----
 allauth/locale/zh_Hant/LC_MESSAGES/django.mo       | Bin 12403 -> 12403 bytes
 allauth/locale/zh_Hant/LC_MESSAGES/django.po       | 110 +++++-----
 allauth/locale/zh_TW/LC_MESSAGES/django.mo         | Bin 12374 -> 12374 bytes
 allauth/locale/zh_TW/LC_MESSAGES/django.po         | 110 +++++-----
 allauth/socialaccount/adapter.py                   |   4 +-
 allauth/socialaccount/admin.py                     |   6 -
 allauth/socialaccount/fields.py                    |  29 +--
 allauth/socialaccount/helpers.py                   |   6 +-
 allauth/socialaccount/migrations/__init__.py       |   5 -
 allauth/socialaccount/models.py                    |   8 +-
 .../socialaccount/providers/authentiq/models.py    |   1 -
 allauth/socialaccount/providers/azure/__init__.py  |   0
 .../providers/{amazon => azure}/models.py          |   0
 allauth/socialaccount/providers/azure/provider.py  |  46 ++++
 allauth/socialaccount/providers/azure/tests.py     |  20 ++
 allauth/socialaccount/providers/azure/urls.py      |   6 +
 allauth/socialaccount/providers/azure/views.py     |  62 ++++++
 allauth/socialaccount/providers/baidu/models.py    |   1 -
 allauth/socialaccount/providers/basecamp/models.py |   1 -
 .../socialaccount/providers/bitbucket/models.py    |   1 -
 .../providers/bitbucket_oauth2/models.py           |   1 -
 allauth/socialaccount/providers/bitly/models.py    |   1 -
 allauth/socialaccount/providers/box/models.py      |   1 -
 allauth/socialaccount/providers/coinbase/models.py |   1 -
 .../socialaccount/providers/digitalocean/models.py |   1 -
 allauth/socialaccount/providers/discord/models.py  |   1 -
 allauth/socialaccount/providers/douban/models.py   |   1 -
 allauth/socialaccount/providers/doximity/models.py |   1 -
 allauth/socialaccount/providers/draugiem/models.py |   1 -
 .../socialaccount/providers/draugiem/provider.py   |   2 +-
 allauth/socialaccount/providers/draugiem/tests.py  |   2 +-
 allauth/socialaccount/providers/draugiem/views.py  |   2 +-
 allauth/socialaccount/providers/dropbox/models.py  |   1 -
 .../providers/dropbox_oauth2/__init__.py           |   7 -
 .../providers/dropbox_oauth2/models.py             |   1 -
 .../providers/dropbox_oauth2/provider.py           |  22 --
 .../providers/dropbox_oauth2/tests.py              |  35 ---
 .../socialaccount/providers/dropbox_oauth2/urls.py |   6 -
 .../providers/dropbox_oauth2/views.py              |  35 ---
 allauth/socialaccount/providers/dwolla/urls.py     |   2 -
 allauth/socialaccount/providers/dwolla/views.py    |   2 -
 allauth/socialaccount/providers/edmodo/models.py   |   1 -
 .../socialaccount/providers/eveonline/models.py    |   1 -
 allauth/socialaccount/providers/evernote/models.py |   1 -
 allauth/socialaccount/providers/facebook/models.py |   1 -
 .../socialaccount/providers/facebook/provider.py   |   2 +-
 allauth/socialaccount/providers/facebook/tests.py  |   2 +-
 allauth/socialaccount/providers/feedly/models.py   |   1 -
 allauth/socialaccount/providers/flickr/models.py   |   1 -
 .../socialaccount/providers/foursquare/models.py   |   1 -
 allauth/socialaccount/providers/github/models.py   |   1 -
 allauth/socialaccount/providers/gitlab/models.py   |   1 -
 allauth/socialaccount/providers/google/models.py   |   1 -
 allauth/socialaccount/providers/google/tests.py    |   2 +-
 allauth/socialaccount/providers/hubic/models.py    |   1 -
 .../socialaccount/providers/instagram/models.py    |   1 -
 allauth/socialaccount/providers/linkedin/models.py |   1 -
 .../socialaccount/providers/linkedin/provider.py   |   2 +-
 .../providers/linkedin_oauth2/models.py            |   1 -
 .../providers/linkedin_oauth2/provider.py          |   2 +-
 allauth/socialaccount/providers/mailru/models.py   |   1 -
 .../socialaccount/providers/microsoft/__init__.py  |   0
 .../providers/{angellist => microsoft}/models.py   |   0
 .../socialaccount/providers/microsoft/provider.py  |  38 ++++
 allauth/socialaccount/providers/microsoft/tests.py |  27 +++
 allauth/socialaccount/providers/microsoft/urls.py  |   6 +
 allauth/socialaccount/providers/microsoft/views.py |  35 +++
 allauth/socialaccount/providers/oauth/models.py    |   1 -
 allauth/socialaccount/providers/oauth/provider.py  |   3 +-
 allauth/socialaccount/providers/oauth/views.py     |   3 +-
 allauth/socialaccount/providers/oauth2/models.py   |   1 -
 allauth/socialaccount/providers/oauth2/provider.py |   3 +-
 allauth/socialaccount/providers/oauth2/views.py    |   2 +-
 .../providers/odnoklassniki/models.py              |   1 -
 allauth/socialaccount/providers/openid/provider.py |   3 +-
 allauth/socialaccount/providers/openid/tests.py    |   2 +-
 allauth/socialaccount/providers/openid/views.py    |   2 +-
 allauth/socialaccount/providers/orcid/models.py    |   1 -
 allauth/socialaccount/providers/paypal/models.py   |   1 -
 allauth/socialaccount/providers/persona/tests.py   |   2 +-
 .../socialaccount/providers/pinterest/models.py    |   1 -
 allauth/socialaccount/providers/reddit/models.py   |   1 -
 .../socialaccount/providers/robinhood/models.py    |   1 -
 .../socialaccount/providers/salesforce/__init__.py |   0
 .../socialaccount/providers/salesforce/provider.py |  51 +++++
 .../socialaccount/providers/salesforce/tests.py    |  66 ++++++
 allauth/socialaccount/providers/salesforce/urls.py |   6 +
 .../socialaccount/providers/salesforce/views.py    |  40 ++++
 allauth/socialaccount/providers/shopify/models.py  |   1 -
 allauth/socialaccount/providers/shopify/tests.py   |   3 +-
 allauth/socialaccount/providers/slack/tests.py     |   2 +-
 .../socialaccount/providers/soundcloud/models.py   |   1 -
 allauth/socialaccount/providers/spotify/models.py  |   1 -
 .../providers/stackexchange/models.py              |   1 -
 allauth/socialaccount/providers/stripe/models.py   |   1 -
 allauth/socialaccount/providers/stripe/provider.py |   4 +-
 allauth/socialaccount/providers/trello/models.py   |   1 -
 allauth/socialaccount/providers/tumblr/models.py   |   1 -
 .../providers/twentythreeandme/models.py           |   1 -
 allauth/socialaccount/providers/twitch/models.py   |   1 -
 allauth/socialaccount/providers/twitter/models.py  |   1 -
 .../socialaccount/providers/untappd/provider.py    |   3 +-
 allauth/socialaccount/providers/vimeo/models.py    |   1 -
 allauth/socialaccount/providers/vk/models.py       |   1 -
 allauth/socialaccount/providers/vk/provider.py     |   2 +-
 allauth/socialaccount/providers/weibo/models.py    |   1 -
 allauth/socialaccount/providers/weixin/models.py   |   1 -
 allauth/socialaccount/providers/weixin/views.py    |   3 +-
 .../socialaccount/providers/windowslive/models.py  |   1 -
 .../providers/windowslive/provider.py              |   2 +-
 .../socialaccount/providers/windowslive/views.py   |  19 +-
 allauth/socialaccount/providers/xing/models.py     |   1 -
 allauth/socialaccount/providers/yahoo/__init__.py  |   0
 .../providers/{auth0 => yahoo}/models.py           |   0
 allauth/socialaccount/providers/yahoo/provider.py  |  46 ++++
 allauth/socialaccount/providers/yahoo/tests.py     |  85 ++++++++
 allauth/socialaccount/providers/yahoo/urls.py      |   6 +
 allauth/socialaccount/providers/yahoo/views.py     |  30 +++
 .../socialaccount/templatetags/socialaccount.py    |  17 +-
 allauth/socialaccount/tests.py                     |  10 +-
 allauth/socialaccount/views.py                     |   2 +-
 allauth/tests.py                                   |  31 +--
 allauth/utils.py                                   |  13 +-
 django_allauth.egg-info/PKG-INFO                   |  12 +-
 django_allauth.egg-info/SOURCES.txt                |  85 ++------
 django_allauth.egg-info/requires.txt               |   4 +-
 docs/advanced.rst                                  |  32 +--
 docs/configuration.rst                             |  12 ++
 docs/decorators.rst                                |   4 +-
 docs/installation.rst                              |   1 -
 docs/overview.rst                                  |  10 +-
 docs/providers.rst                                 | 100 ++++++++-
 setup.py                                           |   7 +-
 test_settings.py                                   |   9 +-
 210 files changed, 2895 insertions(+), 2447 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index d65c1ad..53a0e9e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -27,6 +27,7 @@ Björn Andersson
 Bojan Mihelac
 Chris Beaven
 Chris Davis
+Christian Carter
 Christopher Grebs
 Daniel Eriksson
 Daniel Widerin
@@ -52,6 +53,7 @@ Jakob Gerhard Martinussen
 James Rivett-Carnac
 James Thompson
 Jannis Leidel
+Jannis Vajen
 Jeff Triplett
 Jerome Leclanche
 Joe Vanderstelt
diff --git a/ChangeLog.rst b/ChangeLog.rst
index 166779a..1b16587 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -1,3 +1,21 @@
+0.35.0 (2017-02-02)
+*******************
+
+Security notice
+---------------
+
+- As an extra security measure on top of what the standard Django password reset
+  token generator is already facilitating, allauth now adds the user email
+  address to the hash such that whenever the user's email address changes the
+  token is invalidated.
+
+
+Note worthy changes
+-------------------
+
+- New provider: Azure, Microsoft Graph, Salesforce, Yahoo.
+
+
 0.34.0 (2017-10-29)
 *******************
 
diff --git a/PKG-INFO b/PKG-INFO
index 01cfa3d..60e80e0 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: django-allauth
-Version: 0.34.0
+Version: 0.35.0
 Summary: Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication.
 Home-page: http://github.com/pennersr/django-allauth
 Author: Raymond Penners
@@ -10,16 +10,16 @@ Description: ==========================
         Welcome to django-allauth!
         ==========================
         
-        .. image:: https://badge.fury.io/py/django-allauth.png
+        .. image:: https://badge.fury.io/py/django-allauth.svg
            :target: http://badge.fury.io/py/django-allauth
         
-        .. image:: https://travis-ci.org/pennersr/django-allauth.png
+        .. image:: https://travis-ci.org/pennersr/django-allauth.svg
            :target: http://travis-ci.org/pennersr/django-allauth
         
         .. image:: https://img.shields.io/pypi/v/django-allauth.svg
            :target: https://pypi.python.org/pypi/django-allauth
         
-        .. image:: https://coveralls.io/repos/pennersr/django-allauth/badge.png?branch=master
+        .. image:: https://coveralls.io/repos/pennersr/django-allauth/badge.svg?branch=master
            :alt: Coverage Status
            :target: https://coveralls.io/r/pennersr/django-allauth
         
@@ -103,11 +103,9 @@ Classifier: License :: OSI Approved :: MIT License
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Framework :: Django
-Classifier: Framework :: Django :: 1.8
-Classifier: Framework :: Django :: 1.10
 Classifier: Framework :: Django :: 1.11
+Classifier: Framework :: Django :: 2.0
diff --git a/README.rst b/README.rst
index ed5a479..f213d14 100644
--- a/README.rst
+++ b/README.rst
@@ -2,16 +2,16 @@
 Welcome to django-allauth!
 ==========================
 
-.. image:: https://badge.fury.io/py/django-allauth.png
+.. image:: https://badge.fury.io/py/django-allauth.svg
    :target: http://badge.fury.io/py/django-allauth
 
-.. image:: https://travis-ci.org/pennersr/django-allauth.png
+.. image:: https://travis-ci.org/pennersr/django-allauth.svg
    :target: http://travis-ci.org/pennersr/django-allauth
 
 .. image:: https://img.shields.io/pypi/v/django-allauth.svg
    :target: https://pypi.python.org/pypi/django-allauth
 
-.. image:: https://coveralls.io/repos/pennersr/django-allauth/badge.png?branch=master
+.. image:: https://coveralls.io/repos/pennersr/django-allauth/badge.svg?branch=master
    :alt: Coverage Status
    :target: https://coveralls.io/r/pennersr/django-allauth
 
diff --git a/allauth/__init__.py b/allauth/__init__.py
index 7b72791..9f2f682 100644
--- a/allauth/__init__.py
+++ b/allauth/__init__.py
@@ -1,4 +1,4 @@
-"""
+r"""
     _        ___      __    __  .___________. __    __
  /\| |/\    /   \    |  |  |  | |           ||  |  |  |
  \ ` ' /   /  ^  \   |  |  |  | `---|  |----`|  |__|  |
@@ -8,7 +8,7 @@
 
 """
 
-VERSION = (0, 34, 0, 'final', 0)
+VERSION = (0, 35, 0, 'final', 0)
 
 __title__ = 'django-allauth'
 __version_info__ = VERSION
@@ -16,4 +16,4 @@ __version__ = '.'.join(map(str, VERSION[:3])) + ('-{}{}'.format(
     VERSION[3], VERSION[4] or '') if VERSION[3] != 'final' else '')
 __author__ = 'Raymond Penners'
 __license__ = 'MIT'
-__copyright__ = 'Copyright 2010-2017 Raymond Penners and contributors'
+__copyright__ = 'Copyright 2010-2018 Raymond Penners and contributors'
diff --git a/allauth/account/adapter.py b/allauth/account/adapter.py
index 31e526f..32012ef 100644
--- a/allauth/account/adapter.py
+++ b/allauth/account/adapter.py
@@ -9,11 +9,13 @@ from django import forms
 from django.conf import settings
 from django.contrib import messages
 from django.contrib.auth import (
+    authenticate,
     get_backends,
     login as django_login,
     logout as django_logout,
 )
 from django.contrib.auth.models import AbstractUser
+from django.contrib.auth.password_validation import validate_password
 from django.contrib.sites.shortcuts import get_current_site
 from django.core.cache import cache
 from django.core.mail import EmailMessage, EmailMultiAlternatives
@@ -21,11 +23,12 @@ from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import resolve_url
 from django.template import TemplateDoesNotExist
 from django.template.loader import render_to_string
+from django.urls import reverse
 from django.utils import timezone
+from django.utils.encoding import force_text
 from django.utils.translation import ugettext_lazy as _
 
 from . import app_settings
-from ..compat import authenticate, is_authenticated, reverse, validate_password
 from ..utils import (
     build_absolute_uri,
     email_address_exists,
@@ -35,12 +38,6 @@ from ..utils import (
 )
 
 
-try:
-    from django.utils.encoding import force_text
-except ImportError:
-    from django.utils.encoding import force_unicode as force_text
-
-
 class DefaultAccountAdapter(object):
 
     error_messages = {
@@ -145,7 +142,7 @@ class DefaultAccountAdapter(object):
         that URLs passed explicitly (e.g. by passing along a `next`
         GET parameter) take precedence over the value returned here.
         """
-        assert is_authenticated(request.user)
+        assert request.user.is_authenticated
         url = getattr(settings, "LOGIN_REDIRECT_URLNAME", None)
         if url:
             warnings.warn("LOGIN_REDIRECT_URLNAME is deprecated, simply"
@@ -168,7 +165,7 @@ class DefaultAccountAdapter(object):
         """
         The URL to return to after successful e-mail confirmation.
         """
-        if is_authenticated(request.user):
+        if request.user.is_authenticated:
             if app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL:
                 return  \
                     app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL
@@ -480,7 +477,7 @@ class DefaultAccountAdapter(object):
     def authenticate(self, request, **credentials):
         """Only authenticates, does not actually login. See `login`"""
         self.pre_authenticate(request, **credentials)
-        user = authenticate(request=request, **credentials)
+        user = authenticate(request, **credentials)
         if user:
             cache_key = self._get_login_attempts_cache_key(
                 request, **credentials)
@@ -496,6 +493,9 @@ class DefaultAccountAdapter(object):
         data.append(time.mktime(dt.timetuple()))
         cache.set(cache_key, data, app_settings.LOGIN_ATTEMPTS_TIMEOUT)
 
+    def is_ajax(self, request):
+        return request.is_ajax()
+
 
 def get_adapter(request=None):
     return import_attribute(app_settings.ADAPTER)(request)
diff --git a/allauth/account/admin.py b/allauth/account/admin.py
index a223a03..cfaf93f 100644
--- a/allauth/account/admin.py
+++ b/allauth/account/admin.py
@@ -1,4 +1,3 @@
-import django
 from django.contrib import admin
 
 from . import app_settings
@@ -12,11 +11,6 @@ class EmailAddressAdmin(admin.ModelAdmin):
     search_fields = []
     raw_id_fields = ('user',)
 
-    def __init__(self, *args, **kwargs):
-        super(EmailAddressAdmin, self).__init__(*args, **kwargs)
-        if not self.search_fields and django.VERSION[:2] < (1, 7):
-            self.search_fields = self.get_search_fields(None)
-
     def get_search_fields(self, request):
         base_fields = get_adapter(request).get_user_search_fields()
         return ['email'] + list(map(lambda a: 'user__' + a, base_fields))
diff --git a/allauth/account/app_settings.py b/allauth/account/app_settings.py
index abf7bbd..a69fd5b 100644
--- a/allauth/account/app_settings.py
+++ b/allauth/account/app_settings.py
@@ -141,13 +141,9 @@ class AppSettings(object):
         """
         Minimum password Length
         """
-        import django
         from django.conf import settings
         ret = None
-        has_validators = (
-            django.VERSION[:2] >= (1, 9) and
-            bool(getattr(settings, 'AUTH_PASSWORD_VALIDATORS', [])))
-        if not has_validators:
+        if not settings.AUTH_PASSWORD_VALIDATORS:
             ret = self._setting("PASSWORD_MIN_LENGTH", 6)
         return ret
 
diff --git a/allauth/account/auth_backends.py b/allauth/account/auth_backends.py
index 3432a6c..bd36a57 100644
--- a/allauth/account/auth_backends.py
+++ b/allauth/account/auth_backends.py
@@ -8,7 +8,7 @@ from .utils import filter_users_by_email, filter_users_by_username
 
 class AuthenticationBackend(ModelBackend):
 
-    def authenticate(self, **credentials):
+    def authenticate(self, request, **credentials):
         ret = None
         if app_settings.AUTHENTICATION_METHOD == AuthenticationMethod.EMAIL:
             ret = self._authenticate_by_email(**credentials)
diff --git a/allauth/account/forms.py b/allauth/account/forms.py
index e7d2064..09aee1a 100644
--- a/allauth/account/forms.py
+++ b/allauth/account/forms.py
@@ -4,13 +4,13 @@ import warnings
 from importlib import import_module
 
 from django import forms
-from django.contrib.auth.tokens import default_token_generator
+from django.contrib.auth.tokens import PasswordResetTokenGenerator
 from django.contrib.sites.shortcuts import get_current_site
 from django.core import exceptions, validators
+from django.urls import reverse
 from django.utils.translation import pgettext, ugettext, ugettext_lazy as _
 
 from . import app_settings
-from ..compat import reverse
 from ..utils import (
     build_absolute_uri,
     get_username_max_length,
@@ -24,6 +24,7 @@ from .utils import (
     get_user_model,
     perform_login,
     setup_user_email,
+    sync_user_email_addresses,
     url_str_to_user_pk,
     user_email,
     user_pk_to_url_str,
@@ -31,6 +32,25 @@ from .utils import (
 )
 
 
+class EmailAwarePasswordResetTokenGenerator(PasswordResetTokenGenerator):
+
+    def _make_hash_value(self, user, timestamp):
+        ret = super(
+            EmailAwarePasswordResetTokenGenerator, self)._make_hash_value(
+                user, timestamp)
+        sync_user_email_addresses(user)
+        emails = set([user.email])
+        emails.update(
+            EmailAddress.objects
+            .filter(user=user)
+            .values_list('email', flat=True))
+        ret += '|'.join(sorted(emails))
+        return ret
+
+
+default_token_generator = EmailAwarePasswordResetTokenGenerator()
+
+
 class PasswordVerificationMixin(object):
     def clean(self):
         cleaned_data = super(PasswordVerificationMixin, self).clean()
@@ -50,7 +70,7 @@ class PasswordField(forms.CharField):
                                   app_settings.PASSWORD_INPUT_RENDER_VALUE)
         kwargs['widget'] = forms.PasswordInput(render_value=render_value,
                                                attrs={'placeholder':
-                                                      _(kwargs.get("label"))})
+                                                      kwargs.get("label")})
         super(PasswordField, self).__init__(*args, **kwargs)
 
 
@@ -353,7 +373,7 @@ class SignupForm(BaseSignupForm):
     def clean(self):
         super(SignupForm, self).clean()
 
-        # `password` cannot by of type `SetPasswordField`, as we don't
+        # `password` cannot be of type `SetPasswordField`, as we don't
         # have a `User` yet. So, let's populate a dummy user to be used
         # for password validaton.
         dummy_user = get_user_model()
@@ -559,8 +579,11 @@ class UserTokenForm(forms.Form):
     def clean(self):
         cleaned_data = super(UserTokenForm, self).clean()
 
-        uidb36 = cleaned_data['uidb36']
-        key = cleaned_data['key']
+        uidb36 = cleaned_data.get('uidb36', None)
+        key = cleaned_data.get('key', None)
+
+        if not key:
+            raise forms.ValidationError(self.error_messages['token_invalid'])
 
         self.reset_user = self._get_user(uidb36)
         if (self.reset_user is None or
diff --git a/allauth/account/tests.py b/allauth/account/tests.py
index 8dd7b7d..dc81e77 100644
--- a/allauth/account/tests.py
+++ b/allauth/account/tests.py
@@ -4,7 +4,6 @@ import json
 import uuid
 from datetime import timedelta
 
-import django
 from django import forms
 from django.conf import settings
 from django.contrib.auth.models import AbstractUser, AnonymousUser
@@ -14,6 +13,7 @@ from django.core.exceptions import ValidationError
 from django.db import models
 from django.test.client import Client, RequestFactory
 from django.test.utils import override_settings
+from django.urls import reverse
 from django.utils.timezone import now
 
 from allauth.account.forms import BaseSignupForm, SignupForm
@@ -26,7 +26,6 @@ from allauth.tests import Mock, TestCase, patch
 from allauth.utils import get_user_model, get_username_max_length
 
 from . import app_settings
-from ..compat import is_authenticated, reverse
 from .adapter import get_adapter
 from .auth_backends import AuthenticationBackend
 from .signals import user_logged_out
@@ -135,7 +134,7 @@ class AccountTests(TestCase):
 
     @override_settings(
         ACCOUNT_USERNAME_REQUIRED=True,
-        ACCOUNT_SIGNUP_PASSOWRD_ENTER_TWICE=True)
+        ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE=True)
     def test_signup_password_twice_form_error(self):
         resp = self.client.post(
             reverse('account_signup'),
@@ -185,7 +184,7 @@ class AccountTests(TestCase):
     def _create_user_and_login(self, usable_password=True):
         password = 'doe' if usable_password else False
         user = self._create_user(password=password)
-        self.client_force_login(user)
+        self.client.force_login(user)
         return user
 
     def test_redirect_when_authenticated(self):
@@ -284,6 +283,36 @@ class AccountTests(TestCase):
         self.assertEqual(mail.outbox[0].to, ["john at example.org"])
         return user
 
+    def test_password_reset_flow_with_empty_session(self):
+        """
+        Test the password reset flow when the session is empty:
+        requesting a new password, receiving the reset link via email,
+        following the link, getting redirected to the
+        new link (without the token)
+        Copying the link and using it in a DIFFERENT client (Browser/Device).
+        """
+        # Request new password
+        self._request_new_password()
+        body = mail.outbox[0].body
+        self.assertGreater(body.find('https://'), 0)
+
+        # Extract URL for `password_reset_from_key` view
+        url = body[body.find('/password/reset/'):].split()[0]
+        resp = self.client.get(url)
+
+        reset_pass_url = resp.url
+
+        # Accesing the url via a different session
+        resp = self.client_class().get(reset_pass_url)
+
+        # We should receive the token_fail context_data
+        self.assertTemplateUsed(
+            resp,
+            'account/password_reset_from_key.%s' %
+            app_settings.TEMPLATE_EXTENSION)
+
+        self.assertTrue(resp.context_data['token_fail'])
+
     def test_password_reset_flow(self):
         """
         Tests the password reset flow: requesting a new password,
@@ -349,6 +378,26 @@ class AccountTests(TestCase):
         data = json.loads(response.content.decode('utf8'))
         assert 'invalid' in data['form']['errors'][0]
 
+    def test_password_reset_flow_with_email_changed(self):
+        """
+        Test that the password reset token is invalidated if
+        the user email address was changed.
+        """
+        user = self._request_new_password()
+        body = mail.outbox[0].body
+        self.assertGreater(body.find('https://'), 0)
+        EmailAddress.objects.create(
+            user=user,
+            email='other at email.org')
+        # Extract URL for `password_reset_from_key` view
+        url = body[body.find('/password/reset/'):].split()[0]
+        resp = self.client.get(url)
+        self.assertTemplateUsed(
+            resp,
+            'account/password_reset_from_key.%s' %
+            app_settings.TEMPLATE_EXTENSION)
+        self.assertTrue('token_fail' in resp.context_data)
+
     @override_settings(ACCOUNT_LOGIN_ON_PASSWORD_RESET=True)
     def test_password_reset_ACCOUNT_LOGIN_ON_PASSWORD_RESET(self):
         user = self._request_new_password()
@@ -361,7 +410,7 @@ class AccountTests(TestCase):
             resp.url,
             {'password1': 'newpass123',
              'password2': 'newpass123'})
-        self.assertTrue(is_authenticated(user))
+        self.assertTrue(user.is_authenticated)
         # EmailVerificationMethod.MANDATORY sends us to the confirm-email page
         self.assertRedirects(resp, '/confirm-email/')
 
@@ -656,8 +705,6 @@ class AccountTests(TestCase):
         }
     }])
     def test_django_password_validation(self):
-        if django.VERSION < (1, 9, ):
-            return
         resp = self.client.post(
             reverse('account_signup'),
             {'username': 'johndoe',
@@ -986,11 +1033,13 @@ class AuthenticationBackendTests(TestCase):
         backend = AuthenticationBackend()
         self.assertEqual(
             backend.authenticate(
+                request=None,
                 username=user.username,
                 password=user.username).pk,
             user.pk)
         self.assertEqual(
             backend.authenticate(
+                request=None,
                 username=user.email,
                 password=user.username),
             None)
@@ -1002,11 +1051,13 @@ class AuthenticationBackendTests(TestCase):
         backend = AuthenticationBackend()
         self.assertEqual(
             backend.authenticate(
+                request=None,
                 username=user.email,
                 password=user.username).pk,
             user.pk)
         self.assertEqual(
             backend.authenticate(
+                request=None,
                 username=user.username,
                 password=user.username),
             None)
@@ -1018,11 +1069,13 @@ class AuthenticationBackendTests(TestCase):
         backend = AuthenticationBackend()
         self.assertEqual(
             backend.authenticate(
+                request=None,
                 username=user.email,
                 password=user.username).pk,
             user.pk)
         self.assertEqual(
             backend.authenticate(
+                request=None,
                 username=user.username,
                 password=user.username).pk,
             user.pk)
diff --git a/allauth/account/utils.py b/allauth/account/utils.py
index 608288f..45ad321 100644
--- a/allauth/account/utils.py
+++ b/allauth/account/utils.py
@@ -9,6 +9,7 @@ from django.db import models
 from django.db.models import Q
 from django.http import HttpResponseRedirect
 from django.utils import six
+from django.utils.encoding import force_text
 from django.utils.http import urlencode
 from django.utils.timezone import now
 
@@ -26,12 +27,6 @@ from .adapter import get_adapter
 from .app_settings import EmailVerificationMethod
 
 
-try:
-    from django.utils.encoding import force_text
-except ImportError:
-    from django.utils.encoding import force_unicode as force_text
-
-
 def get_next_redirect_url(request, redirect_field_name="next"):
     """
     Returns the next URL to redirect to, if it was explicitly passed
@@ -422,8 +417,8 @@ def url_str_to_user_pk(s):
     User = get_user_model()
     # TODO: Ugh, isn't there a cleaner way to determine whether or not
     # the PK is a str-like field?
-    if getattr(User._meta.pk, 'rel', None):
-        pk_field = User._meta.pk.rel.to._meta.pk
+    if getattr(User._meta.pk, 'remote_field', None):
+        pk_field = User._meta.pk.remote_field.to._meta.pk
     else:
         pk_field = User._meta.pk
     if issubclass(type(pk_field), models.UUIDField):
diff --git a/allauth/account/views.py b/allauth/account/views.py
index 767d5e5..d3eb6cc 100644
--- a/allauth/account/views.py
+++ b/allauth/account/views.py
@@ -7,13 +7,13 @@ from django.http import (
     HttpResponseRedirect,
 )
 from django.shortcuts import redirect
+from django.urls import reverse, reverse_lazy
 from django.utils.decorators import method_decorator
 from django.views.decorators.debug import sensitive_post_parameters
 from django.views.generic.base import TemplateResponseMixin, TemplateView, View
 from django.views.generic.edit import FormView
 
 from . import app_settings, signals
-from ..compat import is_anonymous, is_authenticated, reverse, reverse_lazy
 from ..exceptions import ImmediateHttpResponse
 from ..utils import get_form_class, get_request_param
 from .adapter import get_adapter
@@ -49,13 +49,14 @@ sensitive_post_parameters_m = method_decorator(
 
 
 def _ajax_response(request, response, form=None, data=None):
-    if request.is_ajax():
+    adapter = get_adapter(request)
+    if adapter.is_ajax(request):
         if (isinstance(response, HttpResponseRedirect) or isinstance(
                 response, HttpResponsePermanentRedirect)):
             redirect_to = response['Location']
         else:
             redirect_to = None
-        response = get_adapter(request).ajax_response(
+        response = adapter.ajax_response(
             request,
             response,
             form=form,
@@ -67,7 +68,7 @@ def _ajax_response(request, response, form=None, data=None):
 class RedirectAuthenticatedUserMixin(object):
 
     def dispatch(self, request, *args, **kwargs):
-        if is_authenticated(request.user) and \
+        if request.user.is_authenticated and \
                 app_settings.AUTHENTICATED_LOGIN_REDIRECTS:
             redirect_to = self.get_authenticated_redirect_url()
             response = HttpResponseRedirect(redirect_to)
@@ -114,7 +115,10 @@ class AjaxCapableProcessFormViewMixin(object):
         return form
 
     def _get_ajax_data_if(self):
-        return self.get_ajax_data() if self.request.is_ajax() else None
+        return (
+            self.get_ajax_data()
+            if get_adapter(self.request).is_ajax(self.request)
+            else None)
 
     def get_ajax_data(self):
         return None
@@ -323,7 +327,7 @@ class ConfirmEmailView(TemplateResponseMixin, View):
         if user_pk_str:
             user_pk = url_str_to_user_pk(user_pk_str)
         user = confirmation.email_address.user
-        if user_pk == user.pk and is_anonymous(self.request.user):
+        if user_pk == user.pk and self.request.user.is_anonymous:
             return perform_login(self.request,
                                  user,
                                  app_settings.EmailVerificationMethod.NONE,
@@ -759,14 +763,14 @@ class LogoutView(TemplateResponseMixin, View):
     def get(self, *args, **kwargs):
         if app_settings.LOGOUT_ON_GET:
             return self.post(*args, **kwargs)
-        if not is_authenticated(self.request.user):
+        if not self.request.user.is_authenticated:
             return redirect(self.get_redirect_url())
         ctx = self.get_context_data()
         return self.render_to_response(ctx)
 
     def post(self, *args, **kwargs):
         url = self.get_redirect_url()
-        if is_authenticated(self.request.user):
+        if self.request.user.is_authenticated:
             self.logout()
         return redirect(url)
 
diff --git a/allauth/compat.py b/allauth/compat.py
index 895988f..585254a 100644
--- a/allauth/compat.py
+++ b/allauth/compat.py
@@ -1,4 +1,3 @@
-import django
 from django.utils import six
 
 
@@ -7,52 +6,11 @@ try:
 except ImportError:
     from UserDict import UserDict  # noqa
 
-if django.VERSION > (1, 10,):
-    from django.urls import NoReverseMatch, reverse, reverse_lazy
-else:
-    from django.core.urlresolvers import NoReverseMatch, reverse, reverse_lazy  # noqa
-
 try:
     from urllib.parse import parse_qsl, parse_qs, urlparse, urlunparse, urljoin
 except ImportError:
     from urlparse import parse_qsl, parse_qs, urlparse, urlunparse, urljoin  # noqa
 
-if django.VERSION >= (1, 9, 0):
-    from django.contrib.auth.password_validation import validate_password
-else:
-    def validate_password(password, user=None, password_validators=None):
-        pass
-
-
-def template_context_value(context, key):
-    try:
-        value = context[key]
-    except KeyError:
-        value = getattr(context, key)
-    return value
-
-
-def is_anonymous(user):
-    if django.VERSION > (1, 10,):
-        return user.is_anonymous
-    else:
-        return user.is_anonymous()
-
-
-def is_authenticated(user):
-    if django.VERSION > (1, 10,):
-        return user.is_authenticated
-    else:
-        return user.is_authenticated()
-
-
-def authenticate(request=None, **credentials):
-    from django.contrib.auth import authenticate
-    if django.VERSION >= (1, 11, 0):
-        return authenticate(request=request, **credentials)
-    else:
-        return authenticate(**credentials)
-
 
 def int_to_base36(i):
     """
diff --git a/allauth/locale/ar/LC_MESSAGES/django.mo b/allauth/locale/ar/LC_MESSAGES/django.mo
index 70d5898..05d616e 100644
Binary files a/allauth/locale/ar/LC_MESSAGES/django.mo and b/allauth/locale/ar/LC_MESSAGES/django.mo differ
diff --git a/allauth/locale/ar/LC_MESSAGES/django.po b/allauth/locale/ar/LC_MESSAGES/django.po
index ba36a6e..81ac0bb 100644
--- a/allauth/locale/ar/LC_MESSAGES/django.po
+++ b/allauth/locale/ar/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-10-29 09:56-0500\n"
+"POT-Creation-Date: 2018-02-02 12:55-0600\n"
 "PO-Revision-Date: 2016-01-19 19:32+0100\n"
 "Last-Translator: David D Lowe <daviddlowe.flimm at gmail.com>\n"
 "Language-Team: Arabic\n"
@@ -19,19 +19,19 @@ msgstr ""
 "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
 "X-Generator: Poedit 1.8.6\n"
 
-#: account/adapter.py:48
+#: account/adapter.py:45
 msgid "Username can not be used. Please use other username."
 msgstr "اسم المستخدم غير مسموح به. الرجاء اختيار اسم اخر‪.‬"
 
-#: account/adapter.py:52
+#: account/adapter.py:49
 msgid "Too many failed login attempts. Try again later."
 msgstr ""
 
-#: account/adapter.py:54
+#: account/adapter.py:51
 msgid "A user is already registered with this e-mail address."
 msgstr "هنالك مستخدم مسجل سابقا مع نفس عنوان البريد الاكتروني‪.‬"
 
-#: account/adapter.py:291
+#: account/adapter.py:288
 #, python-brace-format
 msgid "Password must be a minimum of {0} characters."
 msgstr "كلمة المرور يجب أن لا تقل عن {0} حروف."
@@ -40,109 +40,109 @@ msgstr "كلمة المرور يجب أن لا تقل عن {0} حروف."
 msgid "Accounts"
 msgstr "الحسابات"
 
-#: account/forms.py:41 account/forms.py:378
+#: account/forms.py:61 account/forms.py:398
 msgid "You must type the same password each time."
 msgstr "يجب عليك كتابة نفس كلمة المرور في كل مرة‪.‬"
 
-#: account/forms.py:71 account/forms.py:345 account/forms.py:456
+#: account/forms.py:91 account/forms.py:365 account/forms.py:476
 msgid "Password"
 msgstr "كلمة السر"
 
-#: account/forms.py:72
+#: account/forms.py:92
 msgid "Remember Me"
 msgstr "ذكرني"
 
-#: account/forms.py:78
+#: account/forms.py:98
 msgid "This account is currently inactive."
 msgstr "هذا الحساب غير نشط حاليا."
 
-#: account/forms.py:81
+#: account/forms.py:101
 msgid "The e-mail address and/or password you specified are not correct."
 msgstr "عنوان البريد الإلكتروني و / أو كلمة المرور الذي حددته غير صحيحة."
 
-#: account/forms.py:84
... 13275 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-allauth.git



More information about the Python-modules-commits mailing list