From 1c74773eacbf11f199b6cb388caa182e1faad7d6 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Thu, 14 Nov 2019 11:10:22 -0500 Subject: [PATCH] Delay inputs comparision to after field validation --- awx/api/serializers.py | 10 ++++-- .../functional/api/test_credential_type.py | 31 ++++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 7bb09c4acf..053dc4cd33 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -2456,12 +2456,18 @@ class CredentialTypeSerializer(BaseSerializer): raise PermissionDenied( detail=_("Modifications not allowed for managed credential types") ) + + old_inputs = {} + if self.instance: + old_inputs = copy.deepcopy(self.instance.inputs) + + ret = super(CredentialTypeSerializer, self).validate(attrs) + if self.instance and self.instance.credentials.exists(): - if 'inputs' in attrs and attrs['inputs'] != self.instance.inputs: + if 'inputs' in attrs and old_inputs != self.instance.inputs: raise PermissionDenied( detail= _("Modifications to inputs are not allowed for credential types that are in use") ) - ret = super(CredentialTypeSerializer, self).validate(attrs) if 'kind' in attrs and attrs['kind'] not in ('cloud', 'net'): raise serializers.ValidationError({ diff --git a/awx/main/tests/functional/api/test_credential_type.py b/awx/main/tests/functional/api/test_credential_type.py index 730b3b03d3..ecb11e7e0d 100644 --- a/awx/main/tests/functional/api/test_credential_type.py +++ b/awx/main/tests/functional/api/test_credential_type.py @@ -85,14 +85,35 @@ def test_update_credential_type_in_use_xfail(patch, delete, admin): Credential(credential_type=_type, name='My Custom Cred').save() url = reverse('api:credential_type_detail', kwargs={'pk': _type.pk}) - response = patch(url, {'name': 'Some Other Name'}, admin) - assert response.status_code == 200 + patch(url, {'name': 'Some Other Name'}, admin, expect=200) url = reverse('api:credential_type_detail', kwargs={'pk': _type.pk}) - response = patch(url, {'inputs': {}}, admin) - assert response.status_code == 403 + response = patch(url, {'inputs': {}}, admin, expect=403) + assert response.data['detail'] == 'Modifications to inputs are not allowed for credential types that are in use' - assert delete(url, admin).status_code == 403 + response = delete(url, admin, expect=403) + assert response.data['detail'] == 'Credential types that are in use cannot be deleted' + + +@pytest.mark.django_db +def test_update_credential_type_unvalidated_inputs(post, patch, admin): + simple_inputs = {'fields': [ + {'id': 'api_token', 'label': 'fooo'} + ]} + response = post( + url=reverse('api:credential_type_list'), + data={'name': 'foo', 'kind': 'cloud', 'inputs': simple_inputs}, + user=admin, + expect=201 + ) + # validation adds the type field to the input + _type = CredentialType.objects.get(pk=response.data['id']) + Credential(credential_type=_type, name='My Custom Cred').save() + + # should not raise an error because we should only compare + # post-validation values to other post-validation values + url = reverse('api:credential_type_detail', kwargs={'pk': _type.id}) + patch(url, {'inputs': simple_inputs}, admin, expect=200) @pytest.mark.django_db