diff --git a/awx/main/access.py b/awx/main/access.py index e0274e1fdf..29778b05d6 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -2429,6 +2429,11 @@ class ScheduleAccess(BaseAccess): def can_add(self, data): if not JobLaunchConfigAccess(self.user).can_add(data): return False + if not data: + return UnifiedJobTemplate.accessible_pk_qs( + self.user, 'execute_role' + ).exists() + return self.check_related('unified_job_template', UnifiedJobTemplate, data, role_field='execute_role', mandatory=True) @check_superuser diff --git a/awx/main/tests/functional/api/test_schedules.py b/awx/main/tests/functional/api/test_schedules.py index bdb3534fb3..bae83ef93e 100644 --- a/awx/main/tests/functional/api/test_schedules.py +++ b/awx/main/tests/functional/api/test_schedules.py @@ -365,3 +365,43 @@ def test_zoneinfo(get, admin_user): url = reverse('api:schedule_zoneinfo') r = get(url, admin_user, expect=200) assert {'name': 'America/New_York'} in r.data + + +@pytest.mark.django_db +def test_normal_user_can_create_ujt_schedule(options, post, project, inventory, alice): + jt1 = JobTemplate.objects.create( + name='test-jt', + project=project, + playbook='helloworld.yml', + inventory=inventory + ) + jt1.save() + url = reverse('api:schedule_list') + + # can't create a schedule on JT1 because we don't have execute rights + params = { + 'name': 'My Example Schedule', + 'rrule': RRULE_EXAMPLE, + 'unified_job_template': jt1.id, + } + assert 'POST' not in options(url, user=alice).data['actions'].keys() + post(url, params, alice, expect=403) + + # now we can, because we're allowed to execute JT1 + jt1.execute_role.members.add(alice) + assert 'POST' in options(url, user=alice).data['actions'].keys() + post(url, params, alice, expect=201) + + # can't create a schedule on JT2 because we don't have execute rights + jt2 = JobTemplate.objects.create( + name='test-jt-2', + project=project, + playbook='helloworld.yml', + inventory=inventory + ) + jt2.save() + post(url, { + 'name': 'My Example Schedule', + 'rrule': RRULE_EXAMPLE, + 'unified_job_template': jt2.id, + }, alice, expect=403)