1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 08:21:15 +03:00

Merge pull request #2647 from AlanCoding/jt_can_add_betterment

A route around get_object_or_400 in JT can_add calcs
This commit is contained in:
Alan Rominger 2016-06-28 14:31:44 -04:00 committed by GitHub
commit 513e6c993f
3 changed files with 33 additions and 27 deletions

View File

@ -23,7 +23,6 @@ from django.db import models
# from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text
from django.utils.text import capfirst
from django.forms.models import model_to_dict
# Django REST Framework
from rest_framework.exceptions import ValidationError
@ -1849,9 +1848,8 @@ class JobTemplateSerializer(UnifiedJobTemplateSerializer, JobOptionsSerializer):
d['can_copy'] = not validation_errors
d['can_edit'] = True
else:
jt_data = model_to_dict(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, jt_data)
d['can_copy'] = (not validation_errors) and request.user.can_access(JobTemplate, 'add', {"reference_obj": obj})
d['can_edit'] = request.user.can_access(JobTemplate, 'change', obj, {})
d['recent_jobs'] = self._recent_jobs(obj)
return d

View File

@ -788,6 +788,9 @@ class JobTemplateAccess(BaseAccess):
if not data or '_method' in data: # So the browseable API will work?
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:
self.check_license(feature='system_tracking')
@ -797,51 +800,54 @@ class JobTemplateAccess(BaseAccess):
if self.user.is_superuser:
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.
credential_pk = get_pk_from_dict(data, 'credential')
if credential_pk:
credential = get_object_or_400(Credential, pk=credential_pk)
credential = get_value(Credential, 'credential')
if credential:
if self.user not in credential.use_role:
return False
# If a cloud credential is provided, the user should have use access.
cloud_credential_pk = get_pk_from_dict(data, 'cloud_credential')
if cloud_credential_pk:
cloud_credential = get_object_or_400(Credential,
pk=cloud_credential_pk)
cloud_credential = get_value(Credential, 'cloud_credential')
if cloud_credential:
if self.user not in cloud_credential.use_role:
return False
# If a network credential is provided, the user should have use access.
network_credential_pk = get_pk_from_dict(data, 'network_credential')
if network_credential_pk:
network_credential = get_object_or_400(Credential,
pk=network_credential_pk)
network_credential = get_value(Credential, 'network_credential')
if network_credential:
if self.user not in network_credential.use_role:
return False
# If an inventory is provided, the user should have use access.
inventory_pk = get_pk_from_dict(data, 'inventory')
if inventory_pk:
inventory = get_object_or_400(Inventory, pk=inventory_pk)
inventory = get_value(Inventory, 'inventory')
if inventory:
if self.user not in inventory.use_role:
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 inventory_pk and inventory.organization:
if inventory:
org = inventory.organization
accessible = self.user in org.admin_role
else:
accessible = False
if not project_pk and accessible:
if not project and accessible:
return True
elif not accessible:
return False
# If the user has admin access to the project (as an org admin), should
# be able to proceed without additional checks.
if project_pk:
project = get_object_or_400(Project, pk=project_pk)
if project:
return self.user in project.use_role
else:
return False

View File

@ -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:
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
@ -209,11 +209,13 @@ def test_org_admin_foreign_cred_no_copy_edit(jt_copy_edit, org_admin, machine_cr
serializer.context['request'] = request
response = serializer.to_representation(jt_copy_edit)
assert not response['summary_fields']['can_copy']
assert not response['summary_fields']['can_edit']
assert response['summary_fields']['can_edit']
@pytest.mark.django_db
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
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
response = serializer.to_representation(jt_copy_edit)
assert not response['summary_fields']['can_copy']
assert not response['summary_fields']['can_edit']
assert response['summary_fields']['can_edit']
@pytest.mark.django_db
def test_proj_jt_admin_copy_edit(jt_copy_edit, rando):