151 lines
5.4 KiB
Python
151 lines
5.4 KiB
Python
from dcim.models import ModuleBay
|
|
from django.middleware.csrf import get_token
|
|
from django.urls import reverse
|
|
from netbox.plugins import PluginTemplateExtension
|
|
from tenancy.models import Tenant, TenantGroup
|
|
|
|
from . import __version__
|
|
from .models import (
|
|
CableVLANAssignment,
|
|
DeviceRackPlacement,
|
|
NavigationPreference,
|
|
WirelessLinkVLANAssignment,
|
|
)
|
|
from .navigation_helpers import (
|
|
SIDEBAR_WIDTH_DEFAULT,
|
|
SIDEBAR_WIDTH_MAX,
|
|
SIDEBAR_WIDTH_MIN,
|
|
get_visible_menus,
|
|
normalize_preferences,
|
|
normalize_sidebar_width,
|
|
)
|
|
from .runtime import connection_vlans_enabled, navigation_customization_enabled, tenant_filter_enabled
|
|
|
|
|
|
class UtilitiesGlobalContent(PluginTemplateExtension):
|
|
def head(self):
|
|
request = self.context["request"]
|
|
preference_data = {
|
|
"order": [],
|
|
"hidden": [],
|
|
"menus": [],
|
|
"collapsed": False,
|
|
"width": SIDEBAR_WIDTH_DEFAULT,
|
|
}
|
|
if request.user.is_authenticated and navigation_customization_enabled():
|
|
descriptors = get_visible_menus(request.user)
|
|
preference = NavigationPreference.objects.filter(user=request.user).first()
|
|
order, hidden = normalize_preferences(
|
|
preference.menu_order if preference else [],
|
|
preference.hidden_menus if preference else [],
|
|
[item["key"] for item in descriptors],
|
|
)
|
|
preference_data = {
|
|
"order": order,
|
|
"hidden": hidden,
|
|
"menus": descriptors,
|
|
"collapsed": preference.sidebar_collapsed if preference else False,
|
|
"width": normalize_sidebar_width(preference.sidebar_width if preference else SIDEBAR_WIDTH_DEFAULT),
|
|
"width_min": SIDEBAR_WIDTH_MIN,
|
|
"width_max": SIDEBAR_WIDTH_MAX,
|
|
"layout_update_url": reverse("plugins:netbox_utilities:navigation_layout"),
|
|
"csrf_token": get_token(request),
|
|
}
|
|
return self.render(
|
|
"netbox_utilities/head.html",
|
|
{
|
|
"frontend_enabled": request.user.is_authenticated,
|
|
"frontend_data": {
|
|
"image_attachment_add_url": reverse("extras:imageattachment_add"),
|
|
"bulk_image_upload_url": reverse("plugins:netbox_utilities:bulk_image_upload"),
|
|
},
|
|
"navigation_enabled": request.user.is_authenticated and navigation_customization_enabled(),
|
|
"navigation_preferences": preference_data,
|
|
"asset_version": __version__,
|
|
},
|
|
)
|
|
|
|
def navbar(self):
|
|
request = self.context["request"]
|
|
if not request.user.is_authenticated or not tenant_filter_enabled():
|
|
return ""
|
|
|
|
tenants = Tenant.objects.restrict(request.user, "view").order_by("name")
|
|
tenant_groups = TenantGroup.objects.restrict(request.user, "view").order_by("name")
|
|
return self.render(
|
|
"netbox_utilities/tenant_dropdown.html",
|
|
{
|
|
"tenants": tenants,
|
|
"tenant_groups": tenant_groups,
|
|
"selected_tenant": getattr(request, "netbox_utilities_tenant", None),
|
|
"selected_tenant_group": getattr(request, "netbox_utilities_tenant_group", None),
|
|
"return_url": request.get_full_path(),
|
|
},
|
|
)
|
|
|
|
|
|
class DeviceUtilitiesContent(PluginTemplateExtension):
|
|
models = ["dcim.device"]
|
|
|
|
def buttons(self):
|
|
request = self.context["request"]
|
|
device = self.context["object"]
|
|
if not request.user.has_perm("dcim.add_module"):
|
|
return ""
|
|
if (
|
|
not ModuleBay.objects.restrict(request.user, "view")
|
|
.filter(
|
|
device=device,
|
|
enabled=True,
|
|
installed_module__isnull=True,
|
|
)
|
|
.exists()
|
|
):
|
|
return ""
|
|
return self.render("netbox_utilities/device_bulk_module_button.html")
|
|
|
|
def right_page(self):
|
|
placement = DeviceRackPlacement.objects.filter(device=self.context["object"]).first()
|
|
if placement is None:
|
|
return ""
|
|
return self.render(
|
|
"netbox_utilities/device_rack_width_panel.html",
|
|
{
|
|
"rack_width": f"1/{placement.width}",
|
|
"horizontal_position": placement.horizontal_position,
|
|
},
|
|
)
|
|
|
|
|
|
class ConnectionVLANContent(PluginTemplateExtension):
|
|
models = ["dcim.cable", "wireless.wirelesslink"]
|
|
|
|
def right_page(self):
|
|
if not connection_vlans_enabled():
|
|
return ""
|
|
|
|
connection = self.context["object"]
|
|
if connection._meta.label_lower == "dcim.cable":
|
|
assignment_model = CableVLANAssignment
|
|
lookup = {"cable": connection}
|
|
else:
|
|
assignment_model = WirelessLinkVLANAssignment
|
|
lookup = {"wireless_link": connection}
|
|
|
|
assignment = assignment_model.objects.filter(**lookup).first()
|
|
if assignment is None:
|
|
return ""
|
|
|
|
from ipam.models import VLAN
|
|
|
|
visible_vlans = VLAN.objects.restrict(self.context["request"].user, "view").filter(
|
|
pk__in=assignment.vlans.values("pk")
|
|
)
|
|
return self.render(
|
|
"netbox_utilities/connection_vlans_panel.html",
|
|
{"connection_vlans": visible_vlans},
|
|
)
|
|
|
|
|
|
template_extensions = [UtilitiesGlobalContent, DeviceUtilitiesContent, ConnectionVLANContent]
|