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