[2.0.x] Fixed #29071 -- Fixed contrib.auth.authenticate() crash if a backend doesn't accept a request but a later one does.
Regression in a3ba2662cd
.
This commit is contained in:
parent
ddc49820f7
commit
55e16f25e9
|
@ -82,6 +82,7 @@ def authenticate(request=None, **credentials):
|
|||
|
||||
|
||||
def _authenticate_with_backend(backend, backend_path, request, credentials):
|
||||
credentials = credentials.copy() # Prevent a mutation from propagating.
|
||||
args = (request,)
|
||||
# Does the backend accept a request argument?
|
||||
try:
|
||||
|
|
|
@ -11,3 +11,7 @@ Bugfixes
|
|||
|
||||
* Fixed incorrect foreign key nullification if a model has two foreign keys to
|
||||
the same model and a target model is deleted (:ticket:`29016`).
|
||||
|
||||
* Fixed a regression where ``contrib.auth.authenticate()`` crashes if an
|
||||
authentication backend doesn't accept ``request`` and a later one does
|
||||
(:ticket:`29071`).
|
||||
|
|
|
@ -20,3 +20,7 @@ Bugfixes
|
|||
|
||||
* Fixed a regression where a queryset that annotates with geometry objects
|
||||
crashes (:ticket:`29054`).
|
||||
|
||||
* Fixed a regression where ``contrib.auth.authenticate()`` crashes if an
|
||||
authentication backend doesn't accept ``request`` and a later one does
|
||||
(:ticket:`29071`).
|
||||
|
|
|
@ -13,6 +13,18 @@ class NoRequestBackend:
|
|||
pass
|
||||
|
||||
|
||||
class NoRequestWithKwargs:
|
||||
def authenticate(self, username=None, password=None, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class RequestPositionalArg:
|
||||
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||
assert username == 'username'
|
||||
assert password == 'pass'
|
||||
assert request is mock_request
|
||||
|
||||
|
||||
class RequestNotPositionArgBackend:
|
||||
def authenticate(self, username=None, password=None, request=None):
|
||||
assert username == 'username'
|
||||
|
@ -34,6 +46,8 @@ class AcceptsRequestBackendTest(SimpleTestCase):
|
|||
method without a request parameter.
|
||||
"""
|
||||
no_request_backend = '%s.NoRequestBackend' % __name__
|
||||
no_request_with_kwargs_backend = '%s.NoRequestWithKwargs' % __name__
|
||||
request_positional_arg_backend = '%s.RequestPositionalArg' % __name__
|
||||
request_not_positional_backend = '%s.RequestNotPositionArgBackend' % __name__
|
||||
request_not_positional_with_used_kwarg_backend = '%s.RequestNotPositionArgWithUsedKwargBackend' % __name__
|
||||
|
||||
|
@ -79,6 +93,21 @@ class AcceptsRequestBackendTest(SimpleTestCase):
|
|||
"argument." % self.no_request_backend
|
||||
)
|
||||
|
||||
@override_settings(AUTHENTICATION_BACKENDS=[no_request_with_kwargs_backend, request_positional_arg_backend])
|
||||
def test_credentials_not_mutated(self):
|
||||
"""
|
||||
No problem if a backend doesn't accept `request` and a later one does.
|
||||
"""
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
warnings.simplefilter('always')
|
||||
authenticate(mock_request, username='username', password='pass')
|
||||
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.no_request_with_kwargs_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:
|
||||
|
|
Loading…
Reference in New Issue