Renamed role project_owner to project_admin

* This change brings the role name in line with the upstream (unapproved) spec:
    https://review.openstack.org/#/c/245629/5/specs/common-default-policy.rst
  * Renamed mod_or_owner decorator to mod_or_admin
  * Debian package version bumped to 0.1.1a4

Change-Id: I312c2a6baec22959f83ab1e09370de868076730b
This commit is contained in:
adriant 2016-02-16 10:57:42 +13:00 committed by Dale Smith
parent 853cc9958e
commit b76c3af1f6
14 changed files with 56 additions and 51 deletions

View File

@ -188,7 +188,7 @@ TASK_SETTINGS:
ACTION_SETTINGS: ACTION_SETTINGS:
NewUser: NewUser:
allowed_roles: allowed_roles:
- project_owner - project_admin
- project_mod - project_mod
- heat_stack_owner - heat_stack_owner
- _member_ - _member_
@ -209,12 +209,12 @@ ACTION_SETTINGS:
# mapping between roles and managable roles # mapping between roles and managable roles
ROLES_MAPPING: ROLES_MAPPING:
admin: admin:
- project_owner - project_admin
- project_mod - project_mod
- heat_stack_owner - heat_stack_owner
- _member_ - _member_
project_owner: project_admin:
- project_owner - project_admin
- project_mod - project_mod
- heat_stack_owner - heat_stack_owner
- _member_ - _member_

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
python-stacktask (0.1.1a4) unstable; urgency=medium
* Release with latest patches and project_admin.
-- Dale Smith <dale@catalyst-eu.net> Thu, 18 Feb 2016 12:09:57 +0000
python-stacktask (0.1.1a3) unstable; urgency=medium python-stacktask (0.1.1a3) unstable; urgency=medium
* Initial release. * Initial release.

View File

@ -6,7 +6,7 @@ with open('requirements.txt') as f:
setup( setup(
name='stacktask', name='stacktask',
version='0.1.1a3', version='0.1.1a4',
description='A user task service for openstack.', description='A user task service for openstack.',
long_description=( long_description=(
'A task service to sit alongside keystone and ' + 'A task service to sit alongside keystone and ' +

View File

@ -394,7 +394,7 @@ class NewProject(UserNameAction):
# NOTE(adriant): move these to a config somewhere? # NOTE(adriant): move these to a config somewhere?
default_roles = { default_roles = {
"project_owner", "project_mod", "_member_", "heat_stack_owner" "project_admin", "project_mod", "_member_", "heat_stack_owner"
} }
def _validate(self): def _validate(self):

View File

@ -232,14 +232,13 @@ class ActionTests(TestCase):
token_data = {'password': '123456'} token_data = {'password': '123456'}
action.submit(token_data) action.submit(token_data)
self.assertEquals(action.valid, True) self.assertEquals(action.valid, True)
print tests.temp_cache['users']
self.assertEquals( self.assertEquals(
tests.temp_cache['users']["user_id_1"].email, tests.temp_cache['users']["user_id_1"].email,
'test@example.com') 'test@example.com')
project = tests.temp_cache['projects']['test_project'] project = tests.temp_cache['projects']['test_project']
self.assertEquals( self.assertEquals(
sorted(project.roles["user_id_1"]), sorted(project.roles["user_id_1"]),
sorted(['_member_', 'project_owner', sorted(['_member_', 'project_admin',
'project_mod', 'heat_stack_owner'])) 'project_mod', 'heat_stack_owner']))
@mock.patch('stacktask.actions.models.user_store.IdentityManager', @mock.patch('stacktask.actions.models.user_store.IdentityManager',
@ -291,7 +290,7 @@ class ActionTests(TestCase):
project = tests.temp_cache['projects']['test_project'] project = tests.temp_cache['projects']['test_project']
self.assertEquals( self.assertEquals(
sorted(project.roles["user_id_1"]), sorted(project.roles["user_id_1"]),
sorted(['_member_', 'project_owner', sorted(['_member_', 'project_admin',
'project_mod', 'heat_stack_owner'])) 'project_mod', 'heat_stack_owner']))
@mock.patch('stacktask.actions.models.user_store.IdentityManager', @mock.patch('stacktask.actions.models.user_store.IdentityManager',
@ -340,7 +339,7 @@ class ActionTests(TestCase):
project = tests.temp_cache['projects']['test_project'] project = tests.temp_cache['projects']['test_project']
self.assertEquals( self.assertEquals(
sorted(project.roles[user.id]), sorted(project.roles[user.id]),
sorted(['_member_', 'project_owner', sorted(['_member_', 'project_admin',
'project_mod', 'heat_stack_owner'])) 'project_mod', 'heat_stack_owner']))
@mock.patch('stacktask.actions.models.user_store.IdentityManager', @mock.patch('stacktask.actions.models.user_store.IdentityManager',

View File

@ -37,13 +37,13 @@ def require_roles(roles, func, *args, **kwargs):
@decorator @decorator
def mod_or_owner(func, *args, **kwargs): def mod_or_admin(func, *args, **kwargs):
""" """
Require project mod or owner. Require project_mod or project_admin.
Admin is allowed everything, so is also included. Admin is allowed everything, so is also included.
""" """
return require_roles( return require_roles(
{'project_owner', 'project_mod', 'admin'}, func, *args, **kwargs) {'project_admin', 'project_mod', 'admin'}, func, *args, **kwargs)
@decorator @decorator

View File

@ -25,7 +25,7 @@ from stacktask.api.v1 import tasks
class UserList(tasks.InviteUser): class UserList(tasks.InviteUser):
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request): def get(self, request):
"""Get a list of all users who have been added to a project""" """Get a list of all users who have been added to a project"""
class_conf = settings.TASK_SETTINGS.get('edit_user', {}) class_conf = settings.TASK_SETTINGS.get('edit_user', {})
@ -99,7 +99,7 @@ class UserList(tasks.InviteUser):
class UserDetail(tasks.TaskView): class UserDetail(tasks.TaskView):
task_type = 'edit_user' task_type = 'edit_user'
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request, user_id): def get(self, request, user_id):
""" """
Get user info based on the user id. Get user info based on the user id.
@ -128,7 +128,7 @@ class UserDetail(tasks.TaskView):
"email": getattr(user, 'email', ''), "email": getattr(user, 'email', ''),
'roles': roles}) 'roles': roles})
@utils.mod_or_owner @utils.mod_or_admin
def delete(self, request, user_id): def delete(self, request, user_id):
""" """
Remove this user from the project. Remove this user from the project.
@ -163,7 +163,7 @@ class UserRoles(tasks.TaskView):
default_action = 'EditUserRoles' default_action = 'EditUserRoles'
task_type = 'edit_roles' task_type = 'edit_roles'
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request, user_id): def get(self, request, user_id):
""" """
Get user info based on the user id. Get user info based on the user id.
@ -177,7 +177,7 @@ class UserRoles(tasks.TaskView):
roles.append(role.to_dict()) roles.append(role.to_dict())
return Response({"roles": roles}) return Response({"roles": roles})
@utils.mod_or_owner @utils.mod_or_admin
def put(self, request, user_id, format=None): def put(self, request, user_id, format=None):
""" """
Add user roles to the current project. Add user roles to the current project.
@ -201,7 +201,7 @@ class UserRoles(tasks.TaskView):
% timezone.now()) % timezone.now())
return self.approve(task) return self.approve(task)
@utils.mod_or_owner @utils.mod_or_admin
def delete(self, request, user_id, format=None): def delete(self, request, user_id, format=None):
""" """
Revoke user roles to the current project. Revoke user roles to the current project.
@ -230,7 +230,7 @@ class UserRoles(tasks.TaskView):
class RoleList(tasks.TaskView): class RoleList(tasks.TaskView):
task_type = 'edit_roles' task_type = 'edit_roles'
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request): def get(self, request):
"""Returns a list of roles that may be managed for this project""" """Returns a list of roles that may be managed for this project"""

View File

@ -346,17 +346,17 @@ class InviteUser(TaskView):
default_action = 'NewUser' default_action = 'NewUser'
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request): def get(self, request):
return super(InviteUser, self).get(request) return super(InviteUser, self).get(request)
@utils.mod_or_owner @utils.mod_or_admin
def post(self, request, format=None): def post(self, request, format=None):
""" """
Invites a user to the current tenant. Invites a user to the current tenant.
This endpoint requires either Admin access or the This endpoint requires either Admin access or the
request to come from a project_owner|project_mod. request to come from a project_admin|project_mod.
As such this Task is considered pre-approved. As such this Task is considered pre-approved.
""" """
self.logger.info("(%s) - New AttachUser request." % timezone.now()) self.logger.info("(%s) - New AttachUser request." % timezone.now())
@ -434,7 +434,7 @@ class EditUser(TaskView):
default_action = 'EditUser' default_action = 'EditUser'
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request): def get(self, request):
class_conf = settings.TASK_SETTINGS.get(self.task_type, {}) class_conf = settings.TASK_SETTINGS.get(self.task_type, {})
@ -475,11 +475,11 @@ class EditUser(TaskView):
'required_fields': required_fields, 'required_fields': required_fields,
'users': user_list}) 'users': user_list})
@utils.mod_or_owner @utils.mod_or_admin
def post(self, request, format=None): def post(self, request, format=None):
""" """
This endpoint requires either mod access or the This endpoint requires either mod access or the
request to come from a project_owner. request to come from a project_admin.
As such this Task is considered pre-approved. As such this Task is considered pre-approved.
Runs process_actions, then does the approve step and Runs process_actions, then does the approve step and
post_approve validation, and creates a Token if valid. post_approve validation, and creates a Token if valid.

View File

@ -36,7 +36,7 @@ def setup_temp_cache(projects, users):
'roles': { 'roles': {
'_member_': '_member_', '_member_': '_member_',
'admin': 'admin', 'admin': 'admin',
'project_owner': 'project_owner', 'project_admin': 'project_admin',
'project_mod': 'project_mod', 'project_mod': 'project_mod',
'heat_stack_owner': 'heat_stack_owner' 'heat_stack_owner': 'heat_stack_owner'
} }

View File

@ -490,7 +490,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -666,7 +666,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -712,7 +712,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -746,7 +746,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -793,7 +793,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -872,7 +872,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "owner@example.com", 'username': "owner@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -885,7 +885,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id_2", 'project_id': "test_project_id_2",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -920,7 +920,7 @@ class AdminAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True

View File

@ -47,7 +47,7 @@ class OpenstackAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -80,7 +80,7 @@ class OpenstackAPITests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True

View File

@ -47,7 +47,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -76,7 +76,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -151,7 +151,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -192,7 +192,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -262,7 +262,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -308,7 +308,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True
@ -503,7 +503,7 @@ class TaskViewTests(APITestCase):
headers = { headers = {
'project_name': "test_project", 'project_name': "test_project",
'project_id': "test_project_id", 'project_id': "test_project_id",
'roles': "project_owner,_member_,project_mod", 'roles': "project_admin,_member_,project_mod",
'username': "test@example.com", 'username': "test@example.com",
'user_id': "test_user_id", 'user_id': "test_user_id",
'authenticated': True 'authenticated': True

View File

@ -189,7 +189,7 @@ class TaskList(APIViewWithLogger):
class TaskDetail(APIViewWithLogger): class TaskDetail(APIViewWithLogger):
@utils.mod_or_owner @utils.mod_or_admin
def get(self, request, uuid, format=None): def get(self, request, uuid, format=None):
""" """
Dict representation of a Task object Dict representation of a Task object
@ -442,12 +442,12 @@ class TaskDetail(APIViewWithLogger):
return Response({'approved': ["this field is required."]}, return Response({'approved': ["this field is required."]},
status=400) status=400)
@utils.mod_or_owner @utils.mod_or_admin
def delete(self, request, uuid, format=None): def delete(self, request, uuid, format=None):
""" """
Cancel the Task. Cancel the Task.
Project Owners and Project Mods can only cancel tasks Project Admins and Project Mods can only cancel tasks
associated with their project. associated with their project.
""" """
try: try:
@ -501,7 +501,7 @@ class TokenList(APIViewWithLogger):
token_list.append(token.to_dict()) token_list.append(token.to_dict())
return Response({"tokens": token_list}) return Response({"tokens": token_list})
@utils.mod_or_owner @utils.mod_or_admin
def post(self, request, format=None): def post(self, request, format=None):
""" """
Reissue a token for an approved task. Reissue a token for an approved task.

View File

@ -151,7 +151,7 @@ TASK_SETTINGS = {
ACTION_SETTINGS = { ACTION_SETTINGS = {
'NewUser': { 'NewUser': {
'allowed_roles': ['project_mod', 'project_owner', "_member_"] 'allowed_roles': ['project_mod', 'project_admin', "_member_"]
}, },
'ResetUser': { 'ResetUser': {
'blacklisted_roles': ['admin'] 'blacklisted_roles': ['admin']
@ -170,9 +170,9 @@ ACTION_SETTINGS = {
ROLES_MAPPING = { ROLES_MAPPING = {
'admin': [ 'admin': [
'project_owner', 'project_mod', '_member_', 'heat_stack_owner' 'project_admin', 'project_mod', '_member_', 'heat_stack_owner'
], ],
'project_owner': [ 'project_admin': [
'project_mod', '_member_', 'heat_stack_owner' 'project_mod', '_member_', 'heat_stack_owner'
], ],
'project_mod': [ 'project_mod': [