From 7519dcff03d5cd79ff2ed13d534b4b5cf327e160 Mon Sep 17 00:00:00 2001
From: Magdalena GomezFayren Medina <magdalena.gomez@ext.ec.europa.eu>
Date: Mon, 27 Jan 2025 11:10:41 +0000
Subject: [PATCH 1/3] Added uniqueness validator

---
 netbox_sys_plugin/api/serializers.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/netbox_sys_plugin/api/serializers.py b/netbox_sys_plugin/api/serializers.py
index d8a2579..35af0e1 100644
--- a/netbox_sys_plugin/api/serializers.py
+++ b/netbox_sys_plugin/api/serializers.py
@@ -1,6 +1,5 @@
 from rest_framework import serializers
 from virtualization.models import VirtualMachine, Cluster, ClusterType
-from ipam.models import Service
 from netbox.api.fields import ChoiceField
 from dcim.api.nested_serializers import (
     NestedDeviceSerializer, NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer,
@@ -207,6 +206,12 @@ class WebhookSettingsSerializer(NetBoxModelSerializer):
         model = WebhookSettings
         fields = '__all__'
 
+    def validate(self, data):
+        # Validate uniqueness
+        if not self.partial and WebhookSettings.objects.exists():
+            raise serializers.ValidationError("You can only have one webbook setting.")
+        return data
+
 class ProviderTypeExtraConfigSerializer(NetBoxModelSerializer):
     id = serializers.IntegerField(read_only=True)
     extra_config_structure = serializers.JSONField()
-- 
GitLab


From ebb256f015a0e097583dfa629ec3f3f36c44b0f2 Mon Sep 17 00:00:00 2001
From: Magdalena GomezFayren Medina <magdalena.gomez@ext.ec.europa.eu>
Date: Mon, 27 Jan 2025 11:11:00 +0000
Subject: [PATCH 2/3] Added api tests

---
 .../test_webhook_settings_api.py              | 210 ++++++++++++++++++
 .../test_webhook_settings_view.py             |   4 +-
 2 files changed, 212 insertions(+), 2 deletions(-)
 create mode 100644 netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py

diff --git a/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py b/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py
new file mode 100644
index 0000000..656a948
--- /dev/null
+++ b/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py
@@ -0,0 +1,210 @@
+"""SYS Plugin Webhook Settings API Test Case Class"""
+
+from users.models import ObjectPermission
+from django.contrib.contenttypes.models import ContentType
+from rest_framework import status
+from virtualization.models import ClusterType
+from netbox_sys_plugin.models import WebhookSettings
+from ..base import BaseAPITestCase
+
+class WebhookSettingsApiTestCase(BaseAPITestCase):
+    """Test suite for WebhookSettings API"""
+    model = WebhookSettings
+    brief_fields = ["payload_url","http_content_type"]
+
+
+    @classmethod
+    def setUpTestData(cls):
+
+        """Set up test data for WebhookSettings API"""
+
+        # Data for valid creation
+        cls.valid_create_data = [
+            {
+                "payload_url": "https://www.testAnother.com",
+                "http_content_type": "Test another http content type"
+            }
+        ]
+
+        # Data for invalid creation
+        cls.invalid_create_data = [
+            {
+                "payload_url": "Invalid URL", # Invalid URL
+                "http_content_type": "Test http content type"
+            },
+            {
+                "payload_url": None, # Missing
+                "http_content_type": "Test structure"
+
+            },
+            {
+                "payload_url": "https://www.testAnother.com",
+                "http_content_type": None # Missing
+            },
+        ]
+
+        # Data for checking  unique key
+        cls.valid_check_unique_data = [
+            {
+                "payload_url": "https://www.test1.com",
+                "http_content_type": "Test http content type 1"
+            },
+            {
+                "payload_url": "https://www.test2.com",
+                "http_content_type": "Test http content type 2"
+            }
+        ]
+
+    def test_create_valid_webhook_settings(self):
+        """Test creating a valid webhook settings"""
+
+        obj_perm = ObjectPermission(
+            name="Create Webhook Settings Permission",
+            actions=["add", "view"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        form_data = self.valid_create_data[0]
+        response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
+
+        self.assertHttpStatus(response, status.HTTP_201_CREATED)
+        self.assertEqual(response.data["payload_url"], form_data["payload_url"])
+        self.assertEqual(response.data["http_content_type"], form_data["http_content_type"])
+
+    def test_only_one_webhook_settings(self):
+        """Test the creation of 2 webhook settings"""
+
+        # Create Webhook Settings
+        WebhookSettings.objects.create(
+            payload_url='https://www.test.com',
+            http_content_type='test http content type'
+        )
+
+        obj_perm = ObjectPermission(
+            name="Invalid Webhook Settings Permission",
+            actions=["add", "view"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        for form_data in self.valid_check_unique_data:
+            response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
+        self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
+        self.assertIn('You can only have one webbook setting',str(response.data))
+
+    def test_create_invalid_webhook_settings(self):
+        """Test creating invalid webhook settings"""
+        obj_perm = ObjectPermission(
+            name="Invalid Webhook Settings Permission",
+            actions=["add", "view"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        form_data = self.invalid_create_data[0]
+        response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
+        self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
+        self.assertIn('Enter a valid URL.',str(response.data))
+
+        form_data = self.invalid_create_data[1]
+        response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
+        self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
+        self.assertIn('This field may not be null.',str(response.data))
+
+        form_data = self.invalid_create_data[2]
+        response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
+        self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
+        self.assertIn('This field may not be null.',str(response.data))
+
+    def test_update_webhook_settings(self):
+        """Test updating an existing webhook settings"""
+
+        # Create Webhook Settings
+        WebhookSettings.objects.create(
+            payload_url='https://www.test.com',
+            http_content_type='test http content type'
+        )
+
+        webhook_settings = WebhookSettings.objects.first()
+        obj_perm = ObjectPermission(
+            name="Update Webhook Settings Permission",
+            actions=["change", "view"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        update_data = {"payload_url": "https://www.testupdated.com"}
+        response = self.client.patch(self._get_detail_url(webhook_settings), update_data, format="json", **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertEqual(response.data["payload_url"], update_data["payload_url"])
+
+    def test_get_webhook_settings_list(self):
+        """Test fetching webhook settings list"""
+
+        # Create Webhook Settings
+        WebhookSettings.objects.create(
+            payload_url='https://www.test.com',
+            http_content_type='test http content type'
+        )
+
+        obj_perm = ObjectPermission(
+            name="Create Webhook Settings Permission",
+            actions=["view"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        response = self.client.get(self._get_list_url(), **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertGreaterEqual(len(response.data), 2)
+
+    def test_get_single_webhook_settings(self):
+        """Test fetching a single webhook settings"""
+
+        # Create Webhook Settings
+        WebhookSettings.objects.create(
+            payload_url='https://www.test.com',
+            http_content_type='test http content type'
+        )
+
+        obj_perm = ObjectPermission(
+            name="View Webhook Settings Permission",
+            actions=["view"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        webhook_settings = WebhookSettings.objects.first()
+        response = self.client.get(self._get_detail_url(webhook_settings), **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertEqual(response.data["payload_url"], webhook_settings.payload_url)
+        self.assertEqual(response.data["http_content_type"], webhook_settings.http_content_type)
+
+    def test_delete_webhook_settings(self):
+        """Test deleting a webhook settings"""
+
+        # Create Webhook Settings
+        WebhookSettings.objects.create(
+            payload_url='https://www.test.com',
+            http_content_type='test http content type'
+        )
+
+        webhook_settings = WebhookSettings.objects.first()
+        obj_perm = ObjectPermission(
+            name="Delete Webhook Settings Permission",
+            actions=["delete"],
+        )
+        obj_perm.save()
+        obj_perm.users.add(self.user)
+        obj_perm.object_types.add(ContentType.objects.get_for_model(WebhookSettings))
+
+        response = self.client.delete(self._get_detail_url(webhook_settings), **self.header)
+        self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
+        self.assertFalse(WebhookSettings.objects.filter(id=webhook_settings.id).exists())
diff --git a/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_view.py b/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_view.py
index 5e8e8f7..2104952 100644
--- a/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_view.py
+++ b/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_view.py
@@ -75,11 +75,11 @@ class WebhookSettingsFormTestCase(
             form.errors.get("http_content_type", []),
         )
 
-    def test_create_more_than_one_webhook_settings(self):
+    def test_only_one_webhook_settings(self):
         """Test the creation of 2 webhook settings"""
 
         # pylint: disable=W0201
-        self.vmMachineType1 = WebhookSettings.objects.create(
+        self.webhookSettings = WebhookSettings.objects.create(
             payload_url='https://www.test.com',
             http_content_type='test http content type')
 
-- 
GitLab


From b7af47f6e78f79d0b52ecb92766c73860e71b047 Mon Sep 17 00:00:00 2001
From: Magdalena GomezFayren Medina <magdalena.gomez@ext.ec.europa.eu>
Date: Mon, 27 Jan 2025 11:19:31 +0000
Subject: [PATCH 3/3] Fixed linter

---
 .../tests/webhook_settings/test_webhook_settings_api.py          | 1 -
 1 file changed, 1 deletion(-)

diff --git a/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py b/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py
index 656a948..5412fc7 100644
--- a/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py
+++ b/netbox_sys_plugin/tests/webhook_settings/test_webhook_settings_api.py
@@ -3,7 +3,6 @@
 from users.models import ObjectPermission
 from django.contrib.contenttypes.models import ContentType
 from rest_framework import status
-from virtualization.models import ClusterType
 from netbox_sys_plugin.models import WebhookSettings
 from ..base import BaseAPITestCase
 
-- 
GitLab