From 82c247f3cf7660a24791f3e9e6505b0b18ab99b2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 21 May 2020 15:07:20 -0400 Subject: [PATCH] Transition BulkEditView to use ObjectPermissionRequiredMixin --- netbox/circuits/views.py | 6 +- netbox/dcim/views.py | 77 ++++++++-------------- netbox/extras/views.py | 6 +- netbox/ipam/views.py | 18 ++--- netbox/netbox/tests/test_authentication.py | 2 +- netbox/secrets/views.py | 3 +- netbox/tenancy/views.py | 3 +- netbox/utilities/views.py | 9 ++- netbox/virtualization/views.py | 9 +-- 9 files changed, 48 insertions(+), 85 deletions(-) diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 7ee6a7dc1..3dc7032e4 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -78,8 +78,7 @@ class ProviderBulkImportView(BulkImportView): default_return_url = 'circuits:provider_list' -class ProviderBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'circuits.change_provider' +class ProviderBulkEditView(BulkEditView): queryset = Provider.objects.annotate(count_circuits=Count('circuits')) filterset = filters.ProviderFilterSet table = tables.ProviderTable @@ -181,8 +180,7 @@ class CircuitBulkImportView(BulkImportView): default_return_url = 'circuits:circuit_list' -class CircuitBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'circuits.change_circuit' +class CircuitBulkEditView(BulkEditView): queryset = Circuit.objects.prefetch_related('provider', 'type', 'tenant').prefetch_related('terminations__site') filterset = filters.CircuitFilterSet table = tables.CircuitTable diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index d1882359d..8e2355a9c 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -231,8 +231,7 @@ class SiteBulkImportView(BulkImportView): default_return_url = 'dcim:site_list' -class SiteBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_site' +class SiteBulkEditView(BulkEditView): queryset = Site.objects.prefetch_related('region', 'tenant') filterset = filters.SiteFilterSet table = tables.SiteTable @@ -418,8 +417,7 @@ class RackBulkImportView(BulkImportView): default_return_url = 'dcim:rack_list' -class RackBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_rack' +class RackBulkEditView(BulkEditView): queryset = Rack.objects.prefetch_related('site', 'group', 'tenant', 'role') filterset = filters.RackFilterSet table = tables.RackTable @@ -495,8 +493,7 @@ class RackReservationImportView(BulkImportView): return instance -class RackReservationBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_rackreservation' +class RackReservationBulkEditView(BulkEditView): queryset = RackReservation.objects.prefetch_related('rack', 'user') filterset = filters.RackReservationFilterSet table = tables.RackReservationTable @@ -658,8 +655,7 @@ class DeviceTypeImportView(PermissionRequiredMixin, ObjectImportView): default_return_url = 'dcim:devicetype_import' -class DeviceTypeBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_devicetype' +class DeviceTypeBulkEditView(BulkEditView): queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances')) filterset = filters.DeviceTypeFilterSet table = tables.DeviceTypeTable @@ -696,8 +692,7 @@ class ConsolePortTemplateDeleteView(ObjectDeleteView): queryset = ConsolePortTemplate.objects.all() -class ConsolePortTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_consoleporttemplate' +class ConsolePortTemplateBulkEditView(BulkEditView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable form = forms.ConsolePortTemplateBulkEditForm @@ -730,8 +725,7 @@ class ConsoleServerPortTemplateDeleteView(ObjectDeleteView): queryset = ConsoleServerPortTemplate.objects.all() -class ConsoleServerPortTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_consoleserverporttemplate' +class ConsoleServerPortTemplateBulkEditView(BulkEditView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable form = forms.ConsoleServerPortTemplateBulkEditForm @@ -764,8 +758,7 @@ class PowerPortTemplateDeleteView(ObjectDeleteView): queryset = PowerPortTemplate.objects.all() -class PowerPortTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_powerporttemplate' +class PowerPortTemplateBulkEditView(BulkEditView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable form = forms.PowerPortTemplateBulkEditForm @@ -798,8 +791,7 @@ class PowerOutletTemplateDeleteView(ObjectDeleteView): queryset = PowerOutletTemplate.objects.all() -class PowerOutletTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_poweroutlettemplate' +class PowerOutletTemplateBulkEditView(BulkEditView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable form = forms.PowerOutletTemplateBulkEditForm @@ -832,8 +824,7 @@ class InterfaceTemplateDeleteView(ObjectDeleteView): queryset = InterfaceTemplate.objects.all() -class InterfaceTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_interfacetemplate' +class InterfaceTemplateBulkEditView(BulkEditView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable form = forms.InterfaceTemplateBulkEditForm @@ -866,8 +857,7 @@ class FrontPortTemplateDeleteView(ObjectDeleteView): queryset = FrontPortTemplate.objects.all() -class FrontPortTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_frontporttemplate' +class FrontPortTemplateBulkEditView(BulkEditView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable form = forms.FrontPortTemplateBulkEditForm @@ -900,8 +890,7 @@ class RearPortTemplateDeleteView(ObjectDeleteView): queryset = RearPortTemplate.objects.all() -class RearPortTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_rearporttemplate' +class RearPortTemplateBulkEditView(BulkEditView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable form = forms.RearPortTemplateBulkEditForm @@ -934,7 +923,7 @@ class DeviceBayTemplateDeleteView(ObjectDeleteView): queryset = DeviceBayTemplate.objects.all() -# class DeviceBayTemplateBulkEditView(PermissionRequiredMixin, BulkEditView): +# class DeviceBayTemplateBulkEditView(BulkEditView): # permission_required = 'dcim.change_devicebaytemplate' # queryset = DeviceBayTemplate.objects.all() # table = tables.DeviceBayTemplateTable @@ -1204,8 +1193,7 @@ class ChildDeviceBulkImportView(BulkImportView): return obj -class DeviceBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_device' +class DeviceBulkEditView(BulkEditView): queryset = Device.objects.prefetch_related('tenant', 'site', 'rack', 'device_role', 'device_type__manufacturer') filterset = filters.DeviceFilterSet table = tables.DeviceTable @@ -1257,8 +1245,7 @@ class ConsolePortBulkImportView(BulkImportView): default_return_url = 'dcim:consoleport_list' -class ConsolePortBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_consoleport' +class ConsolePortBulkEditView(BulkEditView): queryset = ConsolePort.objects.all() filterset = filters.ConsolePortFilterSet table = tables.ConsolePortTable @@ -1309,8 +1296,7 @@ class ConsoleServerPortBulkImportView(BulkImportView): default_return_url = 'dcim:consoleserverport_list' -class ConsoleServerPortBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_consoleserverport' +class ConsoleServerPortBulkEditView(BulkEditView): queryset = ConsoleServerPort.objects.all() filterset = filters.ConsoleServerPortFilterSet table = tables.ConsoleServerPortTable @@ -1373,8 +1359,7 @@ class PowerPortBulkImportView(BulkImportView): default_return_url = 'dcim:powerport_list' -class PowerPortBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_powerport' +class PowerPortBulkEditView(BulkEditView): queryset = PowerPort.objects.all() filterset = filters.PowerPortFilterSet table = tables.PowerPortTable @@ -1425,8 +1410,7 @@ class PowerOutletBulkImportView(BulkImportView): default_return_url = 'dcim:poweroutlet_list' -class PowerOutletBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_poweroutlet' +class PowerOutletBulkEditView(BulkEditView): queryset = PowerOutlet.objects.all() filterset = filters.PowerOutletFilterSet table = tables.PowerOutletTable @@ -1526,8 +1510,7 @@ class InterfaceBulkImportView(BulkImportView): default_return_url = 'dcim:interface_list' -class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_interface' +class InterfaceBulkEditView(BulkEditView): queryset = Interface.objects.all() filterset = filters.InterfaceFilterSet table = tables.InterfaceTable @@ -1590,8 +1573,7 @@ class FrontPortBulkImportView(BulkImportView): default_return_url = 'dcim:frontport_list' -class FrontPortBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_frontport' +class FrontPortBulkEditView(BulkEditView): queryset = FrontPort.objects.all() filterset = filters.FrontPortFilterSet table = tables.FrontPortTable @@ -1654,8 +1636,7 @@ class RearPortBulkImportView(BulkImportView): default_return_url = 'dcim:rearport_list' -class RearPortBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_rearport' +class RearPortBulkEditView(BulkEditView): queryset = RearPort.objects.all() filterset = filters.RearPortFilterSet table = tables.RearPortTable @@ -1789,8 +1770,7 @@ class DeviceBayBulkImportView(BulkImportView): default_return_url = 'dcim:devicebay_list' -class DeviceBayBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_devicebay' +class DeviceBayBulkEditView(BulkEditView): queryset = DeviceBay.objects.all() filterset = filters.DeviceBayFilterSet table = tables.DeviceBayTable @@ -2060,8 +2040,7 @@ class CableBulkImportView(BulkImportView): default_return_url = 'dcim:cable_list' -class CableBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_cable' +class CableBulkEditView(BulkEditView): queryset = Cable.objects.prefetch_related('termination_a', 'termination_b') filterset = filters.CableFilterSet table = tables.CableTable @@ -2216,8 +2195,7 @@ class InventoryItemBulkImportView(BulkImportView): default_return_url = 'dcim:inventoryitem_list' -class InventoryItemBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_inventoryitem' +class InventoryItemBulkEditView(BulkEditView): queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer') filterset = filters.InventoryItemFilterSet table = tables.InventoryItemTable @@ -2482,8 +2460,7 @@ class VirtualChassisRemoveMemberView(PermissionRequiredMixin, GetReturnURLMixin, }) -class VirtualChassisBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_virtualchassis' +class VirtualChassisBulkEditView(BulkEditView): queryset = VirtualChassis.objects.all() filterset = filters.VirtualChassisFilterSet table = tables.VirtualChassisTable @@ -2550,8 +2527,7 @@ class PowerPanelBulkImportView(BulkImportView): default_return_url = 'dcim:powerpanel_list' -class PowerPanelBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_powerpanel' +class PowerPanelBulkEditView(BulkEditView): queryset = PowerPanel.objects.prefetch_related('site', 'rack_group') filterset = filters.PowerPanelFilterSet table = tables.PowerPanelTable @@ -2615,8 +2591,7 @@ class PowerFeedBulkImportView(BulkImportView): default_return_url = 'dcim:powerfeed_list' -class PowerFeedBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_powerfeed' +class PowerFeedBulkEditView(BulkEditView): queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack') filterset = filters.PowerFeedFilterSet table = tables.PowerFeedTable diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 63764b683..3aadbda98 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -76,8 +76,7 @@ class TagDeleteView(ObjectDeleteView): default_return_url = 'extras:tag_list' -class TagBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'extras.change_tag' +class TagBulkEditView(BulkEditView): queryset = Tag.objects.annotate( items=Count('extras_taggeditem_items', distinct=True) ).order_by( @@ -137,8 +136,7 @@ class ConfigContextEditView(ObjectEditView): template_name = 'extras/configcontext_edit.html' -class ConfigContextBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'extras.change_configcontext' +class ConfigContextBulkEditView(BulkEditView): queryset = ConfigContext.objects.all() filterset = filters.ConfigContextFilterSet table = ConfigContextTable diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index dbd45b923..ba4b310ef 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -153,8 +153,7 @@ class VRFBulkImportView(BulkImportView): default_return_url = 'ipam:vrf_list' -class VRFBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'ipam.change_vrf' +class VRFBulkEditView(BulkEditView): queryset = VRF.objects.prefetch_related('tenant') filterset = filters.VRFFilterSet table = tables.VRFTable @@ -365,8 +364,7 @@ class AggregateBulkImportView(BulkImportView): default_return_url = 'ipam:aggregate_list' -class AggregateBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'ipam.change_aggregate' +class AggregateBulkEditView(BulkEditView): queryset = Aggregate.objects.prefetch_related('rir') filterset = filters.AggregateFilterSet table = tables.AggregateTable @@ -579,8 +577,7 @@ class PrefixBulkImportView(BulkImportView): default_return_url = 'ipam:prefix_list' -class PrefixBulkEditView(ObjectPermissionRequiredMixin, BulkEditView): - permission_required = 'ipam.change_prefix' +class PrefixBulkEditView(BulkEditView): queryset = Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role') filterset = filters.PrefixFilterSet table = tables.PrefixTable @@ -746,8 +743,7 @@ class IPAddressBulkImportView(BulkImportView): default_return_url = 'ipam:ipaddress_list' -class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'ipam.change_ipaddress' +class IPAddressBulkEditView(BulkEditView): queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant').prefetch_related('interface__device') filterset = filters.IPAddressFilterSet table = tables.IPAddressTable @@ -904,8 +900,7 @@ class VLANBulkImportView(BulkImportView): default_return_url = 'ipam:vlan_list' -class VLANBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'ipam.change_vlan' +class VLANBulkEditView(BulkEditView): queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role') filterset = filters.VLANFilterSet table = tables.VLANTable @@ -972,8 +967,7 @@ class ServiceDeleteView(ObjectDeleteView): queryset = Service.objects.all() -class ServiceBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'ipam.change_service' +class ServiceBulkEditView(BulkEditView): queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = filters.ServiceFilterSet table = tables.ServiceTable diff --git a/netbox/netbox/tests/test_authentication.py b/netbox/netbox/tests/test_authentication.py index d82ef6752..39e82df61 100644 --- a/netbox/netbox/tests/test_authentication.py +++ b/netbox/netbox/tests/test_authentication.py @@ -463,7 +463,7 @@ class ObjectPermissionViewTestCase(TestCase): 'data': form_data, } response = self.client.post(**request) - self.assertHttpStatus(response, 200) + self.assertHttpStatus(response, 302) self.assertEqual(Prefix.objects.get(pk=self.prefixes[3].pk).status, 'active') # Edit permitted objects diff --git a/netbox/secrets/views.py b/netbox/secrets/views.py index 00794f684..877133619 100644 --- a/netbox/secrets/views.py +++ b/netbox/secrets/views.py @@ -235,8 +235,7 @@ class SecretBulkImportView(BulkImportView): }) -class SecretBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'secrets.change_secret' +class SecretBulkEditView(BulkEditView): queryset = Secret.objects.prefetch_related('role', 'device') filterset = filters.SecretFilterSet table = tables.SecretTable diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index f666e606a..fdfcbd7f5 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -105,8 +105,7 @@ class TenantBulkImportView(BulkImportView): default_return_url = 'tenancy:tenant_list' -class TenantBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'tenancy.change_tenant' +class TenantBulkEditView(BulkEditView): queryset = Tenant.objects.prefetch_related('group') filterset = filters.TenantFilterSet table = tables.TenantTable diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 3d11cf25b..1c8ceb525 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -755,7 +755,7 @@ class BulkImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): }) -class BulkEditView(GetReturnURLMixin, View): +class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): """ Edit objects in bulk. @@ -771,6 +771,9 @@ class BulkEditView(GetReturnURLMixin, View): form = None template_name = 'utilities/obj_bulk_edit.html' + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'change') + def get(self, request): return redirect(self.get_return_url(request)) @@ -781,7 +784,7 @@ class BulkEditView(GetReturnURLMixin, View): # If we are editing *all* objects in the queryset, replace the PK list with all matched objects. if request.POST.get('_all') and self.filterset is not None: pk_list = [ - obj.pk for obj in self.filterset(request.GET, model.objects.only('pk')).qs + obj.pk for obj in self.filterset(request.GET, self.queryset.only('pk')).qs ] else: pk_list = request.POST.getlist('pk') @@ -802,7 +805,7 @@ class BulkEditView(GetReturnURLMixin, View): with transaction.atomic(): updated_objects = [] - for obj in model.objects.filter(pk__in=form.cleaned_data['pk']): + for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']): # Update standard fields. If a field is listed in _nullify, delete its value. for name in standard_fields: diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index de4569b83..e565832d8 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -124,8 +124,7 @@ class ClusterBulkImportView(BulkImportView): default_return_url = 'virtualization:cluster_list' -class ClusterBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'virtualization.change_cluster' +class ClusterBulkEditView(BulkEditView): queryset = Cluster.objects.prefetch_related('type', 'group', 'site') filterset = filters.ClusterFilterSet table = tables.ClusterTable @@ -278,8 +277,7 @@ class VirtualMachineBulkImportView(BulkImportView): default_return_url = 'virtualization:virtualmachine_list' -class VirtualMachineBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'virtualization.change_virtualmachine' +class VirtualMachineBulkEditView(BulkEditView): queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role') filterset = filters.VirtualMachineFilterSet table = tables.VirtualMachineTable @@ -317,8 +315,7 @@ class InterfaceDeleteView(ObjectDeleteView): queryset = Interface.objects.all() -class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'dcim.change_interface' +class InterfaceBulkEditView(BulkEditView): queryset = Interface.objects.all() table = tables.InterfaceTable form = forms.InterfaceBulkEditForm