diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 31dd96469b..618e3c2aea 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1588,18 +1588,6 @@ class ResourceAccessListElementSerializer(UserSerializer): class CredentialSerializer(BaseSerializer): # FIXME: may want to make some fields filtered based on user accessing - user = serializers.PrimaryKeyRelatedField( - queryset=User.objects.all(), required=False, default=None, write_only=True, - help_text='Write-only field used to add user to owner role. If provided, ' - 'do not give either team or organization. Only valid for creation.') - team = serializers.PrimaryKeyRelatedField( - queryset=Team.objects.all(), required=False, default=None, write_only=True, - help_text='Write-only field used to add team to owner role. If provided, ' - 'do not give either user or organization. Only valid for creation.') - organization = serializers.PrimaryKeyRelatedField( - queryset=Organization.objects.all(), required=False, default=None, write_only=True, - help_text='Write-only field used to add organization to owner role. If provided, ' - 'do not give either team or team. Only valid for creation.') class Meta: model = Credential @@ -1608,14 +1596,7 @@ class CredentialSerializer(BaseSerializer): 'ssh_key_data', 'ssh_key_unlock', 'become_method', 'become_username', 'become_password', 'vault_password', 'subscription', 'tenant', 'secret', 'client', - 'authorize', 'authorize_password', - 'user', 'team', 'organization') - - def create(self, validated_data): - # Remove the user, team, and organization processed in view - for field in ['user', 'team', 'organization']: - validated_data.pop(field, None) - return super(CredentialSerializer, self).create(validated_data) + 'authorize', 'authorize_password') def build_standard_field(self, field_name, model_field): field_class, field_kwargs = super(CredentialSerializer, self).build_standard_field(field_name, model_field) @@ -1665,6 +1646,35 @@ class CredentialSerializer(BaseSerializer): return summary_dict +class CredentialSerializerCreate(CredentialSerializer): + + user = serializers.PrimaryKeyRelatedField( + queryset=User.objects.all(), + required=False, default=None, write_only=True, allow_null=True, + help_text='Write-only field used to add user to owner role. If provided, ' + 'do not give either team or organization. Only valid for creation.') + team = serializers.PrimaryKeyRelatedField( + queryset=Team.objects.all(), + required=False, default=None, write_only=True, allow_null=True, + help_text='Write-only field used to add team to owner role. If provided, ' + 'do not give either user or organization. Only valid for creation.') + organization = serializers.PrimaryKeyRelatedField( + queryset=Organization.objects.all(), + required=False, default=None, write_only=True, allow_null=True, + help_text='Write-only field used to add organization to owner role. If provided, ' + 'do not give either team or team. Only valid for creation.') + + class Meta: + model = Credential + fields = ('*', 'user', 'team', 'organization') + + def create(self, validated_data): + # Remove the user, team, and organization processed in view + for field in ['user', 'team', 'organization']: + validated_data.pop(field, None) + return super(CredentialSerializer, self).create(validated_data) + + class JobOptionsSerializer(BaseSerializer): class Meta: diff --git a/awx/api/views.py b/awx/api/views.py index ed85173328..5ba7b5e56e 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -1256,9 +1256,14 @@ class UserAccessList(ResourceAccessList): class CredentialList(ListCreateAPIView): model = Credential - serializer_class = CredentialSerializer + serializer_class = CredentialSerializerCreate def post(self, request, *args, **kwargs): + + # Check the validity of POST data, including special fields + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + for field in [x for x in ['user', 'team', 'organization'] if x in request.data and request.data[x] in ('', None)]: request.data.pop(field) kwargs.pop(field, None) diff --git a/awx/main/tests/functional/api/test_credential.py b/awx/main/tests/functional/api/test_credential.py index c122262bc3..afe3bb7f29 100644 --- a/awx/main/tests/functional/api/test_credential.py +++ b/awx/main/tests/functional/api/test_credential.py @@ -21,6 +21,16 @@ def test_create_user_credential_via_credentials_list(post, get, alice): assert response.status_code == 200 assert response.data['count'] == 1 +@pytest.mark.django_db +def test_credential_validation_error_with_bad_user(post, admin): + response = post(reverse('api:credential_list'), { + 'user': 'asdf', + 'name': 'Some name', + 'username': 'someusername' + }, admin) + assert response.status_code == 400 + assert response.data['user'][0] == 'Incorrect type. Expected pk value, received unicode.' + @pytest.mark.django_db def test_create_user_credential_via_user_credentials_list(post, get, alice): response = post(reverse('api:user_credentials_list', args=(alice.pk,)), {