[1.11.x] Fixed #29071 -- Fixed contrib.auth.authenticate() crash if a backend doesn't accept a request but a later one does.
Regression in a3ba2662cdaa36183fdfb8a26dfa157e26fca76a. Backport of 55e16f25e9d2050e95e448f9ab2e4b9fc845a9e5 from stable/2.0.x
This commit is contained in:
parent
649d5eaa8b
commit
4430b83e4b
@ -82,6 +82,7 @@ def authenticate(request=None, **credentials):
|
|||||||
|
|
||||||
|
|
||||||
def _authenticate_with_backend(backend, backend_path, request, credentials):
|
def _authenticate_with_backend(backend, backend_path, request, credentials):
|
||||||
|
credentials = credentials.copy() # Prevent a mutation from propagating.
|
||||||
args = (request,)
|
args = (request,)
|
||||||
# Does the backend accept a request argument?
|
# Does the backend accept a request argument?
|
||||||
try:
|
try:
|
||||||
|
@ -11,3 +11,7 @@ Bugfixes
|
|||||||
|
|
||||||
* Fixed incorrect foreign key nullification if a model has two foreign keys to
|
* Fixed incorrect foreign key nullification if a model has two foreign keys to
|
||||||
the same model and a target model is deleted (:ticket:`29016`).
|
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`).
|
||||||
|
@ -13,6 +13,18 @@ class NoRequestBackend(object):
|
|||||||
pass
|
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:
|
class RequestNotPositionArgBackend:
|
||||||
def authenticate(self, username=None, password=None, request=None):
|
def authenticate(self, username=None, password=None, request=None):
|
||||||
assert username == 'username'
|
assert username == 'username'
|
||||||
@ -34,6 +46,8 @@ class AcceptsRequestBackendTest(SimpleTestCase):
|
|||||||
method without a request parameter.
|
method without a request parameter.
|
||||||
"""
|
"""
|
||||||
no_request_backend = '%s.NoRequestBackend' % __name__
|
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_backend = '%s.RequestNotPositionArgBackend' % __name__
|
||||||
request_not_positional_with_used_kwarg_backend = '%s.RequestNotPositionArgWithUsedKwargBackend' % __name__
|
request_not_positional_with_used_kwarg_backend = '%s.RequestNotPositionArgWithUsedKwargBackend' % __name__
|
||||||
|
|
||||||
@ -79,6 +93,21 @@ class AcceptsRequestBackendTest(SimpleTestCase):
|
|||||||
"argument." % self.no_request_backend
|
"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])
|
@override_settings(AUTHENTICATION_BACKENDS=[request_not_positional_with_used_kwarg_backend])
|
||||||
def test_handles_backend_in_kwargs(self):
|
def test_handles_backend_in_kwargs(self):
|
||||||
with warnings.catch_warnings(record=True) as warns:
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user