Merge "Show domain info in project and user detail panel"
This commit is contained in:
commit
4242987e42
|
@ -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):
|
||||
|
|
|
@ -2,14 +2,20 @@
|
|||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Project Name" %}</dt>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd data-display="{{ project.name|default:project.id }}">{{ project.name }}</dd>
|
||||
<dt>{% trans "Project ID" %}</dt>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ project.id }}</dd>
|
||||
{% if domain_name %}
|
||||
<dt>{% trans "Domain Name" %}</dt>
|
||||
<dd>{{ domain_name }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Domain ID" %}</dt>
|
||||
<dd>{{ project.domain_id }}</dd>
|
||||
<dt>{% trans "Enabled" %}</dt>
|
||||
<dd>{{ project.enabled|yesno|capfirst }}</dd>
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ project.description|default:_("None") }}</dd>
|
||||
<dd>{{ project.description|default:_("-") }}</dd>
|
||||
{% if extras %}
|
||||
{% for key, value in extras.items %}
|
||||
<dt>{{ key }}</dt>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -2,33 +2,32 @@
|
|||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
{% if domain_id %}
|
||||
<dt>{% trans "Domain ID" %}</dt>
|
||||
<dd>{{ domain_id }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd data-display="{{ user.name|default:user.id }}" class="word-wrap">{{ user.name }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ user.id }}</dd>
|
||||
{% if domain_name %}
|
||||
<dt>{% trans "Domain Name" %}</dt>
|
||||
<dd class="word-wrap">{{ domain_name }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "User Name" %}</dt>
|
||||
<dd data-display="{{ user.name|default:user.id }}" class="word-wrap">{{ user.name }}</dd>
|
||||
{% if description %}
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ description }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ user.id }}</dd>
|
||||
<dt>{% trans "Domain ID" %}</dt>
|
||||
<dd>{{ user.domain_id }}</dd>
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ user.description|default:_("-") }}</dd>
|
||||
<dt>{% trans "Email" %}</dt>
|
||||
<dd>{{ user.email|default:_("None") }}</dd>
|
||||
<dd>{{ user.email|default:_("-") }}</dd>
|
||||
<dt>{% trans "Enabled" %}</dt>
|
||||
<dd>{{ user.enabled|yesno|capfirst }}</dd>
|
||||
<dt>{% trans "Password Expires At" %}</dt>
|
||||
<dd>{{ user.password_expires_at }}</dd>
|
||||
<dt>{% trans "Primary Project ID" %}</dt>
|
||||
<dd>{{ user.project_id }}</dd>
|
||||
{% if tenant_name %}
|
||||
<dt>{% trans "Primary Project Name" %}</dt>
|
||||
<dd class="word-wrap">{{ tenant_name }}</dd>
|
||||
<dt>{% trans "Primary Project" %}</dt>
|
||||
{% if user.project_id %}
|
||||
<dd class="word-wrap">
|
||||
<a href="{% url 'horizon:identity:projects:detail' project_id=user.project_id %}">
|
||||
{{ project_name|default:user.project_id }}</a>
|
||||
</dd>
|
||||
{% else %}
|
||||
<dd>{% trans "-" %}</dd>
|
||||
{% endif %}
|
||||
{% if extras %}
|
||||
{% for key, value in extras.items %}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -204,48 +204,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:
|
||||
|
|
Loading…
Reference in New Issue