better manageable roles
* A user cannot edit another user unless all target user roles are a subset of editor manageable roles, not just the roles that are being edited. * User list now returns 'manageable' boolean to indicate if your logged in user can edit roles of the listed user. * Fixing an issue with mocking and test code not actually returning correct values for 'user_list'. * Editing ROLES_MAPPING in settings to match default conf. Change-Id: I3720386b6dfe4465a50ded3e21b5b577f1340dbf
This commit is contained in:
parent
6cdbb8eef1
commit
8a2f2f2107
@ -668,3 +668,46 @@ class UserActionTests(TestCase):
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
self.assertEquals(project.roles[user.id], ['_member_'])
|
||||
|
||||
def test_edit_user_roles_can_manage_all(self):
|
||||
"""
|
||||
Confirm that you cannot edit a user unless all their roles
|
||||
can be managed by you.
|
||||
"""
|
||||
user = mock.Mock()
|
||||
user.id = 'user_id'
|
||||
user.name = "test@example.com"
|
||||
user.email = "test@example.com"
|
||||
user.domain = 'default'
|
||||
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {user.id: ['_member_', 'project_admin']}
|
||||
|
||||
setup_temp_cache({'test_project': project}, {user.id: user})
|
||||
|
||||
task = Task.objects.create(
|
||||
ip_address="0.0.0.0",
|
||||
keystone_user={
|
||||
'roles': ['project_mod'],
|
||||
'project_id': 'test_project_id',
|
||||
'project_domain_id': 'default',
|
||||
})
|
||||
|
||||
data = {
|
||||
'domain_id': 'default',
|
||||
'user_id': 'user_id',
|
||||
'project_id': 'test_project_id',
|
||||
'roles': ['project_mod'],
|
||||
'remove': False
|
||||
}
|
||||
|
||||
action = EditUserRolesAction(data, task=task, order=1)
|
||||
|
||||
action.pre_approve()
|
||||
self.assertEquals(action.valid, False)
|
||||
|
||||
self.assertEquals(
|
||||
project.roles[user.id], ['_member_', 'project_admin'])
|
||||
|
@ -244,6 +244,16 @@ class EditUserRolesAction(UserIdAction, ProjectMixin, UserMixin):
|
||||
# user roles
|
||||
current_roles = id_manager.get_roles(user, project)
|
||||
current_role_names = {role.name for role in current_roles}
|
||||
|
||||
# NOTE(adriant): Only allow someone to edit roles if all roles from
|
||||
# the target user can be managed by editor.
|
||||
can_manage_roles = user_store.get_managable_roles(
|
||||
self.action.task.keystone_user['roles'])
|
||||
if not set(can_manage_roles).issuperset(current_role_names):
|
||||
self.add_note(
|
||||
'Not all target user roles are manageable.')
|
||||
return False
|
||||
|
||||
if self.remove:
|
||||
remaining = set(current_role_names) & set(self.roles)
|
||||
if not remaining:
|
||||
|
@ -37,6 +37,9 @@ class UserList(tasks.InviteUser):
|
||||
project_id = request.keystone_user['project_id']
|
||||
project = id_manager.get_project(project_id)
|
||||
|
||||
can_manage_roles = user_store.get_managable_roles(
|
||||
request.keystone_user['roles'])
|
||||
|
||||
active_emails = set()
|
||||
for user in id_manager.list_users(project):
|
||||
skip = False
|
||||
@ -53,13 +56,15 @@ class UserList(tasks.InviteUser):
|
||||
enabled = getattr(user, 'enabled')
|
||||
user_status = 'Active' if enabled else 'Account Disabled'
|
||||
active_emails.add(email)
|
||||
user_list.append({'id': user.id,
|
||||
'name': user.name,
|
||||
'email': email,
|
||||
'roles': roles,
|
||||
'cohort': 'Member',
|
||||
'status': user_status
|
||||
})
|
||||
user_list.append({
|
||||
'id': user.id,
|
||||
'name': user.name,
|
||||
'email': email,
|
||||
'roles': roles,
|
||||
'cohort': 'Member',
|
||||
'status': user_status,
|
||||
'manageable': set(can_manage_roles).issuperset(roles),
|
||||
})
|
||||
|
||||
# Get my active tasks for this project:
|
||||
project_tasks = models.Task.objects.filter(
|
||||
|
@ -104,14 +104,15 @@ class FakeManager(object):
|
||||
roles = temp_cache['projects'][project.name].roles
|
||||
users = []
|
||||
|
||||
for user_id, roles in roles.iteritems():
|
||||
for user_id, user_roles in roles.iteritems():
|
||||
user = self.get_user(user_id)
|
||||
user.roles = []
|
||||
|
||||
for role in roles:
|
||||
for role in user_roles:
|
||||
r = mock.Mock()
|
||||
r.name = role
|
||||
user.roles.append(r)
|
||||
users.append(user)
|
||||
return users
|
||||
|
||||
def create_user(self, name, password, email, created_on,
|
||||
|
@ -107,6 +107,56 @@ class OpenstackAPITests(APITestCase):
|
||||
|
||||
response = self.client.get(url, headers=headers)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data['users']), 2)
|
||||
|
||||
def test_user_list_managable(self):
|
||||
"""
|
||||
Confirm that the manageable value is set correctly.
|
||||
"""
|
||||
user = mock.Mock()
|
||||
user.id = 'user_id_1'
|
||||
user.name = "test1@example.com"
|
||||
user.email = "test1@example.com"
|
||||
user.domain = 'default'
|
||||
|
||||
user2 = mock.Mock()
|
||||
user2.id = 'user_id_2'
|
||||
user2.name = "test2@example.com"
|
||||
user2.email = "test2@example.com"
|
||||
user2.domain = 'default'
|
||||
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {
|
||||
user.id: ['_member_', 'project_admin'],
|
||||
user2.id: ['_member_', 'project_mod']}
|
||||
|
||||
setup_temp_cache(
|
||||
{'test_project': project},
|
||||
{user.id: user, user2.id: user2})
|
||||
|
||||
url = "/v1/openstack/users"
|
||||
headers = {
|
||||
'project_name': "test_project",
|
||||
'project_id': "test_project_id",
|
||||
'roles': "_member_,project_mod",
|
||||
'username': "test@example.com",
|
||||
'user_id': "test_user_id",
|
||||
'authenticated': True
|
||||
}
|
||||
|
||||
url = "/v1/openstack/users"
|
||||
response = self.client.get(url, headers=headers)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data['users']), 2)
|
||||
|
||||
for st_user in response.data['users']:
|
||||
if st_user['id'] == user.id:
|
||||
self.assertFalse(st_user['manageable'])
|
||||
if st_user['id'] == user2.id:
|
||||
self.assertTrue(st_user['manageable'])
|
||||
|
||||
def test_force_reset_password(self):
|
||||
"""
|
||||
|
@ -234,10 +234,10 @@ ROLES_MAPPING = {
|
||||
'project_admin', 'project_mod', '_member_', 'heat_stack_owner'
|
||||
],
|
||||
'project_admin': [
|
||||
'project_mod', '_member_', 'heat_stack_owner'
|
||||
'project_mod', '_member_', 'heat_stack_owner', 'project_admin',
|
||||
],
|
||||
'project_mod': [
|
||||
'_member_', 'heat_stack_owner'
|
||||
'_member_', 'heat_stack_owner', 'project_mod',
|
||||
],
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user