diff --git a/awx/api/generics.py b/awx/api/generics.py index 3ee486c79a..cce3800deb 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -26,11 +26,10 @@ from rest_framework import views from awx.main.models import * from awx.main.utils import * -# FIXME: machinery for auto-adding audit trail logs to all CREATE/EDITS - -__all__ = ['APIView', 'GenericAPIView', 'ListAPIView', 'SimpleListAPIView', 'ListCreateAPIView', - 'SubListAPIView', 'SubListCreateAPIView', 'RetrieveAPIView', - 'RetrieveUpdateAPIView', 'RetrieveUpdateDestroyAPIView'] +__all__ = ['APIView', 'GenericAPIView', 'ListAPIView', 'SimpleListAPIView', + 'ListCreateAPIView', 'SubListAPIView', 'SubListCreateAPIView', + 'RetrieveAPIView', 'RetrieveUpdateAPIView', + 'RetrieveDestroyAPIView', 'RetrieveUpdateDestroyAPIView'] def get_view_name(cls, suffix=None): ''' @@ -433,7 +432,7 @@ class RetrieveUpdateAPIView(RetrieveAPIView, generics.RetrieveUpdateAPIView): ''' scrub any fields the user cannot/should not put/patch, based on user context. This runs after read-only serialization filtering ''' pass -class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, generics.RetrieveUpdateDestroyAPIView): +class RetrieveDestroyAPIView(RetrieveAPIView, generics.RetrieveDestroyAPIView): def destroy(self, request, *args, **kwargs): # somewhat lame that delete has to call it's own permissions check @@ -450,3 +449,6 @@ class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, generics.RetrieveUpdat else: raise NotImplementedError('destroy() not implemented yet for %s' % obj) return Response(status=status.HTTP_204_NO_CONTENT) + +class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, RetrieveDestroyAPIView): + pass diff --git a/awx/api/templates/api/retrieve_destroy_api_view.md b/awx/api/templates/api/retrieve_destroy_api_view.md new file mode 100644 index 0000000000..7058234f60 --- /dev/null +++ b/awx/api/templates/api/retrieve_destroy_api_view.md @@ -0,0 +1,12 @@ +# Retrieve {{ model_verbose_name|title }}: + +Make GET request to this resource to retrieve a single {{ model_verbose_name }} +record containing the following fields: + +{% include "api/_result_fields_common.md" %} + +# Delete {{ model_verbose_name|title }}: + +Make a DELETE request to this resource to delete this {{ model_verbose_name }}. + +{% include "api/_new_in_awx.md" %} diff --git a/awx/api/templates/api/retrieve_update_api_view.md b/awx/api/templates/api/retrieve_update_api_view.md index 2a0b5f6248..dd5e00d5be 100644 --- a/awx/api/templates/api/retrieve_update_api_view.md +++ b/awx/api/templates/api/retrieve_update_api_view.md @@ -1,4 +1,9 @@ -{% include "api/retrieve_api_view.md" %} +# Retrieve {{ model_verbose_name|title }}: + +Make GET request to this resource to retrieve a single {{ model_verbose_name }} +record containing the following fields: + +{% include "api/_result_fields_common.md" %} # Update {{ model_verbose_name|title }}: diff --git a/awx/api/templates/api/retrieve_update_destroy_api_view.md b/awx/api/templates/api/retrieve_update_destroy_api_view.md index b90fc4bbfd..826fd430f8 100644 --- a/awx/api/templates/api/retrieve_update_destroy_api_view.md +++ b/awx/api/templates/api/retrieve_update_destroy_api_view.md @@ -1,4 +1,9 @@ -{% include "api/retrieve_api_view.md" %} +# Retrieve {{ model_verbose_name|title }}: + +Make GET request to this resource to retrieve a single {{ model_verbose_name }} +record containing the following fields: + +{% include "api/_result_fields_common.md" %} # Update {{ model_verbose_name|title }}: diff --git a/awx/api/views.py b/awx/api/views.py index 82feabe415..40abba8067 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -500,7 +500,7 @@ class ProjectUpdateView(GenericAPIView): else: return self.http_method_not_allowed(request, *args, **kwargs) -class ProjectUpdateDetail(RetrieveAPIView): +class ProjectUpdateDetail(RetrieveDestroyAPIView): model = ProjectUpdate serializer_class = ProjectUpdateSerializer @@ -1064,7 +1064,7 @@ class InventorySourceUpdateView(GenericAPIView): else: return self.http_method_not_allowed(request, *args, **kwargs) -class InventoryUpdateDetail(RetrieveAPIView): +class InventoryUpdateDetail(RetrieveDestroyAPIView): model = InventoryUpdate serializer_class = InventoryUpdateSerializer diff --git a/awx/main/access.py b/awx/main/access.py index 19ce274548..85ff2380ea 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -482,6 +482,7 @@ class InventoryUpdateAccess(BaseAccess): ''' I can see inventory updates when I can see the inventory source. I can change inventory updates whenever I can change their source. + I can delete when I can change/delete the inventory source. ''' model = InventoryUpdate @@ -673,6 +674,7 @@ class ProjectUpdateAccess(BaseAccess): ''' I can see project updates when I can see the project. I can change when I can change the project. + I can delete when I can change/delete the project. ''' model = ProjectUpdate diff --git a/awx/main/tests/inventory.py b/awx/main/tests/inventory.py index 5bc256a251..d73065e550 100644 --- a/awx/main/tests/inventory.py +++ b/awx/main/tests/inventory.py @@ -1094,6 +1094,12 @@ class InventoryUpdatesTest(BaseTransactionTest): }) response = self.put(inv_src_url2, data, expect=400) self.assertTrue('source' in response, response) + # Make sure we can delete the inventory update. + inv_up_url = reverse('api:inventory_update_detail', args=(inventory_update.pk,)) + with self.current_user(self.super_django_user): + self.get(inv_up_url, expect=200) + self.delete(inv_up_url, expect=204) + self.get(inv_up_url, expect=404) def test_put_inventory_source_detail_with_regions(self): creds_url = reverse('api:credential_list') diff --git a/awx/main/tests/projects.py b/awx/main/tests/projects.py index 91ebe17b81..b6c83694fb 100644 --- a/awx/main/tests/projects.py +++ b/awx/main/tests/projects.py @@ -1160,6 +1160,11 @@ class ProjectUpdatesTest(BaseTransactionTest): self.check_project_update(project, should_fail=True)#should_still_fail) else: self.check_project_update(project, should_fail=should_still_fail) + # Test that we can delete project updates. + for pu in project.project_updates.filter(active=True): + pu_url = reverse('api:project_update_detail', args=(pu.pk,)) + with self.current_user(self.super_django_user): + self.delete(pu_url, expect=204) def test_create_project_with_scm(self): scm_url = getattr(settings, 'TEST_GIT_PUBLIC_HTTPS',