diff --git a/horizon/middleware.py b/horizon/middleware.py index 9cd2a6a988..edd4359fc4 100644 --- a/horizon/middleware.py +++ b/horizon/middleware.py @@ -26,8 +26,10 @@ import logging from django import http from django import shortcuts +from django.conf import settings from django.contrib import messages as django_messages from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import redirect_to_login from django.core.urlresolvers import reverse from django.utils import timezone from django.utils.encoding import iri_to_uri @@ -59,20 +61,23 @@ class HorizonMiddleware(object): """ if isinstance(exception, (exceptions.NotAuthorized, exceptions.NotAuthenticated)): - auth_url = reverse("login") + auth_url = settings.LOGIN_URL next_url = iri_to_uri(request.get_full_path()) if next_url != auth_url: - param = "?%s=%s" % (REDIRECT_FIELD_NAME, next_url) - redirect_to = "".join((auth_url, param)) + field_name = REDIRECT_FIELD_NAME else: - redirect_to = auth_url + field_name = None + login_url = request.build_absolute_uri(auth_url) + response = redirect_to_login(next_url, login_url=login_url, + redirect_field_name=field_name) + # TODO(gabriel): Find a way to display an appropriate message to # the user *on* the login form... if request.is_ajax(): response_401 = http.HttpResponse(status=401) - response_401['X-Horizon-Location'] = redirect_to + response_401['X-Horizon-Location'] = response['location'] return response_401 - return shortcuts.redirect(redirect_to) + return response # If an internal "NotFound" error gets this far, return a real 404. if isinstance(exception, exceptions.NotFound): diff --git a/horizon/test/tests/base.py b/horizon/test/tests/base.py index 65b01dc5fe..468219d5d0 100644 --- a/horizon/test/tests/base.py +++ b/horizon/test/tests/base.py @@ -226,7 +226,7 @@ class HorizonTests(BaseHorizonTests): self.client.logout() resp = self.client.get(url) - redirect_url = "?".join([urlresolvers.reverse("login"), + redirect_url = "?".join(['http://testserver' + settings.LOGIN_URL, "next=%s" % url]) self.assertRedirects(resp, redirect_url) @@ -235,8 +235,7 @@ class HorizonTests(BaseHorizonTests): # Response should be HTTP 401 with redirect header self.assertEquals(resp.status_code, 401) self.assertEquals(resp["X-Horizon-Location"], - "?".join([urlresolvers.reverse("login"), - "next=%s" % url])) + redirect_url) def test_required_permissions(self): dash = horizon.get_dashboard("cats") @@ -275,7 +274,7 @@ class HorizonTests(BaseHorizonTests): dogs = horizon.get_dashboard("dogs") puppies = dogs.get_panel("puppies") url = puppies.get_absolute_url() - redirect_url = "?".join([urlresolvers.reverse("login"), + redirect_url = "?".join([settings.LOGIN_URL, "next=%s" % url]) self.client.logout() diff --git a/horizon/test/tests/middleware.py b/horizon/test/tests/middleware.py new file mode 100644 index 0000000000..958e4233fe --- /dev/null +++ b/horizon/test/tests/middleware.py @@ -0,0 +1,34 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from django.conf import settings + +from horizon import exceptions +from horizon import middleware +from horizon.test import helpers as test + + +class MiddlewareTests(test.TestCase): + def test_redirect_login_fail_to_login(self): + url = settings.LOGIN_URL + request = self.factory.post(url) + + mw = middleware.HorizonMiddleware() + resp = mw.process_exception(request, exceptions.NotAuthorized()) + resp.client = self.client + + self.assertRedirects(resp, url)