mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Introduce ObjectView to enforce object-level permissions for individual object views
This commit is contained in:
parent
8fd860a413
commit
e61fc1f709
@ -4,6 +4,10 @@ Utility views are reusable views that handle common CRUD tasks, such as listing
|
|||||||
|
|
||||||
## Individual Views
|
## Individual Views
|
||||||
|
|
||||||
|
### ObjectView
|
||||||
|
|
||||||
|
Retrieve and display a single object.
|
||||||
|
|
||||||
### ObjectListView
|
### ObjectListView
|
||||||
|
|
||||||
Generates a paginated table of objects from a given queryset, which may optionally be filtered.
|
Generates a paginated table of objects from a given queryset, which may optionally be filtered.
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Count, OuterRef
|
from django.db.models import Count, OuterRef
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.views.generic import View
|
|
||||||
from django_tables2 import RequestConfig
|
from django_tables2 import RequestConfig
|
||||||
|
|
||||||
from extras.models import Graph
|
from extras.models import Graph
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
from utilities.paginator import EnhancedPaginator
|
from utilities.paginator import EnhancedPaginator
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
)
|
)
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .choices import CircuitTerminationSideChoices
|
from .choices import CircuitTerminationSideChoices
|
||||||
@ -30,12 +28,12 @@ class ProviderListView(ObjectListView):
|
|||||||
table = tables.ProviderTable
|
table = tables.ProviderTable
|
||||||
|
|
||||||
|
|
||||||
class ProviderView(PermissionRequiredMixin, View):
|
class ProviderView(ObjectView):
|
||||||
permission_required = 'circuits.view_provider'
|
queryset = Provider.objects.all()
|
||||||
|
|
||||||
def get(self, request, slug):
|
def get(self, request, slug):
|
||||||
|
|
||||||
provider = get_object_or_404(Provider, slug=slug)
|
provider = get_object_or_404(self.queryset, slug=slug)
|
||||||
circuits = Circuit.objects.filter(
|
circuits = Circuit.objects.filter(
|
||||||
provider=provider
|
provider=provider
|
||||||
).prefetch_related(
|
).prefetch_related(
|
||||||
@ -135,12 +133,12 @@ class CircuitListView(ObjectListView):
|
|||||||
table = tables.CircuitTable
|
table = tables.CircuitTable
|
||||||
|
|
||||||
|
|
||||||
class CircuitView(PermissionRequiredMixin, View):
|
class CircuitView(ObjectView):
|
||||||
permission_required = 'circuits.view_circuit'
|
queryset = Circuit.objects.prefetch_related('provider', 'type', 'tenant__group')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
circuit = get_object_or_404(Circuit.objects.prefetch_related('provider', 'type', 'tenant__group'), pk=pk)
|
circuit = get_object_or_404(self.queryset, pk=pk)
|
||||||
termination_a = CircuitTermination.objects.prefetch_related(
|
termination_a = CircuitTermination.objects.prefetch_related(
|
||||||
'site__region', 'connected_endpoint__device'
|
'site__region', 'connected_endpoint__device'
|
||||||
).filter(
|
).filter(
|
||||||
|
@ -26,7 +26,7 @@ from utilities.paginator import EnhancedPaginator
|
|||||||
from utilities.utils import csv_format
|
from utilities.utils import csv_format
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, GetReturnURLMixin,
|
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, GetReturnURLMixin,
|
||||||
ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView, ObjectPermissionRequiredMixin,
|
ObjectView, ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView, ObjectPermissionRequiredMixin,
|
||||||
)
|
)
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
@ -185,8 +185,7 @@ class SiteListView(ObjectListView):
|
|||||||
table = tables.SiteTable
|
table = tables.SiteTable
|
||||||
|
|
||||||
|
|
||||||
class SiteView(ObjectPermissionRequiredMixin, View):
|
class SiteView(ObjectView):
|
||||||
permission_required = 'dcim.view_site'
|
|
||||||
queryset = Site.objects.prefetch_related('region', 'tenant__group')
|
queryset = Site.objects.prefetch_related('region', 'tenant__group')
|
||||||
|
|
||||||
def get(self, request, slug):
|
def get(self, request, slug):
|
||||||
@ -362,12 +361,12 @@ class RackElevationListView(PermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class RackView(PermissionRequiredMixin, View):
|
class RackView(ObjectView):
|
||||||
permission_required = 'dcim.view_rack'
|
queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
rack = get_object_or_404(Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role'), pk=pk)
|
rack = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
nonracked_devices = Device.objects.filter(
|
nonracked_devices = Device.objects.filter(
|
||||||
rack=rack,
|
rack=rack,
|
||||||
@ -440,12 +439,12 @@ class RackReservationListView(ObjectListView):
|
|||||||
action_buttons = ('export',)
|
action_buttons = ('export',)
|
||||||
|
|
||||||
|
|
||||||
class RackReservationView(PermissionRequiredMixin, View):
|
class RackReservationView(ObjectView):
|
||||||
permission_required = 'dcim.view_rackreservation'
|
queryset = RackReservation.objects.prefetch_related('rack')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
rackreservation = get_object_or_404(RackReservation.objects.prefetch_related('rack'), pk=pk)
|
rackreservation = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'dcim/rackreservation.html', {
|
return render(request, 'dcim/rackreservation.html', {
|
||||||
'rackreservation': rackreservation,
|
'rackreservation': rackreservation,
|
||||||
@ -546,12 +545,12 @@ class DeviceTypeListView(ObjectListView):
|
|||||||
table = tables.DeviceTypeTable
|
table = tables.DeviceTypeTable
|
||||||
|
|
||||||
|
|
||||||
class DeviceTypeView(PermissionRequiredMixin, View):
|
class DeviceTypeView(ObjectView):
|
||||||
permission_required = 'dcim.view_devicetype'
|
queryset = DeviceType.objects.prefetch_related('manufacturer')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
devicetype = get_object_or_404(DeviceType, pk=pk)
|
devicetype = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Component tables
|
# Component tables
|
||||||
consoleport_table = tables.ConsolePortTemplateTable(
|
consoleport_table = tables.ConsolePortTemplateTable(
|
||||||
@ -990,14 +989,14 @@ class DeviceListView(ObjectListView):
|
|||||||
template_name = 'dcim/device_list.html'
|
template_name = 'dcim/device_list.html'
|
||||||
|
|
||||||
|
|
||||||
class DeviceView(PermissionRequiredMixin, View):
|
class DeviceView(ObjectView):
|
||||||
permission_required = 'dcim.view_device'
|
queryset = Device.objects.prefetch_related(
|
||||||
|
'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform'
|
||||||
|
)
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
device = get_object_or_404(Device.objects.prefetch_related(
|
device = get_object_or_404(self.queryset, pk=pk)
|
||||||
'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform'
|
|
||||||
), pk=pk)
|
|
||||||
|
|
||||||
# VirtualChassis members
|
# VirtualChassis members
|
||||||
if device.virtual_chassis is not None:
|
if device.virtual_chassis is not None:
|
||||||
@ -1068,12 +1067,12 @@ class DeviceView(PermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class DeviceInventoryView(PermissionRequiredMixin, View):
|
class DeviceInventoryView(ObjectView):
|
||||||
permission_required = 'dcim.view_device'
|
queryset = Device.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
device = get_object_or_404(Device, pk=pk)
|
device = get_object_or_404(self.queryset, pk=pk)
|
||||||
inventory_items = InventoryItem.objects.filter(
|
inventory_items = InventoryItem.objects.filter(
|
||||||
device=device, parent=None
|
device=device, parent=None
|
||||||
).prefetch_related(
|
).prefetch_related(
|
||||||
@ -1087,12 +1086,13 @@ class DeviceInventoryView(PermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class DeviceStatusView(PermissionRequiredMixin, View):
|
class DeviceStatusView(ObjectView):
|
||||||
permission_required = ('dcim.view_device', 'dcim.napalm_read')
|
permission_required = ('dcim.view_device', 'dcim.napalm_read')
|
||||||
|
queryset = Device.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
device = get_object_or_404(Device, pk=pk)
|
device = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'dcim/device_status.html', {
|
return render(request, 'dcim/device_status.html', {
|
||||||
'device': device,
|
'device': device,
|
||||||
@ -1102,10 +1102,11 @@ class DeviceStatusView(PermissionRequiredMixin, View):
|
|||||||
|
|
||||||
class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
|
class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
|
||||||
permission_required = ('dcim.view_device', 'dcim.napalm_read')
|
permission_required = ('dcim.view_device', 'dcim.napalm_read')
|
||||||
|
queryset = Device.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
device = get_object_or_404(Device, pk=pk)
|
device = get_object_or_404(self.queryset, pk=pk)
|
||||||
interfaces = device.vc_interfaces.exclude(type__in=NONCONNECTABLE_IFACE_TYPES).prefetch_related(
|
interfaces = device.vc_interfaces.exclude(type__in=NONCONNECTABLE_IFACE_TYPES).prefetch_related(
|
||||||
'_connected_interface__device'
|
'_connected_interface__device'
|
||||||
)
|
)
|
||||||
@ -1119,10 +1120,11 @@ class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
|
|||||||
|
|
||||||
class DeviceConfigView(PermissionRequiredMixin, View):
|
class DeviceConfigView(PermissionRequiredMixin, View):
|
||||||
permission_required = ('dcim.view_device', 'dcim.napalm_read')
|
permission_required = ('dcim.view_device', 'dcim.napalm_read')
|
||||||
|
queryset = Device.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
device = get_object_or_404(Device, pk=pk)
|
device = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'dcim/device_config.html', {
|
return render(request, 'dcim/device_config.html', {
|
||||||
'device': device,
|
'device': device,
|
||||||
@ -1426,12 +1428,12 @@ class InterfaceListView(ObjectListView):
|
|||||||
action_buttons = ('import', 'export')
|
action_buttons = ('import', 'export')
|
||||||
|
|
||||||
|
|
||||||
class InterfaceView(PermissionRequiredMixin, View):
|
class InterfaceView(ObjectView):
|
||||||
permission_required = 'dcim.view_interface'
|
queryset = Interface.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
interface = get_object_or_404(Interface, pk=pk)
|
interface = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Get assigned IP addresses
|
# Get assigned IP addresses
|
||||||
ipaddress_table = InterfaceIPAddressTable(
|
ipaddress_table = InterfaceIPAddressTable(
|
||||||
@ -1878,12 +1880,12 @@ class CableListView(ObjectListView):
|
|||||||
action_buttons = ('import', 'export')
|
action_buttons = ('import', 'export')
|
||||||
|
|
||||||
|
|
||||||
class CableView(PermissionRequiredMixin, View):
|
class CableView(ObjectView):
|
||||||
permission_required = 'dcim.view_cable'
|
queryset = Cable.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
cable = get_object_or_404(Cable, pk=pk)
|
cable = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'dcim/cable.html', {
|
return render(request, 'dcim/cable.html', {
|
||||||
'cable': cable,
|
'cable': cable,
|
||||||
@ -2194,11 +2196,11 @@ class VirtualChassisListView(ObjectListView):
|
|||||||
action_buttons = ('export',)
|
action_buttons = ('export',)
|
||||||
|
|
||||||
|
|
||||||
class VirtualChassisView(PermissionRequiredMixin, View):
|
class VirtualChassisView(ObjectView):
|
||||||
permission_required = 'dcim.view_virtualchassis'
|
queryset = VirtualChassis.objects.prefetch_related('members')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
virtualchassis = get_object_or_404(VirtualChassis.objects.prefetch_related('members'), pk=pk)
|
virtualchassis = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'dcim/virtualchassis.html', {
|
return render(request, 'dcim/virtualchassis.html', {
|
||||||
'virtualchassis': virtualchassis,
|
'virtualchassis': virtualchassis,
|
||||||
@ -2461,12 +2463,12 @@ class PowerPanelListView(ObjectListView):
|
|||||||
table = tables.PowerPanelTable
|
table = tables.PowerPanelTable
|
||||||
|
|
||||||
|
|
||||||
class PowerPanelView(PermissionRequiredMixin, View):
|
class PowerPanelView(ObjectView):
|
||||||
permission_required = 'dcim.view_powerpanel'
|
queryset = PowerPanel.objects.prefetch_related('site', 'rack_group')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
powerpanel = get_object_or_404(PowerPanel.objects.prefetch_related('site', 'rack_group'), pk=pk)
|
powerpanel = get_object_or_404(self.queryset, pk=pk)
|
||||||
powerfeed_table = tables.PowerFeedTable(
|
powerfeed_table = tables.PowerFeedTable(
|
||||||
data=PowerFeed.objects.filter(power_panel=powerpanel).prefetch_related('rack'),
|
data=PowerFeed.objects.filter(power_panel=powerpanel).prefetch_related('rack'),
|
||||||
orderable=False
|
orderable=False
|
||||||
@ -2529,12 +2531,12 @@ class PowerFeedListView(ObjectListView):
|
|||||||
table = tables.PowerFeedTable
|
table = tables.PowerFeedTable
|
||||||
|
|
||||||
|
|
||||||
class PowerFeedView(PermissionRequiredMixin, View):
|
class PowerFeedView(ObjectView):
|
||||||
permission_required = 'dcim.view_powerfeed'
|
queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
powerfeed = get_object_or_404(PowerFeed.objects.prefetch_related('power_panel', 'rack'), pk=pk)
|
powerfeed = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'dcim/powerfeed.html', {
|
return render(request, 'dcim/powerfeed.html', {
|
||||||
'powerfeed': powerfeed,
|
'powerfeed': powerfeed,
|
||||||
|
@ -13,7 +13,7 @@ from django_tables2 import RequestConfig
|
|||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
from utilities.paginator import EnhancedPaginator
|
from utilities.paginator import EnhancedPaginator
|
||||||
from utilities.utils import shallow_compare_dict
|
from utilities.utils import shallow_compare_dict
|
||||||
from utilities.views import BulkDeleteView, BulkEditView, ObjectDeleteView, ObjectEditView, ObjectListView
|
from utilities.views import BulkDeleteView, BulkEditView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView
|
||||||
from . import filters, forms
|
from . import filters, forms
|
||||||
from .models import ConfigContext, ImageAttachment, ObjectChange, ReportResult, Tag, TaggedItem
|
from .models import ConfigContext, ImageAttachment, ObjectChange, ReportResult, Tag, TaggedItem
|
||||||
from .reports import get_report, get_reports
|
from .reports import get_report, get_reports
|
||||||
@ -37,12 +37,12 @@ class TagListView(ObjectListView):
|
|||||||
action_buttons = ()
|
action_buttons = ()
|
||||||
|
|
||||||
|
|
||||||
class TagView(PermissionRequiredMixin, View):
|
class TagView(ObjectView):
|
||||||
permission_required = 'extras.view_tag'
|
queryset = Tag.objects.all()
|
||||||
|
|
||||||
def get(self, request, slug):
|
def get(self, request, slug):
|
||||||
|
|
||||||
tag = get_object_or_404(Tag, slug=slug)
|
tag = get_object_or_404(self.queryset, slug=slug)
|
||||||
tagged_items = TaggedItem.objects.filter(
|
tagged_items = TaggedItem.objects.filter(
|
||||||
tag=tag
|
tag=tag
|
||||||
).prefetch_related(
|
).prefetch_related(
|
||||||
@ -109,11 +109,11 @@ class ConfigContextListView(ObjectListView):
|
|||||||
action_buttons = ('add',)
|
action_buttons = ('add',)
|
||||||
|
|
||||||
|
|
||||||
class ConfigContextView(PermissionRequiredMixin, View):
|
class ConfigContextView(ObjectView):
|
||||||
permission_required = 'extras.view_configcontext'
|
queryset = ConfigContext.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
configcontext = get_object_or_404(ConfigContext, pk=pk)
|
configcontext = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Determine user's preferred output format
|
# Determine user's preferred output format
|
||||||
if request.GET.get('format') in ['json', 'yaml']:
|
if request.GET.get('format') in ['json', 'yaml']:
|
||||||
@ -195,12 +195,12 @@ class ObjectChangeListView(ObjectListView):
|
|||||||
action_buttons = ('export',)
|
action_buttons = ('export',)
|
||||||
|
|
||||||
|
|
||||||
class ObjectChangeView(PermissionRequiredMixin, View):
|
class ObjectChangeView(ObjectView):
|
||||||
permission_required = 'extras.view_objectchange'
|
queryset = ObjectChange.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
objectchange = get_object_or_404(ObjectChange, pk=pk)
|
objectchange = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
related_changes = ObjectChange.objects.filter(request_id=objectchange.request_id).exclude(pk=objectchange.pk)
|
related_changes = ObjectChange.objects.filter(request_id=objectchange.request_id).exclude(pk=objectchange.pk)
|
||||||
related_changes_table = ObjectChangeTable(
|
related_changes_table = ObjectChangeTable(
|
||||||
|
@ -10,8 +10,8 @@ from django_tables2 import RequestConfig
|
|||||||
from dcim.models import Device, Interface
|
from dcim.models import Device, Interface
|
||||||
from utilities.paginator import EnhancedPaginator
|
from utilities.paginator import EnhancedPaginator
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkCreateView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
BulkCreateView, BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView,
|
||||||
ObjectPermissionRequiredMixin,
|
ObjectListView,
|
||||||
)
|
)
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
@ -120,12 +120,12 @@ class VRFListView(ObjectListView):
|
|||||||
table = tables.VRFTable
|
table = tables.VRFTable
|
||||||
|
|
||||||
|
|
||||||
class VRFView(PermissionRequiredMixin, View):
|
class VRFView(ObjectView):
|
||||||
permission_required = 'ipam.view_vrf'
|
queryset = VRF.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
vrf = get_object_or_404(VRF.objects.all(), pk=pk)
|
vrf = get_object_or_404(self.queryset, pk=pk)
|
||||||
prefix_count = Prefix.objects.filter(vrf=vrf).count()
|
prefix_count = Prefix.objects.filter(vrf=vrf).count()
|
||||||
|
|
||||||
return render(request, 'ipam/vrf.html', {
|
return render(request, 'ipam/vrf.html', {
|
||||||
@ -298,12 +298,12 @@ class AggregateListView(ObjectListView):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AggregateView(PermissionRequiredMixin, View):
|
class AggregateView(ObjectView):
|
||||||
permission_required = 'ipam.view_aggregate'
|
queryset = Aggregate.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
aggregate = get_object_or_404(Aggregate, pk=pk)
|
aggregate = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Find all child prefixes contained by this aggregate
|
# Find all child prefixes contained by this aggregate
|
||||||
child_prefixes = Prefix.objects.filter(
|
child_prefixes = Prefix.objects.filter(
|
||||||
@ -422,8 +422,7 @@ class PrefixListView(ObjectListView):
|
|||||||
return self.queryset.annotate_depth(limit=limit)
|
return self.queryset.annotate_depth(limit=limit)
|
||||||
|
|
||||||
|
|
||||||
class PrefixView(ObjectPermissionRequiredMixin, View):
|
class PrefixView(ObjectView):
|
||||||
permission_required = 'ipam.view_prefix'
|
|
||||||
queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role')
|
queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
@ -465,12 +464,12 @@ class PrefixView(ObjectPermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class PrefixPrefixesView(PermissionRequiredMixin, View):
|
class PrefixPrefixesView(ObjectView):
|
||||||
permission_required = 'ipam.view_prefix'
|
queryset = Prefix.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
prefix = get_object_or_404(Prefix.objects.all(), pk=pk)
|
prefix = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Child prefixes table
|
# Child prefixes table
|
||||||
child_prefixes = prefix.get_child_prefixes().prefetch_related(
|
child_prefixes = prefix.get_child_prefixes().prefetch_related(
|
||||||
@ -509,12 +508,12 @@ class PrefixPrefixesView(PermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class PrefixIPAddressesView(PermissionRequiredMixin, View):
|
class PrefixIPAddressesView(ObjectView):
|
||||||
permission_required = 'ipam.view_prefix'
|
queryset = Prefix.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
prefix = get_object_or_404(Prefix.objects.all(), pk=pk)
|
prefix = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Find all IPAddresses belonging to this Prefix
|
# Find all IPAddresses belonging to this Prefix
|
||||||
ipaddresses = prefix.get_child_ips().prefetch_related(
|
ipaddresses = prefix.get_child_ips().prefetch_related(
|
||||||
@ -601,12 +600,12 @@ class IPAddressListView(ObjectListView):
|
|||||||
table = tables.IPAddressDetailTable
|
table = tables.IPAddressDetailTable
|
||||||
|
|
||||||
|
|
||||||
class IPAddressView(PermissionRequiredMixin, View):
|
class IPAddressView(ObjectView):
|
||||||
permission_required = 'ipam.view_ipaddress'
|
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
ipaddress = get_object_or_404(IPAddress.objects.prefetch_related('vrf__tenant', 'tenant'), pk=pk)
|
ipaddress = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
# Parent prefixes table
|
# Parent prefixes table
|
||||||
parent_prefixes = Prefix.objects.filter(
|
parent_prefixes = Prefix.objects.filter(
|
||||||
@ -833,14 +832,12 @@ class VLANListView(ObjectListView):
|
|||||||
table = tables.VLANDetailTable
|
table = tables.VLANDetailTable
|
||||||
|
|
||||||
|
|
||||||
class VLANView(PermissionRequiredMixin, View):
|
class VLANView(ObjectView):
|
||||||
permission_required = 'ipam.view_vlan'
|
queryset = VLAN.objects.prefetch_related('site__region', 'tenant__group', 'role')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
vlan = get_object_or_404(VLAN.objects.prefetch_related(
|
vlan = get_object_or_404(self.queryset, pk=pk)
|
||||||
'site__region', 'tenant__group', 'role'
|
|
||||||
), pk=pk)
|
|
||||||
prefixes = Prefix.objects.filter(vlan=vlan).prefetch_related('vrf', 'site', 'role')
|
prefixes = Prefix.objects.filter(vlan=vlan).prefetch_related('vrf', 'site', 'role')
|
||||||
prefix_table = tables.PrefixTable(list(prefixes), orderable=False)
|
prefix_table = tables.PrefixTable(list(prefixes), orderable=False)
|
||||||
prefix_table.exclude = ('vlan',)
|
prefix_table.exclude = ('vlan',)
|
||||||
@ -851,12 +848,12 @@ class VLANView(PermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class VLANMembersView(PermissionRequiredMixin, View):
|
class VLANMembersView(ObjectView):
|
||||||
permission_required = 'ipam.view_vlan'
|
queryset = VLAN.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
vlan = get_object_or_404(VLAN.objects.all(), pk=pk)
|
vlan = get_object_or_404(self.queryset, pk=pk)
|
||||||
members = vlan.get_members().prefetch_related('device', 'virtual_machine')
|
members = vlan.get_members().prefetch_related('device', 'virtual_machine')
|
||||||
|
|
||||||
members_table = tables.VLANMemberTable(members)
|
members_table = tables.VLANMemberTable(members)
|
||||||
@ -920,12 +917,12 @@ class ServiceListView(ObjectListView):
|
|||||||
action_buttons = ('export',)
|
action_buttons = ('export',)
|
||||||
|
|
||||||
|
|
||||||
class ServiceView(PermissionRequiredMixin, View):
|
class ServiceView(ObjectView):
|
||||||
permission_required = 'ipam.view_service'
|
queryset = Service.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
service = get_object_or_404(Service, pk=pk)
|
service = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'ipam/service.html', {
|
return render(request, 'ipam/service.html', {
|
||||||
'service': service,
|
'service': service,
|
||||||
|
@ -9,7 +9,8 @@ from django.urls import reverse
|
|||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkDeleteView, BulkEditView, BulkImportView, GetReturnURLMixin, ObjectDeleteView, ObjectEditView, ObjectListView,
|
BulkDeleteView, BulkEditView, BulkImportView, GetReturnURLMixin, ObjectView, ObjectDeleteView, ObjectEditView,
|
||||||
|
ObjectListView,
|
||||||
)
|
)
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .decorators import userkey_required
|
from .decorators import userkey_required
|
||||||
@ -66,12 +67,12 @@ class SecretListView(ObjectListView):
|
|||||||
action_buttons = ('import', 'export')
|
action_buttons = ('import', 'export')
|
||||||
|
|
||||||
|
|
||||||
class SecretView(PermissionRequiredMixin, View):
|
class SecretView(ObjectView):
|
||||||
permission_required = 'secrets.view_secret'
|
queryset = Secret.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
secret = get_object_or_404(Secret, pk=pk)
|
secret = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
|
||||||
return render(request, 'secrets/secret.html', {
|
return render(request, 'secrets/secret.html', {
|
||||||
'secret': secret,
|
'secret': secret,
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.views.generic import View
|
|
||||||
|
|
||||||
from circuits.models import Circuit
|
from circuits.models import Circuit
|
||||||
from dcim.models import Site, Rack, Device, RackReservation
|
from dcim.models import Site, Rack, Device, RackReservation
|
||||||
from ipam.models import IPAddress, Prefix, VLAN, VRF
|
from ipam.models import IPAddress, Prefix, VLAN, VRF
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
)
|
)
|
||||||
from virtualization.models import VirtualMachine, Cluster
|
from virtualization.models import VirtualMachine, Cluster
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
@ -59,12 +57,12 @@ class TenantListView(ObjectListView):
|
|||||||
table = tables.TenantTable
|
table = tables.TenantTable
|
||||||
|
|
||||||
|
|
||||||
class TenantView(PermissionRequiredMixin, View):
|
class TenantView(ObjectView):
|
||||||
permission_required = 'tenancy.view_tenant'
|
queryset = Tenant.objects.prefetch_related('group')
|
||||||
|
|
||||||
def get(self, request, slug):
|
def get(self, request, slug):
|
||||||
|
|
||||||
tenant = get_object_or_404(Tenant, slug=slug)
|
tenant = get_object_or_404(self.queryset, slug=slug)
|
||||||
stats = {
|
stats = {
|
||||||
'site_count': Site.objects.filter(tenant=tenant).count(),
|
'site_count': Site.objects.filter(tenant=tenant).count(),
|
||||||
'rack_count': Rack.objects.filter(tenant=tenant).count(),
|
'rack_count': Rack.objects.filter(tenant=tenant).count(),
|
||||||
|
@ -118,6 +118,18 @@ class GetReturnURLMixin(object):
|
|||||||
# Generic views
|
# Generic views
|
||||||
#
|
#
|
||||||
|
|
||||||
|
class ObjectView(ObjectPermissionRequiredMixin, View):
|
||||||
|
"""
|
||||||
|
Retrieve a single object for display.
|
||||||
|
|
||||||
|
:param queryset: The base queryset for retrieving the object.
|
||||||
|
"""
|
||||||
|
queryset = None
|
||||||
|
|
||||||
|
def get_required_permission(self):
|
||||||
|
return get_permission_for_model(self.queryset.model, 'view')
|
||||||
|
|
||||||
|
|
||||||
class ObjectListView(ObjectPermissionRequiredMixin, View):
|
class ObjectListView(ObjectPermissionRequiredMixin, View):
|
||||||
"""
|
"""
|
||||||
List a series of objects.
|
List a series of objects.
|
||||||
|
@ -11,8 +11,8 @@ from dcim.tables import DeviceTable
|
|||||||
from extras.views import ObjectConfigContextView
|
from extras.views import ObjectConfigContextView
|
||||||
from ipam.models import Service
|
from ipam.models import Service
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectDeleteView,
|
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectView,
|
||||||
ObjectEditView, ObjectListView,
|
ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
)
|
)
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
||||||
@ -85,12 +85,12 @@ class ClusterListView(ObjectListView):
|
|||||||
filterset_form = forms.ClusterFilterForm
|
filterset_form = forms.ClusterFilterForm
|
||||||
|
|
||||||
|
|
||||||
class ClusterView(PermissionRequiredMixin, View):
|
class ClusterView(ObjectView):
|
||||||
permission_required = 'virtualization.view_cluster'
|
queryset = Cluster.objects.all()
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
cluster = get_object_or_404(Cluster, pk=pk)
|
cluster = get_object_or_404(self.queryset, pk=pk)
|
||||||
devices = Device.objects.filter(cluster=cluster).prefetch_related(
|
devices = Device.objects.filter(cluster=cluster).prefetch_related(
|
||||||
'site', 'rack', 'tenant', 'device_type__manufacturer'
|
'site', 'rack', 'tenant', 'device_type__manufacturer'
|
||||||
)
|
)
|
||||||
@ -233,12 +233,12 @@ class VirtualMachineListView(ObjectListView):
|
|||||||
template_name = 'virtualization/virtualmachine_list.html'
|
template_name = 'virtualization/virtualmachine_list.html'
|
||||||
|
|
||||||
|
|
||||||
class VirtualMachineView(PermissionRequiredMixin, View):
|
class VirtualMachineView(ObjectView):
|
||||||
permission_required = 'virtualization.view_virtualmachine'
|
queryset = VirtualMachine.objects.prefetch_related('tenant__group')
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
virtualmachine = get_object_or_404(VirtualMachine.objects.prefetch_related('tenant__group'), pk=pk)
|
virtualmachine = get_object_or_404(self.queryset, pk=pk)
|
||||||
interfaces = Interface.objects.filter(virtual_machine=virtualmachine)
|
interfaces = Interface.objects.filter(virtual_machine=virtualmachine)
|
||||||
services = Service.objects.filter(virtual_machine=virtualmachine)
|
services = Service.objects.filter(virtual_machine=virtualmachine)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user