Simplified LogoutView.get_success_url().

This preserves the behavior of redirecting to the logout URL without
query string parameters when an insecure ?next=... parameter is given.

It changes the behavior of a POST to the logout URL, as shown by the
test that is changed. Currently, this results in a GET to the logout
URL. However, such GET requests are deprecated. This change would be
necessary in Django 5.0 anyway. This commit merely anticipates it.
This commit is contained in:
Aymeric Augustin 2022-04-16 20:21:29 +02:00 committed by Mariusz Felisiak
parent 5fcd9b8c33
commit 04bc2564b6
2 changed files with 13 additions and 18 deletions

View File

@ -146,8 +146,8 @@ class LogoutView(RedirectURLMixin, TemplateView):
"""Logout may be done via POST."""
auth_logout(request)
redirect_to = self.get_success_url()
if redirect_to:
# Redirect to this page until the session has been cleared.
if redirect_to != request.get_full_path():
# Redirect to target page once the session has been cleared.
return HttpResponseRedirect(redirect_to)
return super().get(request, *args, **kwargs)
@ -155,28 +155,16 @@ class LogoutView(RedirectURLMixin, TemplateView):
get = post
def get_default_redirect_url(self):
"""Return the default redirect URL, or None if no URL is configured."""
"""Return the default redirect URL."""
if self.next_page:
return resolve_url(self.next_page)
elif settings.LOGOUT_REDIRECT_URL:
return resolve_url(settings.LOGOUT_REDIRECT_URL)
else:
return None
return self.request.path
def get_success_url(self):
next_page = self.get_default_redirect_url()
if (
self.redirect_field_name in self.request.POST
or self.redirect_field_name in self.request.GET
):
next_page = self.get_redirect_url()
if next_page == "":
if settings.LOGOUT_REDIRECT_URL:
next_page = resolve_url(settings.LOGOUT_REDIRECT_URL)
else:
next_page = self.request.path
return next_page
return self.get_redirect_url() or self.get_default_redirect_url()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)

View File

@ -984,6 +984,8 @@ class LogoutThenLoginTests(AuthViewsTestCase):
csrf_token = get_token(req)
req.COOKIES[settings.CSRF_COOKIE_NAME] = csrf_token
req.POST = {"csrfmiddlewaretoken": csrf_token}
req.META["SERVER_NAME"] = "testserver"
req.META["SERVER_PORT"] = 80
req.session = self.client.session
response = logout_then_login(req)
self.confirm_logged_out()
@ -996,6 +998,8 @@ class LogoutThenLoginTests(AuthViewsTestCase):
csrf_token = get_token(req)
req.COOKIES[settings.CSRF_COOKIE_NAME] = csrf_token
req.POST = {"csrfmiddlewaretoken": csrf_token}
req.META["SERVER_NAME"] = "testserver"
req.META["SERVER_PORT"] = 80
req.session = self.client.session
response = logout_then_login(req, login_url="/custom/")
self.confirm_logged_out()
@ -1007,6 +1011,8 @@ class LogoutThenLoginTests(AuthViewsTestCase):
self.login()
req = HttpRequest()
req.method = "GET"
req.META["SERVER_NAME"] = "testserver"
req.META["SERVER_PORT"] = 80
req.session = self.client.session
response = logout_then_login(req)
# RemovedInDjango50Warning: When the deprecation ends, replace with
@ -1345,7 +1351,8 @@ class LogoutTest(AuthViewsTestCase):
def test_logout_redirect_url_named_setting(self):
self.login()
response = self.client.post("/logout/")
self.assertRedirects(response, "/logout/", fetch_redirect_response=False)
self.assertContains(response, "Logged out")
self.confirm_logged_out()
def get_perm(Model, perm):