From 10e6bf57c3398c73ec47dabd91fbd37f35017abc Mon Sep 17 00:00:00 2001 From: David Lyle Date: Thu, 24 Mar 2016 12:22:29 -0600 Subject: [PATCH] Fixing updating user with no default project The selector for setting the default project passes on an empty string if the value is not changed. This is causing an error from keystone as an empty string is not a valid project ID. To fix, a couple of things have been done: First, as user_update is a PATCH, we no longer pass on the default project as a parameter in the update when using keystone v3 and the value did not change when editing the user. Second, there is currently no way to unset the default project using keystoneclient. An entry in the default project select "select a project" has been removed when the default project is already set. The entry was selectable and resulted in the problematic empty string. The current default project is already selected at load time. The ability to select a different default project is maintained. Additionally, keystone v2.0 functionality is not effected, as the default project id is required in v2.0. A test was added to cover the case of editing the default project. Closes-Bug: #1561612 Change-Id: I3c84ee5c7af846b5a58f2dd0342a537d312323cf (cherry picked from commit 32510d8211a43d83ebac6478fce17a8856cf9a0c) --- .../dashboards/identity/users/forms.py | 8 ++- .../dashboards/identity/users/tests.py | 50 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/openstack_dashboard/dashboards/identity/users/forms.py b/openstack_dashboard/dashboards/identity/users/forms.py index 79ee882a99..dd6ccd89d5 100644 --- a/openstack_dashboard/dashboards/identity/users/forms.py +++ b/openstack_dashboard/dashboards/identity/users/forms.py @@ -68,6 +68,7 @@ class BaseUserForm(forms.SelfHandlingForm): # the user has access to. user_id = kwargs['initial'].get('id', None) domain_id = kwargs['initial'].get('domain_id', None) + default_project_id = kwargs['initial'].get('project', None) try: if api.keystone.VERSIONS.active >= 3: @@ -82,7 +83,9 @@ class BaseUserForm(forms.SelfHandlingForm): project_choices.append((project.id, project.name)) if not project_choices: project_choices.insert(0, ('', _("No available projects"))) - elif len(project_choices) > 1: + # TODO(david-lyle): if keystoneclient is fixed to allow unsetting + # the default project, then this condition should be removed. + elif len(project_choices) > 1 and default_project_id is None: project_choices.insert(0, ('', _("Select a project"))) self.fields['project'].choices = project_choices @@ -227,6 +230,9 @@ class UpdateUserForm(BaseUserForm): data.pop('domain_id') data.pop('domain_name') + if not PROJECT_REQUIRED and 'project' not in self.changed_data: + data.pop('project') + if 'description' not in self.changed_data: data.pop('description') try: diff --git a/openstack_dashboard/dashboards/identity/users/tests.py b/openstack_dashboard/dashboards/identity/users/tests.py index 504de15baf..80f58a8526 100644 --- a/openstack_dashboard/dashboards/identity/users/tests.py +++ b/openstack_dashboard/dashboards/identity/users/tests.py @@ -359,8 +359,7 @@ class UsersViewTests(test.BaseAdminViewTests): api.keystone.user_update(IsA(http.HttpRequest), user.id, email=user.email, - name=user.name, - project=self.tenant.id).AndReturn(None) + name=user.name).AndReturn(None) self.mox.ReplayAll() @@ -375,6 +374,52 @@ class UsersViewTests(test.BaseAdminViewTests): self.assertNoFormErrors(res) + @test.create_stubs({api.keystone: ('user_get', + 'domain_get', + 'tenant_list', + 'user_update_tenant', + 'user_update_password', + 'user_update', + 'roles_for_user', )}) + def test_update_default_project(self): + user = self.users.get(id="1") + domain_id = user.domain_id + domain = self.domains.get(id=domain_id) + new_project_id = self.tenants.get(id="3").id + + api.keystone.user_get(IsA(http.HttpRequest), '1', + admin=True).AndReturn(user) + api.keystone.domain_get(IsA(http.HttpRequest), + domain_id).AndReturn(domain) + + if api.keystone.VERSIONS.active >= 3: + api.keystone.tenant_list( + IgnoreArg(), domain=domain.id).AndReturn( + [self.tenants.list(), False]) + else: + api.keystone.tenant_list( + IgnoreArg(), user=user.id).AndReturn( + [self.tenants.list(), False]) + + api.keystone.user_update(IsA(http.HttpRequest), + user.id, + email=user.email, + name=user.name, + project=new_project_id).AndReturn(None) + + self.mox.ReplayAll() + + formData = {'method': 'UpdateUserForm', + 'id': user.id, + 'name': user.name, + 'description': user.description, + 'email': user.email, + 'project': new_project_id} + + res = self.client.post(USER_UPDATE_URL, formData) + + self.assertNoFormErrors(res) + @test.create_stubs({api.keystone: ('user_get', 'domain_get', 'tenant_list', @@ -808,7 +853,6 @@ class UsersViewTests(test.BaseAdminViewTests): user.id, email=user.email, name=user.name, - project=self.tenant.id, description='changed').AndReturn(None) self.mox.ReplayAll()