mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 08:21:15 +03:00
job template serializer can_add calc to avoid lookups of known related objects
This commit is contained in:
parent
358f267e14
commit
7b0f20e90d
@ -23,7 +23,6 @@ from django.db import models
|
|||||||
# from django.utils.translation import ugettext_lazy as _
|
# from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.forms.models import model_to_dict
|
|
||||||
|
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
@ -1861,9 +1860,8 @@ class JobTemplateSerializer(UnifiedJobTemplateSerializer, JobOptionsSerializer):
|
|||||||
d['can_copy'] = not validation_errors
|
d['can_copy'] = not validation_errors
|
||||||
d['can_edit'] = True
|
d['can_edit'] = True
|
||||||
else:
|
else:
|
||||||
jt_data = model_to_dict(obj)
|
d['can_copy'] = (not validation_errors) and request.user.can_access(JobTemplate, 'add', {"reference_obj": obj})
|
||||||
d['can_copy'] = (not validation_errors) and request.user.can_access(JobTemplate, 'add', jt_data)
|
d['can_edit'] = request.user.can_access(JobTemplate, 'change', obj, {})
|
||||||
d['can_edit'] = request.user.can_access(JobTemplate, 'change', obj, jt_data)
|
|
||||||
|
|
||||||
d['recent_jobs'] = self._recent_jobs(obj)
|
d['recent_jobs'] = self._recent_jobs(obj)
|
||||||
return d
|
return d
|
||||||
|
@ -788,6 +788,9 @@ class JobTemplateAccess(BaseAccess):
|
|||||||
if not data or '_method' in data: # So the browseable API will work?
|
if not data or '_method' in data: # So the browseable API will work?
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# if reference_obj is provided, determine if it can be coppied
|
||||||
|
reference_obj = data.pop('reference_obj', None)
|
||||||
|
|
||||||
if 'job_type' in data and data['job_type'] == PERM_INVENTORY_SCAN:
|
if 'job_type' in data and data['job_type'] == PERM_INVENTORY_SCAN:
|
||||||
self.check_license(feature='system_tracking')
|
self.check_license(feature='system_tracking')
|
||||||
|
|
||||||
@ -797,51 +800,54 @@ class JobTemplateAccess(BaseAccess):
|
|||||||
if self.user.is_superuser:
|
if self.user.is_superuser:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_value(Class, field):
|
||||||
|
if reference_obj:
|
||||||
|
return getattr(reference_obj, field, None)
|
||||||
|
else:
|
||||||
|
pk = get_pk_from_dict(data, field)
|
||||||
|
if pk:
|
||||||
|
return get_object_or_400(Class, pk=pk)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
# If a credential is provided, the user should have use access to it.
|
# If a credential is provided, the user should have use access to it.
|
||||||
credential_pk = get_pk_from_dict(data, 'credential')
|
credential = get_value(Credential, 'credential')
|
||||||
if credential_pk:
|
if credential:
|
||||||
credential = get_object_or_400(Credential, pk=credential_pk)
|
|
||||||
if self.user not in credential.use_role:
|
if self.user not in credential.use_role:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If a cloud credential is provided, the user should have use access.
|
# If a cloud credential is provided, the user should have use access.
|
||||||
cloud_credential_pk = get_pk_from_dict(data, 'cloud_credential')
|
cloud_credential = get_value(Credential, 'cloud_credential')
|
||||||
if cloud_credential_pk:
|
if cloud_credential:
|
||||||
cloud_credential = get_object_or_400(Credential,
|
|
||||||
pk=cloud_credential_pk)
|
|
||||||
if self.user not in cloud_credential.use_role:
|
if self.user not in cloud_credential.use_role:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If a network credential is provided, the user should have use access.
|
# If a network credential is provided, the user should have use access.
|
||||||
network_credential_pk = get_pk_from_dict(data, 'network_credential')
|
network_credential = get_value(Credential, 'network_credential')
|
||||||
if network_credential_pk:
|
if network_credential:
|
||||||
network_credential = get_object_or_400(Credential,
|
|
||||||
pk=network_credential_pk)
|
|
||||||
if self.user not in network_credential.use_role:
|
if self.user not in network_credential.use_role:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If an inventory is provided, the user should have use access.
|
# If an inventory is provided, the user should have use access.
|
||||||
inventory_pk = get_pk_from_dict(data, 'inventory')
|
inventory = get_value(Inventory, 'inventory')
|
||||||
if inventory_pk:
|
if inventory:
|
||||||
inventory = get_object_or_400(Inventory, pk=inventory_pk)
|
|
||||||
if self.user not in inventory.use_role:
|
if self.user not in inventory.use_role:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
project_pk = get_pk_from_dict(data, 'project')
|
project = get_value(Project, 'project')
|
||||||
if 'job_type' in data and data['job_type'] == PERM_INVENTORY_SCAN:
|
if 'job_type' in data and data['job_type'] == PERM_INVENTORY_SCAN:
|
||||||
if inventory_pk and inventory.organization:
|
if inventory:
|
||||||
org = inventory.organization
|
org = inventory.organization
|
||||||
accessible = self.user in org.admin_role
|
accessible = self.user in org.admin_role
|
||||||
else:
|
else:
|
||||||
accessible = False
|
accessible = False
|
||||||
if not project_pk and accessible:
|
if not project and accessible:
|
||||||
return True
|
return True
|
||||||
elif not accessible:
|
elif not accessible:
|
||||||
return False
|
return False
|
||||||
# If the user has admin access to the project (as an org admin), should
|
# If the user has admin access to the project (as an org admin), should
|
||||||
# be able to proceed without additional checks.
|
# be able to proceed without additional checks.
|
||||||
if project_pk:
|
if project:
|
||||||
project = get_object_or_400(Project, pk=project_pk)
|
|
||||||
return self.user in project.use_role
|
return self.user in project.use_role
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -195,7 +195,7 @@ def test_org_admin_foreign_cred_no_copy_edit(jt_copy_edit, org_admin, machine_cr
|
|||||||
"""
|
"""
|
||||||
Organization admins without access to the 3 related resources:
|
Organization admins without access to the 3 related resources:
|
||||||
SHOULD NOT be able to copy JT
|
SHOULD NOT be able to copy JT
|
||||||
SHOULD NOT be able to edit that job template
|
SHOULD be able to edit that job template, for nonsensitive changes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Attach credential to JT that org admin can not use
|
# Attach credential to JT that org admin can not use
|
||||||
@ -209,11 +209,13 @@ def test_org_admin_foreign_cred_no_copy_edit(jt_copy_edit, org_admin, machine_cr
|
|||||||
serializer.context['request'] = request
|
serializer.context['request'] = request
|
||||||
response = serializer.to_representation(jt_copy_edit)
|
response = serializer.to_representation(jt_copy_edit)
|
||||||
assert not response['summary_fields']['can_copy']
|
assert not response['summary_fields']['can_copy']
|
||||||
assert not response['summary_fields']['can_edit']
|
assert response['summary_fields']['can_edit']
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_jt_admin_copy_edit(jt_copy_edit, rando):
|
def test_jt_admin_copy_edit(jt_copy_edit, rando):
|
||||||
"JT admins wihout access to associated resources SHOULD NOT be able to copy"
|
"""
|
||||||
|
JT admins wihout access to associated resources SHOULD NOT be able to copy
|
||||||
|
SHOULD be able to make nonsensitive changes"""
|
||||||
|
|
||||||
# random user given JT admin access only
|
# random user given JT admin access only
|
||||||
jt_copy_edit.admin_role.members.add(rando)
|
jt_copy_edit.admin_role.members.add(rando)
|
||||||
@ -226,7 +228,7 @@ def test_jt_admin_copy_edit(jt_copy_edit, rando):
|
|||||||
serializer.context['request'] = request
|
serializer.context['request'] = request
|
||||||
response = serializer.to_representation(jt_copy_edit)
|
response = serializer.to_representation(jt_copy_edit)
|
||||||
assert not response['summary_fields']['can_copy']
|
assert not response['summary_fields']['can_copy']
|
||||||
assert not response['summary_fields']['can_edit']
|
assert response['summary_fields']['can_edit']
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_proj_jt_admin_copy_edit(jt_copy_edit, rando):
|
def test_proj_jt_admin_copy_edit(jt_copy_edit, rando):
|
||||||
|
Loading…
Reference in New Issue
Block a user