Add role assignment tab in the user details view.
Add an extra tab "role assignments" in the user details view which displays all the project/role domain/role of the current user. The role assignments are displayed in a table. The project/domain column is clickable and forward to the project /domain detail view. Change-Id: Iefe17856e60b84d089f722c3a30e9ede21d8ce47 Partial-Bug: #1792524 Co-Authored-By: Akihiro Motoki <amotoki@gmail.com>
This commit is contained in:
parent
254e3791d3
commit
ba82055f05
@ -0,0 +1,93 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django import urls
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
|
||||
from openstack_dashboard import policy
|
||||
|
||||
|
||||
def get_project_name(datum):
|
||||
if "project" in datum.scope:
|
||||
if "name" in datum.scope["project"]:
|
||||
return datum.scope["project"]["name"]
|
||||
return datum.scope["project"]["id"]
|
||||
|
||||
|
||||
def get_project_link(datum, request):
|
||||
if "project" not in datum.scope:
|
||||
return
|
||||
if policy.check((("identity", "identity:get_project"),),
|
||||
request, target={"project": datum}):
|
||||
return urls.reverse("horizon:identity:projects:detail",
|
||||
args=(datum.scope["project"]["id"],))
|
||||
|
||||
|
||||
def get_domain_name(datum):
|
||||
if "domain" in datum.scope:
|
||||
if "name" in datum.scope["domain"]:
|
||||
return datum.scope["domain"]["name"]
|
||||
return datum.scope["domain"]["id"]
|
||||
|
||||
|
||||
def get_system_scope(datum):
|
||||
if "system" in datum.scope:
|
||||
return ', '.join(datum.scope["system"].keys())
|
||||
|
||||
|
||||
def get_role_name(datum):
|
||||
if "name" in datum.role:
|
||||
return datum.role["name"]
|
||||
return datum.role["id"]
|
||||
|
||||
|
||||
class RoleAssignmentsTable(tables.DataTable):
|
||||
|
||||
project = tables.WrappingColumn(get_project_name,
|
||||
verbose_name=_('Project'),
|
||||
link=get_project_link,
|
||||
form_field=forms.CharField(max_length=64))
|
||||
|
||||
domain = tables.WrappingColumn(get_domain_name,
|
||||
verbose_name=_('Domain'),
|
||||
form_field=forms.CharField(max_length=64))
|
||||
|
||||
system = tables.WrappingColumn(get_system_scope,
|
||||
verbose_name=_('System Scope'),
|
||||
form_field=forms.CharField(max_length=64))
|
||||
|
||||
role = tables.Column(get_role_name,
|
||||
verbose_name=_('Role'),
|
||||
form_field=forms.CharField(
|
||||
widget=forms.Textarea(attrs={'rows': 4}),
|
||||
required=False))
|
||||
|
||||
def get_object_id(self, datum):
|
||||
"""Identifier of the role assignment."""
|
||||
|
||||
# Role assignment doesn't have identifier so one will be created
|
||||
# from the identifier of scope, user and role. This will guaranty the
|
||||
# unicity.
|
||||
scope_id = ""
|
||||
if "project" in datum.scope:
|
||||
scope_id = datum.scope["project"]["id"]
|
||||
elif "domain" in datum.scope:
|
||||
scope_id = datum.scope["domain"]["id"]
|
||||
|
||||
return "%s%s%s" % (datum.user["id"], datum.role["id"], scope_id)
|
||||
|
||||
class Meta(object):
|
||||
name = "roleassignmentstable"
|
||||
verbose_name = _("Role assignments")
|
@ -13,8 +13,13 @@
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.identity.users.role_assignments \
|
||||
import tables as role_assignments_tables
|
||||
|
||||
|
||||
class OverviewTab(tabs.Tab):
|
||||
"""Overview of the user.
|
||||
@ -29,6 +34,33 @@ class OverviewTab(tabs.Tab):
|
||||
return {"user": self.tab_group.kwargs['user']}
|
||||
|
||||
|
||||
class RoleAssignmentsTab(tabs.TableTab):
|
||||
"""Role assignment of the user to domain/project."""
|
||||
table_classes = (role_assignments_tables.RoleAssignmentsTable,)
|
||||
name = _("Role assignments")
|
||||
slug = "roleassignments"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
preload = False
|
||||
|
||||
def get_roleassignmentstable_data(self):
|
||||
user = self.tab_group.kwargs['user']
|
||||
|
||||
try:
|
||||
# Get all the roles of the user
|
||||
user_roles = api.keystone.role_assignments_list(
|
||||
self.request, user=user, include_subtree=False,
|
||||
include_names=True)
|
||||
|
||||
return user_roles
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(
|
||||
self.request,
|
||||
_("Unable to display the role assignments of this user."))
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class UserDetailTabs(tabs.DetailTabsGroup):
|
||||
slug = "user_details"
|
||||
tabs = (OverviewTab,)
|
||||
tabs = (OverviewTab, RoleAssignmentsTab,)
|
||||
|
@ -922,6 +922,96 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(),
|
||||
user.project_id)
|
||||
|
||||
@test.create_mocks({api.keystone: ('domain_get',
|
||||
'user_get',
|
||||
'tenant_get',
|
||||
'role_assignments_list')})
|
||||
def test_detail_view_role_assignments_tab(self):
|
||||
"""Test the role assignments tab of the detail view ."""
|
||||
domain = self._get_default_domain()
|
||||
user = self.users.get(id="1")
|
||||
tenant = self.tenants.get(id=user.project_id)
|
||||
role_assignments = self.role_assignments.filter(user={'id': user.id})
|
||||
|
||||
self.mock_domain_get.return_value = domain
|
||||
self.mock_user_get.return_value = user
|
||||
self.mock_tenant_get.return_value = tenant
|
||||
self.mock_role_assignments_list.return_value = role_assignments
|
||||
|
||||
# Url of the role assignment tab of the detail view
|
||||
url = USER_DETAIL_URL % [user.id]
|
||||
detail_view = tabs.UserDetailTabs(self.request, user=user)
|
||||
role_assignments_tab_link = "?%s=%s" % (
|
||||
detail_view.param_name,
|
||||
detail_view.get_tab("roleassignments").get_id()
|
||||
)
|
||||
url += role_assignments_tab_link
|
||||
|
||||
res = self.client.get(url)
|
||||
|
||||
# Check the template expected has been used
|
||||
self.assertTemplateUsed(res,
|
||||
"horizon/common/_detail_table.html")
|
||||
|
||||
# Check the table contains the expected data
|
||||
role_assignments_expected = role_assignments
|
||||
role_assignments_observed = res.context["table"].data
|
||||
self.assertItemsEqual(role_assignments_expected,
|
||||
role_assignments_observed)
|
||||
|
||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), '1')
|
||||
self.mock_user_get.assert_called_once_with(test.IsHttpRequest(), '1',
|
||||
admin=False)
|
||||
self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(),
|
||||
user.project_id)
|
||||
self.mock_role_assignments_list.assert_called_once_with(
|
||||
test.IsHttpRequest(), user=user, include_subtree=False,
|
||||
include_names=True)
|
||||
|
||||
@test.create_mocks({api.keystone: ('domain_get',
|
||||
'user_get',
|
||||
'tenant_get',
|
||||
'role_assignments_list')})
|
||||
def test_detail_view_role_assignments_tab_with_exception(self):
|
||||
"""Test the role assignments tab with exception.
|
||||
|
||||
The table is displayed empty and an error message pop if the role
|
||||
assignment request fails.
|
||||
"""
|
||||
domain = self._get_default_domain()
|
||||
user = self.users.get(id="1")
|
||||
tenant = self.tenants.get(id=user.project_id)
|
||||
|
||||
self.mock_domain_get.return_value = domain
|
||||
self.mock_user_get.return_value = user
|
||||
self.mock_tenant_get.return_value = tenant
|
||||
self.mock_role_assignments_list.side_effect = self.exceptions.keystone
|
||||
|
||||
# Url of the role assignment tab of the detail view
|
||||
url = USER_DETAIL_URL % [user.id]
|
||||
detail_view = tabs.UserDetailTabs(self.request, user=user)
|
||||
role_assignments_tab_link = "?%s=%s" % (
|
||||
detail_view.param_name,
|
||||
detail_view.get_tab("roleassignments").get_id()
|
||||
)
|
||||
url += role_assignments_tab_link
|
||||
|
||||
res = self.client.get(url)
|
||||
|
||||
# Check the role assignment table is empty
|
||||
self.assertEqual(res.context["table"].data, [])
|
||||
# Check one error message is displayed
|
||||
self.assertMessageCount(res, error=1)
|
||||
|
||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), '1')
|
||||
self.mock_user_get.assert_called_once_with(test.IsHttpRequest(), '1',
|
||||
admin=False)
|
||||
self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(),
|
||||
user.project_id)
|
||||
self.mock_role_assignments_list.assert_called_once_with(
|
||||
test.IsHttpRequest(), user=user, include_subtree=False,
|
||||
include_names=True)
|
||||
|
||||
@test.create_mocks({api.keystone: ('user_get',
|
||||
'domain_get',
|
||||
'tenant_list',)})
|
||||
|
Loading…
Reference in New Issue
Block a user