From 6591ea0b296aa07b2c0142a8c4c0b7a5459e1835 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Mon, 23 Jan 2023 17:51:01 +0530 Subject: [PATCH] Support for NetBox v3.4 (#99) * initial changes for nb 3.4 --- .devcontainer/Dockerfile-plugin_dev | 4 +- .github/ISSUE_TEMPLATE/bug_report.yml | 4 +- .github/ISSUE_TEMPLATE/feature_request.yml | 2 +- README.md | 11 +- netbox_acls/__init__.py | 5 +- netbox_acls/api/views.py | 8 +- netbox_acls/navigation.py | 137 +++++----- netbox_acls/template_content.py | 98 -------- .../inc/assigned_host/access_lists.html | 13 - .../assigned_host/assigned_access_lists.html | 27 -- .../inc/assigned_interface/access_lists.html | 13 - .../assigned_access_lists.html | 29 --- netbox_acls/templates/inc/view_tab.html | 31 +++ netbox_acls/urls.py | 36 +-- netbox_acls/views.py | 237 ++++++++++++++++-- setup.py | 1 + 16 files changed, 345 insertions(+), 311 deletions(-) delete mode 100644 netbox_acls/template_content.py delete mode 100644 netbox_acls/templates/inc/assigned_host/access_lists.html delete mode 100644 netbox_acls/templates/inc/assigned_host/assigned_access_lists.html delete mode 100644 netbox_acls/templates/inc/assigned_interface/access_lists.html delete mode 100644 netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html create mode 100644 netbox_acls/templates/inc/view_tab.html 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 @@ -
-
- Access Lists -
-
- {% 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 %} - - - - - - - - - {% for object in access_lists %} - - - - - {% if object.type == 'standard' %} - - {% elif object.type == 'extended' %} - - {% endif %} - - {% endfor %} -
NameTypeDefault ActionRule Count
{{ object|linkify }}{{ object.type|title }}{{ object.default_action|title }}{{ object.aclstandardrules.count|placeholder }}{{ object.aclextendedrules.count|placeholder }}
-{% 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 @@ -
-
- Access Lists -
-
- {% 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 %} - - - - - - - - - - {% for object in acl_interface_assignments %} - - - - - {% if object.access_list.type == 'standard' %} - - {% elif object.access_list.type == 'extended' %} - - {% endif %} - - - {% endfor %} -
NameTypeDefault ActionRule CountDirection
{{ object.access_list|linkify }}{{ object.access_list.type|title }}{{ object.access_list.default_action|title }}{{ object.access_list.aclstandardrules.count|placeholder }}{{ object.access_list.aclextendedrules.count|placeholder }}{{ object.direction|title }}
-{% 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 %} +
+ {% csrf_token %} +
+
+ {% include 'htmx/table.html' %} +
+
+
+{% 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,