From bdd71cfeac8e7a27bcc9a0af070c263c8870e6df Mon Sep 17 00:00:00 2001
From: Vincent Simonin <vincent.simonin@ext.ec.europa.eu>
Date: Mon, 4 Dec 2023 10:18:57 +0100
Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20source=20URL=20and=20tar?=
 =?UTF-8?q?get=20URL=20can=20be=20equal?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ..._alter_mapping_extra_protocols_and_more.py | 37 +++++++++++++++++++
 .../netbox_rps_plugin/models.py               | 16 ++++++++
 .../tests/e2e/test_mapping_unique.py          | 21 +++++++++++
 3 files changed, 74 insertions(+)
 create mode 100644 plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0011_alter_mapping_extra_protocols_and_more.py

diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0011_alter_mapping_extra_protocols_and_more.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0011_alter_mapping_extra_protocols_and_more.py
new file mode 100644
index 0000000..205331e
--- /dev/null
+++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0011_alter_mapping_extra_protocols_and_more.py
@@ -0,0 +1,37 @@
+"""Migration File"""
+# pylint: disable=C0103
+
+import django.contrib.postgres.fields
+from django.db import migrations, models
+import netbox_rps_plugin.models
+
+
+class Migration(migrations.Migration):
+    """Migration Class"""
+
+    dependencies = [
+        (
+            "netbox_rps_plugin",
+            "0010_alter_httpheader_options_alter_mapping_options_and_more",
+        ),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="mapping",
+            name="extra_protocols",
+            field=django.contrib.postgres.fields.ArrayField(
+                base_field=models.CharField(max_length=32),
+                blank=True,
+                default=netbox_rps_plugin.models.default_protocol,
+                size=None,
+            ),
+        ),
+        migrations.AddConstraint(
+            model_name="mapping",
+            constraint=models.CheckConstraint(
+                check=models.Q(("source__exact", models.F("target")), _negated=True),
+                name="netbox_rps_plugin_mapping_check_target_source_url",
+            ),
+        ),
+    ]
diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py
index 03a32e8..2f64d81 100644
--- a/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py
+++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py
@@ -1,5 +1,6 @@
 """Models definitions"""
 
+from django.core.exceptions import ValidationError
 from django.conf import settings
 from django.db import models
 from django.urls import reverse
@@ -120,6 +121,12 @@ class Mapping(NetBoxModel):
 
     class Meta:
         ordering = ("source", "target")
+        constraints = [
+            models.CheckConstraint(
+                check=~models.Q(source__exact=models.F("target")),
+                name="%(app_label)s_%(class)s_check_target_source_url",
+            )
+        ]
 
     def __str__(self):
         return f"{self.source}"
@@ -128,6 +135,15 @@ class Mapping(NetBoxModel):
         """override"""
         return reverse("plugins:netbox_rps_plugin:mapping", args=[self.pk])
 
+    def clean(self):
+        """Clean model method for validation"""
+        super().clean()
+
+        if self.source == self.target:
+            raise ValidationError(
+                {"target": "Target URL cannot be equal to source URL."}
+            )
+
 
 class SamlConfig(NetBoxModel):
     """SAML config definition class"""
diff --git a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py
index 8121fac..e0c17cd 100644
--- a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py
+++ b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py
@@ -50,6 +50,27 @@ class TestMappingUnique(Base):
             response.content, b'{"source":["mapping with this Source already exists."]}'
         )
 
+    def test_that_source_url_cannot_be_equal_to_destination_url(self) -> None:
+        """Test that source ULR cannot be equal to destination URL"""
+
+        response = requests.post(
+            url=f"http://{HOST}:{PORT}/api/plugins/rps/mapping/",
+            json={
+                "source": "https://truc8.com/api",
+                "target": "https://truc8.com/api",
+                "authentication": "none",
+                "testingpage": None,
+            },
+            headers={"Authorization": f"Token {API_KEY}"},
+            timeout=5,
+        )
+
+        self.assertEqual(response.status_code, 400)
+        self.assertEqual(
+            response.content,
+            b'{"target":["Target URL cannot be equal to source URL."]}',
+        )
+
 
 if __name__ == "__main__":
     unittest.main()
-- 
GitLab