From f128fc968c4d08ad319773863923bcaf2f60273b Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Sat, 21 Jan 2023 14:32:02 +0530 Subject: [PATCH 1/3] added migration --- .../0002_alter_accesslist_options_and_more.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 netbox_acls/migrations/0002_alter_accesslist_options_and_more.py diff --git a/netbox_acls/migrations/0002_alter_accesslist_options_and_more.py b/netbox_acls/migrations/0002_alter_accesslist_options_and_more.py new file mode 100644 index 0000000..da0d912 --- /dev/null +++ b/netbox_acls/migrations/0002_alter_accesslist_options_and_more.py @@ -0,0 +1,94 @@ +# Generated by Django 4.0.8 on 2023-01-21 09:00 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('netbox_acls', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='accesslist', + options={'ordering': ['assigned_object_type', 'assigned_object_id', 'name'], 'verbose_name': 'Access List', 'verbose_name_plural': 'Access Lists'}, + ), + migrations.AlterModelOptions( + name='aclextendedrule', + options={'ordering': ['access_list', 'index'], 'verbose_name': 'ACL Extended Rule', 'verbose_name_plural': 'ACL Extended Rules'}, + ), + migrations.AlterModelOptions( + name='aclinterfaceassignment', + options={'ordering': ['assigned_object_type', 'assigned_object_id', 'access_list', 'direction'], 'verbose_name': 'ACL Interface Assignment', 'verbose_name_plural': 'ACL Interface Assignments'}, + ), + migrations.AlterModelOptions( + name='aclstandardrule', + options={'ordering': ['access_list', 'index'], 'verbose_name': 'ACL Standard Rule', 'verbose_name_plural': 'ACL Standard Rules'}, + ), + migrations.AlterField( + model_name='accesslist', + name='assigned_object_id', + field=models.PositiveBigIntegerField(), + ), + migrations.AlterField( + model_name='accesslist', + name='assigned_object_type', + field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'device')), models.Q(('app_label', 'dcim'), ('model', 'virtualchassis')), models.Q(('app_label', 'virtualization'), ('model', 'virtualmachine')), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + ), + migrations.AlterField( + model_name='accesslist', + name='name', + field=models.CharField(max_length=500, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z,-,_]*$', 'Only alphanumeric, hyphens, and underscores characters are allowed.')]), + ), + migrations.AlterField( + model_name='accesslist', + name='type', + field=models.CharField(max_length=30), + ), + migrations.AlterField( + model_name='aclextendedrule', + name='access_list', + field=models.ForeignKey(limit_choices_to={'type': 'extended'}, on_delete=django.db.models.deletion.CASCADE, related_name='aclextendedrules', to='netbox_acls.accesslist'), + ), + migrations.AlterField( + model_name='aclextendedrule', + name='remark', + field=models.CharField(blank=True, default='', max_length=500), + preserve_default=False, + ), + migrations.AlterField( + model_name='aclinterfaceassignment', + name='access_list', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='netbox_acls.accesslist'), + ), + migrations.AlterField( + model_name='aclinterfaceassignment', + name='assigned_object_id', + field=models.PositiveBigIntegerField(), + ), + migrations.AlterField( + model_name='aclinterfaceassignment', + name='assigned_object_type', + field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'interface')), models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + ), + migrations.AlterField( + model_name='aclinterfaceassignment', + name='direction', + field=models.CharField(max_length=30), + ), + migrations.AlterField( + model_name='aclstandardrule', + name='access_list', + field=models.ForeignKey(limit_choices_to={'type': 'standard'}, on_delete=django.db.models.deletion.CASCADE, related_name='aclstandardrules', to='netbox_acls.accesslist'), + ), + migrations.AlterField( + model_name='aclstandardrule', + name='remark', + field=models.CharField(blank=True, default='', max_length=500), + preserve_default=False, + ), + ] From d223e336795e33005fb3d1b13c5327332ef43540 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Sat, 21 Jan 2023 14:49:19 +0530 Subject: [PATCH 2/3] added vm filtering in acl add/edit page --- netbox_acls/forms/models.py | 45 ++++++++++++++++--- .../netbox_acls/accesslist_edit.html | 3 ++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/netbox_acls/forms/models.py b/netbox_acls/forms/models.py index a8800e5..38f7c0c 100644 --- a/netbox_acls/forms/models.py +++ b/netbox_acls/forms/models.py @@ -14,7 +14,13 @@ from utilities.forms import ( DynamicModelChoiceField, DynamicModelMultipleChoiceField, ) -from virtualization.models import VirtualMachine, VMInterface +from virtualization.models import ( + Cluster, + ClusterGroup, + ClusterType, + VirtualMachine, + VMInterface, +) from ..models import ( AccessList, @@ -59,6 +65,7 @@ class AccessListForm(NetBoxModelForm): Requires a device, a name, a type, and a default_action. """ + # Device selector region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -85,21 +92,49 @@ class AccessListForm(NetBoxModelForm): "site_id": "$site", }, ) + + # Virtual Chassis selector virtual_chassis = DynamicModelChoiceField( queryset=VirtualChassis.objects.all(), required=False, label="Virtual Chassis", ) + + # Virtual Machine selector + cluster_type = DynamicModelChoiceField( + queryset=ClusterType.objects.all(), + required=False, + ) + + cluster_group = DynamicModelChoiceField( + queryset=ClusterGroup.objects.all(), + required=False, + query_params={ + "type_id": "$cluster_type", + }, + ) + + cluster = DynamicModelChoiceField( + queryset=Cluster.objects.all(), + required=False, + query_params={ + "type_id": "$cluster_type", + "group_id": "$cluster_group", + }, + ) + virtual_machine = DynamicModelChoiceField( queryset=VirtualMachine.objects.all(), required=False, label="Virtual Machine", + query_params={ + "cluster_type_id": "$cluster_type", + "cluster_group_id": "$cluster_group", + "cluster_id": "$cluster", + }, ) + comments = CommentField() - tags = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False, - ) class Meta: model = AccessList diff --git a/netbox_acls/templates/netbox_acls/accesslist_edit.html b/netbox_acls/templates/netbox_acls/accesslist_edit.html index 64b46cb..a197daa 100644 --- a/netbox_acls/templates/netbox_acls/accesslist_edit.html +++ b/netbox_acls/templates/netbox_acls/accesslist_edit.html @@ -67,6 +67,9 @@ {% render_field form.virtual_chassis %}
+ {% render_field form.cluster_type %} + {% render_field form.cluster_group %} + {% render_field form.cluster %} {% render_field form.virtual_machine %}
From 80d9fe6573af41a1172e7e9b3b1cce17422b2f7b Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Sat, 21 Jan 2023 18:05:18 +0530 Subject: [PATCH 3/3] Added clone fields and cleaned templates (#80) --- netbox_acls/models/access_list_rules.py | 2 + netbox_acls/models/access_lists.py | 7 + .../templates/netbox_acls/accesslist.html | 129 +++++++----------- .../netbox_acls/aclinterfaceassignment.html | 32 ----- 4 files changed, 60 insertions(+), 110 deletions(-) diff --git a/netbox_acls/models/access_list_rules.py b/netbox_acls/models/access_list_rules.py index 2dff662..f37aca8 100644 --- a/netbox_acls/models/access_list_rules.py +++ b/netbox_acls/models/access_list_rules.py @@ -52,6 +52,8 @@ class ACLRule(NetBoxModel): verbose_name="Source Prefix", ) + clone_fields = ("access_list", "action", "source_prefix") + def __str__(self): return f"{self.access_list}: Rule {self.index}" diff --git a/netbox_acls/models/access_lists.py b/netbox_acls/models/access_lists.py index 729e024..1feb635 100644 --- a/netbox_acls/models/access_lists.py +++ b/netbox_acls/models/access_lists.py @@ -59,6 +59,11 @@ class AccessList(NetBoxModel): blank=True, ) + clone_fields = ( + "type", + "default_action", + ) + class Meta: unique_together = ["assigned_object_type", "assigned_object_id", "name"] ordering = ["assigned_object_type", "assigned_object_id", "name"] @@ -113,6 +118,8 @@ class ACLInterfaceAssignment(NetBoxModel): blank=True, ) + clone_fields = ("access_list", "direction") + class Meta: unique_together = [ "assigned_object_type", diff --git a/netbox_acls/templates/netbox_acls/accesslist.html b/netbox_acls/templates/netbox_acls/accesslist.html index 6870f30..5821402 100644 --- a/netbox_acls/templates/netbox_acls/accesslist.html +++ b/netbox_acls/templates/netbox_acls/accesslist.html @@ -1,90 +1,63 @@ {% extends 'generic/object.html' %} {% load render_table from django_tables2 %} -{% block breadcrumbs %} - -{% endblock %} -{% block controls %} -
+{% block extra_controls %} {% if perms.netbox_acls.change_policy %} - {% if object.type == 'extended' %} - - {% elif object.type == 'standard' %} - - {% endif %} - Rule - - - Edit + {% if object.type == 'extended' %} + + {% elif object.type == 'standard' %} + + {% endif %} + Rule {% endif %} - {% if perms.netbox_acls.delete_policy %} - - Delete - - {% endif %} -
-{% endblock controls %} -{% block tabs %} - -{% endblock tabs %} +{% endblock extra_controls %} {% block content %} -
-
-
-
Access List
-
- - - - - - - - - - - - {% if object.type == 'standard' %} - - {% elif object.type == 'extended' %} - - {% endif %} - - - - - -
Type{{ object.get_type_display }}
Default Action{% badge object.get_default_action_display bg_color=object.get_default_action_color %}
Rules{{ object.aclstandardrules.count|placeholder }}{{ object.aclextendedrules.count|placeholder }}
Assigned Host{{ object.assigned_object|linkify }}
+
+
+
+
Access List
+
+ + + + + + + + + + + + {% if object.type == 'standard' %} + + {% elif object.type == 'extended' %} + + {% endif %} + + + + + +
Type{{ object.get_type_display }}
Default Action{% badge object.get_default_action_display bg_color=object.get_default_action_color %}
Rules{{ object.aclstandardrules.count|placeholder }}{{ object.aclextendedrules.count|placeholder }}
Assigned Host{{ object.assigned_object|linkify }}
+
+
+ {% include 'inc/panels/custom_fields.html' %}
-
- {% include 'inc/panels/custom_fields.html' %} -
-
- {% include 'inc/panels/tags.html' %} - {% include 'inc/panels/comments.html' %} -
-
-
-
-
-
{{ object.get_type_display }} Rules
-
- {% render_table rules_table %} +
+ {% include 'inc/panels/tags.html' %} + {% include 'inc/panels/comments.html' %} +
+
+
+
+
+
{{ object.get_type_display }} Rules
+
+ {% render_table rules_table %} +
+
-
-
{% endblock content %} diff --git a/netbox_acls/templates/netbox_acls/aclinterfaceassignment.html b/netbox_acls/templates/netbox_acls/aclinterfaceassignment.html index b46a26a..4cabeb0 100644 --- a/netbox_acls/templates/netbox_acls/aclinterfaceassignment.html +++ b/netbox_acls/templates/netbox_acls/aclinterfaceassignment.html @@ -1,38 +1,6 @@ {% extends 'generic/object.html' %} {% load render_table from django_tables2 %} -{% block breadcrumbs %} - -{% endblock %} -{% block controls %} -
- {% if perms.netbox_acls.change_policy %} - - Edit - - {% endif %} - {% if perms.netbox_acls.delete_policy %} - - Delete - - {% endif %} -
-{% endblock controls %} -{% block tabs %} - -{% endblock tabs %} - {% block content %}