Assign roles to group for a region

This patch provides the fuctionality of assigning roles to group
for a particular region.

Change-Id: Ie1a246d46fffe3d8976546c2e276efd93a3b424d
This commit is contained in:
Chi Lo 2019-05-22 20:32:56 -07:00
parent cf78b0eaf5
commit b400f52e9d
12 changed files with 193 additions and 63 deletions

View File

@ -352,6 +352,22 @@ def add_to_parser(service_sub):
'datafile', type=argparse.FileType('r'),
help='<data file with group role(s) assignment JSON>')
# assign group region roles
parser_assign_group_region_roles = subparsers.add_parser(
'assign_group_region_roles',
help='[<"X-RANGER-Client" '
'header>] <group id> <region_id> '
'<data file with group role(s) assignment JSON>')
parser_assign_group_region_roles.add_argument(
'client', **cli_common.ORM_CLIENT_KWARGS)
parser_assign_group_region_roles.add_argument(
'groupid', type=str, help='<groupid id>')
parser_assign_group_region_roles.add_argument(
'regionid', type=str, help='<regionid id>')
parser_assign_group_region_roles.add_argument(
'datafile', type=argparse.FileType('r'),
help='<data file with group role(s) assignment JSON>')
# unassign group roles
parser_unassign_group_role = subparsers.add_parser(
'unassign_group_role',
@ -536,6 +552,9 @@ def cmd_details(args):
return requests.get, 'groups/%s' % param
elif args.subcmd == 'assign_group_roles':
return requests.post, 'groups/%s/roles' % args.groupid
elif args.subcmd == 'assign_group_region_roles':
return requests.post, 'groups/%s/regions/%s/roles' % (
args.groupid, args.regionid)
elif args.subcmd == 'unassign_group_role':
if args.customer and args.domain:
print("--customer and --domain cannot be specified "

View File

@ -0,0 +1,69 @@
from oslo_db.exception import DBDuplicateEntry
from pecan import request, rest
from wsmeext.pecan import wsexpose
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import utils
from orm.services.customer_manager.cms_rest.logger import get_logger
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.logic.group_logic import GroupLogic
from orm.services.customer_manager.cms_rest.model.GroupModels import \
RoleAssignment, RoleResultWrapper
from orm.services.customer_manager.cms_rest.utils import authentication
LOG = get_logger(__name__)
class RegionRoleController(rest.RestController):
@wsexpose(str, str, str, rest_content_types='json')
def get(self, group_id, region):
return "This is groups region role controller group id:{0} " \
"region:{1}".format(group_id, region)
@wsexpose(RoleResultWrapper, str, str, body=[RoleAssignment],
rest_content_types='json', status_code=200)
def post(self, group_id, region, role_assignments):
LOG.info("RegionRoleController - Assign Roles to group id [{0}] for "
"region [{1}] roles [{2}]".format(
group_id, region, str(role_assignments)))
authentication.authorize(request, 'groups:assign_region_role')
try:
group_logic = GroupLogic()
result = group_logic.assign_roles(group_id,
role_assignments,
request.transaction_id,
region)
LOG.info("RegionRoleController - Roles assigned: " + str(result))
event_details = 'Group {} - region roles assigned'.format(group_id)
utils.audit_trail('assigned group region roles',
request.transaction_id,
request.headers,
group_id,
event_details=event_details)
except DBDuplicateEntry as exception:
LOG.log_exception(
"DBDuplicateEntry-Group Region Roles already assigned.",
exception)
raise err_utils.get_error(
request.transaction_id,
status_code=409,
message='Duplicate Entry-Group Region Roles already assigned.',
error_details=exception.message)
except ErrorStatus as exception:
LOG.log_exception(
"ErrorStatus - Failed to assign roles for region.", exception)
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=exception.status_code)
except Exception as exception:
LOG.log_exception(
"Exception - Failed in assign roles for region.", exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=str(exception))
return result

View File

@ -4,8 +4,10 @@ from wsmeext.pecan import wsexpose
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import utils
from orm.services.customer_manager.cms_rest.controllers.v1.orm.group.region_users \
import RegionUserController
from orm.services.customer_manager.cms_rest.controllers.v1.orm.group.\
region_roles import RegionRoleController
from orm.services.customer_manager.cms_rest.controllers.v1.orm.group.\
region_users import RegionUserController
from orm.services.customer_manager.cms_rest.logger import get_logger
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.logic.group_logic import GroupLogic
@ -19,6 +21,7 @@ LOG = get_logger(__name__)
class RegionController(rest.RestController):
users = RegionUserController()
roles = RegionRoleController()
@wsexpose([str], str, str, rest_content_types='json')
def get(self, group_id, region_id):

View File

@ -109,7 +109,7 @@ class RoleController(rest.RestController):
status_code=500,
error_details=str(exception))
@wsexpose(RoleResult, str, str, str, str, rest_content_types='json')
@wsexpose([RoleResult], str, str, str, str, rest_content_types='json')
def get_all(self, group_id, region=None, customer=None, domain=None):
LOG.info("RoleController - GetRolelist")
authentication.authorize(request, 'groups:get_all_roles')

View File

@ -40,11 +40,9 @@ class GroupsCustomerRoleRecord:
str(groups_customer_role), exception)
raise
def get_customer_role_by_keys(self,
def get_customer_roles_by_region(self,
group_uuid,
role_id,
region_name,
customer_id):
region_name):
region_record = RegionRecord(self.session)
region_id = region_record.get_region_id_from_name(region_name)
if region_id is None:
@ -54,16 +52,13 @@ class GroupsCustomerRoleRecord:
try:
group = self.session.query(GroupsCustomerRole).filter(
GroupsCustomerRole.group_id == group_uuid,
GroupsCustomerRole.customer_id == customer_id,
GroupsCustomerRole.region_id == region_id,
GroupsCustomerRole.role_id == role_id)
return group.first()
GroupsCustomerRole.region_id == region_id)
return group.all()
except Exception as exception:
message = "Failed to get group/project by keys: " \
" group_uuid:%s customer_id:%s region_name:%s " \
" role_id:%s " \
% group_uuid, customer_id, region_id, role_id
message = "Failed to get roles by region: " \
" group_uuid:%s region_name:%s " \
% group_uuid, region_name
LOG.log_exception(message, exception)
raise

View File

@ -40,11 +40,9 @@ class GroupsDomainRoleRecord:
str(groups_domain_role), exception)
raise
def get_domain_role_by_keys(self,
def get_domain_roles_by_region(self,
group_uuid,
region_name,
domain,
role_id):
region_name):
region_record = RegionRecord(self.session)
region_id = region_record.get_region_id_from_name(region_name)
if region_id is None:
@ -54,15 +52,13 @@ class GroupsDomainRoleRecord:
try:
group = self.session.query(GroupsDomainRole).filter(
GroupsDomainRole.group_id == group_uuid,
GroupsDomainRole.domain_name == domain,
GroupsDomainRole.region_id == region_id,
GroupsDomainRole.role_id == role_id)
return group.first()
GroupsDomainRole.region_id == region_id)
return group.all()
except Exception as exception:
message = "Failed to get group/domain by primary keys: " \
" group_uuid:%s domain:%s region_name:%s role_id: %s" \
% group_uuid, domain, region_id, role_id
message = "Failed to get group roles by region: " \
" group_uuid:%s region_name:%s " \
% group_uuid, region_name
LOG.log_exception(message, exception)
raise

View File

@ -43,7 +43,6 @@ class GroupsRegionRecord:
group_regions = []
try:
group_record = GroupRecord(self.session)
query = self.session.query(GroupsRegion).filter(
GroupsRegion.group_id == group_uuid,
GroupsRegion.region_id != -1)
@ -57,6 +56,27 @@ class GroupsRegionRecord:
LOG.log_exception(message, exception)
raise
def get_region_by_keys(self, group_uuid, region_name):
# get region id by name
region_record = RegionRecord(self.session)
region_id = region_record.get_region_id_from_name(region_name)
if region_id is None:
raise ValueError(
'region with the region name {0} not found'.format(
region_name))
try:
query = self.session.query(GroupsRegion).filter(
GroupsRegion.group_id == group_uuid,
GroupsRegion.region_id == region_id)
return query.first()
except Exception as exception:
message = "Failed to get groups region record by keys: " \
" group_uuid:%s region_name:%s " \
% group_uuid, region_name
LOG.log_exception(message, exception)
raise
def delete_region_for_group(self, group_uuid, region_name):
# get region id by name
region_record = RegionRecord(self.session)

View File

@ -129,12 +129,8 @@ class Groups(Base, CMSBaseModel):
regions = [group_region.to_wsme() for group_region in
self.group_regions if group_region.region_id != -1]
roles = []
customer_roles = [customer_role.get_role_name() for customer_role in
self.groups_customer_roles]
domain_roles = [domain_role.get_role_name() for domain_role in
self.groups_domain_roles]
roles = sorted(set(customer_roles + domain_roles))
roles = [group_role.get_role_name() for group_role in
self.groups_roles]
users = []
unique_domain = {}
@ -153,7 +149,7 @@ class Groups(Base, CMSBaseModel):
name=name,
uuid=uuid,
regions=regions,
roles=list(roles),
roles=sorted(roles),
users=users,
enabled=enabled,
domain=domain_name)
@ -255,6 +251,9 @@ class GroupsRole(Base, CMSBaseModel):
"group_id": self.group_id
}
def get_role_name(self):
return self.role.name
'''
' GroupsCustomerRole is a DataObject and contains all the fields defined in
@ -299,9 +298,6 @@ class GroupsCustomerRole(Base, CMSBaseModel):
"role_name": self.groups_role.role.name
}
def get_role_name(self):
return self.groups_role.role.name
'''
' GroupsDomainRole is a DataObject and contains all the fields defined in
@ -344,9 +340,6 @@ class GroupsDomainRole(Base, CMSBaseModel):
"role_name": self.groups_role.role.name
}
def get_role_name(self):
return self.groups_role.role.name
'''
' GroupsUser is a DataObject and contains all the fields defined in GroupRole

View File

@ -45,6 +45,7 @@
"groups:add_region": "rule:admin_or_support_or_creator",
"groups:delete_region": "rule:admin_or_creator",
"groups:assign_role": "rule:admin_or_support_or_creator",
"groups:assign_region_role": "rule:admin_or_support_or_creator",
"groups:unassign_role": "rule:admin_or_creator",
"groups:add_group_default_users": "rule:admin_or_support",
"groups:delete_group_default_user": "rule:admin",

View File

@ -3,9 +3,9 @@ from pecan import conf, request
import requests
from orm.common.orm_common.utils import utils
from orm.common.orm_common.utils.cross_api_utils import (get_regions_of_group,
from orm.common.orm_common.utils.cross_api_utils import (
get_regions_of_group,
set_utils_conf)
from orm.services.customer_manager.cms_rest.data.data_manager import \
DataManager
from orm.services.customer_manager.cms_rest.logger import get_logger
@ -91,7 +91,8 @@ class GroupLogic(object):
def assign_roles(self,
group_uuid,
role_assignments,
transaction_id):
transaction_id,
region=None):
datamanager = DataManager()
try:
@ -99,8 +100,16 @@ class GroupLogic(object):
group_record = datamanager.get_record('group')
region_record = datamanager.get_record('groups_region')
groups_regions = region_record.get_regions_for_group(group_uuid)
# If region is not specified, then get all the regions already
# associated with the group for role assginement; otherwise,
# just assign roles for the passed in region only.
if region is None:
groups_regions = region_record.get_regions_for_group(
group_uuid)
else:
groups_regions = [region_record.get_region_by_keys(
group_uuid, region)]
for role_assignment in role_assignments:
for role in role_assignment.roles:
role_id = datamanager.get_role_id_by_name(role)
@ -704,27 +713,60 @@ class GroupLogic(object):
if customer_uuid is not None and domain_name is not None:
raise ErrorStatus(400, "customer and domain cannot be used at "
"the same time for query in request uri.")
if customer_uuid is None and domain_name is None:
raise ErrorStatus(400, "customer or domain is required for query "
"in request uri.")
role_result = []
roles = []
datamanager = DataManager()
# filter by region
if customer_uuid is None and domain_name is None:
record = datamanager.get_record('groups_customer_role')
sql_customers_roles = record.get_customer_roles_by_region(
group_uuid, region_name)
record = datamanager.get_record('groups_domain_role')
sql_domains_roles = record.get_domain_roles_by_region(
group_uuid, region_name)
unique_customer = {}
for customer in sql_customers_roles:
if customer.customer.uuid in unique_customer:
unique_customer[customer.customer.uuid].append(customer.groups_role.role.name)
else:
unique_customer[customer.customer.uuid] = [customer.groups_role.role.name]
for customer, role_list in unique_customer.items():
role_result.append(RoleResult(roles=role_list, customer=customer))
unique_domain = {}
for domain in sql_domains_roles:
if domain.domain_name in unique_domain:
unique_domain[domain.domain_name].append(domain.groups_role.role.name)
else:
unique_domain[domain.domain_name] = [domain.groups_role.role.name]
for domain, role_list in unique_domain.items():
role_result.append(RoleResult(roles=role_list, domain=domain))
return role_result
# filter by customer
elif customer_uuid is not None:
customer_id = datamanager.get_customer_id_by_uuid(customer_uuid)
if customer_uuid is not None:
record = datamanager.get_record('groups_customer_role')
sql_roles = record.get_customer_roles_by_criteria(
group_uuid, region_name, customer_id)
# filter by domain
else:
record = datamanager.get_record('groups_domain_role')
sql_roles = record.get_domain_roles_by_criteria(
group_uuid, region_name, domain_name)
roles = []
if sql_roles:
roles = [sql_role.groups_role.role.name for sql_role in sql_roles
if sql_role and sql_role.groups_role.role.name]
return RoleResult(roles=roles)
return [RoleResult(roles=roles)]
def delete_group_by_uuid(self, group_id):
datamanager = DataManager()

View File

@ -331,7 +331,6 @@ class TestGroupLogic(FunctionalTest):
logic.get_group_roles_by_criteria(
'group_uuid', 'region', None, 'domain')
self.assertTrue(data_manager_mock.get_customer_id_by_uuid.called)
self.assertTrue(data_manager_mock.get_record.called)
self.assertTrue(record_mock.get_domain_roles_by_criteria.called)
@ -342,13 +341,6 @@ class TestGroupLogic(FunctionalTest):
self.assertEqual(cm.exception.status_code, 400)
self.assertIn('region must be specified', cm.exception.message)
def test_get_group_roles_by_criteria_missing_optional_parms(self):
logic = group_logic.GroupLogic()
with self.assertRaises(ErrorStatus) as cm:
logic.get_group_roles_by_criteria('group', 'region', None, None)
self.assertEqual(cm.exception.status_code, 400)
self.assertIn('customer or domain is required', cm.exception.message)
def test_get_group_roles_by_criteria_conflicting_optional_parms(self):
logic = group_logic.GroupLogic()
with self.assertRaises(ErrorStatus) as cm:

View File

@ -181,7 +181,7 @@ def get_mock_group_logic():
group_logic_mock.assign_roles.return_value = res
group_logic_mock.unassign_roles.return_value = res1
group_logic_mock.get_group_roles_by_criteria.return_value = list_res
group_logic_mock.get_group_roles_by_criteria.return_value = [list_res]
elif roles.GroupLogic.return_error == 1:
group_logic_mock.assign_roles.side_effect = SystemError()