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: