diff --git a/awx/main/access.py b/awx/main/access.py index d2a2aa9f3b..cdb0c0eb53 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -777,6 +777,11 @@ class OrganizationAccess(NotificationAttachMixin, BaseAccess): @check_superuser def can_change(self, obj, data): + if data and data.get('default_environment'): + ee = get_object_from_data('default_environment', ExecutionEnvironment, data) + if not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + return self.user in obj.admin_role def can_delete(self, obj): @@ -1385,14 +1390,29 @@ class ProjectAccess(NotificationAttachMixin, BaseAccess): def can_add(self, data): if not data: # So the browseable API will work return Organization.accessible_objects(self.user, 'project_admin_role').exists() - return (self.check_related('organization', Organization, data, role_field='project_admin_role', mandatory=True) and - self.check_related('credential', Credential, data, role_field='use_role')) + + if data.get('default_environment'): + ee = get_object_from_data('default_environment', ExecutionEnvironment, data) + if not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + + return ( + self.check_related('organization', Organization, data, role_field='project_admin_role', mandatory=True) and + self.check_related('credential', Credential, data, role_field='use_role') + ) @check_superuser def can_change(self, obj, data): - return (self.check_related('organization', Organization, data, obj=obj, role_field='project_admin_role') and - self.user in obj.admin_role and - self.check_related('credential', Credential, data, obj=obj, role_field='use_role')) + if data and data.get('default_environment'): + ee = get_object_from_data('default_environment', ExecutionEnvironment, data, obj=obj) + if not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + + return ( + self.check_related('organization', Organization, data, obj=obj, role_field='project_admin_role') and + self.user in obj.admin_role and + self.check_related('credential', Credential, data, obj=obj, role_field='use_role') + ) @check_superuser def can_start(self, obj, validate_license=True): @@ -1497,6 +1517,10 @@ class JobTemplateAccess(NotificationAttachMixin, BaseAccess): if self.user not in inventory.use_role: return False + ee = get_value(ExecutionEnvironment, 'execution_environment') + if ee and not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + project = get_value(Project, 'project') # If the user has admin access to the project (as an org admin), should # be able to proceed without additional checks. @@ -1544,6 +1568,11 @@ class JobTemplateAccess(NotificationAttachMixin, BaseAccess): if self.changes_are_non_sensitive(obj, data): return True + if data.get('execution_environment'): + ee = get_object_from_data('execution_environment', ExecutionEnvironment, data) + if not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + for required_field, cls in (('inventory', Inventory), ('project', Project)): is_mandatory = True if not getattr(obj, '{}_id'.format(required_field)): @@ -1974,6 +2003,11 @@ class WorkflowJobTemplateAccess(NotificationAttachMixin, BaseAccess): if not data: # So the browseable API will work return Organization.accessible_objects(self.user, 'workflow_admin_role').exists() + if data.get('execution_environment'): + ee = get_object_from_data('execution_environment', ExecutionEnvironment, data) + if not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + return ( self.check_related('organization', Organization, data, role_field='workflow_admin_role', mandatory=True) and self.check_related('inventory', Inventory, data, role_field='use_role') @@ -2023,6 +2057,11 @@ class WorkflowJobTemplateAccess(NotificationAttachMixin, BaseAccess): if self.user.is_superuser: return True + if data and data.get('execution_environment'): + ee = get_object_from_data('execution_environment', ExecutionEnvironment, data) + if not self.user.can_access(ExecutionEnvironment, 'read', ee): + return False + return ( self.check_related('organization', Organization, data, role_field='workflow_admin_role', obj=obj) and self.check_related('inventory', Inventory, data, role_field='use_role', obj=obj) and