Browse Source

Refs #25187 -- Required the authenticate() method of authentication backends to have request as the first positional argument.

Per deprecation timeline.
Tim Graham 7 years ago
parent
commit
5e31be1b96

+ 6 - 37
django/contrib/auth/__init__.py

@@ -1,13 +1,11 @@
 import inspect
 import re
-import warnings
 
 from django.apps import apps as django_apps
 from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured, PermissionDenied
 from django.middleware.csrf import rotate_token
 from django.utils.crypto import constant_time_compare
-from django.utils.deprecation import RemovedInDjango21Warning
 from django.utils.module_loading import import_string
 from django.utils.translation import LANGUAGE_SESSION_KEY
 
@@ -67,7 +65,12 @@ def authenticate(request=None, **credentials):
     """
     for backend, backend_path in _get_backends(return_tuples=True):
         try:
-            user = _authenticate_with_backend(backend, backend_path, request, credentials)
+            inspect.getcallargs(backend.authenticate, request, **credentials)
+        except TypeError:
+            # This backend doesn't accept these credentials as arguments. Try the next one.
+            continue
+        try:
+            user = backend.authenticate(request, **credentials)
         except PermissionDenied:
             # This backend says to stop in our tracks - this user should not be allowed in at all.
             break
@@ -81,40 +84,6 @@ def authenticate(request=None, **credentials):
     user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)
 
 
-def _authenticate_with_backend(backend, backend_path, request, credentials):
-    args = (request,)
-    # Does the backend accept a request argument?
-    try:
-        inspect.getcallargs(backend.authenticate, request, **credentials)
-    except TypeError:
-        args = ()
-        credentials.pop('request', None)
-        # Does the backend accept a request keyword argument?
-        try:
-            inspect.getcallargs(backend.authenticate, request=request, **credentials)
-        except TypeError:
-            # Does the backend accept credentials without request?
-            try:
-                inspect.getcallargs(backend.authenticate, **credentials)
-            except TypeError:
-                # This backend doesn't accept these credentials as arguments. Try the next one.
-                return None
-            else:
-                warnings.warn(
-                    "Update %s.authenticate() to accept a positional "
-                    "`request` argument." % backend_path,
-                    RemovedInDjango21Warning
-                )
-        else:
-            credentials['request'] = request
-            warnings.warn(
-                "In %s.authenticate(), move the `request` keyword argument "
-                "to the first positional argument." % backend_path,
-                RemovedInDjango21Warning
-            )
-    return backend.authenticate(*args, **credentials)
-
-
 def login(request, user, backend=None):
     """
     Persist a user id and a backend in the request. This way a user doesn't

+ 3 - 0
docs/releases/2.1.txt

@@ -246,3 +246,6 @@ how to remove usage of these features.
   tag is removed.
 
 * ``DatabaseIntrospection.get_indexes()`` is removed.
+
+* The ``authenticate()`` method of authentication backends requires ``request``
+  as the first positional argument.

+ 0 - 5
docs/topics/auth/customizing.txt

@@ -167,11 +167,6 @@ object the first time a user authenticates::
             except User.DoesNotExist:
                 return None
 
-.. versionchanged:: 1.11
-
-    The ``request`` parameter was added to ``authenticate()`` and support for
-    backends that don't accept it will be removed in Django 2.1.
-
 .. _authorization_methods:
 
 Handling authorization in custom backends

+ 0 - 92
tests/auth_tests/test_auth_backends_deprecation.py

@@ -1,92 +0,0 @@
-import warnings
-
-from django.contrib.auth import authenticate
-from django.test import SimpleTestCase, override_settings
-
-mock_request = object()
-mock_backend = object()
-
-
-class NoRequestBackend:
-    def authenticate(self, username=None, password=None):
-        # Doesn't accept a request parameter.
-        pass
-
-
-class RequestNotPositionArgBackend:
-    def authenticate(self, username=None, password=None, request=None):
-        assert username == 'username'
-        assert password == 'pass'
-        assert request is mock_request
-
-
-class RequestNotPositionArgWithUsedKwargBackend:
-    def authenticate(self, username=None, password=None, request=None, backend=None):
-        assert username == 'username'
-        assert password == 'pass'
-        assert request is mock_request
-        assert backend is mock_backend
-
-
-class AcceptsRequestBackendTest(SimpleTestCase):
-    """
-    A deprecation warning is shown for backends that have an authenticate()
-    method without a request parameter.
-    """
-    no_request_backend = '%s.NoRequestBackend' % __name__
-    request_not_positional_backend = '%s.RequestNotPositionArgBackend' % __name__
-    request_not_positional_with_used_kwarg_backend = '%s.RequestNotPositionArgWithUsedKwargBackend' % __name__
-
-    @override_settings(AUTHENTICATION_BACKENDS=[no_request_backend])
-    def test_no_request_deprecation_warning(self):
-        with warnings.catch_warnings(record=True) as warns:
-            warnings.simplefilter('always')
-            authenticate(username='test', password='test')
-        self.assertEqual(len(warns), 1)
-        self.assertEqual(
-            str(warns[0].message),
-            "Update %s.authenticate() to accept a positional `request` "
-            "argument." % self.no_request_backend
-        )
-
-    @override_settings(AUTHENTICATION_BACKENDS=[request_not_positional_backend])
-    def test_request_keyword_arg_deprecation_warning(self):
-        with warnings.catch_warnings(record=True) as warns:
-            warnings.simplefilter('always')
-            authenticate(username='username', password='pass', request=mock_request)
-        self.assertEqual(len(warns), 1)
-        self.assertEqual(
-            str(warns[0].message),
-            "In %s.authenticate(), move the `request` keyword argument to the "
-            "first positional argument." % self.request_not_positional_backend
-        )
-
-    @override_settings(AUTHENTICATION_BACKENDS=[request_not_positional_backend, no_request_backend])
-    def test_both_types_of_deprecation_warning(self):
-        with warnings.catch_warnings(record=True) as warns:
-            warnings.simplefilter('always')
-            authenticate(mock_request, username='username', password='pass')
-
-        self.assertEqual(len(warns), 2)
-        self.assertEqual(
-            str(warns[0].message),
-            "In %s.authenticate(), move the `request` keyword argument to the "
-            "first positional argument." % self.request_not_positional_backend
-        )
-        self.assertEqual(
-            str(warns[1].message),
-            "Update %s.authenticate() to accept a positional `request` "
-            "argument." % self.no_request_backend
-        )
-
-    @override_settings(AUTHENTICATION_BACKENDS=[request_not_positional_with_used_kwarg_backend])
-    def test_handles_backend_in_kwargs(self):
-        with warnings.catch_warnings(record=True) as warns:
-            warnings.simplefilter('always')
-            authenticate(username='username', password='pass', request=mock_request, backend=mock_backend)
-        self.assertEqual(len(warns), 1)
-        self.assertEqual(
-            str(warns[0].message),
-            "In %s.authenticate(), move the `request` keyword argument to the "
-            "first positional argument." % self.request_not_positional_with_used_kwarg_backend
-        )