mirror of
https://github.com/ansible/awx.git
synced 2024-11-02 18:21:12 +03:00
JT OPTIONS based on RBAC, refactoring toward combinational prefetching
This commit is contained in:
parent
0406431337
commit
1ca7ce1bd4
@ -2544,6 +2544,7 @@ class LabelSerializer(BaseSerializer):
|
||||
return res
|
||||
|
||||
class ScheduleSerializer(BaseSerializer):
|
||||
show_capabilities = ['edit', 'delete']
|
||||
|
||||
class Meta:
|
||||
model = Schedule
|
||||
|
@ -222,8 +222,8 @@ class BaseAccess(object):
|
||||
def get_user_capabilities(self, obj, method_list):
|
||||
user_capabilities = {}
|
||||
|
||||
# Custom ordering to loop through methods so we can reuse earlier calcs
|
||||
for display_method in ['edit', 'delete', 'start', 'schedule', 'copy', 'adhoc']:
|
||||
# Custom ordering of methods used so we can reuse earlier calcs
|
||||
if display_method not in method_list:
|
||||
continue
|
||||
|
||||
@ -233,54 +233,38 @@ class BaseAccess(object):
|
||||
continue
|
||||
|
||||
# Aliases for going form UI language to API language
|
||||
# speedups in certain cases by deferring to earlier property
|
||||
if display_method == 'edit':
|
||||
method = 'change'
|
||||
elif display_method == 'copy':
|
||||
method = 'add'
|
||||
elif display_method == 'schedule' and 'edit' in user_capabilities:
|
||||
user_capabilities['schedule'] = user_capabilities['edit']
|
||||
continue
|
||||
elif display_method == 'delete' and not isinstance(obj, (User, UnifiedJob)):
|
||||
user_capabilities['delete'] = user_capabilities['edit']
|
||||
continue
|
||||
elif display_method == 'adhoc':
|
||||
method = 'run_ad_hoc_commands'
|
||||
else:
|
||||
method = display_method
|
||||
|
||||
# Shortcuts in certain cases by deferring to earlier property
|
||||
if display_method == 'schedule' and 'edit' in user_capabilities:
|
||||
user_capabilities['schedule'] = user_capabilities['edit']
|
||||
continue
|
||||
elif display_method == 'delete' and not isinstance(obj, (User, UnifiedJob)):
|
||||
user_capabilities['delete'] = user_capabilities['edit']
|
||||
continue
|
||||
|
||||
# Preprocessing before the access method is called
|
||||
data = None
|
||||
if method == 'add':
|
||||
data = {}
|
||||
|
||||
access_instance = self
|
||||
obj_check = obj
|
||||
if isinstance(obj, (Group, Host)):
|
||||
if method == 'start':
|
||||
if obj.inventory_source:
|
||||
obj_check = obj.inventory_source
|
||||
else:
|
||||
user_capabilities[method] = False
|
||||
continue
|
||||
else:
|
||||
obj_check = obj.inventory
|
||||
access_class = access_registry.get(type(obj_check), [])[0]
|
||||
access_instance = access_class(self.user)
|
||||
if isinstance(obj, JobTemplate):
|
||||
data = {'reference_obj': obj}
|
||||
elif method == 'add':
|
||||
data = {}
|
||||
|
||||
# try:
|
||||
access_method = getattr(access_instance, "can_%s" % method)
|
||||
# Compute permission
|
||||
access_method = getattr(self, "can_%s" % method)
|
||||
if method in ['change']: # 3 args
|
||||
user_capabilities[display_method] = access_method(obj_check, data)
|
||||
user_capabilities[display_method] = access_method(obj, data)
|
||||
elif method in ['delete', 'start', 'run_ad_hoc_commands']: # 2 args
|
||||
user_capabilities[display_method] = access_method(obj_check)
|
||||
user_capabilities[display_method] = access_method(obj)
|
||||
elif method in ['add']: # 2 args with data
|
||||
user_capabilities[display_method] = access_method(data)
|
||||
# except Exception as exc:
|
||||
# user_capabilities[display_method] = False
|
||||
# print(exc)
|
||||
|
||||
return user_capabilities
|
||||
|
||||
@ -603,6 +587,12 @@ class GroupAccess(BaseAccess):
|
||||
"active_jobs": active_jobs})
|
||||
return True
|
||||
|
||||
def can_start(self, obj):
|
||||
# Used as another alias to inventory_source start access
|
||||
if obj and obj.inventory_source:
|
||||
return self.user.can_access(InventorySource, 'start', obj.inventory_source)
|
||||
return False
|
||||
|
||||
class InventorySourceAccess(BaseAccess):
|
||||
'''
|
||||
I can see inventory sources whenever I can see their group or inventory.
|
||||
@ -938,7 +928,9 @@ class JobTemplateAccess(BaseAccess):
|
||||
Users who are able to create deploy jobs can also run normal and check (dry run) jobs.
|
||||
'''
|
||||
if not data: # So the browseable API will work
|
||||
return True
|
||||
return (
|
||||
Project.accessible_objects(self.user, 'use_role').exists() or
|
||||
Inventory.accessible_objects(self.user, 'use_role').exists())
|
||||
|
||||
# if reference_obj is provided, determine if it can be coppied
|
||||
reference_obj = data.pop('reference_obj', None)
|
||||
|
@ -416,6 +416,9 @@ def cache_list_capabilities(page, role_types, model, user):
|
||||
'''
|
||||
page_ids = [obj.id for obj in page]
|
||||
id_lists = {}
|
||||
for obj in page:
|
||||
obj.capabilities_cache = {}
|
||||
|
||||
for role_type in role_types:
|
||||
# Role name translation to UI names for methods
|
||||
display_method = role_type
|
||||
@ -423,14 +426,15 @@ def cache_list_capabilities(page, role_types, model, user):
|
||||
display_method = 'edit'
|
||||
elif role_type in ['execute', 'update']:
|
||||
display_method = 'start'
|
||||
|
||||
# Query for union of page objects & role accessible_objects
|
||||
id_lists[display_method] = model.accessible_objects(
|
||||
user, '%s_role' % role_type).filter(pk__in=page_ids).values_list('pk', flat=True)
|
||||
# Save data item-by-item
|
||||
for obj in page:
|
||||
obj.capabilities_cache = {display_method: False for display_method in id_lists.keys()}
|
||||
for display_method, id_list in id_lists.iteritems():
|
||||
if obj.pk in id_list:
|
||||
ids_with_role = set(model.accessible_objects(
|
||||
user, '%s_role' % role_type).filter(pk__in=page_ids).values_list('pk', flat=True))
|
||||
|
||||
# Save data item-by-item
|
||||
for obj in page:
|
||||
obj.capabilities_cache[display_method] = False
|
||||
if obj.pk in ids_with_role:
|
||||
obj.capabilities_cache[display_method] = True
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user