Просмотр исходного кода

Merge pull request #3222 from hellerve/tmp

Fix error message on trying to delete protected models
Jeremy Stretch 6 лет назад
Родитель
Сommit
a7ca49c44d
3 измененных файлов с 35 добавлено и 2 удалено
  1. 18 0
      netbox/ipam/tests/test_api.py
  2. 17 1
      netbox/utilities/api.py
  3. 0 1
      netbox/utilities/middleware.py

+ 18 - 0
netbox/ipam/tests/test_api.py

@@ -1,3 +1,5 @@
+import json
+
 from django.urls import reverse
 from netaddr import IPNetwork
 from rest_framework import status
@@ -870,6 +872,8 @@ class VLANTest(APITestCase):
         self.vlan2 = VLAN.objects.create(vid=2, name='Test VLAN 2')
         self.vlan3 = VLAN.objects.create(vid=3, name='Test VLAN 3')
 
+        self.prefix1 = Prefix.objects.create(prefix=IPNetwork('192.168.1.0/24'))
+
     def test_get_vlan(self):
 
         url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk})
@@ -960,6 +964,20 @@ class VLANTest(APITestCase):
         self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
         self.assertEqual(VLAN.objects.count(), 2)
 
+    def test_delete_vlan_with_prefix(self):
+        self.prefix1.vlan = self.vlan1
+        self.prefix1.save()
+
+        url = reverse('ipam-api:vlan-detail', kwargs={'pk': self.vlan1.pk})
+        response = self.client.delete(url, **self.header)
+
+        # can't use assertHttpStatus here because we don't have response.data
+        self.assertEqual(response.status_code, 409)
+
+        content = json.loads(response.content.decode('utf-8'))
+        self.assertIn('detail', content)
+        self.assertTrue(content['detail'].startswith('You tried deleting a model that is protected by:'))
+
 
 class ServiceTest(APITestCase):
 

+ 17 - 1
netbox/utilities/api.py

@@ -4,7 +4,7 @@ import pytz
 from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist
-from django.db.models import ManyToManyField
+from django.db.models import ManyToManyField, ProtectedError
 from django.http import Http404
 from rest_framework.exceptions import APIException
 from rest_framework.permissions import BasePermission
@@ -248,6 +248,22 @@ class ModelViewSet(_ModelViewSet):
         # Fall back to the hard-coded serializer class
         return self.serializer_class
 
+    def dispatch(self, request, *args, **kwargs):
+        try:
+            return super().dispatch(request, *args, **kwargs)
+        except ProtectedError as e:
+            models = '\n'.join(
+                '- {} ({})'.format(o, o._meta)
+                for o in e.protected_objects.all()
+            )
+            msg = 'You tried deleting a model that is protected by:\n{}'.format(models)
+            return self.finalize_response(
+                request,
+                Response({'detail': msg}, status=409),
+                *args,
+                **kwargs
+            )
+
 
 class FieldChoicesViewSet(ViewSet):
     """

+ 0 - 1
netbox/utilities/middleware.py

@@ -70,7 +70,6 @@ class ExceptionHandlingMiddleware(object):
             custom_template = 'exceptions/import_error.html'
         elif isinstance(exception, PermissionError):
             custom_template = 'exceptions/permission_error.html'
-
         # Return a custom error message, or fall back to Django's default 500 error handling
         if custom_template:
             return server_error(request, template_name=custom_template)