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:
NewUser:
allowed_roles:
- project_owner
- project_admin
- project_mod
- heat_stack_owner
- _member_
@ -209,12 +209,12 @@ ACTION_SETTINGS:
# mapping between roles and managable roles
ROLES_MAPPING:
admin:
- project_owner
- project_admin
- project_mod
- heat_stack_owner
- _member_
project_owner:
- project_owner
project_admin:
- project_admin
- project_mod
- heat_stack_owner
- _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
* Initial release.

View File

@ -6,7 +6,7 @@ with open('requirements.txt') as f:
setup(
name='stacktask',
version='0.1.1a3',
version='0.1.1a4',
description='A user task service for openstack.',
long_description=(
'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?
default_roles = {
"project_owner", "project_mod", "_member_", "heat_stack_owner"
"project_admin", "project_mod", "_member_", "heat_stack_owner"
}
def _validate(self):

View File

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

View File

@ -37,13 +37,13 @@ def require_roles(roles, func, *args, **kwargs):
@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.
"""
return require_roles(
{'project_owner', 'project_mod', 'admin'}, func, *args, **kwargs)
{'project_admin', 'project_mod', 'admin'}, func, *args, **kwargs)
@decorator

View File

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

View File

@ -346,17 +346,17 @@ class InviteUser(TaskView):
default_action = 'NewUser'
@utils.mod_or_owner
@utils.mod_or_admin
def get(self, request):
return super(InviteUser, self).get(request)
@utils.mod_or_owner
@utils.mod_or_admin
def post(self, request, format=None):
"""
Invites a user to the current tenant.
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.
"""
self.logger.info("(%s) - New AttachUser request." % timezone.now())
@ -434,7 +434,7 @@ class EditUser(TaskView):
default_action = 'EditUser'
@utils.mod_or_owner
@utils.mod_or_admin
def get(self, request):
class_conf = settings.TASK_SETTINGS.get(self.task_type, {})
@ -475,11 +475,11 @@ class EditUser(TaskView):
'required_fields': required_fields,
'users': user_list})
@utils.mod_or_owner
@utils.mod_or_admin
def post(self, request, format=None):
"""
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.
Runs process_actions, then does the approve step and
post_approve validation, and creates a Token if valid.

View File

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

View File

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

View File

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

View File

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

View File

@ -189,7 +189,7 @@ class TaskList(APIViewWithLogger):
class TaskDetail(APIViewWithLogger):
@utils.mod_or_owner
@utils.mod_or_admin
def get(self, request, uuid, format=None):
"""
Dict representation of a Task object
@ -442,12 +442,12 @@ class TaskDetail(APIViewWithLogger):
return Response({'approved': ["this field is required."]},
status=400)
@utils.mod_or_owner
@utils.mod_or_admin
def delete(self, request, uuid, format=None):
"""
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.
"""
try:
@ -501,7 +501,7 @@ class TokenList(APIViewWithLogger):
token_list.append(token.to_dict())
return Response({"tokens": token_list})
@utils.mod_or_owner
@utils.mod_or_admin
def post(self, request, format=None):
"""
Reissue a token for an approved task.

View File

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