From c1772a87bf2b4e62fcc51fdfffb3b198d31f3c5c Mon Sep 17 00:00:00 2001
From: Vincent Simonin <vincent.simonin@ext.ec.europa.eu>
Date: Tue, 11 Jul 2023 19:17:30 +0200
Subject: [PATCH] Source Mapping must be unique

---
 .../netbox_rps_plugin/__init__.py             |  2 +-
 .../0005_source_mapping_unique_constraint.py  | 17 ++++++
 .../netbox_rps_plugin/models.py               |  1 +
 plugins/netbox-rps-plugin/setup.py            |  2 +-
 .../tests/e2e/test_mapping_creation.py        | 25 ++++++++
 .../tests/e2e/test_mapping_unique.py          | 57 +++++++++++++++++++
 .../tests/e2e/test_unauthenticated.py         | 11 ----
 7 files changed, 102 insertions(+), 13 deletions(-)
 create mode 100644 plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0005_source_mapping_unique_constraint.py
 create mode 100644 plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py
 create mode 100644 plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py

diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/__init__.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/__init__.py
index 60fba73..0709e6b 100644
--- a/plugins/netbox-rps-plugin/netbox_rps_plugin/__init__.py
+++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/__init__.py
@@ -5,7 +5,7 @@ class NetBoxRpsConfig(PluginConfig):
     name = 'netbox_rps_plugin'
     verbose_name = 'NetBox RPS'
     description = 'A Netbox plugin to add RPS resources'
-    version = '0.8.3'
+    version = '0.8.4'
     author = "Vincent Simonin"
     author_email = "vincent.simonin@ext.ec.europa.eu"
     base_url = 'rps'
diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0005_source_mapping_unique_constraint.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0005_source_mapping_unique_constraint.py
new file mode 100644
index 0000000..ece2181
--- /dev/null
+++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/migrations/0005_source_mapping_unique_constraint.py
@@ -0,0 +1,17 @@
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('netbox_rps_plugin', '0004_testingpage_nullable')
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='mapping',
+            name='source',
+            field=models.CharField(null=False, blank=False, max_length=120, unique=True),
+        ),
+    ]
diff --git a/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py b/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py
index c4504cf..1110787 100644
--- a/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py
+++ b/plugins/netbox-rps-plugin/netbox_rps_plugin/models.py
@@ -36,6 +36,7 @@ class Mapping(NetBoxModel):
         blank=False,
         verbose_name='Source',
         validators=[URLValidator(message='It must be a url')],
+        unique=True
     )
     target = models.CharField(
         max_length=120,
diff --git a/plugins/netbox-rps-plugin/setup.py b/plugins/netbox-rps-plugin/setup.py
index 3eb90ed..79bdd00 100644
--- a/plugins/netbox-rps-plugin/setup.py
+++ b/plugins/netbox-rps-plugin/setup.py
@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
 
 setup(
     name='netbox_rps_plugin',
-    version='0.8.3',
+    version='0.8.4',
     description='A Netbox plugin to add RPS resources',
     install_requires=[],
     packages=find_packages(),
diff --git a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py
new file mode 100644
index 0000000..fbed01a
--- /dev/null
+++ b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_creation.py
@@ -0,0 +1,25 @@
+import unittest
+import requests
+
+
+class TestMappingCreation(unittest.TestCase):
+
+    def test_that_mapping_is_created(self):
+        r = requests.post(
+            url='http://localhost:8000/api/plugins/rps/mapping/',
+            json={
+                "source": "https://truc6.com/api",
+                "target": "http://10.10.10.10:1886/api",
+                "authentication": "none",
+                "testingpage": None
+            },
+            headers={
+                "Authorization": "Token 52121418bdd7411f6a0ee99b41561099810a8785"
+            }
+        )
+
+        self.assertEqual(r.status_code, 201)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py
new file mode 100644
index 0000000..636c7ad
--- /dev/null
+++ b/plugins/netbox-rps-plugin/tests/e2e/test_mapping_unique.py
@@ -0,0 +1,57 @@
+import unittest
+import requests
+import json
+from pprint import pp
+
+
+class TestMappingUnique(unittest.TestCase):
+    mappingId=None
+
+    def test_that_mapping_is_unique(self):
+        r = requests.post(
+            url='http://localhost:8000/api/plugins/rps/mapping/',
+            json={
+                "source": "https://truc7.com/api",
+                "target": "http://10.10.10.10:1886/api",
+                "authentication": "none",
+                "testingpage": None
+            },
+            headers={
+                "Authorization": "Token 52121418bdd7411f6a0ee99b41561099810a8785"
+            }
+        )
+
+        self.assertEqual(r.status_code, 201)
+
+        self.mappingId = json.loads(r.content)['id'];
+
+        r = requests.post(
+            url='http://localhost:8000/api/plugins/rps/mapping/',
+            json={
+                "source": "https://truc7.com/api",
+                "target": "http://10.10.10.10:1886/api",
+                "authentication": "none",
+                "testingpage": None
+            },
+            headers={
+                "Authorization": "Token 52121418bdd7411f6a0ee99b41561099810a8785"
+            }
+        )
+
+        self.assertEqual(r.status_code, 400)
+        self.assertEqual(r.content, b'{"source":["mapping with this Source already exists."]}')
+
+    def tearDown(self) -> None:
+        requests.delete(
+            url='http://localhost:8000/api/plugins/rps/mapping/',
+            json=[{
+                "id": self.mappingId
+            }],
+            headers={
+                "Authorization": "Token 52121418bdd7411f6a0ee99b41561099810a8785"
+            }
+        )
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/plugins/netbox-rps-plugin/tests/e2e/test_unauthenticated.py b/plugins/netbox-rps-plugin/tests/e2e/test_unauthenticated.py
index 4ae2d5f..d4a4129 100644
--- a/plugins/netbox-rps-plugin/tests/e2e/test_unauthenticated.py
+++ b/plugins/netbox-rps-plugin/tests/e2e/test_unauthenticated.py
@@ -1,14 +1,8 @@
 import unittest
 import requests
 
-
 class TestUnauthenticatedMappings(unittest.TestCase):
 
-    def test_mappings_get_unauthenticated(self):
-        r = requests.get('http://localhost:8000/api/plugins/rps/')
-
-        self.assertEqual(r.status_code, 403)
-
     def test_mappings_get_unauthenticated(self):
         r = requests.get('http://localhost:8000/api/plugins/rps/mapping/')
 
@@ -29,11 +23,6 @@ class TestUnauthenticatedMappings(unittest.TestCase):
 
         self.assertEqual(r.status_code, 403)
 
-    def test_mappings_put_unauthenticated(self):
-        r = requests.put('http://localhost:8000/api/plugins/rps/mapping')
-
-        self.assertEqual(r.status_code, 403)
-
 
 if __name__ == '__main__':
     unittest.main()
-- 
GitLab