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 0000000000000000000000000000000000000000..205331e8942241c74d52eb64983df379577b2fcc --- /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 03a32e8cae28a5a3c685e304fc788319c90dfe1b..2f64d8141350c3182e69b182a0336fd30b9662a3 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 8121fac3c28ad66332a1f4fd378cbb034c4b44f2..e0c17cd8b77c0ce502d297a98f95839bc03d0302 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()