Fixed #31443 -- Fixed login redirection in auth mixins when LOGIN_URL is off-site URL.
This commit is contained in:
parent
136ec9b62b
commit
cc7c16af98
|
@ -1,7 +1,10 @@
|
|||
from urllib.parse import urlparse
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||
from django.shortcuts import resolve_url
|
||||
|
||||
|
||||
class AccessMixin:
|
||||
|
@ -41,7 +44,23 @@ class AccessMixin:
|
|||
def handle_no_permission(self):
|
||||
if self.raise_exception or self.request.user.is_authenticated:
|
||||
raise PermissionDenied(self.get_permission_denied_message())
|
||||
return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
|
||||
|
||||
path = self.request.build_absolute_uri()
|
||||
resolved_login_url = resolve_url(self.get_login_url())
|
||||
# If the login url is the same scheme and net location then use the
|
||||
# path as the "next" url.
|
||||
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
|
||||
current_scheme, current_netloc = urlparse(path)[:2]
|
||||
if (
|
||||
(not login_scheme or login_scheme == current_scheme) and
|
||||
(not login_netloc or login_netloc == current_netloc)
|
||||
):
|
||||
path = self.request.get_full_path()
|
||||
return redirect_to_login(
|
||||
path,
|
||||
resolved_login_url,
|
||||
self.get_redirect_field_name(),
|
||||
)
|
||||
|
||||
|
||||
class LoginRequiredMixin(AccessMixin):
|
||||
|
|
|
@ -94,6 +94,20 @@ class AccessMixinTests(TestCase):
|
|||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, '/accounts/login/?next=/rand')
|
||||
|
||||
def test_access_mixin_permission_denied_remote_login_url(self):
|
||||
class AView(AlwaysFalseView):
|
||||
login_url = 'https://www.remote.example.com/login'
|
||||
|
||||
view = AView.as_view()
|
||||
request = self.factory.get('/rand')
|
||||
request.user = AnonymousUser()
|
||||
response = view(request)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(
|
||||
response.url,
|
||||
'https://www.remote.example.com/login?next=http%3A//testserver/rand',
|
||||
)
|
||||
|
||||
@mock.patch.object(models.User, 'is_authenticated', False)
|
||||
def test_stacked_mixins_not_logged_in(self):
|
||||
user = models.User.objects.create(username='joe', password='qwerty')
|
||||
|
|
Loading…
Reference in New Issue