From 0a150f36e16f58937659ab607897f7601dd383e2 Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Sun, 17 Aug 2025 17:09:11 +0200 Subject: [PATCH 1/2] Use slug validation for AccessList name Instead of using a custom RegexValidator, the name of an access list can be validated using Django's slug validator. This reduces the overhead of a custom implementation and its testing. Additionally, this resolves an issue involving an invalid escape sequence in the related test case. --- .../migrations/0005_alter_accesslist_name.py | 17 +++++++++++++++++ netbox_acls/models/access_lists.py | 10 +--------- netbox_acls/tests/models/test_accesslists.py | 16 ---------------- 3 files changed, 18 insertions(+), 25 deletions(-) create mode 100644 netbox_acls/migrations/0005_alter_accesslist_name.py diff --git a/netbox_acls/migrations/0005_alter_accesslist_name.py b/netbox_acls/migrations/0005_alter_accesslist_name.py new file mode 100644 index 00000000..27e1a756 --- /dev/null +++ b/netbox_acls/migrations/0005_alter_accesslist_name.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.4 on 2025-08-17 15:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("netbox_acls", "0004_netbox_acls"), + ] + + operations = [ + migrations.AlterField( + model_name="accesslist", + name="name", + field=models.SlugField(max_length=500), + ), + ] diff --git a/netbox_acls/models/access_lists.py b/netbox_acls/models/access_lists.py index 5035a8df..8dc1fe94 100644 --- a/netbox_acls/models/access_lists.py +++ b/netbox_acls/models/access_lists.py @@ -6,7 +6,6 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError -from django.core.validators import RegexValidator from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ @@ -22,21 +21,14 @@ ) -alphanumeric_plus = RegexValidator( - r"^[a-zA-Z0-9-_]+$", - _("Only alphanumeric, hyphens, and underscores characters are allowed."), -) - - class AccessList(NetBoxModel): """ Model definition for Access Lists. """ - name = models.CharField( + name = models.SlugField( verbose_name=_("Name"), max_length=500, - validators=[alphanumeric_plus], ) assigned_object_type = models.ForeignKey( to=ContentType, diff --git a/netbox_acls/tests/models/test_accesslists.py b/netbox_acls/tests/models/test_accesslists.py index 579bd719..0098ab42 100644 --- a/netbox_acls/tests/models/test_accesslists.py +++ b/netbox_acls/tests/models/test_accesslists.py @@ -153,22 +153,6 @@ def test_duplicate_name_success(self): ) vm_acl.full_clean() - def test_alphanumeric_plus_fail(self): - """ - Test that AccessList names with non-alphanumeric (excluding '_' and '-') characters fail validation. - """ - non_alphanumeric_plus_chars = " !@#$%^&*()[]{};:,./<>?\|~=+" - - for i, char in enumerate(non_alphanumeric_plus_chars, start=1): - bad_acl_name = AccessList( - name=f"Test-ACL-bad_name_{i}_{char}", - assigned_object=self.device1, - comments=f'ACL with "{char}" in name', - **self.common_acl_params, - ) - with self.assertRaises(ValidationError): - bad_acl_name.full_clean() - def test_duplicate_name_per_device_fail(self): """ Test that AccessList names must be unique per device. From 13a948aa7e100c8b173b4a125bd7fb3cf75b400e Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Wed, 20 Aug 2025 13:16:42 +0200 Subject: [PATCH 2/2] Use CharField for AccessList name Although slug validation works for an access list name, the field should remain a CharField to clearly indicate its purpose. Using slug validation explicitly ensures that existing validation rules are used. --- .../migrations/0005_alter_accesslist_name.py | 16 ++++++++++++++-- netbox_acls/models/access_lists.py | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/netbox_acls/migrations/0005_alter_accesslist_name.py b/netbox_acls/migrations/0005_alter_accesslist_name.py index 27e1a756..6e873a61 100644 --- a/netbox_acls/migrations/0005_alter_accesslist_name.py +++ b/netbox_acls/migrations/0005_alter_accesslist_name.py @@ -1,5 +1,8 @@ -# Generated by Django 5.2.4 on 2025-08-17 15:21 +# Generated by Django 5.2.5 on 2025-08-20 11:14 +import re + +import django.core.validators from django.db import migrations, models @@ -12,6 +15,15 @@ class Migration(migrations.Migration): migrations.AlterField( model_name="accesslist", name="name", - field=models.SlugField(max_length=500), + field=models.CharField( + max_length=500, + validators=[ + django.core.validators.RegexValidator( + re.compile("^[-a-zA-Z0-9_]+\\Z"), + "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.", + "invalid", + ) + ], + ), ), ] diff --git a/netbox_acls/models/access_lists.py b/netbox_acls/models/access_lists.py index 8dc1fe94..04694150 100644 --- a/netbox_acls/models/access_lists.py +++ b/netbox_acls/models/access_lists.py @@ -6,6 +6,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError +from django.core.validators import validate_slug from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ @@ -26,9 +27,10 @@ class AccessList(NetBoxModel): Model definition for Access Lists. """ - name = models.SlugField( + name = models.CharField( verbose_name=_("Name"), max_length=500, + validators=[validate_slug], ) assigned_object_type = models.ForeignKey( to=ContentType,