diff --git a/awx/api/views.py b/awx/api/views.py index fdce0b9f3b..eebc1f7b24 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -2358,7 +2358,7 @@ class HostAdHocCommandsList(AdHocCommandList, SubListCreateAPIView): relationship = 'ad_hoc_commands' -class AdHocCommandDetail(RetrieveAPIView): +class AdHocCommandDetail(RetrieveDestroyAPIView): model = AdHocCommand serializer_class = AdHocCommandSerializer diff --git a/awx/main/access.py b/awx/main/access.py index c487187941..cd63cc41e4 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -1226,7 +1226,7 @@ class AdHocCommandAccess(BaseAccess): return False def can_delete(self, obj): - return False + return self.can_read(obj) def can_start(self, obj): return self.can_add({ diff --git a/awx/main/tests/ad_hoc.py b/awx/main/tests/ad_hoc.py index 2b729a17ba..00d87ece66 100644 --- a/awx/main/tests/ad_hoc.py +++ b/awx/main/tests/ad_hoc.py @@ -560,12 +560,14 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): def test_ad_hoc_command_detail(self): with self.current_user('admin'): - response = self.run_test_ad_hoc_command() + response1 = self.run_test_ad_hoc_command() + response2 = self.run_test_ad_hoc_command() + response3 = self.run_test_ad_hoc_command() # Retrieve detail for ad hoc command. Only GET is supported. - url = reverse('api:ad_hoc_command_detail', args=(response['id'],)) - self.assertEqual(url, response['url']) with self.current_user('admin'): + url = reverse('api:ad_hoc_command_detail', args=(response1['id'],)) + self.assertEqual(url, response1['url']) response = self.get(url, expect=200) self.assertEqual(response['credential'], self.credential.pk) self.assertEqual(response['related']['credential'], @@ -580,22 +582,28 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): self.assertTrue(response['related']['activity_stream']) self.put(url, {}, expect=405) self.patch(url, {}, expect=405) - self.delete(url, expect=405) + self.delete(url, expect=204) + self.delete(url, expect=404) with self.current_user('normal'): + url = reverse('api:ad_hoc_command_detail', args=(response2['id'],)) + self.assertEqual(url, response2['url']) response = self.get(url, expect=200) self.put(url, {}, expect=405) self.patch(url, {}, expect=405) - self.delete(url, expect=405) + self.delete(url, expect=204) + self.delete(url, expect=404) + url = reverse('api:ad_hoc_command_detail', args=(response3['id'],)) + self.assertEqual(url, response3['url']) with self.current_user('other'): response = self.get(url, expect=403) self.put(url, {}, expect=405) self.patch(url, {}, expect=405) - self.delete(url, expect=405) + self.delete(url, expect=403) with self.current_user('nobody'): response = self.get(url, expect=403) self.put(url, {}, expect=405) self.patch(url, {}, expect=405) - self.delete(url, expect=405) + self.delete(url, expect=403) with self.current_user(None): response = self.get(url, expect=401) self.put(url, {}, expect=401) @@ -603,13 +611,16 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): self.delete(url, expect=401) # Verify that the credential and inventory are null when they have - # been deleted. + # been deleted, can delete an ad hoc command without inventory or + # credential. self.credential.mark_inactive() self.inventory.mark_inactive() with self.current_user('admin'): response = self.get(url, expect=200) self.assertEqual(response['credential'], None) self.assertEqual(response['inventory'], None) + self.delete(url, expect=204) + self.delete(url, expect=404) def test_ad_hoc_command_cancel(self): # Override setting so that ad hoc command isn't actually started.