diff --git a/.devcontainer/Dockerfile-plugin_dev b/.devcontainer/Dockerfile-plugin_dev
index 55fd2cb..17e5393 100644
--- a/.devcontainer/Dockerfile-plugin_dev
+++ b/.devcontainer/Dockerfile-plugin_dev
@@ -1,8 +1,8 @@
-ARG NETBOX_VARIANT=v3.3
+ARG NETBOX_VARIANT=v3.4
FROM netboxcommunity/netbox:${NETBOX_VARIANT}
-ARG NETBOX_INITIALIZERS_VARIANT=3.3.*
+ARG NETBOX_INITIALIZERS_VARIANT=3.4.0
ARG DEBIAN_FRONTEND=noninteractive
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a88d335..ac362e9 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -23,14 +23,14 @@ body:
attributes:
label: NetBox access-list plugin version
description: What version of the NetBox access-list plugin are you currently running?
- placeholder: v0.1
+ placeholder: v1.2.0
validations:
required: true
- type: input
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
- placeholder: v3.2.7
+ placeholder: v3.4.3
validations:
required: true
- type: textarea
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index a388992..ca31eaf 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -15,7 +15,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
- placeholder: v3.2.5
+ placeholder: v3.4.3
validations:
required: true
- type: dropdown
diff --git a/README.md b/README.md
index 5f864ad..400e581 100644
--- a/README.md
+++ b/README.md
@@ -37,10 +37,13 @@ See the [CONTRIBUTING](CONTRIBUTING.md) for more information.
Each Plugin Version listed below has been tested with its corresponding NetBox Version.
| NetBox Version | Plugin Version |
-|----------------|----------------|
-| 3.2 | 1.0.1 |
-| 3.3 | 1.1.1 |
-| 3.4 | 1.2.0(coming) |
+|:--------------:|:--------------:|
+| 3.2 | 1.0.1 |
+| 3.3 | 1.1.0 |
+| 3.4 | 1.2.0
+
+
+
## Installing
diff --git a/netbox_acls/__init__.py b/netbox_acls/__init__.py
index 4709253..fa5e548 100644
--- a/netbox_acls/__init__.py
+++ b/netbox_acls/__init__.py
@@ -17,9 +17,8 @@ class NetBoxACLsConfig(PluginConfig):
version = __version__
description = "Manage simple ACLs in NetBox"
base_url = "access-lists"
- min_version = "3.3.0"
- max_version = "3.3.99"
- # default_settings = {}
+ min_version = "3.4.0"
+ max_version = "3.4.99"
config = NetBoxACLsConfig
diff --git a/netbox_acls/api/views.py b/netbox_acls/api/views.py
index 2db85ba..cdff48d 100644
--- a/netbox_acls/api/views.py
+++ b/netbox_acls/api/views.py
@@ -28,8 +28,12 @@ class AccessListViewSet(NetBoxModelViewSet):
Defines the view set for the django AccessList model & associates it to a view.
"""
- queryset = models.AccessList.objects.prefetch_related("tags").annotate(
- rule_count=Count("aclextendedrules") + Count("aclstandardrules"),
+ queryset = (
+ models.AccessList.objects.prefetch_related("tags")
+ .annotate(
+ rule_count=Count("aclextendedrules") + Count("aclstandardrules"),
+ )
+ .prefetch_related("tags")
)
serializer_class = AccessListSerializer
filterset_class = filtersets.AccessListFilterSet
diff --git a/netbox_acls/navigation.py b/netbox_acls/navigation.py
index bb96b8f..6d784f5 100644
--- a/netbox_acls/navigation.py
+++ b/netbox_acls/navigation.py
@@ -2,82 +2,77 @@
Define the plugin menu buttons & the plugin navigation bar enteries.
"""
-from extras.plugins import PluginMenuButton, PluginMenuItem
+from extras.plugins import PluginMenu, PluginMenuButton, PluginMenuItem
from utilities.choices import ButtonColorChoices
#
# Define plugin menu buttons
#
-accesslist_buttons = [
- PluginMenuButton(
- link="plugins:netbox_acls:accesslist_add",
- title="Add",
- icon_class="mdi mdi-plus-thick",
- color=ButtonColorChoices.GREEN,
- permissions=["netbox_acls.add_accesslist"],
- ),
-]
-
-aclstandardrule_butons = [
- PluginMenuButton(
- link="plugins:netbox_acls:aclstandardrule_add",
- title="Add",
- icon_class="mdi mdi-plus-thick",
- color=ButtonColorChoices.GREEN,
- permissions=["netbox_acls.add_aclstandardrule"],
- ),
-]
-
-aclextendedrule_butons = [
- PluginMenuButton(
- link="plugins:netbox_acls:aclextendedrule_add",
- title="Add",
- icon_class="mdi mdi-plus-thick",
- color=ButtonColorChoices.GREEN,
- permissions=["netbox_acls.add_aclextendedrule"],
- ),
-]
-
-accesslistassignment_buttons = [
- PluginMenuButton(
- link="plugins:netbox_acls:aclinterfaceassignment_add",
- title="Add",
- icon_class="mdi mdi-plus-thick",
- color=ButtonColorChoices.GREEN,
- permissions=["netbox_acls.add_aclinterfaceassignment"],
- ),
-]
-
-#
-# Define navigation bar links including the above buttons defined.
-#
-
-menu_items = (
- PluginMenuItem(
- link="plugins:netbox_acls:accesslist_list",
- link_text="Access Lists",
- buttons=accesslist_buttons,
- permissions=["netbox_acls.view_accesslist"],
- ),
- # Comment out Standard Access List rule to force creation in the ACL view
- PluginMenuItem(
- link="plugins:netbox_acls:aclstandardrule_list",
- link_text="ACL Standard Rules",
- buttons=aclstandardrule_butons,
- permissions=["netbox_acls.view_aclstandardrule"],
- ),
- # Comment out Extended Access List rule to force creation in the ACL view
- PluginMenuItem(
- link="plugins:netbox_acls:aclextendedrule_list",
- link_text="ACL Extended Rules",
- buttons=aclextendedrule_butons,
- permissions=["netbox_acls.view_aclextendedrule"],
- ),
- PluginMenuItem(
- link="plugins:netbox_acls:aclinterfaceassignment_list",
- link_text="ACL Interface Assignments",
- buttons=accesslistassignment_buttons,
- permissions=["netbox_acls.view_aclinterfaceassignment"],
+menu = PluginMenu(
+ label="Access Lists",
+ groups=(
+ (
+ "ACLs",
+ (
+ PluginMenuItem(
+ link="plugins:netbox_acls:accesslist_list",
+ link_text="Access Lists",
+ permissions=["netbox_acls.view_accesslist"],
+ buttons=(
+ PluginMenuButton(
+ link="plugins:netbox_acls:accesslist_add",
+ title="Add",
+ icon_class="mdi mdi-plus-thick",
+ color=ButtonColorChoices.GREEN,
+ permissions=["netbox_acls.add_accesslist"],
+ ),
+ ),
+ ),
+ PluginMenuItem(
+ link="plugins:netbox_acls:aclstandardrule_list",
+ link_text="Standard Rules",
+ permissions=["netbox_acls.view_aclstandardrule"],
+ buttons=(
+ PluginMenuButton(
+ link="plugins:netbox_acls:aclstandardrule_add",
+ title="Add",
+ icon_class="mdi mdi-plus-thick",
+ color=ButtonColorChoices.GREEN,
+ permissions=["netbox_acls.add_aclstandardrule"],
+ ),
+ ),
+ ),
+ PluginMenuItem(
+ link="plugins:netbox_acls:aclextendedrule_list",
+ link_text="Extended Rules",
+ permissions=["netbox_acls.view_aclextendedrule"],
+ buttons=(
+ PluginMenuButton(
+ link="plugins:netbox_acls:aclextendedrule_add",
+ title="Add",
+ icon_class="mdi mdi-plus-thick",
+ color=ButtonColorChoices.GREEN,
+ permissions=["netbox_acls.add_aclextendedrule"],
+ ),
+ ),
+ ),
+ PluginMenuItem(
+ link="plugins:netbox_acls:aclinterfaceassignment_list",
+ link_text="Interface Assignments",
+ permissions=["netbox_acls.view_aclinterfaceassignment"],
+ buttons=(
+ PluginMenuButton(
+ link="plugins:netbox_acls:aclinterfaceassignment_add",
+ title="Add",
+ icon_class="mdi mdi-plus-thick",
+ color=ButtonColorChoices.GREEN,
+ permissions=["netbox_acls.add_aclinterfaceassignment"],
+ ),
+ ),
+ ),
+ ),
+ ),
),
+ icon_class="mdi mdi-lock",
)
diff --git a/netbox_acls/template_content.py b/netbox_acls/template_content.py
deleted file mode 100644
index 598e71d..0000000
--- a/netbox_acls/template_content.py
+++ /dev/null
@@ -1,98 +0,0 @@
-from django.contrib.contenttypes.models import ContentType
-from extras.plugins import PluginTemplateExtension
-
-from .models import AccessList, ACLInterfaceAssignment
-
-__all__ = (
- "AccessLists",
- "ACLInterfaceAssignments",
- "DeviceAccessLists",
- "VirtualChassisAccessLists",
- "VMAccessLists",
- "DeviceACLInterfaceAssignments",
- "VMAACLInterfaceAssignments",
-)
-
-
-class ACLInterfaceAssignments(PluginTemplateExtension):
- def right_page(self):
- obj = self.context["object"]
-
- acl_interface_assignments = None
- ctype = ContentType.objects.get_for_model(obj)
- if ctype.model in ["interface", "vminterface"]:
- acl_interface_assignments = ACLInterfaceAssignment.objects.filter(
- assigned_object_id=obj.pk,
- assigned_object_type=ctype,
- )
- if ctype.model == "interface":
- parent_type = "device"
- parent_id = obj.device.pk
- elif ctype.model == "vminterface":
- parent_type = "virtual_machine"
- parent_id = obj.virtual_machine.pk
- else:
- parent_type = None
- parent_id = None
-
- return self.render(
- "inc/assigned_interface/access_lists.html",
- extra_context={
- "acl_interface_assignments": acl_interface_assignments,
- "type": ctype.model,
- "parent_type": parent_type,
- "parent_id": parent_id,
- },
- )
-
-
-class AccessLists(PluginTemplateExtension):
- def right_page(self):
- obj = self.context["object"]
-
- access_lists = None
- ctype = ContentType.objects.get_for_model(obj)
- if ctype.model in ["device", "virtualchassis", "virtualmachine"]:
- access_lists = AccessList.objects.filter(
- assigned_object_id=obj.pk,
- assigned_object_type=ctype,
- )
-
- return self.render(
- "inc/assigned_host/access_lists.html",
- extra_context={
- "access_lists": access_lists,
- "type": ctype.model
- if ctype.model == "device"
- else ctype.name.replace(" ", "_"),
- },
- )
-
-
-class DeviceAccessLists(AccessLists):
- model = "dcim.device"
-
-
-class VirtualChassisAccessLists(AccessLists):
- model = "dcim.virtualchassis"
-
-
-class VMAccessLists(AccessLists):
- model = "virtualization.virtualmachine"
-
-
-class DeviceACLInterfaceAssignments(ACLInterfaceAssignments):
- model = "dcim.interface"
-
-
-class VMAACLInterfaceAssignments(ACLInterfaceAssignments):
- model = "virtualization.vminterface"
-
-
-template_extensions = [
- DeviceAccessLists,
- VirtualChassisAccessLists,
- VMAccessLists,
- DeviceACLInterfaceAssignments,
- VMAACLInterfaceAssignments,
-]
diff --git a/netbox_acls/templates/inc/assigned_host/access_lists.html b/netbox_acls/templates/inc/assigned_host/access_lists.html
deleted file mode 100644
index 9738fa9..0000000
--- a/netbox_acls/templates/inc/assigned_host/access_lists.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
- {% include 'inc/assigned_host/assigned_access_lists.html' %}
-
-
-
diff --git a/netbox_acls/templates/inc/assigned_host/assigned_access_lists.html b/netbox_acls/templates/inc/assigned_host/assigned_access_lists.html
deleted file mode 100644
index f7ce8a3..0000000
--- a/netbox_acls/templates/inc/assigned_host/assigned_access_lists.html
+++ /dev/null
@@ -1,27 +0,0 @@
-{% if access_lists %}
-
-
-
- | Name |
- Type |
- Default Action |
- Rule Count |
-
- {% for object in access_lists %}
-
- | {{ object|linkify }} |
- {{ object.type|title }} |
- {{ object.default_action|title }} |
- {% if object.type == 'standard' %}
- {{ object.aclstandardrules.count|placeholder }} |
- {% elif object.type == 'extended' %}
- {{ object.aclextendedrules.count|placeholder }} |
- {% endif %}
-
- {% endfor %}
-
-{% else %}
-
- None found
-
-{% endif %}
diff --git a/netbox_acls/templates/inc/assigned_interface/access_lists.html b/netbox_acls/templates/inc/assigned_interface/access_lists.html
deleted file mode 100644
index 165b0bf..0000000
--- a/netbox_acls/templates/inc/assigned_interface/access_lists.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
- {% include 'inc/assigned_interface/assigned_access_lists.html' %}
-
-
-
diff --git a/netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html b/netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html
deleted file mode 100644
index 26bb009..0000000
--- a/netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% if acl_interface_assignments %}
-
-
-
- | Name |
- Type |
- Default Action |
- Rule Count |
- Direction |
-
- {% for object in acl_interface_assignments %}
-
- | {{ object.access_list|linkify }} |
- {{ object.access_list.type|title }} |
- {{ object.access_list.default_action|title }} |
- {% if object.access_list.type == 'standard' %}
- {{ object.access_list.aclstandardrules.count|placeholder }} |
- {% elif object.access_list.type == 'extended' %}
- {{ object.access_list.aclextendedrules.count|placeholder }} |
- {% endif %}
- {{ object.direction|title }} |
-
- {% endfor %}
-
-{% else %}
-
- None
-
-{% endif %}
diff --git a/netbox_acls/templates/inc/view_tab.html b/netbox_acls/templates/inc/view_tab.html
new file mode 100644
index 0000000..2109252
--- /dev/null
+++ b/netbox_acls/templates/inc/view_tab.html
@@ -0,0 +1,31 @@
+{% extends 'generic/object.html' %}
+{% load buttons %}
+{% load helpers %}
+{% load plugins %}
+{% load render_table from django_tables2 %}
+
+{% block extra_controls %}
+ {% if perms.netbox_todo.add_accesslist %}
+
+ Add Access List
+
+ {% endif %}
+{% endblock extra_controls %}
+
+{% block content %}
+ {% include 'inc/table_controls_htmx.html' with table_modal=table_config %}
+
+{% endblock content %}
+
+{% block modals %}
+ {{ block.super }}
+ {% table_config_form table %}
+{% endblock modals %}
diff --git a/netbox_acls/urls.py b/netbox_acls/urls.py
index f5ed0db..c5f07a1 100644
--- a/netbox_acls/urls.py
+++ b/netbox_acls/urls.py
@@ -2,8 +2,8 @@
Map Views to URLs.
"""
-from django.urls import path
-from netbox.views.generic import ObjectChangeLogView
+from django.urls import include, path
+from utilities.urls import get_model_urls
from . import models, views
@@ -33,12 +33,8 @@ urlpatterns = (
name="accesslist_delete",
),
path(
- "access-lists//changelog/",
- ObjectChangeLogView.as_view(),
- name="accesslist_changelog",
- kwargs={
- "model": models.AccessList,
- },
+ "access-lists//",
+ include(get_model_urls("netbox_acls", "accesslist")),
),
# Access List Interface Assignments
path(
@@ -73,12 +69,8 @@ urlpatterns = (
name="aclinterfaceassignment_delete",
),
path(
- "interface-assignments//changelog/",
- ObjectChangeLogView.as_view(),
- name="aclinterfaceassignment_changelog",
- kwargs={
- "model": models.ACLInterfaceAssignment,
- },
+ "interface-assignments//",
+ include(get_model_urls("netbox_acls", "aclinterfaceassignment")),
),
# Standard Access List Rules
path(
@@ -112,12 +104,8 @@ urlpatterns = (
name="aclstandardrule_delete",
),
path(
- "standard-rules//changelog/",
- ObjectChangeLogView.as_view(),
- name="aclstandardrule_changelog",
- kwargs={
- "model": models.ACLStandardRule,
- },
+ "standard-rules//",
+ include(get_model_urls("netbox_acls", "aclstandardrule")),
),
# Extended Access List Rules
path(
@@ -151,11 +139,7 @@ urlpatterns = (
name="aclextendedrule_delete",
),
path(
- "extended-rules//changelog/",
- ObjectChangeLogView.as_view(),
- name="aclextendedrule_changelog",
- kwargs={
- "model": models.ACLExtendedRule,
- },
+ "extended-rules//",
+ include(get_model_urls("netbox_acls", "aclextendedrule")),
),
)
diff --git a/netbox_acls/views.py b/netbox_acls/views.py
index 853f9b9..d986945 100644
--- a/netbox_acls/views.py
+++ b/netbox_acls/views.py
@@ -3,8 +3,11 @@ Defines the business logic for the plugin.
Specifically, all the various interactions with a client.
"""
+from dcim.models import Device, Interface, VirtualChassis
from django.db.models import Count
from netbox.views import generic
+from utilities.views import ViewTab, register_model_view
+from virtualization.models import VirtualMachine, VMInterface
from . import choices, filtersets, forms, models, tables
@@ -37,12 +40,13 @@ __all__ = (
#
+@register_model_view(models.AccessList)
class AccessListView(generic.ObjectView):
"""
Defines the view for the AccessLists django model.
"""
- queryset = models.AccessList.objects.all()
+ queryset = models.AccessList.objects.prefetch_related("tags")
def get_extra_context(self, request, instance):
"""
@@ -73,47 +77,121 @@ class AccessListListView(generic.ObjectListView):
queryset = models.AccessList.objects.annotate(
rule_count=Count("aclextendedrules") + Count("aclstandardrules"),
- )
+ ).prefetch_related("tags")
table = tables.AccessListTable
filterset = filtersets.AccessListFilterSet
filterset_form = forms.AccessListFilterForm
+@register_model_view(models.AccessList, "edit")
class AccessListEditView(generic.ObjectEditView):
"""
Defines the edit view for the AccessLists django model.
"""
- queryset = models.AccessList.objects.all()
+ queryset = models.AccessList.objects.prefetch_related("tags")
form = forms.AccessListForm
template_name = "netbox_acls/accesslist_edit.html"
+@register_model_view(models.AccessList, "delete")
class AccessListDeleteView(generic.ObjectDeleteView):
"""
Defines delete view for the AccessLists django model.
"""
- queryset = models.AccessList.objects.all()
+ queryset = models.AccessList.objects.prefetch_related("tags")
class AccessListBulkDeleteView(generic.BulkDeleteView):
- queryset = models.AccessList.objects.all()
+ queryset = models.AccessList.objects.prefetch_related("tags")
filterset = filtersets.AccessListFilterSet
table = tables.AccessListTable
+class AccessListChildView(generic.ObjectChildrenView):
+ """
+ Defines the child view for the AccessLists model.
+ """
+
+ child_model = models.AccessList
+ table = tables.AccessListTable
+ filterset = filtersets.AccessListFilterSet
+ template_name = "inc/view_tab.html"
+
+ def get_extra_context(self, request, instance):
+ return {
+ "table_config": self.table.__name__,
+ "model_type": self.queryset.model._meta.verbose_name.replace(" ", "_"),
+ "add_url": "plugins:netbox_acls:accesslist_add",
+ }
+
+ def prep_table_data(self, request, queryset, parent):
+ return queryset.annotate(
+ rule_count=Count("aclextendedrules") + Count("aclstandardrules"),
+ )
+
+
+@register_model_view(Device, "access_lists")
+class DeviceAccessListView(AccessListChildView):
+ queryset = Device.objects.prefetch_related("tags")
+ tab = ViewTab(
+ label="Access Lists",
+ badge=lambda obj: models.AccessList.objects.filter(device=obj).count(),
+ permission="netbox_acls.view_accesslist",
+ )
+
+ def get_children(self, request, parent):
+ return self.child_model.objects.restrict(request.user, "view").filter(
+ device=parent,
+ )
+
+
+@register_model_view(VirtualChassis, "access_lists")
+class VirtualChassisAccessListView(AccessListChildView):
+ queryset = VirtualChassis.objects.prefetch_related("tags")
+ tab = ViewTab(
+ label="Access Lists",
+ badge=lambda obj: models.AccessList.objects.filter(virtual_chassis=obj).count(),
+ permission="netbox_acls.view_accesslist",
+ )
+
+ def get_children(self, request, parent):
+ return self.child_model.objects.restrict(request.user, "view").filter(
+ virtual_chassis=parent,
+ )
+
+
+@register_model_view(VirtualMachine, "access_lists")
+class VirtualMachineAccessListView(AccessListChildView):
+ queryset = VirtualMachine.objects.prefetch_related("tags")
+ tab = ViewTab(
+ label="Access Lists",
+ badge=lambda obj: models.AccessList.objects.filter(virtual_machine=obj).count(),
+ permission="netbox_acls.view_accesslist",
+ )
+
+ def get_children(self, request, parent):
+ return self.child_model.objects.restrict(request.user, "view").filter(
+ virtual_machine=parent,
+ )
+
+
#
# ACLInterfaceAssignment views
#
+@register_model_view(models.ACLInterfaceAssignment)
class ACLInterfaceAssignmentView(generic.ObjectView):
"""
Defines the view for the ACLInterfaceAssignments django model.
"""
- queryset = models.ACLInterfaceAssignment.objects.all()
+ queryset = models.ACLInterfaceAssignment.objects.prefetch_related(
+ "access_list",
+ "tags",
+ )
class ACLInterfaceAssignmentListView(generic.ObjectListView):
@@ -121,18 +199,25 @@ class ACLInterfaceAssignmentListView(generic.ObjectListView):
Defines the list view for the ACLInterfaceAssignments django model.
"""
- queryset = models.ACLInterfaceAssignment.objects.all()
+ queryset = models.ACLInterfaceAssignment.objects.prefetch_related(
+ "access_list",
+ "tags",
+ )
table = tables.ACLInterfaceAssignmentTable
filterset = filtersets.ACLInterfaceAssignmentFilterSet
filterset_form = forms.ACLInterfaceAssignmentFilterForm
+@register_model_view(models.ACLInterfaceAssignment, "edit")
class ACLInterfaceAssignmentEditView(generic.ObjectEditView):
"""
Defines the edit view for the ACLInterfaceAssignments django model.
"""
- queryset = models.ACLInterfaceAssignment.objects.all()
+ queryset = models.ACLInterfaceAssignment.objects.prefetch_related(
+ "access_list",
+ "tags",
+ )
form = forms.ACLInterfaceAssignmentForm
template_name = "netbox_acls/aclinterfaceassignment_edit.html"
@@ -148,31 +233,97 @@ class ACLInterfaceAssignmentEditView(generic.ObjectEditView):
}
+@register_model_view(models.ACLInterfaceAssignment, "delete")
class ACLInterfaceAssignmentDeleteView(generic.ObjectDeleteView):
"""
Defines delete view for the ACLInterfaceAssignments django model.
"""
- queryset = models.ACLInterfaceAssignment.objects.all()
+ queryset = models.ACLInterfaceAssignment.objects.prefetch_related(
+ "access_list",
+ "tags",
+ )
class ACLInterfaceAssignmentBulkDeleteView(generic.BulkDeleteView):
- queryset = models.ACLInterfaceAssignment.objects.all()
+ queryset = models.ACLInterfaceAssignment.objects.prefetch_related(
+ "access_list",
+ "tags",
+ )
filterset = filtersets.ACLInterfaceAssignmentFilterSet
table = tables.ACLInterfaceAssignmentTable
+class ACLInterfaceAssignmentChildView(generic.ObjectChildrenView):
+ """
+ Defines the child view for the ACLInterfaceAssignments model.
+ """
+
+ child_model = models.ACLInterfaceAssignment
+ table = tables.ACLInterfaceAssignmentTable
+ filterset = filtersets.ACLInterfaceAssignmentFilterSet
+ template_name = "inc/view_tab.html"
+
+ def get_extra_context(self, request, instance):
+ return {
+ "table_config": self.table.__name__,
+ "model_type": self.queryset.model._meta.verbose_name.replace(" ", "_"),
+ "add_url": "plugins:netbox_acls:aclinterfaceassignment_add",
+ }
+
+
+@register_model_view(Interface, "acl_interface_assignments")
+class InterfaceACLInterfaceAssignmentView(ACLInterfaceAssignmentChildView):
+ queryset = Interface.objects.prefetch_related("device", "tags")
+ tab = ViewTab(
+ label="ACL Interface Assignments",
+ badge=lambda obj: models.ACLInterfaceAssignment.objects.filter(
+ interface=obj,
+ ).count(),
+ permission="netbox_acls.view_aclinterfaceassignment",
+ )
+
+ def get_children(self, request, parent):
+ return self.child_model.objects.restrict(request.user, "view").filter(
+ interface=parent,
+ )
+
+
+@register_model_view(VMInterface, "acl_interface_assignments")
+class VirtualMachineInterfaceACLInterfaceAssignmentView(
+ ACLInterfaceAssignmentChildView,
+):
+ queryset = VMInterface.objects.prefetch_related("virtual_machine", "tags")
+ tab = ViewTab(
+ label="ACL Interface Assignments",
+ badge=lambda obj: models.ACLInterfaceAssignment.objects.filter(
+ vminterface=obj,
+ ).count(),
+ permission="netbox_acls.view_aclinterfaceassignment",
+ )
+
+ def get_children(self, request, parent):
+ return self.child_model.objects.restrict(request.user, "view").filter(
+ vminterface=parent,
+ )
+
+
#
# ACLStandardRule views
#
+@register_model_view(models.ACLStandardRule)
class ACLStandardRuleView(generic.ObjectView):
"""
Defines the view for the ACLStandardRule django model.
"""
- queryset = models.ACLStandardRule.objects.all()
+ queryset = models.ACLStandardRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ )
class ACLStandardRuleListView(generic.ObjectListView):
@@ -180,18 +331,27 @@ class ACLStandardRuleListView(generic.ObjectListView):
Defines the list view for the ACLStandardRule django model.
"""
- queryset = models.ACLStandardRule.objects.all()
+ queryset = models.ACLStandardRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ )
table = tables.ACLStandardRuleTable
filterset = filtersets.ACLStandardRuleFilterSet
filterset_form = forms.ACLStandardRuleFilterForm
+@register_model_view(models.ACLStandardRule, "edit")
class ACLStandardRuleEditView(generic.ObjectEditView):
"""
Defines the edit view for the ACLStandardRule django model.
"""
- queryset = models.ACLStandardRule.objects.all()
+ queryset = models.ACLStandardRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ )
form = forms.ACLStandardRuleForm
def get_extra_addanother_params(self, request):
@@ -205,16 +365,25 @@ class ACLStandardRuleEditView(generic.ObjectEditView):
}
+@register_model_view(models.ACLStandardRule, "delete")
class ACLStandardRuleDeleteView(generic.ObjectDeleteView):
"""
Defines delete view for the ACLStandardRules django model.
"""
- queryset = models.ACLStandardRule.objects.all()
+ queryset = models.ACLStandardRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ )
class ACLStandardRuleBulkDeleteView(generic.BulkDeleteView):
- queryset = models.ACLStandardRule.objects.all()
+ queryset = models.ACLStandardRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ )
filterset = filtersets.ACLStandardRuleFilterSet
table = tables.ACLStandardRuleTable
@@ -224,12 +393,18 @@ class ACLStandardRuleBulkDeleteView(generic.BulkDeleteView):
#
+@register_model_view(models.ACLExtendedRule)
class ACLExtendedRuleView(generic.ObjectView):
"""
Defines the view for the ACLExtendedRule django model.
"""
- queryset = models.ACLExtendedRule.objects.all()
+ queryset = models.ACLExtendedRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ "destination_prefix",
+ )
class ACLExtendedRuleListView(generic.ObjectListView):
@@ -237,18 +412,29 @@ class ACLExtendedRuleListView(generic.ObjectListView):
Defines the list view for the ACLExtendedRule django model.
"""
- queryset = models.ACLExtendedRule.objects.all()
+ queryset = models.ACLExtendedRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ "destination_prefix",
+ )
table = tables.ACLExtendedRuleTable
filterset = filtersets.ACLExtendedRuleFilterSet
filterset_form = forms.ACLExtendedRuleFilterForm
+@register_model_view(models.ACLExtendedRule, "edit")
class ACLExtendedRuleEditView(generic.ObjectEditView):
"""
Defines the edit view for the ACLExtendedRule django model.
"""
- queryset = models.ACLExtendedRule.objects.all()
+ queryset = models.ACLExtendedRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ "destination_prefix",
+ )
form = forms.ACLExtendedRuleForm
def get_extra_addanother_params(self, request):
@@ -262,15 +448,26 @@ class ACLExtendedRuleEditView(generic.ObjectEditView):
}
+@register_model_view(models.ACLExtendedRule, "delete")
class ACLExtendedRuleDeleteView(generic.ObjectDeleteView):
"""
Defines delete view for the ACLExtendedRules django model.
"""
- queryset = models.ACLExtendedRule.objects.all()
+ queryset = models.ACLExtendedRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ "destination_prefix",
+ )
class ACLExtendedRuleBulkDeleteView(generic.BulkDeleteView):
- queryset = models.ACLExtendedRule.objects.all()
+ queryset = models.ACLExtendedRule.objects.prefetch_related(
+ "access_list",
+ "tags",
+ "source_prefix",
+ "destination_prefix",
+ )
filterset = filtersets.ACLExtendedRuleFilterSet
table = tables.ACLExtendedRuleTable
diff --git a/setup.py b/setup.py
index 1b55f67..eada466 100644
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,7 @@ def get_version(rel_path):
setup(
name="netbox-acls",
+ version="1.2.0",
version=get_version("netbox_acls/version.py"),
description="A NetBox plugin for Access List management",
long_description=long_description,