diff --git a/awx/main/access.py b/awx/main/access.py index 06f270701c8f..0d505611974f 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -1623,6 +1623,15 @@ def can_start(self, obj, validate_license=True): return self.user in obj.execute_role def can_change(self, obj, data): + """ + User can modify any JT setting (like diff_mode) that does not involve related objects + - if they have the admin_role to the JT + + If they modify a related project or inventory it becomes more complicated. + - they can set the EE if they have read_role to the EE, irrelevant of current + - they always need use_role to current and new inventory + - they need use_role only to the new project, if changing the project + """ if self.user not in obj.admin_role and not self.user.is_superuser: return False if data is None: @@ -1631,18 +1640,12 @@ def can_change(self, obj, data): data = dict(data) if self.changes_are_non_sensitive(obj, data): return True - if not self.check_related('execution_environment', ExecutionEnvironment, data, obj=obj, role_field='read_role'): - return False - for required_field, cls in (('inventory', Inventory), ('project', Project)): - is_mandatory = True - if not getattr(obj, '{}_id'.format(required_field)): - is_mandatory = False - if not self.check_related(required_field, cls, data, obj=obj, role_field='use_role', mandatory=is_mandatory): - if required_field in data: - new_obj = get_object_from_data(required_field, cls, data) - return self.user in new_obj.use_role and (self.user in obj.inventory.use_role or self.user in obj.project.use_role) - return False - return True + + return bool( + self.check_related('execution_environment', ExecutionEnvironment, data, obj=obj, role_field='read_role') + and self.check_related('inventory', Inventory, data, obj=obj, role_field='use_role', mandatory=True) + and self.check_related('project', Project, data, obj=None, role_field='use_role') + ) def changes_are_non_sensitive(self, obj, data): """ diff --git a/awx/main/tests/functional/test_rbac_job_templates.py b/awx/main/tests/functional/test_rbac_job_templates.py index b92ccc4ad3ed..3772a3f5610d 100644 --- a/awx/main/tests/functional/test_rbac_job_templates.py +++ b/awx/main/tests/functional/test_rbac_job_templates.py @@ -356,12 +356,15 @@ def test_job_template_mixed_permission(rando, bob, project, inventory): # remove use perm on inventory and add use to associated project job_template.inventory.use_role.members.remove(rando) job_template.project.use_role.members.add(rando) + + assert not access.can_change(job_template, {'project': proj1.pk}) # blocked by inventory + proj1.use_role.members.remove(rando) inv1.use_role.members.add(rando) assert not access.can_change(job_template, {'project': proj2.pk}) - assert access.can_change(job_template, {'project': project.pk}) - assert access.can_change(job_template, {'inventory': inv1.pk}) + assert access.can_change(job_template, {'project': job_template.project.pk}) # no change... + assert not access.can_change(job_template, {'inventory': inv1.pk}) # lacks inv1 access # remove project and inventory permission job_template.project.use_role.members.remove(rando)