From af66c03e4254b40ffb484a9e5724c73dd9d2d06e Mon Sep 17 00:00:00 2001 From: Gabriel Hurley Date: Thu, 12 Jan 2012 16:47:41 -0800 Subject: [PATCH] Makes all dashboards (and all views under them) login_required by default. Change-Id: I435a4cbca669a7fdb6fa9ac483984c3c5fb2a58d --- horizon/horizon/base.py | 10 +++++++++ .../access_and_security/floating_ips/forms.py | 1 - .../dashboards/nova/containers/views.py | 1 - .../nova/images_and_snapshots/images/views.py | 4 ---- .../images_and_snapshots/snapshots/views.py | 3 --- .../nova/images_and_snapshots/views.py | 2 -- .../instances_and_volumes/instances/views.py | 8 ------- .../nova/instances_and_volumes/views.py | 2 -- .../instances_and_volumes/volumes/views.py | 5 ----- .../horizon/dashboards/nova/networks/views.py | 1 - .../dashboards/settings/tenant/views.py | 2 -- .../horizon/dashboards/settings/user/views.py | 2 -- .../dashboards/syspanel/flavors/views.py | 1 - .../dashboards/syspanel/images/views.py | 4 ---- .../dashboards/syspanel/instances/views.py | 1 - .../dashboards/syspanel/quotas/views.py | 1 - .../dashboards/syspanel/services/views.py | 1 - .../dashboards/syspanel/tenants/views.py | 1 - .../dashboards/syspanel/users/views.py | 1 - horizon/horizon/tests/base_tests.py | 21 +++++++++++++++++-- 20 files changed, 29 insertions(+), 43 deletions(-) diff --git a/horizon/horizon/base.py b/horizon/horizon/base.py index 22acf5a36a..1dd4da9a1e 100644 --- a/horizon/horizon/base.py +++ b/horizon/horizon/base.py @@ -29,6 +29,7 @@ import logging from django.conf import settings from django.conf.urls.defaults import patterns, url, include +from django.contrib.auth.decorators import login_required from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import reverse, RegexURLPattern from django.utils.functional import SimpleLazyObject @@ -318,6 +319,11 @@ class Dashboard(Registry, HorizonComponent): support for projects/tenants. If set to ``True`` this dashboard's naviagtion will include a UI element that allows the user to select project/tenant. Default: ``False``. + + .. attribute:: public + + Boolean value to determine whether this dashboard can be viewed + without being logged in. Defaults to ``False``. """ _registerable_class = Panel name = '' @@ -327,6 +333,7 @@ class Dashboard(Registry, HorizonComponent): default_panel = None nav = True supports_tenants = False + public = False def __repr__(self): return "" % self.__unicode__() @@ -399,6 +406,9 @@ class Dashboard(Registry, HorizonComponent): urlpatterns += patterns('', url(r'', include(default_panel._decorated_urls))) + # Require login if not public. + if not self.public: + _decorate_urlconf(urlpatterns, login_required) # Apply access controls to all views in the patterns roles = getattr(self, 'roles', []) _decorate_urlconf(urlpatterns, require_roles, roles) diff --git a/horizon/horizon/dashboards/nova/access_and_security/floating_ips/forms.py b/horizon/horizon/dashboards/nova/access_and_security/floating_ips/forms.py index 8179d5b50d..231e28dffe 100644 --- a/horizon/horizon/dashboards/nova/access_and_security/floating_ips/forms.py +++ b/horizon/horizon/dashboards/nova/access_and_security/floating_ips/forms.py @@ -21,7 +21,6 @@ import logging from django.contrib import messages -from django.contrib.auth.decorators import login_required from django import shortcuts from django.utils.translation import ugettext as _ from novaclient import exceptions as novaclient_exceptions diff --git a/horizon/horizon/dashboards/nova/containers/views.py b/horizon/horizon/dashboards/nova/containers/views.py index 7c36c22a79..72d6466dae 100644 --- a/horizon/horizon/dashboards/nova/containers/views.py +++ b/horizon/horizon/dashboards/nova/containers/views.py @@ -26,7 +26,6 @@ import os from django import http from django.contrib import messages -from django.contrib.auth.decorators import login_required from django import shortcuts from horizon import api diff --git a/horizon/horizon/dashboards/nova/images_and_snapshots/images/views.py b/horizon/horizon/dashboards/nova/images_and_snapshots/images/views.py index 6e37fab199..a2f51808db 100644 --- a/horizon/horizon/dashboards/nova/images_and_snapshots/images/views.py +++ b/horizon/horizon/dashboards/nova/images_and_snapshots/images/views.py @@ -26,7 +26,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from glance.common import exception as glance_exception from novaclient import exceptions as novaclient_exceptions @@ -40,7 +39,6 @@ from .forms import UpdateImageForm, LaunchForm, DeleteImage LOG = logging.getLogger(__name__) -@login_required def index(request): for f in (DeleteImage, ): unused, handled = f.maybe_handle(request) @@ -74,7 +72,6 @@ def index(request): 'images': images}) -@login_required def launch(request, image_id): def flavorlist(): try: @@ -140,7 +137,6 @@ def launch(request, image_id): 'quotas': quotas}) -@login_required def update(request, image_id): try: image = api.image_get_meta(request, image_id) diff --git a/horizon/horizon/dashboards/nova/images_and_snapshots/snapshots/views.py b/horizon/horizon/dashboards/nova/images_and_snapshots/snapshots/views.py index a3aafddc5a..bd76492c71 100644 --- a/horizon/horizon/dashboards/nova/images_and_snapshots/snapshots/views.py +++ b/horizon/horizon/dashboards/nova/images_and_snapshots/snapshots/views.py @@ -29,7 +29,6 @@ from django import http from django import shortcuts from django import template from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from glance.common import exception as glance_exception from openstackx.api import exceptions as api_exceptions @@ -43,7 +42,6 @@ from horizon.dashboards.nova.images_and_snapshots.snapshots.forms import \ LOG = logging.getLogger(__name__) -@login_required def index(request): images = [] @@ -63,7 +61,6 @@ def index(request): {'images': images}) -@login_required def create(request, instance_id): tenant_id = request.user.tenant_id form, handled = CreateSnapshot.maybe_handle(request, diff --git a/horizon/horizon/dashboards/nova/images_and_snapshots/views.py b/horizon/horizon/dashboards/nova/images_and_snapshots/views.py index 07bfd7e649..befa552a94 100644 --- a/horizon/horizon/dashboards/nova/images_and_snapshots/views.py +++ b/horizon/horizon/dashboards/nova/images_and_snapshots/views.py @@ -27,7 +27,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from glance.common import exception as glance_exception from novaclient import exceptions as novaclient_exceptions @@ -41,7 +40,6 @@ from horizon.dashboards.nova.images_and_snapshots.images.forms import \ LOG = logging.getLogger(__name__) -@login_required def index(request): for f in (DeleteImage, ): unused, handled = f.maybe_handle(request) diff --git a/horizon/horizon/dashboards/nova/instances_and_volumes/instances/views.py b/horizon/horizon/dashboards/nova/instances_and_volumes/instances/views.py index 38bc93881c..45e7ecc15d 100644 --- a/horizon/horizon/dashboards/nova/instances_and_volumes/instances/views.py +++ b/horizon/horizon/dashboards/nova/instances_and_volumes/instances/views.py @@ -27,7 +27,6 @@ import logging from django import http from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.datastructures import SortedDict from django.utils.translation import ugettext as _ import openstackx.api.exceptions as api_exceptions @@ -44,7 +43,6 @@ from horizon.dashboards.nova.instances_and_volumes.instances.forms import ( LOG = logging.getLogger(__name__) -@login_required def index(request): tenant_id = request.user.tenant_id for f in (TerminateInstance, RebootInstance): @@ -97,7 +95,6 @@ def index(request): 'reboot_form': reboot_form}) -@login_required def refresh(request): tenant_id = request.user.tenant_id instances = [] @@ -129,7 +126,6 @@ def refresh(request): 'reboot_form': reboot_form}) -@login_required def usage(request, tenant_id=None): tenant_id = tenant_id or request.user.tenant_id today = test.today() @@ -197,7 +193,6 @@ def usage(request, tenant_id=None): content_type=mimetype) -@login_required def console(request, instance_id): tenant_id = request.user.tenant_id try: @@ -219,7 +214,6 @@ def console(request, instance_id): 'horizon:nova:instances_and_volumes:instances:index') -@login_required def vnc(request, instance_id): tenant_id = request.user.tenant_id try: @@ -236,7 +230,6 @@ def vnc(request, instance_id): 'horizon:nova:instances_and_volumes:instances:index') -@login_required def update(request, instance_id): tenant_id = request.user.tenant_id try: @@ -263,7 +256,6 @@ def update(request, instance_id): 'form': form}) -@login_required def detail(request, instance_id): tenant_id = request.user.tenant_id try: diff --git a/horizon/horizon/dashboards/nova/instances_and_volumes/views.py b/horizon/horizon/dashboards/nova/instances_and_volumes/views.py index f29dde013b..64bba0db6d 100644 --- a/horizon/horizon/dashboards/nova/instances_and_volumes/views.py +++ b/horizon/horizon/dashboards/nova/instances_and_volumes/views.py @@ -28,7 +28,6 @@ import logging from django import http from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from django.utils.datastructures import SortedDict from novaclient import exceptions as novaclient_exceptions @@ -47,7 +46,6 @@ CreateForm, DeleteForm, AttachForm, DetachForm) LOG = logging.getLogger(__name__) -@login_required def index(request): for f in (TerminateInstance, PauseInstance, UnpauseInstance, SuspendInstance, ResumeInstance, RebootInstance, diff --git a/horizon/horizon/dashboards/nova/instances_and_volumes/volumes/views.py b/horizon/horizon/dashboards/nova/instances_and_volumes/volumes/views.py index de0aca6b46..69c85abc35 100644 --- a/horizon/horizon/dashboards/nova/instances_and_volumes/volumes/views.py +++ b/horizon/horizon/dashboards/nova/instances_and_volumes/volumes/views.py @@ -22,7 +22,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from novaclient import exceptions as novaclient_exceptions @@ -34,7 +33,6 @@ from horizon.dashboards.nova.instances_and_volumes.volumes.forms \ LOG = logging.getLogger(__name__) -@login_required def index(request): delete_form, handled = DeleteForm.maybe_handle(request) detach_form, handled = DetachForm.maybe_handle(request) @@ -59,7 +57,6 @@ def index(request): 'detach_form': detach_form}) -@login_required def detail(request, volume_id): try: volume = api.volume_get(request, volume_id) @@ -82,7 +79,6 @@ def detail(request, volume_id): 'instance': instance}) -@login_required def create(request): create_form, handled = CreateForm.maybe_handle(request) @@ -94,7 +90,6 @@ def create(request): 'create_form': create_form}) -@login_required def attach(request, volume_id): instances = api.server_list(request) attach_form, handled = AttachForm.maybe_handle(request, diff --git a/horizon/horizon/dashboards/nova/networks/views.py b/horizon/horizon/dashboards/nova/networks/views.py index 101b04a02f..3d02a30dfa 100644 --- a/horizon/horizon/dashboards/nova/networks/views.py +++ b/horizon/horizon/dashboards/nova/networks/views.py @@ -28,7 +28,6 @@ import warnings from django import shortcuts from django import template from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from horizon import api diff --git a/horizon/horizon/dashboards/settings/tenant/views.py b/horizon/horizon/dashboards/settings/tenant/views.py index e0aa40d3d6..4c0d542ba8 100644 --- a/horizon/horizon/dashboards/settings/tenant/views.py +++ b/horizon/horizon/dashboards/settings/tenant/views.py @@ -15,11 +15,9 @@ # under the License. from django import shortcuts -from django.contrib.auth.decorators import login_required from horizon.dashboards.settings.tenant.forms import DownloadOpenRCForm -@login_required def index(request): form, handled = DownloadOpenRCForm.maybe_handle(request, initial={'tenant': request.user.tenant_id}) diff --git a/horizon/horizon/dashboards/settings/user/views.py b/horizon/horizon/dashboards/settings/user/views.py index 60538d0b52..434f725877 100644 --- a/horizon/horizon/dashboards/settings/user/views.py +++ b/horizon/horizon/dashboards/settings/user/views.py @@ -15,10 +15,8 @@ # under the License. from django import shortcuts -from django.contrib.auth.decorators import login_required from horizon.dashboards.settings.tenant.forms import DownloadOpenRCForm -@login_required def index(request): return shortcuts.render(request, 'settings/user/settings.html', {}) diff --git a/horizon/horizon/dashboards/syspanel/flavors/views.py b/horizon/horizon/dashboards/syspanel/flavors/views.py index 2e24b778c6..3b5f471e16 100644 --- a/horizon/horizon/dashboards/syspanel/flavors/views.py +++ b/horizon/horizon/dashboards/syspanel/flavors/views.py @@ -22,7 +22,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from novaclient import exceptions as api_exceptions diff --git a/horizon/horizon/dashboards/syspanel/images/views.py b/horizon/horizon/dashboards/syspanel/images/views.py index 05f76b5e28..9f4e473efb 100644 --- a/horizon/horizon/dashboards/syspanel/images/views.py +++ b/horizon/horizon/dashboards/syspanel/images/views.py @@ -22,7 +22,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from glance.common import exception as glance_exception @@ -34,7 +33,6 @@ from horizon.dashboards.syspanel.images.forms import (DeleteImage, LOG = logging.getLogger(__name__) -@login_required def index(request): for f in (DeleteImage, ToggleImage): form, handled = f.maybe_handle(request) @@ -67,7 +65,6 @@ def index(request): 'images': images}) -@login_required def update(request, image_id): try: image = api.image_get_meta(request, image_id) @@ -146,7 +143,6 @@ def update(request, image_id): 'form': form}) -@login_required def upload(request): if request.method == "POST": form = UploadImageForm(request.POST) diff --git a/horizon/horizon/dashboards/syspanel/instances/views.py b/horizon/horizon/dashboards/syspanel/instances/views.py index 5d3aa9a00a..7e678acecd 100644 --- a/horizon/horizon/dashboards/syspanel/instances/views.py +++ b/horizon/horizon/dashboards/syspanel/instances/views.py @@ -25,7 +25,6 @@ from django import template from django import http from django.conf import settings from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.shortcuts import render_to_response, redirect from django.utils.translation import ugettext as _ diff --git a/horizon/horizon/dashboards/syspanel/quotas/views.py b/horizon/horizon/dashboards/syspanel/quotas/views.py index 57b52f769d..2312515097 100644 --- a/horizon/horizon/dashboards/syspanel/quotas/views.py +++ b/horizon/horizon/dashboards/syspanel/quotas/views.py @@ -22,7 +22,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from horizon import api from horizon import tables diff --git a/horizon/horizon/dashboards/syspanel/services/views.py b/horizon/horizon/dashboards/syspanel/services/views.py index e9b70c4690..607427d314 100644 --- a/horizon/horizon/dashboards/syspanel/services/views.py +++ b/horizon/horizon/dashboards/syspanel/services/views.py @@ -25,7 +25,6 @@ import urlparse from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from openstackx.api import exceptions as api_exceptions diff --git a/horizon/horizon/dashboards/syspanel/tenants/views.py b/horizon/horizon/dashboards/syspanel/tenants/views.py index f0e40cfb1c..4077404f11 100644 --- a/horizon/horizon/dashboards/syspanel/tenants/views.py +++ b/horizon/horizon/dashboards/syspanel/tenants/views.py @@ -24,7 +24,6 @@ from django import shortcuts from django import http from django.conf import settings from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from keystoneclient import exceptions as api_exceptions diff --git a/horizon/horizon/dashboards/syspanel/users/views.py b/horizon/horizon/dashboards/syspanel/users/views.py index 1faa2cae9e..ca49f1f0c2 100644 --- a/horizon/horizon/dashboards/syspanel/users/views.py +++ b/horizon/horizon/dashboards/syspanel/users/views.py @@ -22,7 +22,6 @@ import logging from django import shortcuts from django.contrib import messages -from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from keystoneclient import exceptions as api_exceptions diff --git a/horizon/horizon/tests/base_tests.py b/horizon/horizon/tests/base_tests.py index aa373bf6b9..5c15c221b4 100644 --- a/horizon/horizon/tests/base_tests.py +++ b/horizon/horizon/tests/base_tests.py @@ -21,13 +21,14 @@ import copy from django.core.urlresolvers import NoReverseMatch +from django.test.client import Client import horizon from horizon import base from horizon import exceptions from horizon import test +from horizon import users from horizon.base import Horizon -from horizon.users import User class MyDash(horizon.Dashboard): @@ -91,7 +92,7 @@ class HorizonTests(test.TestCase): self.assertEqual(repr(Horizon), "") dash = Horizon.get_dashboard('nova') self.assertEqual(Horizon.get_default_dashboard(), dash) - user = User() + user = users.User() self.assertEqual(Horizon.get_user_home(user), dash.get_absolute_url()) def test_dashboard(self): @@ -143,3 +144,19 @@ class HorizonTests(test.TestCase): # The following two methods simply should not raise any exceptions iter(urlpatterns) reversed(urlpatterns) + + +class HorizonBaseViewTests(test.BaseViewTests): + def setUp(self): + super(HorizonBaseViewTests, self).setUp() + users.get_user_from_request = self._real_get_user_from_request + + def test_public(self): + settings = horizon.get_dashboard("settings") + # Known to have no restrictions on it other than being logged in. + user_panel = settings.get_panel("user") + url = user_panel.get_absolute_url() + client = Client() # Get a clean, logged out client instance. + client.logout() + resp = client.get(url) + self.assertRedirectsNoFollow(resp, '/accounts/login/?next=/settings/')