From f59ecbef7839e2d6a711f49362353739b0fde69e Mon Sep 17 00:00:00 2001 From: Gabriel Hurley Date: Sun, 18 Mar 2012 17:24:23 -0700 Subject: [PATCH] Fixed a variable being clobbered in the auth_forms handler. Adds some new test data and a regression test for this bug. Fixes bug 953806. Change-Id: I1873e7f2cf0ce4431a6f6fb0ad7b0ef0cbd34334 --- horizon/tests/auth_tests.py | 36 +++++++++++++++++++++++- horizon/tests/context_processor_tests.py | 4 +-- horizon/tests/test_data/keystone_data.py | 7 ++++- horizon/tests/testsettings.py | 1 + horizon/views/auth_forms.py | 23 +++++++-------- 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/horizon/tests/auth_tests.py b/horizon/tests/auth_tests.py index 5cf46c663..ba1647777 100644 --- a/horizon/tests/auth_tests.py +++ b/horizon/tests/auth_tests.py @@ -86,7 +86,7 @@ class AuthViewTests(test.TestCase): 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.list()) + aToken.id).AndReturn([self.tenants.first()]) api.token_create_scoped(IsA(http.HttpRequest), self.tenant.id, aToken.id).AndReturn(bToken) @@ -96,6 +96,40 @@ class AuthViewTests(test.TestCase): res = self.client.post(reverse('horizon:auth_login'), form_data) self.assertRedirectsNoFollow(res, DASH_INDEX_URL) + def test_login_first_tenant_invalid(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 + disabled_tenant = self.tenants.get(name="disabled_tenant") + tenant = self.tenants.get(name="test_tenant") + tenants = [tenant, disabled_tenant] + 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(tenants) + exc = keystone_exceptions.Unauthorized("Not authorized.") + api.token_create_scoped(IsA(http.HttpRequest), + disabled_tenant.id, + aToken.id).AndRaise(exc) + api.token_create_scoped(IsA(http.HttpRequest), + tenant.id, + aToken.id).AndReturn(bToken) + + self.mox.ReplayAll() + + res = self.client.post(reverse('horizon:auth_login'), form_data) + self.assertNoFormErrors(res) + self.assertNoMessages() + self.assertRedirectsNoFollow(res, DASH_INDEX_URL) + def test_login_invalid_credentials(self): self.mox.StubOutWithMock(api, 'token_create') unauthorized = keystone_exceptions.Unauthorized("Invalid") diff --git a/horizon/tests/context_processor_tests.py b/horizon/tests/context_processor_tests.py index a47123976..5bf319b36 100644 --- a/horizon/tests/context_processor_tests.py +++ b/horizon/tests/context_processor_tests.py @@ -58,6 +58,4 @@ class ContextProcessorTests(test.TestCase): self.request.horizon['dashboard'] = ProjectDash self.assertTrue(self.request.user.is_authenticated()) context = context_processors.horizon(self.request) - self.assertEqual(len(context['authorized_tenants']), 1) - tenant = context['authorized_tenants'].pop() - self.assertEqual(tenant.id, self.tenant.id) + self.assertItemsEqual(context['authorized_tenants'], tenant_list) diff --git a/horizon/tests/test_data/keystone_data.py b/horizon/tests/test_data/keystone_data.py index 7343bb94b..180b10f6d 100644 --- a/horizon/tests/test_data/keystone_data.py +++ b/horizon/tests/test_data/keystone_data.py @@ -117,8 +117,13 @@ def data(TEST): 'name': 'test_tenant', 'description': "a test tenant.", 'enabled': True} + tenant_dict_2 = {'id': "2", + 'name': 'disabled_tenant', + 'description': "a disabled test tenant.", + 'enabled': False} tenant = tenants.Tenant(tenants.TenantManager, tenant_dict) - TEST.tenants.add(tenant) + disabled_tenant = tenants.Tenant(tenants.TenantManager, tenant_dict_2) + TEST.tenants.add(tenant, disabled_tenant) TEST.tenant = tenant # Your "current" tenant scoped_token = tokens.Token(tokens.TokenManager, diff --git a/horizon/tests/testsettings.py b/horizon/tests/testsettings.py index d4424ea35..59607f74d 100644 --- a/horizon/tests/testsettings.py +++ b/horizon/tests/testsettings.py @@ -67,6 +67,7 @@ SITE_NAME = 'openstack' TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' NOSE_ARGS = ['--nocapture', + '--nologcapture', '--cover-package=horizon', '--cover-inclusive'] # For nose-selenium integration diff --git a/horizon/views/auth_forms.py b/horizon/views/auth_forms.py index 88b7f1db8..370524c3a 100644 --- a/horizon/views/auth_forms.py +++ b/horizon/views/auth_forms.py @@ -94,8 +94,9 @@ class Login(forms.SelfHandlingForm): data['password']) tenants = api.tenant_list_for_token(request, token.id) except: + msg = _('Unable to authenticate for that project.') exceptions.handle(request, - message=_('Unable to authenticate tenant.'), + message=msg, escalate=True) _set_session_data(request, token) user = users.get_user_from_request(request) @@ -104,10 +105,10 @@ class Login(forms.SelfHandlingForm): elif data.get('username', None): try: - token = api.token_create(request, - '', - data['username'], - data['password']) + unscoped_token = api.token_create(request, + '', + data['username'], + data['password']) except keystone_exceptions.Unauthorized: exceptions.handle(request, _('Invalid user name or password.')) @@ -122,13 +123,13 @@ class Login(forms.SelfHandlingForm): escalate=True) # Unscoped token - request.session['unscoped_token'] = token.id + request.session['unscoped_token'] = unscoped_token.id request.user.username = data['username'] # Get the tenant list, and log in using first tenant # FIXME (anthony): add tenant chooser here? try: - tenants = api.tenant_list_for_token(request, token.id) + tenants = api.tenant_list_for_token(request, unscoped_token.id) except: exceptions.handle(request) tenants = [] @@ -136,7 +137,7 @@ class Login(forms.SelfHandlingForm): # Abort if there are no valid tenants for this user if not tenants: messages.error(request, - _('No tenants present for user: %(user)s') % + _('You are not authorized for any projects.') % {"user": data['username']}, extra_tags="login") return @@ -151,16 +152,16 @@ class Login(forms.SelfHandlingForm): try: token = api.token_create_scoped(request, tenant.id, - token.id) + unscoped_token.id) break except: - # This will continue for recognized "unauthorized" + # This will continue for recognized Unauthorized # exceptions from keystoneclient. exceptions.handle(request, ignore=True) token = None if token is None: raise exceptions.NotAuthorized( - _("You are not authorized for any available tenants.")) + _("You are not authorized for any available projects.")) _set_session_data(request, token) user = users.get_user_from_request(request)