diff --git a/awx/ui/client/src/access/rbac-role-column/roleList.directive.js b/awx/ui/client/src/access/rbac-role-column/roleList.directive.js index 0ee778939f..fe7472ce65 100644 --- a/awx/ui/client/src/access/rbac-role-column/roleList.directive.js +++ b/awx/ui/client/src/access/rbac-role-column/roleList.directive.js @@ -21,9 +21,40 @@ export default })) .concat(scope.deleteTarget.summary_fields .indirect_access.map((i) => { - i.role.explicit = false; - return i.role; + // Indirect access roles describe the role on another object that + // gives the user access to this object, so we must introspect them. + // + // If the user has indirect admin access, they are system admin, org admin, + // or a _admin. Return the role name directly. + if (i.descendant_roles.includes('admin_role')) { + i.role.explicit = false; + return i.role; + } + // Return other specific roles that grant read access + if (i.role.name.includes('Auditor')) { + i.role.explicit = false; + return i.role; + } + // Handle more complex cases + // This includes roles team<->team roles, and roles an org admin + // inherits from teams in their organization. + // + // For these, we want to describe the actual permissions for the + // object we are retrieving the access_list for, so replace + // the role name with the descendant_roles. + let indirect_roles = []; + i.descendant_roles.forEach((descendant_role) => { + let r = _.cloneDeep(i.role); + r.name = descendant_role.replace('_role',''); + r.explicit = false; + // Do not include the read role unless it is the only descendant role. + if (r.name !== 'read' || i.descendant_roles.length === 1) { + indirect_roles.push(r); + } + }); + return indirect_roles; })) + .flat() .filter((role) => { return Boolean(attrs.teamRoleList) === Boolean(role.team_id); })