From de4e95f39617b08045596483da004294b3b2a4ec Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Wed, 21 Feb 2018 09:25:43 -0500 Subject: [PATCH 1/2] correct permission check for job rescheduling --- awx/api/views.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/awx/api/views.py b/awx/api/views.py index 5a6aebebc1..c06ca42c7a 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -4095,8 +4095,6 @@ class JobCreateSchedule(RetrieveAPIView): status=status.HTTP_400_BAD_REQUEST) config = obj.launch_config - if not request.user.can_access(JobLaunchConfig, 'add', {'reference_obj': obj}): - raise PermissionDenied() # Make up a name for the schedule, guarentee that it is unique name = 'Auto-generated schedule from job {}'.format(obj.id) @@ -4109,7 +4107,7 @@ class JobCreateSchedule(RetrieveAPIView): alt_name = '{} - number {}'.format(name, idx) name = alt_name - schedule = Schedule.objects.create( + schedule_data = dict( name=name, unified_job_template=obj.unified_job_template, enabled=False, @@ -4117,11 +4115,18 @@ class JobCreateSchedule(RetrieveAPIView): extra_data=config.extra_data, survey_passwords=config.survey_passwords, inventory=config.inventory, - char_prompts=config.char_prompts + char_prompts=config.char_prompts, + credentials=set(config.credentials.all()) ) - schedule.credentials.add(*config.credentials.all()) + if not request.user.can_access(Schedule, 'add', schedule_data): + raise PermissionDenied() + + creds_list = schedule_data.pop('credentials') + schedule = Schedule.objects.create(**schedule_data) + schedule.credentials.add(*creds_list) data = ScheduleSerializer(schedule, context=self.get_serializer_context()).data + data.serializer.instance = None # hack to avoid permissions.py assuming this is Job model headers = {'Location': schedule.get_absolute_url(request=request)} return Response(data, status=status.HTTP_201_CREATED, headers=headers) From 992d7831b182d44e763e9f1489bb06d1e235db5a Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Wed, 21 Feb 2018 13:40:23 -0500 Subject: [PATCH 2/2] add test for ScheduleAccess prompts --- .../functional/test_rbac_job_templates.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/awx/main/tests/functional/test_rbac_job_templates.py b/awx/main/tests/functional/test_rbac_job_templates.py index 34a6b06e97..a12bc31b70 100644 --- a/awx/main/tests/functional/test_rbac_job_templates.py +++ b/awx/main/tests/functional/test_rbac_job_templates.py @@ -275,3 +275,24 @@ class TestJobTemplateSchedules: schedule = Schedule.objects.create(unified_job_template=job_template, rrule=self.rrule, created_by=rando) access = ScheduleAccess(rando) assert access.can_change(schedule, {'rrule': self.rrule2}) + + def test_prompts_access_checked(self, job_template, inventory, credential, rando): + job_template.execute_role.members.add(rando) + access = ScheduleAccess(rando) + data = dict( + unified_job_template=job_template, + rrule=self.rrule, + created_by=rando, + inventory=inventory, + credentials=[credential] + ) + with mock.patch('awx.main.access.JobLaunchConfigAccess.can_add') as mock_add: + mock_add.return_value = True + assert access.can_add(data) + mock_add.assert_called_once_with(data) + data.pop('credentials') + schedule = Schedule.objects.create(**data) + with mock.patch('awx.main.access.JobLaunchConfigAccess.can_change') as mock_change: + mock_change.return_value = True + assert access.can_change(schedule, {'inventory': 42}) + mock_change.assert_called_once_with(schedule, {'inventory': 42})