From 3a584a90c1ba8f5b06f3dd04747f193d9b003bdd Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Fri, 21 Dec 2018 01:58:16 +0900 Subject: [PATCH] Show domain info in project and user detail panel Domain info in the user detail panel was previously displayed but it has been broken after the user detail panel was tabbified. This commit fixes the handling of context data. This covers domain_name, project_name and extras. Similar change is applied to the project detail panel too. Change-Id: I575ae9697783c36fdae5dd397d6783b979d0c4a6 Closes-Bug: #1809284 --- .../dashboards/identity/projects/tabs.py | 34 ++++++++++--- .../templates/projects/_detail_overview.html | 12 +++-- .../dashboards/identity/projects/tests.py | 32 +++++++++++- .../dashboards/identity/users/tabs.py | 50 ++++++++++++++++++- .../templates/users/_detail_overview.html | 35 +++++++------ .../dashboards/identity/users/tests.py | 4 +- .../dashboards/identity/users/views.py | 36 ------------- 7 files changed, 135 insertions(+), 68 deletions(-) diff --git a/openstack_dashboard/dashboards/identity/projects/tabs.py b/openstack_dashboard/dashboards/identity/projects/tabs.py index bb71f1baf0..18a301a885 100644 --- a/openstack_dashboard/dashboards/identity/projects/tabs.py +++ b/openstack_dashboard/dashboards/identity/projects/tabs.py @@ -17,6 +17,7 @@ from horizon import exceptions from horizon import tabs from openstack_dashboard import api +from openstack_dashboard import policy from openstack_dashboard.dashboards.identity.projects.groups \ import tables as groups_tables @@ -32,15 +33,36 @@ class OverviewTab(tabs.Tab): def get_context_data(self, request): project = self.tab_group.kwargs['project'] - context = {"project": project} + return { + "project": project, + "domain_name": self._get_domain_name(project), + "extras": self._get_extras(project), + } + def _get_domain_name(self, project): + domain_name = '' + if api.keystone.VERSIONS.active >= 3: + try: + if policy.check((("identity", "identity:get_domain"),), + self.request): + domain = api.keystone.domain_get( + self.request, project.domain_id) + domain_name = domain.name + else: + domain = api.keystone.get_default_domain(self.request) + domain_name = domain.get('name') + except Exception: + exceptions.handle(self.request, + _('Unable to retrieve project domain.')) + return domain_name + + def _get_extras(self, project): if api.keystone.VERSIONS.active >= 3: extra_info = getattr(settings, 'PROJECT_TABLE_EXTRA_INFO', {}) - context['extras'] = dict( - (display_key, getattr(project, key, '')) - for key, display_key in extra_info.items()) - - return context + return dict((display_key, getattr(project, key, '')) + for key, display_key in extra_info.items()) + else: + return {} class UsersTab(tabs.TableTab): diff --git a/openstack_dashboard/dashboards/identity/projects/templates/projects/_detail_overview.html b/openstack_dashboard/dashboards/identity/projects/templates/projects/_detail_overview.html index 5ba6d92c8c..68654408f9 100644 --- a/openstack_dashboard/dashboards/identity/projects/templates/projects/_detail_overview.html +++ b/openstack_dashboard/dashboards/identity/projects/templates/projects/_detail_overview.html @@ -2,14 +2,20 @@
-
{% trans "Project Name" %}
+
{% trans "Name" %}
{{ project.name }}
-
{% trans "Project ID" %}
+
{% trans "ID" %}
{{ project.id }}
+ {% if domain_name %} +
{% trans "Domain Name" %}
+
{{ domain_name }}
+ {% endif %} +
{% trans "Domain ID" %}
+
{{ project.domain_id }}
{% trans "Enabled" %}
{{ project.enabled|yesno|capfirst }}
{% trans "Description" %}
-
{{ project.description|default:_("None") }}
+
{{ project.description|default:_("-") }}
{% if extras %} {% for key, value in extras.items %}
{{ key }}
diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py index 815e5adb45..a7f40c5be9 100644 --- a/openstack_dashboard/dashboards/identity/projects/tests.py +++ b/openstack_dashboard/dashboards/identity/projects/tests.py @@ -1286,12 +1286,14 @@ class UsageViewTests(test.BaseAdminViewTests): class DetailProjectViewTests(test.BaseAdminViewTests): - @test.create_mocks({api.keystone: ('tenant_get',), + @test.create_mocks({api.keystone: ('tenant_get', 'domain_get'), quotas: ('enabled_quotas',)}) def test_detail_view(self): project = self.tenants.first() + domain = self.domains.first() self.mock_tenant_get.return_value = project + self.mock_domain_get.return_value = domain self.mock_enabled_quotas.return_value = ('instances',) res = self.client.get(PROJECT_DETAIL_URL, args=[project.id]) @@ -1304,6 +1306,8 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), + domain.id) self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest()) @test.create_mocks({api.keystone: ('tenant_get',)}) @@ -1319,7 +1323,7 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) - @test.create_mocks({api.keystone: ('tenant_get',), + @test.create_mocks({api.keystone: ('tenant_get', 'domain_get'), quotas: ('enabled_quotas',)}) def test_detail_view_overview_tab(self): """Test the overview tab of the detail view . @@ -1327,8 +1331,10 @@ class DetailProjectViewTests(test.BaseAdminViewTests): Test the overview tab using directly the url targeting the tab. """ project = self.tenants.first() + domain = self.domains.first() self.mock_tenant_get.return_value = project + self.mock_domain_get.return_value = domain self.mock_enabled_quotas.return_value = ('instances',) # Url of the overview tab of the detail view @@ -1348,6 +1354,8 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), + domain.id) self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest()) def _get_users_in_group(self, group_id): @@ -1375,6 +1383,7 @@ class DetailProjectViewTests(test.BaseAdminViewTests): return roles @test.create_mocks({api.keystone: ('tenant_get', + 'domain_get', 'user_list', 'get_project_users_roles', 'get_project_groups_roles', @@ -1383,6 +1392,7 @@ class DetailProjectViewTests(test.BaseAdminViewTests): quotas: ('enabled_quotas',)}) def test_detail_view_users_tab(self): project = self.tenants.first() + domain = self.domains.first() users = self.users.filter(domain_id=project.domain_id) groups = self.groups.filter(domain_id=project.domain_id) role_assignments = self.role_assignments.filter( @@ -1394,6 +1404,7 @@ class DetailProjectViewTests(test.BaseAdminViewTests): # Prepare mocks self.mock_tenant_get.return_value = project + self.mock_domain_get.return_value = domain self.mock_enabled_quotas.return_value = ('instances',) self.mock_role_list.return_value = self.roles.list() @@ -1443,6 +1454,8 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), + domain.id) self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest()) self.mock_role_list.assert_called_once_with(test.IsHttpRequest()) self.mock_group_list.assert_called_once_with(test.IsHttpRequest()) @@ -1456,13 +1469,16 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_user_list.assert_has_calls(calls) @test.create_mocks({api.keystone: ("tenant_get", + "domain_get", "role_list",), quotas: ('enabled_quotas',)}) def test_detail_view_users_tab_exception(self): project = self.tenants.first() + domain = self.domains.first() # Prepare mocks self.mock_tenant_get.return_value = project + self.mock_domain_get.return_value = domain self.mock_enabled_quotas.return_value = ('instances',) self.mock_role_list.side_effect = self.exceptions.keystone @@ -1483,16 +1499,20 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), + domain.id) self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest()) self.mock_role_list.assert_called_once_with(test.IsHttpRequest()) @test.create_mocks({api.keystone: ("tenant_get", + "domain_get", "get_project_groups_roles", "role_list", "group_list"), quotas: ('enabled_quotas',)}) def test_detail_view_groups_tab(self): project = self.tenants.first() + domain = self.domains.first() groups = self.groups.filter(domain_id=project.domain_id) role_assignments = self.role_assignments.filter( scope={'project': {'id': project.id}}) @@ -1501,6 +1521,7 @@ class DetailProjectViewTests(test.BaseAdminViewTests): # Prepare mocks self.mock_tenant_get.return_value = project + self.mock_domain_get.return_value = domain self.mock_enabled_quotas.return_value = ('instances',) self.mock_get_project_groups_roles.return_value = project_groups_roles self.mock_group_list.return_value = groups @@ -1535,6 +1556,8 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), + domain.id) self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest()) self.mock_role_list.assert_called_once_with(test.IsHttpRequest()) self.mock_group_list.assert_called_once_with(test.IsHttpRequest()) @@ -1542,13 +1565,16 @@ class DetailProjectViewTests(test.BaseAdminViewTests): test.IsHttpRequest(), project=project.id) @test.create_mocks({api.keystone: ("tenant_get", + "domain_get", "get_project_groups_roles"), quotas: ('enabled_quotas',)}) def test_detail_view_groups_tab_exception(self): project = self.tenants.first() + domain = self.domains.first() # Prepare mocks self.mock_tenant_get.return_value = project + self.mock_domain_get.return_value = domain self.mock_enabled_quotas.return_value = ('instances',) self.mock_get_project_groups_roles.side_effect = \ self.exceptions.keystone @@ -1570,6 +1596,8 @@ class DetailProjectViewTests(test.BaseAdminViewTests): self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), self.tenant.id) + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), + domain.id) self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest()) self.mock_get_project_groups_roles.assert_called_once_with( test.IsHttpRequest(), project=project.id) diff --git a/openstack_dashboard/dashboards/identity/users/tabs.py b/openstack_dashboard/dashboards/identity/users/tabs.py index 55f72607c7..8267f9e4aa 100644 --- a/openstack_dashboard/dashboards/identity/users/tabs.py +++ b/openstack_dashboard/dashboards/identity/users/tabs.py @@ -10,7 +10,9 @@ # License for the specific language governing permissions and limitations # under the License. +import logging +from django.conf import settings from django.utils.translation import ugettext_lazy as _ from horizon import exceptions @@ -21,6 +23,10 @@ from openstack_dashboard.dashboards.identity.users.groups \ import tables as groups_tables from openstack_dashboard.dashboards.identity.users.role_assignments \ import tables as role_assignments_tables +from openstack_dashboard import policy + + +LOG = logging.getLogger(__name__) class OverviewTab(tabs.Tab): @@ -32,8 +38,50 @@ class OverviewTab(tabs.Tab): slug = "overview" template_name = 'identity/users/_detail_overview.html' + def _get_domain_name(self, user): + domain_name = '' + if api.keystone.VERSIONS.active >= 3: + try: + if policy.check((("identity", "identity:get_domain"),), + self.request): + domain = api.keystone.domain_get( + self.request, user.domain_id) + domain_name = domain.name + else: + domain = api.keystone.get_default_domain(self.request) + domain_name = domain.get('name') + except Exception: + exceptions.handle(self.request, + _('Unable to retrieve user domain.')) + return domain_name + + def _get_project_name(self, user): + project_id = user.project_id + if not project_id: + return + try: + tenant = api.keystone.tenant_get(self.request, project_id) + return tenant.name + except Exception as e: + LOG.error('Failed to get tenant %(project_id)s: %(reason)s', + {'project_id': project_id, 'reason': e}) + + def _get_extras(self, user): + if api.keystone.VERSIONS.active >= 3: + extra_info = getattr(settings, 'USER_TABLE_EXTRA_INFO', {}) + return dict((display_key, getattr(user, key, '')) + for key, display_key in extra_info.items()) + else: + return {} + def get_context_data(self, request): - return {"user": self.tab_group.kwargs['user']} + user = self.tab_group.kwargs['user'] + return { + "user": user, + "domain_name": self._get_domain_name(user), + 'extras': self._get_extras(user), + 'project_name': self._get_project_name(user), + } class RoleAssignmentsTab(tabs.TableTab): diff --git a/openstack_dashboard/dashboards/identity/users/templates/users/_detail_overview.html b/openstack_dashboard/dashboards/identity/users/templates/users/_detail_overview.html index db9c385f39..2f031ecd06 100644 --- a/openstack_dashboard/dashboards/identity/users/templates/users/_detail_overview.html +++ b/openstack_dashboard/dashboards/identity/users/templates/users/_detail_overview.html @@ -2,33 +2,32 @@
- {% if domain_id %} -
{% trans "Domain ID" %}
-
{{ domain_id }}
- {% endif %} +
{% trans "Name" %}
+
{{ user.name }}
+
{% trans "ID" %}
+
{{ user.id }}
{% if domain_name %}
{% trans "Domain Name" %}
{{ domain_name }}
{% endif %} -
{% trans "User Name" %}
-
{{ user.name }}
- {% if description %} -
{% trans "Description" %}
-
{{ description }}
- {% endif %} -
{% trans "ID" %}
-
{{ user.id }}
+
{% trans "Domain ID" %}
+
{{ user.domain_id }}
+
{% trans "Description" %}
+
{{ user.description|default:_("-") }}
{% trans "Email" %}
-
{{ user.email|default:_("None") }}
+
{{ user.email|default:_("-") }}
{% trans "Enabled" %}
{{ user.enabled|yesno|capfirst }}
{% trans "Password Expires At" %}
{{ user.password_expires_at }}
-
{% trans "Primary Project ID" %}
-
{{ user.project_id }}
- {% if tenant_name %} -
{% trans "Primary Project Name" %}
-
{{ tenant_name }}
+
{% trans "Primary Project" %}
+ {% if user.project_id %} +
+ + {{ project_name|default:user.project_id }} +
+ {% else %} +
{% trans "-" %}
{% endif %} {% if extras %} {% for key, value in extras.items %} diff --git a/openstack_dashboard/dashboards/identity/users/tests.py b/openstack_dashboard/dashboards/identity/users/tests.py index 1cd9ab1b8f..aab535171e 100644 --- a/openstack_dashboard/dashboards/identity/users/tests.py +++ b/openstack_dashboard/dashboards/identity/users/tests.py @@ -864,7 +864,7 @@ class UsersViewTests(test.BaseAdminViewTests): self.assertTemplateUsed(res, 'identity/users/_detail_overview.html') self.assertEqual(res.context['user'].name, user.name) self.assertEqual(res.context['user'].id, user.id) - self.assertEqual(res.context['tenant_name'], tenant.name) + self.assertEqual(res.context['project_name'], tenant.name) self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), '1') self.mock_user_get.assert_called_once_with(test.IsHttpRequest(), '1', @@ -914,7 +914,7 @@ class UsersViewTests(test.BaseAdminViewTests): self.assertTemplateUsed(res, 'identity/users/_detail_overview.html') self.assertEqual(res.context['user'].name, user.name) self.assertEqual(res.context['user'].id, user.id) - self.assertEqual(res.context['tenant_name'], tenant.name) + self.assertEqual(res.context['project_name'], tenant.name) self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), '1') self.mock_user_get.assert_called_once_with(test.IsHttpRequest(), '1', diff --git a/openstack_dashboard/dashboards/identity/users/views.py b/openstack_dashboard/dashboards/identity/users/views.py index 576413300f..7d2ce9dd33 100644 --- a/openstack_dashboard/dashboards/identity/users/views.py +++ b/openstack_dashboard/dashboards/identity/users/views.py @@ -207,48 +207,12 @@ class DetailView(tabs.TabView): def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) user = self.get_data() - tenant = self.get_tenant(user.project_id) table = project_tables.UsersTable(self.request) - domain_id = getattr(user, "domain_id", None) - domain_name = '' - if api.keystone.VERSIONS.active >= 3: - try: - if policy.check((("identity", "identity:get_domain"),), - self.request): - domain = api.keystone.domain_get( - self.request, domain_id) - domain_name = domain.name - else: - domain = api.keystone.get_default_domain(self.request) - domain_name = domain.get('name') - except Exception: - exceptions.handle(self.request, - _('Unable to retrieve project domain.')) - context["description"] = getattr(user, "description", _("None")) - extra_info = getattr(settings, 'USER_TABLE_EXTRA_INFO', {}) - context['extras'] = dict( - (display_key, getattr(user, key, '')) - for key, display_key in extra_info.items()) context["user"] = user - if tenant: - context["tenant_name"] = tenant.name - context["domain_id"] = domain_id - context["domain_name"] = domain_name context["url"] = self.get_redirect_url() context["actions"] = table.render_row_actions(user) return context - @memoized.memoized_method - def get_tenant(self, project_id): - tenant = None - if project_id: - try: - tenant = api.keystone.tenant_get(self.request, project_id) - except Exception as e: - LOG.error('Failed to get tenant %(project_id)s: %(reason)s', - {'project_id': project_id, 'reason': e}) - return tenant - @memoized.memoized_method def get_data(self): try: