mirror of
https://github.com/ansible/awx.git
synced 2026-03-07 19:51:08 -03:30
Merge pull request #6201 from ryanpetrello/new_credential_model
Make CredentialType conditionally editable/readonly
This commit is contained in:
@@ -1857,10 +1857,14 @@ class CredentialTypeSerializer(BaseSerializer):
|
|||||||
if self.instance and self.instance.managed_by_tower:
|
if self.instance and self.instance.managed_by_tower:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
{"detail": _("Modifications not allowed for credential types managed by Tower")})
|
{"detail": _("Modifications not allowed for credential types managed by Tower")})
|
||||||
|
if self.instance and self.instance.credentials.exists():
|
||||||
|
if 'inputs' in attrs and attrs['inputs'] != self.instance.inputs:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{"inputs": _("Modifications to inputs are not allowed for credential types that are in use")})
|
||||||
fields = attrs.get('inputs', {}).get('fields', [])
|
fields = attrs.get('inputs', {}).get('fields', [])
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field.get('ask_at_runtime', False):
|
if field.get('ask_at_runtime', False):
|
||||||
raise serializers.ValidationError({"detail": _("'ask_at_runtime' is not supported for custom credentials.")})
|
raise serializers.ValidationError({"inputs": _("'ask_at_runtime' is not supported for custom credentials.")})
|
||||||
return super(CredentialTypeSerializer, self).validate(attrs)
|
return super(CredentialTypeSerializer, self).validate(attrs)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1504,6 +1504,12 @@ class CredentialTypeDetail(RetrieveUpdateDestroyAPIView):
|
|||||||
new_in_320 = True
|
new_in_320 = True
|
||||||
new_in_api_v2 = True
|
new_in_api_v2 = True
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.managed_by_tower or instance.credentials.exists():
|
||||||
|
raise PermissionDenied(detail=_("Credential types that are in use cannot be deleted."))
|
||||||
|
return super(CredentialTypeDetail, self).destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CredentialList(ListCreateAPIView):
|
class CredentialList(ListCreateAPIView):
|
||||||
|
|
||||||
|
|||||||
@@ -809,8 +809,6 @@ class CredentialTypeAccess(BaseAccess):
|
|||||||
- I'm a superuser:
|
- I'm a superuser:
|
||||||
I can change when:
|
I can change when:
|
||||||
- I'm a superuser and the type is not "managed by Tower"
|
- I'm a superuser and the type is not "managed by Tower"
|
||||||
I can change/delete when:
|
|
||||||
- I'm a superuser and the type is not "managed by Tower"
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
model = CredentialType
|
model = CredentialType
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import json
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from awx.main.models.credential import CredentialType
|
from awx.main.models.credential import CredentialType, Credential
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
|
|
||||||
|
|
||||||
@@ -35,16 +35,55 @@ def test_create_as_unauthorized_xfail(get, post):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_update_as_unauthorized_xfail(patch):
|
def test_update_as_unauthorized_xfail(patch, delete):
|
||||||
ssh = CredentialType.defaults['ssh']()
|
ssh = CredentialType.defaults['ssh']()
|
||||||
ssh.save()
|
ssh.save()
|
||||||
response = patch(
|
url = reverse('api:credential_type_detail', kwargs={'pk': ssh.pk})
|
||||||
reverse('api:credential_type_detail', kwargs={'pk': ssh.pk}),
|
response = patch(url, {'name': 'Some Other Name'})
|
||||||
{
|
|
||||||
'name': 'Some Other Name'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
assert response.status_code == 401
|
assert response.status_code == 401
|
||||||
|
assert delete(url).status_code == 401
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_update_managed_by_tower_xfail(patch, delete, admin):
|
||||||
|
ssh = CredentialType.defaults['ssh']()
|
||||||
|
ssh.save()
|
||||||
|
url = reverse('api:credential_type_detail', kwargs={'pk': ssh.pk})
|
||||||
|
response = patch(url, {'name': 'Some Other Name'}, admin)
|
||||||
|
assert response.status_code == 400
|
||||||
|
assert delete(url, admin).status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_update_credential_type_in_use_xfail(patch, delete, admin):
|
||||||
|
ssh = CredentialType.defaults['ssh']()
|
||||||
|
ssh.managed_by_tower = False
|
||||||
|
ssh.save()
|
||||||
|
Credential(credential_type=ssh, name='My SSH Key').save()
|
||||||
|
|
||||||
|
url = reverse('api:credential_type_detail', kwargs={'pk': ssh.pk})
|
||||||
|
response = patch(url, {'name': 'Some Other Name'}, admin)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
url = reverse('api:credential_type_detail', kwargs={'pk': ssh.pk})
|
||||||
|
response = patch(url, {'inputs': {}}, admin)
|
||||||
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
assert delete(url, admin).status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_update_credential_type_success(get, patch, delete, admin):
|
||||||
|
ssh = CredentialType.defaults['ssh']()
|
||||||
|
ssh.managed_by_tower = False
|
||||||
|
ssh.save()
|
||||||
|
|
||||||
|
url = reverse('api:credential_type_detail', kwargs={'pk': ssh.pk})
|
||||||
|
response = patch(url, {'name': 'Some Other Name'}, admin)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
assert get(url, admin).data.get('name') == 'Some Other Name'
|
||||||
|
assert delete(url, admin).status_code == 204
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
|
|||||||
Reference in New Issue
Block a user