From 8f4e02c96d3bce9ed56ef2aec40f885951769d4e Mon Sep 17 00:00:00 2001 From: Ivan Kolodyazhny Date: Mon, 7 Aug 2017 15:43:38 +0300 Subject: [PATCH] Show NotAuthorized error message on a separate page Change-Id: I02d9d610a0e5feff7da14f86d003ec21010ab26a Closes-Bug: #1709077 --- horizon/exceptions.py | 15 ++------------- horizon/middleware/base.py | 8 ++------ horizon/templates/not_authorized.html | 10 ++++++++++ horizon/test/tests/base.py | 18 ++++++++---------- horizon/test/tests/middleware.py | 2 +- .../dashboards/project/instances/tests.py | 11 ++--------- .../dashboards/project/overview/tests.py | 12 ++---------- 7 files changed, 27 insertions(+), 49 deletions(-) create mode 100644 horizon/templates/not_authorized.html diff --git a/horizon/exceptions.py b/horizon/exceptions.py index a8eb154d1c..4fc1ef74cb 100644 --- a/horizon/exceptions.py +++ b/horizon/exceptions.py @@ -226,19 +226,8 @@ def handle_unauthorized(request, message, redirect, ignore, escalate, handled, # some clients, so let's define our own fallback. fallback = _("Unauthorized. Please try logging in again.") messages.error(request, message or fallback) - # Escalation means logging the user out and raising NotAuthorized - # so the middleware will redirect them appropriately. - if escalate: - # Prevents creation of circular import. django.contrib.auth - # requires openstack_dashboard.settings to be loaded (by trying to - # access settings.CACHES in django.core.caches) while - # openstack_dashboard.settings requires django.contrib.auth to be - # loaded while importing openstack_auth.utils - from django.contrib.auth import logout - logout(request) - raise NotAuthorized - # Otherwise continue and present our "unauthorized" error message. - return NotAuthorized + # Continue and present our "unauthorized" error message. + raise NotAuthorized def handle_notfound(request, message, redirect, ignore, escalate, handled, diff --git a/horizon/middleware/base.py b/horizon/middleware/base.py index 8fd3c407fd..4b47fab1f5 100644 --- a/horizon/middleware/base.py +++ b/horizon/middleware/base.py @@ -30,7 +30,6 @@ from django import http from django import shortcuts from django.utils.encoding import iri_to_uri from django.utils import timezone -from django.utils.translation import ugettext_lazy as _ from openstack_auth import views as auth_views @@ -128,12 +127,9 @@ class HorizonMiddleware(object): response = redirect_to_login(next_url, login_url=login_url, redirect_field_name=field_name) if isinstance(exception, exceptions.NotAuthorized): - logout_reason = _("Unauthorized. Please try logging in again.") - utils.add_logout_reason(request, response, logout_reason, - 'error') - # delete messages, created in get_data() method - # since we are going to redirect user to the login page response.delete_cookie('messages') + return shortcuts.render(request, 'not_authorized.html', + status=403) if request.is_ajax(): response_401 = http.HttpResponse(status=401) diff --git a/horizon/templates/not_authorized.html b/horizon/templates/not_authorized.html new file mode 100644 index 0000000000..87e1fffbec --- /dev/null +++ b/horizon/templates/not_authorized.html @@ -0,0 +1,10 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block breadcrumb_nav %} +{% endblock %} +{% block title %}{% trans "Unauthorized. Please try logging in again." %}{% endblock %} + +{% block main %} + {% trans "You are mot authorized to access this page" %} + {% trans "Login" %} +{% endblock %} \ No newline at end of file diff --git a/horizon/test/tests/base.py b/horizon/test/tests/base.py index 43aea570d0..9316ec63f7 100644 --- a/horizon/test/tests/base.py +++ b/horizon/test/tests/base.py @@ -277,18 +277,17 @@ class HorizonTests(BaseHorizonTests): self.assertQuerysetEqual(self.user.get_all_permissions(), []) resp = self.client.get(panel.get_absolute_url()) - self.assertEqual(302, resp.status_code) + self.assertEqual(403, resp.status_code) resp = self.client.get(panel.get_absolute_url(), follow=False, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - self.assertEqual(401, resp.status_code) + self.assertEqual(403, resp.status_code) # Test insufficient permissions for logged-in user resp = self.client.get(panel.get_absolute_url(), follow=True) - self.assertEqual(200, resp.status_code) - self.assertTemplateUsed(resp, "auth/login.html") - self.assertContains(resp, "Login as different user", 1, 200) + self.assertEqual(403, resp.status_code) + self.assertTemplateUsed(resp, "not_authorized.html") # Set roles for admin user self.set_permissions(permissions=['test']) @@ -440,18 +439,17 @@ class CustomPermissionsTests(BaseHorizonTests): self.assertQuerysetEqual(self.user.get_all_permissions(), []) resp = self.client.get(panel.get_absolute_url()) - self.assertEqual(302, resp.status_code) + self.assertEqual(403, resp.status_code) resp = self.client.get(panel.get_absolute_url(), follow=False, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - self.assertEqual(401, resp.status_code) + self.assertEqual(403, resp.status_code) # Test customized permissions for logged-in user resp = self.client.get(panel.get_absolute_url(), follow=True) - self.assertEqual(200, resp.status_code) - self.assertTemplateUsed(resp, "auth/login.html") - self.assertContains(resp, "Login as different user", 1, 200) + self.assertEqual(403, resp.status_code) + self.assertTemplateUsed(resp, "not_authorized.html") # Set roles for admin user self.set_permissions(permissions=['test']) diff --git a/horizon/test/tests/middleware.py b/horizon/test/tests/middleware.py index 81e4f86981..9994650daf 100644 --- a/horizon/test/tests/middleware.py +++ b/horizon/test/tests/middleware.py @@ -41,7 +41,7 @@ class MiddlewareTests(test.TestCase): request = self.factory.post(url) mw = middleware.HorizonMiddleware() - resp = mw.process_exception(request, exceptions.NotAuthorized()) + resp = mw.process_exception(request, exceptions.NotAuthenticated()) resp.client = self.client if django.VERSION >= (1, 9): diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py index 967381b5ca..a7207936c5 100644 --- a/openstack_dashboard/dashboards/project/instances/tests.py +++ b/openstack_dashboard/dashboards/project/instances/tests.py @@ -23,7 +23,6 @@ import sys import django from django.conf import settings -from django.contrib.auth import REDIRECT_FIELD_NAME from django.core.urlresolvers import reverse from django.forms import widgets from django import http @@ -1155,11 +1154,9 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase): def test_instance_details_unauthorized(self): server = self.servers.first() - api.nova.server_get(IsA(http.HttpRequest), server.id)\ - .AndRaise(self.exceptions.nova_unauthorized) self.mox.ReplayAll() - url = reverse('horizon:project:instances:detail', + url = reverse('horizon:admin:instances:detail', args=[server.id]) # Avoid the log message in the test @@ -1168,11 +1165,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase): res = self.client.get(url) logging.disable(logging.NOTSET) - self.assertEqual(302, res.status_code) - self.assertEqual(('Location', settings.TESTSERVER + - settings.LOGIN_URL + '?' + - REDIRECT_FIELD_NAME + '=' + url), - res._headers.get('location', None),) + self.assertEqual(403, res.status_code) def test_instance_details_flavor_not_found(self): server = self.servers.first() diff --git a/openstack_dashboard/dashboards/project/overview/tests.py b/openstack_dashboard/dashboards/project/overview/tests.py index ac5479296c..e126a9a072 100644 --- a/openstack_dashboard/dashboards/project/overview/tests.py +++ b/openstack_dashboard/dashboards/project/overview/tests.py @@ -19,8 +19,6 @@ import datetime import logging -from django.conf import settings -from django.contrib.auth import REDIRECT_FIELD_NAME from django.core.urlresolvers import reverse from django import http from django.test.utils import override_settings @@ -166,11 +164,9 @@ class UsageViewTests(test.TestCase): self._nova_stu_enabled(exception) def test_unauthorized(self): - self._stub_nova_api_calls_unauthorized( - self.exceptions.nova_unauthorized) self.mox.ReplayAll() - url = reverse('horizon:project:overview:index') + url = reverse('horizon:admin:volumes:index') # Avoid the log message in the test # when unauthorized exception will be logged @@ -178,11 +174,7 @@ class UsageViewTests(test.TestCase): res = self.client.get(url) logging.disable(logging.NOTSET) - self.assertEqual(302, res.status_code) - self.assertEqual(('Location', settings.TESTSERVER + - settings.LOGIN_URL + '?' + - REDIRECT_FIELD_NAME + '=' + url), - res._headers.get('location', None),) + self.assertEqual(403, res.status_code) def test_usage_csv(self): self._test_usage_csv(nova_stu_enabled=True)