diff --git a/awx/main/access.py b/awx/main/access.py index 7e2289df42..30b2bc1fa4 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -839,10 +839,23 @@ class JobAccess(BaseAccess): if self.user.is_superuser: return qs.all() - return qs.filter( + qs_jt = qs.filter( job_template__in=JobTemplate.accessible_objects(self.user, 'read_role') ) + admin_of_organizations_qs = self.user.admin_of_organizations + if not admin_of_organizations_qs.exists(): + return qs_jt + + qs_scan_orphan = qs.filter( + job_type=PERM_INVENTORY_SCAN, + inventory__organization__in=admin_of_organizations_qs + ) + qs_orphan = qs.filter( + project__organization__in=admin_of_organizations_qs + ).exclude(job_type=PERM_INVENTORY_SCAN) + return (qs_jt | qs_orphan | qs_scan_orphan).distinct() + def can_add(self, data): if not data or '_method' in data: # So the browseable API will work? return True diff --git a/awx/main/tests/functional/test_rbac_job.py b/awx/main/tests/functional/test_rbac_job.py new file mode 100644 index 0000000000..4a176062d5 --- /dev/null +++ b/awx/main/tests/functional/test_rbac_job.py @@ -0,0 +1,30 @@ +import pytest + +from awx.main.access import JobAccess +from awx.main.models import Job + + +@pytest.fixture +def orphan_job(deploy_jobtemplate): + return Job.objects.create( + job_template=None, + project=deploy_jobtemplate.project, + inventory=deploy_jobtemplate.inventory + ) + +@pytest.mark.django_db +def test_superuser_sees_orphans(admin_user, orphan_job): + access = JobAccess(admin_user) + assert access.can_read(orphan_job) + +@pytest.mark.django_db +def test_org_member_does_not_see_orphans(org_member, orphan_job, project): + # Check that privledged access to project still does not grant access + project.admin_role.members.add(org_member) + access = JobAccess(org_member) + assert not access.can_read(orphan_job) + +@pytest.mark.django_db +def test_org_admin_sees_orphans(org_admin, orphan_job): + access = JobAccess(org_admin) + assert access.can_read(orphan_job)