def test_jt_admin_copy_edit(self, jt_copy_edit, rando): """ JT admins wihout access to associated resources SHOULD NOT be able to copy SHOULD be able to make nonsensitive changes""" # random user given JT admin access only jt_copy_edit.admin_role.members.add(rando) jt_copy_edit.save() serializer = JobTemplateSerializer(jt_copy_edit, context=self.fake_context(rando)) response = serializer.to_representation(jt_copy_edit) assert not response['summary_fields']['user_capabilities']['copy'] assert response['summary_fields']['user_capabilities']['edit']
def test_proj_jt_admin_copy_edit(self, jt_copy_edit, rando): "JT admins with access to associated resources SHOULD be able to copy" # random user given JT and project admin abilities jt_copy_edit.admin_role.members.add(rando) jt_copy_edit.save() jt_copy_edit.project.admin_role.members.add(rando) jt_copy_edit.project.save() serializer = JobTemplateSerializer(jt_copy_edit, context=self.fake_context(rando)) response = serializer.to_representation(jt_copy_edit) assert response['summary_fields']['user_capabilities']['copy'] assert response['summary_fields']['user_capabilities']['edit']
def test_job_template_vault_cred_check(self, mocker, job_template, vault_credential, rando, project): # TODO: remove in 3.3 job_template.admin_role.members.add(rando) # not allowed to use the vault cred # this is checked in the serializer validate method, not access.py view = mocker.MagicMock() view.request = mocker.MagicMock() view.request.user = rando serializer = JobTemplateSerializer(job_template, context={'view': view}) with pytest.raises(PermissionDenied): serializer.validate({ 'vault_credential': vault_credential.pk, 'project': project, # necessary because job_template fixture fails validation 'ask_inventory_on_launch': True, })
def test_new_jt_with_vault(self, mocker, vault_credential, project, rando): project.admin_role.members.add(rando) # TODO: remove in 3.3 # this is checked in the serializer validate method, not access.py view = mocker.MagicMock() view.request = mocker.MagicMock() view.request.user = rando serializer = JobTemplateSerializer(context={'view': view}) with pytest.raises(PermissionDenied): serializer.validate({ 'vault_credential': vault_credential.pk, 'project': project, 'playbook': 'helloworld.yml', 'ask_inventory_on_launch': True, 'name': 'asdf' })
def test_validation_bad_data_copy_edit(self, admin_user, project): """ If a required resource (inventory here) was deleted, copying not allowed because doing so would caues a validation error """ jt_res = JobTemplate.objects.create( job_type='run', project=project, inventory=None, ask_inventory_on_launch=False, # not allowed ask_credential_on_launch=True, name='deploy-job-template' ) serializer = JobTemplateSerializer(jt_res, context=self.fake_context(admin_user)) response = serializer.to_representation(jt_res) assert not response['summary_fields']['user_capabilities']['copy'] assert response['summary_fields']['user_capabilities']['edit']
def test_job_template_vault_cred_check_noop(self, mocker, job_template, vault_credential, rando, project): # TODO: remove in 3.4 job_template.credentials.add(vault_credential) job_template.admin_role.members.add(rando) # not allowed to use the vault cred # this is checked in the serializer validate method, not access.py view = mocker.MagicMock() view.request = mocker.MagicMock() view.request.user = rando serializer = JobTemplateSerializer(job_template, context={'view': view}) # should not raise error: serializer.validate({ 'vault_credential': vault_credential.pk, 'project': project, # necessary because job_template fixture fails validation 'playbook': 'helloworld.yml', 'ask_inventory_on_launch': True, })
def test_org_admin_foreign_cred_no_copy_edit(self, jt_copy_edit, org_admin, machine_credential): """ Organization admins without access to the 3 related resources: SHOULD NOT be able to copy JT SHOULD be able to edit that job template, for nonsensitive changes """ # Attach credential to JT that org admin cannot use jt_copy_edit.credential = machine_credential jt_copy_edit.save() serializer = JobTemplateSerializer(jt_copy_edit) serializer.context = self.fake_context(org_admin) response = serializer.to_representation(jt_copy_edit) assert not response['summary_fields']['user_capabilities']['copy'] assert response['summary_fields']['user_capabilities']['edit']
def test__recent_jobs(self, mocker, job_template, jobs): job_template.jobs.all = mocker.MagicMock( **{'order_by.return_value': jobs}) job_template.jobs.all.return_value = job_template.jobs.all serializer = JobTemplateSerializer() recent_jobs = serializer._recent_jobs(job_template) job_template.jobs.all.assert_called_once_with() job_template.jobs.all.order_by.assert_called_once_with('-created') assert len(recent_jobs) == 10 for x in jobs[:10]: assert recent_jobs == [{ 'id': x.id, 'status': x.status, 'finished': x.finished } for x in jobs[:10]]
def test_jt_deprecated_summary_fields(project, inventory, machine_credential, net_credential, vault_credential, mocker): jt = JobTemplate.objects.create(project=project, inventory=inventory, playbook='helloworld.yml') class MockView: kwargs = {} request = None class MockRequest: version = 'v1' user = None view = MockView() request = MockRequest() view.request = request serializer = JobTemplateSerializer(instance=jt, context={ 'view': view, 'request': request }) for kwargs in [{}, {'pk': 1}]: # detail vs. list view for version in ['v1', 'v2']: view.kwargs = kwargs request.version = version sf = serializer.get_summary_fields(jt) assert 'credential' not in sf assert 'vault_credential' not in sf jt.credentials.add(machine_credential, net_credential, vault_credential) view.kwargs = {'pk': 1} for version in ['v1', 'v2']: request.version = version sf = serializer.get_summary_fields(jt) assert 'credential' in sf assert sf['credential'] # not empty dict assert 'vault_credential' in sf assert sf['vault_credential']
def test_copy_edit_standard(self, mocker, job_template_factory): """Verify that the exact output of the access.py methods are put into the serializer user_capabilities""" jt_obj = job_template_factory('testJT', project='proj1', persisted=False).job_template jt_obj.id = 5 jt_obj.admin_role = Role(id=9, role_field='admin_role') jt_obj.execute_role = Role(id=8, role_field='execute_role') jt_obj.read_role = Role(id=7, role_field='execute_role') user = User(username="******") serializer = JobTemplateSerializer(job_template) serializer.show_capabilities = ['copy', 'edit'] serializer._summary_field_labels = lambda self: [] serializer._recent_jobs = lambda self: [] request = APIRequestFactory().get('/api/v2/job_templates/42/') request.user = user view = JobTemplateDetail() view.request = request view.kwargs = {} serializer.context['view'] = view with mocker.patch("awx.api.serializers.role_summary_fields_generator", return_value='Can eat pie'): with mocker.patch("awx.main.access.JobTemplateAccess.can_change", return_value='foobar'): with mocker.patch("awx.main.access.JobTemplateAccess.can_add", return_value='foo'): with mock.patch.object(jt_obj.__class__, 'get_deprecated_credential', return_value=None): response = serializer.get_summary_fields(jt_obj) assert response['user_capabilities']['copy'] == 'foo' assert response['user_capabilities']['edit'] == 'foobar'
def test_sys_admin_copy_edit(self, jt_copy_edit, admin_user): "Absent a validation error, system admins can do everything" serializer = JobTemplateSerializer(jt_copy_edit, context=self.fake_context(admin_user)) response = serializer.to_representation(jt_copy_edit) assert response['summary_fields']['user_capabilities']['copy'] assert response['summary_fields']['user_capabilities']['edit']
def test_org_admin_copy_edit(self, jt_copy_edit, org_admin): "Organization admins SHOULD be able to copy a JT firmly in their org" serializer = JobTemplateSerializer(jt_copy_edit, context=self.fake_context(org_admin)) response = serializer.to_representation(jt_copy_edit) assert response['summary_fields']['user_capabilities']['copy'] assert response['summary_fields']['user_capabilities']['edit']