diff --git a/horizon/base.py b/horizon/base.py index 4a2ffa125..d04d44313 100644 --- a/horizon/base.py +++ b/horizon/base.py @@ -52,7 +52,8 @@ HORIZON_CONFIG = { 'dashboards': None, # Name of a default dashboard; defaults to first alphabetically if None 'default_dashboard': None, - 'user_home': None, + # Default redirect url for users' home + 'user_home': settings.LOGIN_REDIRECT_URL, 'exceptions': {'unauthorized': [], 'not_found': [], 'recoverable': []} @@ -700,9 +701,11 @@ class Site(Registry, HorizonComponent): {"user_home": "/home",} # A URL {"user_home": "my_module.get_user_home",} # Path to a function {"user_home": lambda user: "/" + user.name,} # A function + {"user_home": None,} # Will always return the default dashboard This can be useful if the default dashboard may not be accessible - to all users. + to all users. When user_home is missing from HORIZON_CONFIG, + it will default to the settings.LOGIN_REDIRECT_URL value. """ user_home = self._conf['user_home'] if user_home: diff --git a/horizon/site_urls.py b/horizon/site_urls.py index 2d4fe4ca6..b5056958b 100644 --- a/horizon/site_urls.py +++ b/horizon/site_urls.py @@ -19,14 +19,17 @@ # under the License. from django.conf.urls.defaults import patterns, url, include +from django.conf import settings from horizon.views.auth import LoginView urlpatterns = patterns('horizon.views.auth', url(r'home/$', 'user_home', name='user_home'), - url(r'auth/login/$', LoginView.as_view(), name='auth_login'), - url(r'auth/logout/$', 'logout', name='auth_logout'), + url(r"^%s$" % settings.LOGIN_URL.lstrip('/'), LoginView.as_view(), + name='auth_login'), + url(r"^%s$" % settings.LOGOUT_URL.lstrip('/'), 'logout', + name='auth_logout'), url(r'auth/switch/(?P[^/]+)/$', 'switch_tenants', name='auth_switch')) diff --git a/horizon/tests/auth_tests.py b/horizon/tests/auth_tests.py index 87132ab66..26f1e6eb6 100644 --- a/horizon/tests/auth_tests.py +++ b/horizon/tests/auth_tests.py @@ -21,6 +21,7 @@ import time from django import http +from django.conf import settings from django.core.urlresolvers import reverse from keystoneclient import exceptions as keystone_exceptions from mox import IsA @@ -72,19 +73,25 @@ class AuthViewTests(test.TestCase): self.assertTemplateUsed(res, 'horizon/auth/login.html') + @test.create_stubs({api: ('token_create', 'tenant_list_for_token', + 'token_create_scoped')}) def test_login(self): form_data = {'method': 'Login', 'region': 'http://localhost:5000/v2.0', 'password': self.user.password, 'username': self.user.name} - self.mox.StubOutWithMock(api, 'token_create') - self.mox.StubOutWithMock(api, 'tenant_list_for_token') - self.mox.StubOutWithMock(api, 'token_create_scoped') - aToken = self.tokens.unscoped_token bToken = self.tokens.scoped_token + api.token_create(IsA(http.HttpRequest), "", self.user.name, + self.user.password).AndReturn(aToken) + api.tenant_list_for_token(IsA(http.HttpRequest), + aToken.id).AndReturn([self.tenants.first()]) + api.token_create_scoped(IsA(http.HttpRequest), + self.tenant.id, + aToken.id).AndReturn(bToken) + api.token_create(IsA(http.HttpRequest), "", self.user.name, self.user.password).AndReturn(aToken) api.tenant_list_for_token(IsA(http.HttpRequest), @@ -98,6 +105,12 @@ class AuthViewTests(test.TestCase): res = self.client.post(reverse('horizon:auth_login'), form_data) self.assertRedirectsNoFollow(res, DASH_INDEX_URL) + # Test default Django LOGIN_REDIRECT_URL + user_home = settings.HORIZON_CONFIG.pop('user_home') + res = self.client.post(reverse('horizon:auth_login'), form_data) + self.assertRedirectsNoFollow(res, settings.LOGIN_REDIRECT_URL) + settings.HORIZON_CONFIG['user_home'] = user_home + def test_login_first_tenant_invalid(self): form_data = {'method': 'Login', 'region': 'http://localhost:5000/v2.0', diff --git a/horizon/tests/testsettings.py b/horizon/tests/testsettings.py index 51de8df4a..607331fc3 100644 --- a/horizon/tests/testsettings.py +++ b/horizon/tests/testsettings.py @@ -25,6 +25,10 @@ from django.utils.translation import ugettext_lazy as _ socket.setdefaulttimeout(1) +LOGIN_URL = '/auth/login/' +LOGOUT_URL = '/auth/logout/' +LOGIN_REDIRECT_URL = '/' + ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) DEBUG = True TESTSERVER = 'http://testserver' @@ -101,6 +105,7 @@ HORIZON_CONFIG = { "regex": '^.{8,18}$', "help_text": _("Password must be between 8 and 18 characters.") }, + 'user_home': None } AVAILABLE_REGIONS = [ diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index c73647e75..ed867b8cf 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -34,7 +34,11 @@ TEMPLATE_DEBUG = DEBUG SITE_ID = 1 SITE_BRANDING = 'OpenStack' -LOGIN_URL = '/auth/login' +LOGIN_URL = '/auth/login/' +LOGOUT_URL = '/auth/logout/' +# LOGIN_REDIRECT_URL can be used as an alternative for +# HORIZON_CONFIG.user_home, if user_home is not set. +# Do not set it to '/home/', as this will cause circular redirect loop LOGIN_REDIRECT_URL = '/' MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media'))