Selaa lähdekoodia

Transition ObjectEditView to use ObjectPermissionRequiredMixin

Jeremy Stretch 5 vuotta sitten
vanhempi
commit
406b076b95

+ 4 - 4
netbox/circuits/urls.py

@@ -10,7 +10,7 @@ urlpatterns = [
 
 
     # Providers
     # Providers
     path('providers/', views.ProviderListView.as_view(), name='provider_list'),
     path('providers/', views.ProviderListView.as_view(), name='provider_list'),
-    path('providers/add/', views.ProviderCreateView.as_view(), name='provider_add'),
+    path('providers/add/', views.ProviderEditView.as_view(), name='provider_add'),
     path('providers/import/', views.ProviderBulkImportView.as_view(), name='provider_import'),
     path('providers/import/', views.ProviderBulkImportView.as_view(), name='provider_import'),
     path('providers/edit/', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
     path('providers/edit/', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
     path('providers/delete/', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
     path('providers/delete/', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
@@ -21,7 +21,7 @@ urlpatterns = [
 
 
     # Circuit types
     # Circuit types
     path('circuit-types/', views.CircuitTypeListView.as_view(), name='circuittype_list'),
     path('circuit-types/', views.CircuitTypeListView.as_view(), name='circuittype_list'),
-    path('circuit-types/add/', views.CircuitTypeCreateView.as_view(), name='circuittype_add'),
+    path('circuit-types/add/', views.CircuitTypeEditView.as_view(), name='circuittype_add'),
     path('circuit-types/import/', views.CircuitTypeBulkImportView.as_view(), name='circuittype_import'),
     path('circuit-types/import/', views.CircuitTypeBulkImportView.as_view(), name='circuittype_import'),
     path('circuit-types/delete/', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'),
     path('circuit-types/delete/', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'),
     path('circuit-types/<slug:slug>/edit/', views.CircuitTypeEditView.as_view(), name='circuittype_edit'),
     path('circuit-types/<slug:slug>/edit/', views.CircuitTypeEditView.as_view(), name='circuittype_edit'),
@@ -29,7 +29,7 @@ urlpatterns = [
 
 
     # Circuits
     # Circuits
     path('circuits/', views.CircuitListView.as_view(), name='circuit_list'),
     path('circuits/', views.CircuitListView.as_view(), name='circuit_list'),
-    path('circuits/add/', views.CircuitCreateView.as_view(), name='circuit_add'),
+    path('circuits/add/', views.CircuitEditView.as_view(), name='circuit_add'),
     path('circuits/import/', views.CircuitBulkImportView.as_view(), name='circuit_import'),
     path('circuits/import/', views.CircuitBulkImportView.as_view(), name='circuit_import'),
     path('circuits/edit/', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
     path('circuits/edit/', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
     path('circuits/delete/', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
     path('circuits/delete/', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
@@ -41,7 +41,7 @@ urlpatterns = [
 
 
     # Circuit terminations
     # Circuit terminations
 
 
-    path('circuits/<int:circuit>/terminations/add/', views.CircuitTerminationCreateView.as_view(), name='circuittermination_add'),
+    path('circuits/<int:circuit>/terminations/add/', views.CircuitTerminationEditView.as_view(), name='circuittermination_add'),
     path('circuit-terminations/<int:pk>/edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
     path('circuit-terminations/<int:pk>/edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
     path('circuit-terminations/<int:pk>/delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
     path('circuit-terminations/<int:pk>/delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
     path('circuit-terminations/<int:termination_a_id>/connect/<str:termination_b_type>/', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}),
     path('circuit-terminations/<int:termination_a_id>/connect/<str:termination_b_type>/', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}),

+ 4 - 24
netbox/circuits/views.py

@@ -59,18 +59,13 @@ class ProviderView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class ProviderCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'circuits.add_provider'
+class ProviderEditView(ObjectEditView):
     queryset = Provider.objects.all()
     queryset = Provider.objects.all()
     model_form = forms.ProviderForm
     model_form = forms.ProviderForm
     template_name = 'circuits/provider_edit.html'
     template_name = 'circuits/provider_edit.html'
     default_return_url = 'circuits:provider_list'
     default_return_url = 'circuits:provider_list'
 
 
 
 
-class ProviderEditView(ProviderCreateView):
-    permission_required = 'circuits.change_provider'
-
-
 class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'circuits.delete_provider'
     permission_required = 'circuits.delete_provider'
     queryset = Provider.objects.all()
     queryset = Provider.objects.all()
@@ -111,17 +106,12 @@ class CircuitTypeListView(ObjectListView):
     table = tables.CircuitTypeTable
     table = tables.CircuitTypeTable
 
 
 
 
-class CircuitTypeCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'circuits.add_circuittype'
+class CircuitTypeEditView(ObjectEditView):
     queryset = CircuitType.objects.all()
     queryset = CircuitType.objects.all()
     model_form = forms.CircuitTypeForm
     model_form = forms.CircuitTypeForm
     default_return_url = 'circuits:circuittype_list'
     default_return_url = 'circuits:circuittype_list'
 
 
 
 
-class CircuitTypeEditView(CircuitTypeCreateView):
-    permission_required = 'circuits.change_circuittype'
-
-
 class CircuitTypeBulkImportView(PermissionRequiredMixin, BulkImportView):
 class CircuitTypeBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'circuits.add_circuittype'
     permission_required = 'circuits.add_circuittype'
     queryset = CircuitType.objects.all()
     queryset = CircuitType.objects.all()
@@ -175,18 +165,13 @@ class CircuitView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class CircuitCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'circuits.add_circuit'
+class CircuitEditView(ObjectEditView):
     queryset = Circuit.objects.all()
     queryset = Circuit.objects.all()
     model_form = forms.CircuitForm
     model_form = forms.CircuitForm
     template_name = 'circuits/circuit_edit.html'
     template_name = 'circuits/circuit_edit.html'
     default_return_url = 'circuits:circuit_list'
     default_return_url = 'circuits:circuit_list'
 
 
 
 
-class CircuitEditView(CircuitCreateView):
-    permission_required = 'circuits.change_circuit'
-
-
 class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'circuits.delete_circuit'
     permission_required = 'circuits.delete_circuit'
     queryset = Circuit.objects.all()
     queryset = Circuit.objects.all()
@@ -271,8 +256,7 @@ def circuit_terminations_swap(request, pk):
 # Circuit terminations
 # Circuit terminations
 #
 #
 
 
-class CircuitTerminationCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'circuits.add_circuittermination'
+class CircuitTerminationEditView(ObjectEditView):
     queryset = CircuitTermination.objects.all()
     queryset = CircuitTermination.objects.all()
     model_form = forms.CircuitTerminationForm
     model_form = forms.CircuitTerminationForm
     template_name = 'circuits/circuittermination_edit.html'
     template_name = 'circuits/circuittermination_edit.html'
@@ -286,10 +270,6 @@ class CircuitTerminationCreateView(PermissionRequiredMixin, ObjectEditView):
         return obj.circuit.get_absolute_url()
         return obj.circuit.get_absolute_url()
 
 
 
 
-class CircuitTerminationEditView(CircuitTerminationCreateView):
-    permission_required = 'circuits.change_circuittermination'
-
-
 class CircuitTerminationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class CircuitTerminationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'circuits.delete_circuittermination'
     permission_required = 'circuits.delete_circuittermination'
     queryset = CircuitTermination.objects.all()
     queryset = CircuitTermination.objects.all()

+ 15 - 15
netbox/dcim/urls.py

@@ -1,7 +1,7 @@
 from django.urls import path
 from django.urls import path
 
 
 from extras.views import ObjectChangeLogView, ImageAttachmentEditView
 from extras.views import ObjectChangeLogView, ImageAttachmentEditView
-from ipam.views import ServiceCreateView
+from ipam.views import ServiceEditView
 from . import views
 from . import views
 from .models import (
 from .models import (
     Cable, ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, FrontPort, Interface, Manufacturer, Platform,
     Cable, ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, FrontPort, Interface, Manufacturer, Platform,
@@ -14,7 +14,7 @@ urlpatterns = [
 
 
     # Regions
     # Regions
     path('regions/', views.RegionListView.as_view(), name='region_list'),
     path('regions/', views.RegionListView.as_view(), name='region_list'),
-    path('regions/add/', views.RegionCreateView.as_view(), name='region_add'),
+    path('regions/add/', views.RegionEditView.as_view(), name='region_add'),
     path('regions/import/', views.RegionBulkImportView.as_view(), name='region_import'),
     path('regions/import/', views.RegionBulkImportView.as_view(), name='region_import'),
     path('regions/delete/', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
     path('regions/delete/', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
     path('regions/<int:pk>/edit/', views.RegionEditView.as_view(), name='region_edit'),
     path('regions/<int:pk>/edit/', views.RegionEditView.as_view(), name='region_edit'),
@@ -22,7 +22,7 @@ urlpatterns = [
 
 
     # Sites
     # Sites
     path('sites/', views.SiteListView.as_view(), name='site_list'),
     path('sites/', views.SiteListView.as_view(), name='site_list'),
-    path('sites/add/', views.SiteCreateView.as_view(), name='site_add'),
+    path('sites/add/', views.SiteEditView.as_view(), name='site_add'),
     path('sites/import/', views.SiteBulkImportView.as_view(), name='site_import'),
     path('sites/import/', views.SiteBulkImportView.as_view(), name='site_import'),
     path('sites/edit/', views.SiteBulkEditView.as_view(), name='site_bulk_edit'),
     path('sites/edit/', views.SiteBulkEditView.as_view(), name='site_bulk_edit'),
     path('sites/delete/', views.SiteBulkDeleteView.as_view(), name='site_bulk_delete'),
     path('sites/delete/', views.SiteBulkDeleteView.as_view(), name='site_bulk_delete'),
@@ -34,7 +34,7 @@ urlpatterns = [
 
 
     # Rack groups
     # Rack groups
     path('rack-groups/', views.RackGroupListView.as_view(), name='rackgroup_list'),
     path('rack-groups/', views.RackGroupListView.as_view(), name='rackgroup_list'),
-    path('rack-groups/add/', views.RackGroupCreateView.as_view(), name='rackgroup_add'),
+    path('rack-groups/add/', views.RackGroupEditView.as_view(), name='rackgroup_add'),
     path('rack-groups/import/', views.RackGroupBulkImportView.as_view(), name='rackgroup_import'),
     path('rack-groups/import/', views.RackGroupBulkImportView.as_view(), name='rackgroup_import'),
     path('rack-groups/delete/', views.RackGroupBulkDeleteView.as_view(), name='rackgroup_bulk_delete'),
     path('rack-groups/delete/', views.RackGroupBulkDeleteView.as_view(), name='rackgroup_bulk_delete'),
     path('rack-groups/<int:pk>/edit/', views.RackGroupEditView.as_view(), name='rackgroup_edit'),
     path('rack-groups/<int:pk>/edit/', views.RackGroupEditView.as_view(), name='rackgroup_edit'),
@@ -42,7 +42,7 @@ urlpatterns = [
 
 
     # Rack roles
     # Rack roles
     path('rack-roles/', views.RackRoleListView.as_view(), name='rackrole_list'),
     path('rack-roles/', views.RackRoleListView.as_view(), name='rackrole_list'),
-    path('rack-roles/add/', views.RackRoleCreateView.as_view(), name='rackrole_add'),
+    path('rack-roles/add/', views.RackRoleEditView.as_view(), name='rackrole_add'),
     path('rack-roles/import/', views.RackRoleBulkImportView.as_view(), name='rackrole_import'),
     path('rack-roles/import/', views.RackRoleBulkImportView.as_view(), name='rackrole_import'),
     path('rack-roles/delete/', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'),
     path('rack-roles/delete/', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'),
     path('rack-roles/<int:pk>/edit/', views.RackRoleEditView.as_view(), name='rackrole_edit'),
     path('rack-roles/<int:pk>/edit/', views.RackRoleEditView.as_view(), name='rackrole_edit'),
@@ -50,7 +50,7 @@ urlpatterns = [
 
 
     # Rack reservations
     # Rack reservations
     path('rack-reservations/', views.RackReservationListView.as_view(), name='rackreservation_list'),
     path('rack-reservations/', views.RackReservationListView.as_view(), name='rackreservation_list'),
-    path('rack-reservations/add/', views.RackReservationCreateView.as_view(), name='rackreservation_add'),
+    path('rack-reservations/add/', views.RackReservationEditView.as_view(), name='rackreservation_add'),
     path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'),
     path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'),
     path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'),
     path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'),
     path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'),
     path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'),
@@ -62,7 +62,7 @@ urlpatterns = [
     # Racks
     # Racks
     path('racks/', views.RackListView.as_view(), name='rack_list'),
     path('racks/', views.RackListView.as_view(), name='rack_list'),
     path('rack-elevations/', views.RackElevationListView.as_view(), name='rack_elevation_list'),
     path('rack-elevations/', views.RackElevationListView.as_view(), name='rack_elevation_list'),
-    path('racks/add/', views.RackCreateView.as_view(), name='rack_add'),
+    path('racks/add/', views.RackEditView.as_view(), name='rack_add'),
     path('racks/import/', views.RackBulkImportView.as_view(), name='rack_import'),
     path('racks/import/', views.RackBulkImportView.as_view(), name='rack_import'),
     path('racks/edit/', views.RackBulkEditView.as_view(), name='rack_bulk_edit'),
     path('racks/edit/', views.RackBulkEditView.as_view(), name='rack_bulk_edit'),
     path('racks/delete/', views.RackBulkDeleteView.as_view(), name='rack_bulk_delete'),
     path('racks/delete/', views.RackBulkDeleteView.as_view(), name='rack_bulk_delete'),
@@ -74,7 +74,7 @@ urlpatterns = [
 
 
     # Manufacturers
     # Manufacturers
     path('manufacturers/', views.ManufacturerListView.as_view(), name='manufacturer_list'),
     path('manufacturers/', views.ManufacturerListView.as_view(), name='manufacturer_list'),
-    path('manufacturers/add/', views.ManufacturerCreateView.as_view(), name='manufacturer_add'),
+    path('manufacturers/add/', views.ManufacturerEditView.as_view(), name='manufacturer_add'),
     path('manufacturers/import/', views.ManufacturerBulkImportView.as_view(), name='manufacturer_import'),
     path('manufacturers/import/', views.ManufacturerBulkImportView.as_view(), name='manufacturer_import'),
     path('manufacturers/delete/', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'),
     path('manufacturers/delete/', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'),
     path('manufacturers/<slug:slug>/edit/', views.ManufacturerEditView.as_view(), name='manufacturer_edit'),
     path('manufacturers/<slug:slug>/edit/', views.ManufacturerEditView.as_view(), name='manufacturer_edit'),
@@ -82,7 +82,7 @@ urlpatterns = [
 
 
     # Device types
     # Device types
     path('device-types/', views.DeviceTypeListView.as_view(), name='devicetype_list'),
     path('device-types/', views.DeviceTypeListView.as_view(), name='devicetype_list'),
-    path('device-types/add/', views.DeviceTypeCreateView.as_view(), name='devicetype_add'),
+    path('device-types/add/', views.DeviceTypeEditView.as_view(), name='devicetype_add'),
     path('device-types/import/', views.DeviceTypeImportView.as_view(), name='devicetype_import'),
     path('device-types/import/', views.DeviceTypeImportView.as_view(), name='devicetype_import'),
     path('device-types/edit/', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
     path('device-types/edit/', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
     path('device-types/delete/', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
     path('device-types/delete/', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
@@ -149,7 +149,7 @@ urlpatterns = [
 
 
     # Device roles
     # Device roles
     path('device-roles/', views.DeviceRoleListView.as_view(), name='devicerole_list'),
     path('device-roles/', views.DeviceRoleListView.as_view(), name='devicerole_list'),
-    path('device-roles/add/', views.DeviceRoleCreateView.as_view(), name='devicerole_add'),
+    path('device-roles/add/', views.DeviceRoleEditView.as_view(), name='devicerole_add'),
     path('device-roles/import/', views.DeviceRoleBulkImportView.as_view(), name='devicerole_import'),
     path('device-roles/import/', views.DeviceRoleBulkImportView.as_view(), name='devicerole_import'),
     path('device-roles/delete/', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'),
     path('device-roles/delete/', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'),
     path('device-roles/<slug:slug>/edit/', views.DeviceRoleEditView.as_view(), name='devicerole_edit'),
     path('device-roles/<slug:slug>/edit/', views.DeviceRoleEditView.as_view(), name='devicerole_edit'),
@@ -157,7 +157,7 @@ urlpatterns = [
 
 
     # Platforms
     # Platforms
     path('platforms/', views.PlatformListView.as_view(), name='platform_list'),
     path('platforms/', views.PlatformListView.as_view(), name='platform_list'),
-    path('platforms/add/', views.PlatformCreateView.as_view(), name='platform_add'),
+    path('platforms/add/', views.PlatformEditView.as_view(), name='platform_add'),
     path('platforms/import/', views.PlatformBulkImportView.as_view(), name='platform_import'),
     path('platforms/import/', views.PlatformBulkImportView.as_view(), name='platform_import'),
     path('platforms/delete/', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'),
     path('platforms/delete/', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'),
     path('platforms/<slug:slug>/edit/', views.PlatformEditView.as_view(), name='platform_edit'),
     path('platforms/<slug:slug>/edit/', views.PlatformEditView.as_view(), name='platform_edit'),
@@ -165,7 +165,7 @@ urlpatterns = [
 
 
     # Devices
     # Devices
     path('devices/', views.DeviceListView.as_view(), name='device_list'),
     path('devices/', views.DeviceListView.as_view(), name='device_list'),
-    path('devices/add/', views.DeviceCreateView.as_view(), name='device_add'),
+    path('devices/add/', views.DeviceEditView.as_view(), name='device_add'),
     path('devices/import/', views.DeviceBulkImportView.as_view(), name='device_import'),
     path('devices/import/', views.DeviceBulkImportView.as_view(), name='device_import'),
     path('devices/import/child-devices/', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
     path('devices/import/child-devices/', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
     path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
     path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
@@ -179,7 +179,7 @@ urlpatterns = [
     path('devices/<int:pk>/status/', views.DeviceStatusView.as_view(), name='device_status'),
     path('devices/<int:pk>/status/', views.DeviceStatusView.as_view(), name='device_status'),
     path('devices/<int:pk>/lldp-neighbors/', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'),
     path('devices/<int:pk>/lldp-neighbors/', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'),
     path('devices/<int:pk>/config/', views.DeviceConfigView.as_view(), name='device_config'),
     path('devices/<int:pk>/config/', views.DeviceConfigView.as_view(), name='device_config'),
-    path('devices/<int:device>/services/assign/', ServiceCreateView.as_view(), name='device_service_assign'),
+    path('devices/<int:device>/services/assign/', ServiceEditView.as_view(), name='device_service_assign'),
     path('devices/<int:object_id>/images/add/', ImageAttachmentEditView.as_view(), name='device_add_image', kwargs={'model': Device}),
     path('devices/<int:object_id>/images/add/', ImageAttachmentEditView.as_view(), name='device_add_image', kwargs={'model': Device}),
 
 
     # Console ports
     # Console ports
@@ -332,7 +332,7 @@ urlpatterns = [
 
 
     # Power panels
     # Power panels
     path('power-panels/', views.PowerPanelListView.as_view(), name='powerpanel_list'),
     path('power-panels/', views.PowerPanelListView.as_view(), name='powerpanel_list'),
-    path('power-panels/add/', views.PowerPanelCreateView.as_view(), name='powerpanel_add'),
+    path('power-panels/add/', views.PowerPanelEditView.as_view(), name='powerpanel_add'),
     path('power-panels/import/', views.PowerPanelBulkImportView.as_view(), name='powerpanel_import'),
     path('power-panels/import/', views.PowerPanelBulkImportView.as_view(), name='powerpanel_import'),
     path('power-panels/edit/', views.PowerPanelBulkEditView.as_view(), name='powerpanel_bulk_edit'),
     path('power-panels/edit/', views.PowerPanelBulkEditView.as_view(), name='powerpanel_bulk_edit'),
     path('power-panels/delete/', views.PowerPanelBulkDeleteView.as_view(), name='powerpanel_bulk_delete'),
     path('power-panels/delete/', views.PowerPanelBulkDeleteView.as_view(), name='powerpanel_bulk_delete'),
@@ -343,7 +343,7 @@ urlpatterns = [
 
 
     # Power feeds
     # Power feeds
     path('power-feeds/', views.PowerFeedListView.as_view(), name='powerfeed_list'),
     path('power-feeds/', views.PowerFeedListView.as_view(), name='powerfeed_list'),
-    path('power-feeds/add/', views.PowerFeedCreateView.as_view(), name='powerfeed_add'),
+    path('power-feeds/add/', views.PowerFeedEditView.as_view(), name='powerfeed_add'),
     path('power-feeds/import/', views.PowerFeedBulkImportView.as_view(), name='powerfeed_import'),
     path('power-feeds/import/', views.PowerFeedBulkImportView.as_view(), name='powerfeed_import'),
     path('power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'),
     path('power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'),
     path('power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'),
     path('power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'),

+ 31 - 114
netbox/dcim/views.py

@@ -154,17 +154,12 @@ class RegionListView(ObjectListView):
     table = tables.RegionTable
     table = tables.RegionTable
 
 
 
 
-class RegionCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_region'
+class RegionEditView(ObjectEditView):
     queryset = Region.objects.all()
     queryset = Region.objects.all()
     model_form = forms.RegionForm
     model_form = forms.RegionForm
     default_return_url = 'dcim:region_list'
     default_return_url = 'dcim:region_list'
 
 
 
 
-class RegionEditView(RegionCreateView):
-    permission_required = 'dcim.change_region'
-
-
 class RegionBulkImportView(PermissionRequiredMixin, BulkImportView):
 class RegionBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'dcim.add_region'
     permission_required = 'dcim.add_region'
     queryset = Region.objects.all()
     queryset = Region.objects.all()
@@ -218,18 +213,13 @@ class SiteView(ObjectPermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class SiteCreateView(ObjectPermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_site'
+class SiteEditView(ObjectEditView):
     queryset = Site.objects.all()
     queryset = Site.objects.all()
     model_form = forms.SiteForm
     model_form = forms.SiteForm
     template_name = 'dcim/site_edit.html'
     template_name = 'dcim/site_edit.html'
     default_return_url = 'dcim:site_list'
     default_return_url = 'dcim:site_list'
 
 
 
 
-class SiteEditView(SiteCreateView):
-    permission_required = 'dcim.change_site'
-
-
 class SiteDeleteView(ObjectPermissionRequiredMixin, ObjectDeleteView):
 class SiteDeleteView(ObjectPermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_site'
     permission_required = 'dcim.delete_site'
     queryset = Site.objects.all()
     queryset = Site.objects.all()
@@ -278,17 +268,12 @@ class RackGroupListView(ObjectListView):
     table = tables.RackGroupTable
     table = tables.RackGroupTable
 
 
 
 
-class RackGroupCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_rackgroup'
+class RackGroupEditView(ObjectEditView):
     queryset = RackGroup.objects.all()
     queryset = RackGroup.objects.all()
     model_form = forms.RackGroupForm
     model_form = forms.RackGroupForm
     default_return_url = 'dcim:rackgroup_list'
     default_return_url = 'dcim:rackgroup_list'
 
 
 
 
-class RackGroupEditView(RackGroupCreateView):
-    permission_required = 'dcim.change_rackgroup'
-
-
 class RackGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
 class RackGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'dcim.add_rackgroup'
     permission_required = 'dcim.add_rackgroup'
     queryset = RackGroup.objects.all()
     queryset = RackGroup.objects.all()
@@ -314,17 +299,12 @@ class RackRoleListView(ObjectListView):
     table = tables.RackRoleTable
     table = tables.RackRoleTable
 
 
 
 
-class RackRoleCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_rackrole'
+class RackRoleEditView(ObjectEditView):
     queryset = RackRole.objects.all()
     queryset = RackRole.objects.all()
     model_form = forms.RackRoleForm
     model_form = forms.RackRoleForm
     default_return_url = 'dcim:rackrole_list'
     default_return_url = 'dcim:rackrole_list'
 
 
 
 
-class RackRoleEditView(RackRoleCreateView):
-    permission_required = 'dcim.change_rackrole'
-
-
 class RackRoleBulkImportView(PermissionRequiredMixin, BulkImportView):
 class RackRoleBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'dcim.add_rackrole'
     permission_required = 'dcim.add_rackrole'
     queryset = RackRole.objects.all()
     queryset = RackRole.objects.all()
@@ -424,18 +404,13 @@ class RackView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class RackCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_rack'
+class RackEditView(ObjectEditView):
     queryset = Rack.objects.all()
     queryset = Rack.objects.all()
     model_form = forms.RackForm
     model_form = forms.RackForm
     template_name = 'dcim/rack_edit.html'
     template_name = 'dcim/rack_edit.html'
     default_return_url = 'dcim:rack_list'
     default_return_url = 'dcim:rack_list'
 
 
 
 
-class RackEditView(RackCreateView):
-    permission_required = 'dcim.change_rack'
-
-
 class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_rack'
     permission_required = 'dcim.delete_rack'
     queryset = Rack.objects.all()
     queryset = Rack.objects.all()
@@ -491,8 +466,7 @@ class RackReservationView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class RackReservationCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_rackreservation'
+class RackReservationEditView(ObjectEditView):
     queryset = RackReservation.objects.all()
     queryset = RackReservation.objects.all()
     model_form = forms.RackReservationForm
     model_form = forms.RackReservationForm
     template_name = 'dcim/rackreservation_edit.html'
     template_name = 'dcim/rackreservation_edit.html'
@@ -506,10 +480,6 @@ class RackReservationCreateView(PermissionRequiredMixin, ObjectEditView):
         return obj
         return obj
 
 
 
 
-class RackReservationEditView(RackReservationCreateView):
-    permission_required = 'dcim.change_rackreservation'
-
-
 class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_rackreservation'
     permission_required = 'dcim.delete_rackreservation'
     queryset = RackReservation.objects.all()
     queryset = RackReservation.objects.all()
@@ -564,17 +534,12 @@ class ManufacturerListView(ObjectListView):
     table = tables.ManufacturerTable
     table = tables.ManufacturerTable
 
 
 
 
-class ManufacturerCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_manufacturer'
+class ManufacturerEditView(ObjectEditView):
     queryset = Manufacturer.objects.all()
     queryset = Manufacturer.objects.all()
     model_form = forms.ManufacturerForm
     model_form = forms.ManufacturerForm
     default_return_url = 'dcim:manufacturer_list'
     default_return_url = 'dcim:manufacturer_list'
 
 
 
 
-class ManufacturerEditView(ManufacturerCreateView):
-    permission_required = 'dcim.change_manufacturer'
-
-
 class ManufacturerBulkImportView(PermissionRequiredMixin, BulkImportView):
 class ManufacturerBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'dcim.add_manufacturer'
     permission_required = 'dcim.add_manufacturer'
     queryset = Manufacturer.objects.all()
     queryset = Manufacturer.objects.all()
@@ -664,18 +629,13 @@ class DeviceTypeView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class DeviceTypeCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_devicetype'
+class DeviceTypeEditView(ObjectEditView):
     queryset = DeviceType.objects.all()
     queryset = DeviceType.objects.all()
     model_form = forms.DeviceTypeForm
     model_form = forms.DeviceTypeForm
     template_name = 'dcim/devicetype_edit.html'
     template_name = 'dcim/devicetype_edit.html'
     default_return_url = 'dcim:devicetype_list'
     default_return_url = 'dcim:devicetype_list'
 
 
 
 
-class DeviceTypeEditView(DeviceTypeCreateView):
-    permission_required = 'dcim.change_devicetype'
-
-
 class DeviceTypeDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class DeviceTypeDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_devicetype'
     permission_required = 'dcim.delete_devicetype'
     queryset = DeviceType.objects.all()
     queryset = DeviceType.objects.all()
@@ -738,8 +698,7 @@ class ConsolePortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class ConsolePortTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_consoleporttemplate'
+class ConsolePortTemplateEditView(ObjectEditView):
     queryset = ConsolePortTemplate.objects.all()
     queryset = ConsolePortTemplate.objects.all()
     model_form = forms.ConsolePortTemplateForm
     model_form = forms.ConsolePortTemplateForm
 
 
@@ -774,8 +733,7 @@ class ConsoleServerPortTemplateCreateView(PermissionRequiredMixin, ComponentCrea
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class ConsoleServerPortTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_consoleserverporttemplate'
+class ConsoleServerPortTemplateEditView(ObjectEditView):
     queryset = ConsoleServerPortTemplate.objects.all()
     queryset = ConsoleServerPortTemplate.objects.all()
     model_form = forms.ConsoleServerPortTemplateForm
     model_form = forms.ConsoleServerPortTemplateForm
 
 
@@ -810,8 +768,7 @@ class PowerPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class PowerPortTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_powerporttemplate'
+class PowerPortTemplateEditView(ObjectEditView):
     queryset = PowerPortTemplate.objects.all()
     queryset = PowerPortTemplate.objects.all()
     model_form = forms.PowerPortTemplateForm
     model_form = forms.PowerPortTemplateForm
 
 
@@ -846,8 +803,7 @@ class PowerOutletTemplateCreateView(PermissionRequiredMixin, ComponentCreateView
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class PowerOutletTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_poweroutlettemplate'
+class PowerOutletTemplateEditView(ObjectEditView):
     queryset = PowerOutletTemplate.objects.all()
     queryset = PowerOutletTemplate.objects.all()
     model_form = forms.PowerOutletTemplateForm
     model_form = forms.PowerOutletTemplateForm
 
 
@@ -882,8 +838,7 @@ class InterfaceTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class InterfaceTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_interfacetemplate'
+class InterfaceTemplateEditView(ObjectEditView):
     queryset = InterfaceTemplate.objects.all()
     queryset = InterfaceTemplate.objects.all()
     model_form = forms.InterfaceTemplateForm
     model_form = forms.InterfaceTemplateForm
 
 
@@ -918,8 +873,7 @@ class FrontPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class FrontPortTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_frontporttemplate'
+class FrontPortTemplateEditView(ObjectEditView):
     queryset = FrontPortTemplate.objects.all()
     queryset = FrontPortTemplate.objects.all()
     model_form = forms.FrontPortTemplateForm
     model_form = forms.FrontPortTemplateForm
 
 
@@ -954,8 +908,7 @@ class RearPortTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class RearPortTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_rearporttemplate'
+class RearPortTemplateEditView(ObjectEditView):
     queryset = RearPortTemplate.objects.all()
     queryset = RearPortTemplate.objects.all()
     model_form = forms.RearPortTemplateForm
     model_form = forms.RearPortTemplateForm
 
 
@@ -990,8 +943,7 @@ class DeviceBayTemplateCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class DeviceBayTemplateEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_devicebaytemplate'
+class DeviceBayTemplateEditView(ObjectEditView):
     queryset = DeviceBayTemplate.objects.all()
     queryset = DeviceBayTemplate.objects.all()
     model_form = forms.DeviceBayTemplateForm
     model_form = forms.DeviceBayTemplateForm
 
 
@@ -1023,17 +975,12 @@ class DeviceRoleListView(ObjectListView):
     table = tables.DeviceRoleTable
     table = tables.DeviceRoleTable
 
 
 
 
-class DeviceRoleCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_devicerole'
+class DeviceRoleEditView(ObjectEditView):
     queryset = DeviceRole.objects.all()
     queryset = DeviceRole.objects.all()
     model_form = forms.DeviceRoleForm
     model_form = forms.DeviceRoleForm
     default_return_url = 'dcim:devicerole_list'
     default_return_url = 'dcim:devicerole_list'
 
 
 
 
-class DeviceRoleEditView(DeviceRoleCreateView):
-    permission_required = 'dcim.change_devicerole'
-
-
 class DeviceRoleBulkImportView(PermissionRequiredMixin, BulkImportView):
 class DeviceRoleBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'dcim.add_devicerole'
     permission_required = 'dcim.add_devicerole'
     queryset = DeviceRole.objects.all()
     queryset = DeviceRole.objects.all()
@@ -1058,17 +1005,12 @@ class PlatformListView(ObjectListView):
     table = tables.PlatformTable
     table = tables.PlatformTable
 
 
 
 
-class PlatformCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_platform'
+class PlatformEditView(ObjectEditView):
     queryset = Platform.objects.all()
     queryset = Platform.objects.all()
     model_form = forms.PlatformForm
     model_form = forms.PlatformForm
     default_return_url = 'dcim:platform_list'
     default_return_url = 'dcim:platform_list'
 
 
 
 
-class PlatformEditView(PlatformCreateView):
-    permission_required = 'dcim.change_platform'
-
-
 class PlatformBulkImportView(PermissionRequiredMixin, BulkImportView):
 class PlatformBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'dcim.add_platform'
     permission_required = 'dcim.add_platform'
     queryset = Platform.objects.all()
     queryset = Platform.objects.all()
@@ -1244,18 +1186,13 @@ class DeviceConfigContextView(PermissionRequiredMixin, ObjectConfigContextView):
     base_template = 'dcim/device.html'
     base_template = 'dcim/device.html'
 
 
 
 
-class DeviceCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_device'
+class DeviceEditView(ObjectEditView):
     queryset = Device.objects.all()
     queryset = Device.objects.all()
     model_form = forms.DeviceForm
     model_form = forms.DeviceForm
     template_name = 'dcim/device_edit.html'
     template_name = 'dcim/device_edit.html'
     default_return_url = 'dcim:device_list'
     default_return_url = 'dcim:device_list'
 
 
 
 
-class DeviceEditView(DeviceCreateView):
-    permission_required = 'dcim.change_device'
-
-
 class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_device'
     permission_required = 'dcim.delete_device'
     queryset = Device.objects.all()
     queryset = Device.objects.all()
@@ -1328,8 +1265,7 @@ class ConsolePortCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class ConsolePortEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_consoleport'
+class ConsolePortEditView(ObjectEditView):
     queryset = ConsolePort.objects.all()
     queryset = ConsolePort.objects.all()
     model_form = forms.ConsolePortForm
     model_form = forms.ConsolePortForm
 
 
@@ -1383,8 +1319,7 @@ class ConsoleServerPortCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class ConsoleServerPortEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_consoleserverport'
+class ConsoleServerPortEditView(ObjectEditView):
     queryset = ConsoleServerPort.objects.all()
     queryset = ConsoleServerPort.objects.all()
     model_form = forms.ConsoleServerPortForm
     model_form = forms.ConsoleServerPortForm
 
 
@@ -1450,8 +1385,7 @@ class PowerPortCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class PowerPortEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_powerport'
+class PowerPortEditView(ObjectEditView):
     queryset = PowerPort.objects.all()
     queryset = PowerPort.objects.all()
     model_form = forms.PowerPortForm
     model_form = forms.PowerPortForm
 
 
@@ -1505,8 +1439,7 @@ class PowerOutletCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class PowerOutletEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_poweroutlet'
+class PowerOutletEditView(ObjectEditView):
     queryset = PowerOutlet.objects.all()
     queryset = PowerOutlet.objects.all()
     model_form = forms.PowerOutletForm
     model_form = forms.PowerOutletForm
 
 
@@ -1608,8 +1541,7 @@ class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class InterfaceEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_interface'
+class InterfaceEditView(ObjectEditView):
     queryset = Interface.objects.all()
     queryset = Interface.objects.all()
     model_form = forms.InterfaceForm
     model_form = forms.InterfaceForm
     template_name = 'dcim/interface_edit.html'
     template_name = 'dcim/interface_edit.html'
@@ -1676,8 +1608,7 @@ class FrontPortCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class FrontPortEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_frontport'
+class FrontPortEditView(ObjectEditView):
     queryset = FrontPort.objects.all()
     queryset = FrontPort.objects.all()
     model_form = forms.FrontPortForm
     model_form = forms.FrontPortForm
 
 
@@ -1743,8 +1674,7 @@ class RearPortCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class RearPortEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_rearport'
+class RearPortEditView(ObjectEditView):
     queryset = RearPort.objects.all()
     queryset = RearPort.objects.all()
     model_form = forms.RearPortForm
     model_form = forms.RearPortForm
 
 
@@ -1812,8 +1742,7 @@ class DeviceBayCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'dcim/device_component_add.html'
     template_name = 'dcim/device_component_add.html'
 
 
 
 
-class DeviceBayEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_devicebay'
+class DeviceBayEditView(ObjectEditView):
     queryset = DeviceBay.objects.all()
     queryset = DeviceBay.objects.all()
     model_form = forms.DeviceBayForm
     model_form = forms.DeviceBayForm
 
 
@@ -2152,8 +2081,7 @@ class CableCreateView(PermissionRequiredMixin, GetReturnURLMixin, View):
         })
         })
 
 
 
 
-class CableEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_cable'
+class CableEditView(ObjectEditView):
     queryset = Cable.objects.all()
     queryset = Cable.objects.all()
     model_form = forms.CableForm
     model_form = forms.CableForm
     template_name = 'dcim/cable_edit.html'
     template_name = 'dcim/cable_edit.html'
@@ -2306,8 +2234,7 @@ class InventoryItemListView(ObjectListView):
     action_buttons = ('import', 'export')
     action_buttons = ('import', 'export')
 
 
 
 
-class InventoryItemEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_inventoryitem'
+class InventoryItemEditView(ObjectEditView):
     queryset = InventoryItem.objects.all()
     queryset = InventoryItem.objects.all()
     model_form = forms.InventoryItemForm
     model_form = forms.InventoryItemForm
 
 
@@ -2650,17 +2577,12 @@ class PowerPanelView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class PowerPanelCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_powerpanel'
+class PowerPanelEditView(ObjectEditView):
     queryset = PowerPanel.objects.all()
     queryset = PowerPanel.objects.all()
     model_form = forms.PowerPanelForm
     model_form = forms.PowerPanelForm
     default_return_url = 'dcim:powerpanel_list'
     default_return_url = 'dcim:powerpanel_list'
 
 
 
 
-class PowerPanelEditView(PowerPanelCreateView):
-    permission_required = 'dcim.change_powerpanel'
-
-
 class PowerPanelDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class PowerPanelDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_powerpanel'
     permission_required = 'dcim.delete_powerpanel'
     queryset = PowerPanel.objects.all()
     queryset = PowerPanel.objects.all()
@@ -2721,18 +2643,13 @@ class PowerFeedView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class PowerFeedCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.add_powerfeed'
+class PowerFeedEditView(ObjectEditView):
     queryset = PowerFeed.objects.all()
     queryset = PowerFeed.objects.all()
     model_form = forms.PowerFeedForm
     model_form = forms.PowerFeedForm
     template_name = 'dcim/powerfeed_edit.html'
     template_name = 'dcim/powerfeed_edit.html'
     default_return_url = 'dcim:powerfeed_list'
     default_return_url = 'dcim:powerfeed_list'
 
 
 
 
-class PowerFeedEditView(PowerFeedCreateView):
-    permission_required = 'dcim.change_powerfeed'
-
-
 class PowerFeedDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class PowerFeedDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'dcim.delete_powerfeed'
     permission_required = 'dcim.delete_powerfeed'
     queryset = PowerFeed.objects.all()
     queryset = PowerFeed.objects.all()

+ 1 - 1
netbox/extras/urls.py

@@ -18,7 +18,7 @@ urlpatterns = [
 
 
     # Config contexts
     # Config contexts
     path('config-contexts/', views.ConfigContextListView.as_view(), name='configcontext_list'),
     path('config-contexts/', views.ConfigContextListView.as_view(), name='configcontext_list'),
-    path('config-contexts/add/', views.ConfigContextCreateView.as_view(), name='configcontext_add'),
+    path('config-contexts/add/', views.ConfigContextEditView.as_view(), name='configcontext_add'),
     path('config-contexts/edit/', views.ConfigContextBulkEditView.as_view(), name='configcontext_bulk_edit'),
     path('config-contexts/edit/', views.ConfigContextBulkEditView.as_view(), name='configcontext_bulk_edit'),
     path('config-contexts/delete/', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'),
     path('config-contexts/delete/', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'),
     path('config-contexts/<int:pk>/', views.ConfigContextView.as_view(), name='configcontext'),
     path('config-contexts/<int:pk>/', views.ConfigContextView.as_view(), name='configcontext'),

+ 3 - 10
netbox/extras/views.py

@@ -64,8 +64,7 @@ class TagView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class TagEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'extras.change_tag'
+class TagEditView(ObjectEditView):
     queryset = Tag.objects.all()
     queryset = Tag.objects.all()
     model_form = forms.TagForm
     model_form = forms.TagForm
     default_return_url = 'extras:tag_list'
     default_return_url = 'extras:tag_list'
@@ -132,18 +131,13 @@ class ConfigContextView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class ConfigContextCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'extras.add_configcontext'
+class ConfigContextEditView(ObjectEditView):
     queryset = ConfigContext.objects.all()
     queryset = ConfigContext.objects.all()
     model_form = forms.ConfigContextForm
     model_form = forms.ConfigContextForm
     default_return_url = 'extras:configcontext_list'
     default_return_url = 'extras:configcontext_list'
     template_name = 'extras/configcontext_edit.html'
     template_name = 'extras/configcontext_edit.html'
 
 
 
 
-class ConfigContextEditView(ConfigContextCreateView):
-    permission_required = 'extras.change_configcontext'
-
-
 class ConfigContextBulkEditView(PermissionRequiredMixin, BulkEditView):
 class ConfigContextBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'extras.change_configcontext'
     permission_required = 'extras.change_configcontext'
     queryset = ConfigContext.objects.all()
     queryset = ConfigContext.objects.all()
@@ -301,8 +295,7 @@ class ObjectChangeLogView(View):
 # Image attachments
 # Image attachments
 #
 #
 
 
-class ImageAttachmentEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'extras.change_imageattachment'
+class ImageAttachmentEditView(ObjectEditView):
     queryset = ImageAttachment.objects.all()
     queryset = ImageAttachment.objects.all()
     model_form = forms.ImageAttachmentForm
     model_form = forms.ImageAttachmentForm
 
 

+ 8 - 8
netbox/ipam/urls.py

@@ -9,7 +9,7 @@ urlpatterns = [
 
 
     # VRFs
     # VRFs
     path('vrfs/', views.VRFListView.as_view(), name='vrf_list'),
     path('vrfs/', views.VRFListView.as_view(), name='vrf_list'),
-    path('vrfs/add/', views.VRFCreateView.as_view(), name='vrf_add'),
+    path('vrfs/add/', views.VRFEditView.as_view(), name='vrf_add'),
     path('vrfs/import/', views.VRFBulkImportView.as_view(), name='vrf_import'),
     path('vrfs/import/', views.VRFBulkImportView.as_view(), name='vrf_import'),
     path('vrfs/edit/', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'),
     path('vrfs/edit/', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'),
     path('vrfs/delete/', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'),
     path('vrfs/delete/', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'),
@@ -20,7 +20,7 @@ urlpatterns = [
 
 
     # RIRs
     # RIRs
     path('rirs/', views.RIRListView.as_view(), name='rir_list'),
     path('rirs/', views.RIRListView.as_view(), name='rir_list'),
-    path('rirs/add/', views.RIRCreateView.as_view(), name='rir_add'),
+    path('rirs/add/', views.RIREditView.as_view(), name='rir_add'),
     path('rirs/import/', views.RIRBulkImportView.as_view(), name='rir_import'),
     path('rirs/import/', views.RIRBulkImportView.as_view(), name='rir_import'),
     path('rirs/delete/', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
     path('rirs/delete/', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
     path('rirs/<slug:slug>/edit/', views.RIREditView.as_view(), name='rir_edit'),
     path('rirs/<slug:slug>/edit/', views.RIREditView.as_view(), name='rir_edit'),
@@ -28,7 +28,7 @@ urlpatterns = [
 
 
     # Aggregates
     # Aggregates
     path('aggregates/', views.AggregateListView.as_view(), name='aggregate_list'),
     path('aggregates/', views.AggregateListView.as_view(), name='aggregate_list'),
-    path('aggregates/add/', views.AggregateCreateView.as_view(), name='aggregate_add'),
+    path('aggregates/add/', views.AggregateEditView.as_view(), name='aggregate_add'),
     path('aggregates/import/', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
     path('aggregates/import/', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
     path('aggregates/edit/', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'),
     path('aggregates/edit/', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'),
     path('aggregates/delete/', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'),
     path('aggregates/delete/', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'),
@@ -39,7 +39,7 @@ urlpatterns = [
 
 
     # Roles
     # Roles
     path('roles/', views.RoleListView.as_view(), name='role_list'),
     path('roles/', views.RoleListView.as_view(), name='role_list'),
-    path('roles/add/', views.RoleCreateView.as_view(), name='role_add'),
+    path('roles/add/', views.RoleEditView.as_view(), name='role_add'),
     path('roles/import/', views.RoleBulkImportView.as_view(), name='role_import'),
     path('roles/import/', views.RoleBulkImportView.as_view(), name='role_import'),
     path('roles/delete/', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'),
     path('roles/delete/', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'),
     path('roles/<slug:slug>/edit/', views.RoleEditView.as_view(), name='role_edit'),
     path('roles/<slug:slug>/edit/', views.RoleEditView.as_view(), name='role_edit'),
@@ -47,7 +47,7 @@ urlpatterns = [
 
 
     # Prefixes
     # Prefixes
     path('prefixes/', views.PrefixListView.as_view(), name='prefix_list'),
     path('prefixes/', views.PrefixListView.as_view(), name='prefix_list'),
-    path('prefixes/add/', views.PrefixCreateView.as_view(), name='prefix_add'),
+    path('prefixes/add/', views.PrefixEditView.as_view(), name='prefix_add'),
     path('prefixes/import/', views.PrefixBulkImportView.as_view(), name='prefix_import'),
     path('prefixes/import/', views.PrefixBulkImportView.as_view(), name='prefix_import'),
     path('prefixes/edit/', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'),
     path('prefixes/edit/', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'),
     path('prefixes/delete/', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'),
     path('prefixes/delete/', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'),
@@ -60,7 +60,7 @@ urlpatterns = [
 
 
     # IP addresses
     # IP addresses
     path('ip-addresses/', views.IPAddressListView.as_view(), name='ipaddress_list'),
     path('ip-addresses/', views.IPAddressListView.as_view(), name='ipaddress_list'),
-    path('ip-addresses/add/', views.IPAddressCreateView.as_view(), name='ipaddress_add'),
+    path('ip-addresses/add/', views.IPAddressEditView.as_view(), name='ipaddress_add'),
     path('ip-addresses/bulk-add/', views.IPAddressBulkCreateView.as_view(), name='ipaddress_bulk_add'),
     path('ip-addresses/bulk-add/', views.IPAddressBulkCreateView.as_view(), name='ipaddress_bulk_add'),
     path('ip-addresses/import/', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'),
     path('ip-addresses/import/', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'),
     path('ip-addresses/edit/', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
     path('ip-addresses/edit/', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
@@ -73,7 +73,7 @@ urlpatterns = [
 
 
     # VLAN groups
     # VLAN groups
     path('vlan-groups/', views.VLANGroupListView.as_view(), name='vlangroup_list'),
     path('vlan-groups/', views.VLANGroupListView.as_view(), name='vlangroup_list'),
-    path('vlan-groups/add/', views.VLANGroupCreateView.as_view(), name='vlangroup_add'),
+    path('vlan-groups/add/', views.VLANGroupEditView.as_view(), name='vlangroup_add'),
     path('vlan-groups/import/', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'),
     path('vlan-groups/import/', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'),
     path('vlan-groups/delete/', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'),
     path('vlan-groups/delete/', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'),
     path('vlan-groups/<int:pk>/edit/', views.VLANGroupEditView.as_view(), name='vlangroup_edit'),
     path('vlan-groups/<int:pk>/edit/', views.VLANGroupEditView.as_view(), name='vlangroup_edit'),
@@ -82,7 +82,7 @@ urlpatterns = [
 
 
     # VLANs
     # VLANs
     path('vlans/', views.VLANListView.as_view(), name='vlan_list'),
     path('vlans/', views.VLANListView.as_view(), name='vlan_list'),
-    path('vlans/add/', views.VLANCreateView.as_view(), name='vlan_add'),
+    path('vlans/add/', views.VLANEditView.as_view(), name='vlan_add'),
     path('vlans/import/', views.VLANBulkImportView.as_view(), name='vlan_import'),
     path('vlans/import/', views.VLANBulkImportView.as_view(), name='vlan_import'),
     path('vlans/edit/', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'),
     path('vlans/edit/', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'),
     path('vlans/delete/', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'),
     path('vlans/delete/', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'),

+ 9 - 53
netbox/ipam/views.py

@@ -134,18 +134,13 @@ class VRFView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class VRFCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_vrf'
+class VRFEditView(ObjectEditView):
     queryset = VRF.objects.all()
     queryset = VRF.objects.all()
     model_form = forms.VRFForm
     model_form = forms.VRFForm
     template_name = 'ipam/vrf_edit.html'
     template_name = 'ipam/vrf_edit.html'
     default_return_url = 'ipam:vrf_list'
     default_return_url = 'ipam:vrf_list'
 
 
 
 
-class VRFEditView(VRFCreateView):
-    permission_required = 'ipam.change_vrf'
-
-
 class VRFDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class VRFDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'ipam.delete_vrf'
     permission_required = 'ipam.delete_vrf'
     queryset = VRF.objects.all()
     queryset = VRF.objects.all()
@@ -257,17 +252,12 @@ class RIRListView(ObjectListView):
         return rirs
         return rirs
 
 
 
 
-class RIRCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_rir'
+class RIREditView(ObjectEditView):
     queryset = RIR.objects.all()
     queryset = RIR.objects.all()
     model_form = forms.RIRForm
     model_form = forms.RIRForm
     default_return_url = 'ipam:rir_list'
     default_return_url = 'ipam:rir_list'
 
 
 
 
-class RIREditView(RIRCreateView):
-    permission_required = 'ipam.change_rir'
-
-
 class RIRBulkImportView(PermissionRequiredMixin, BulkImportView):
 class RIRBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'ipam.add_rir'
     permission_required = 'ipam.add_rir'
     queryset = RIR.objects.all()
     queryset = RIR.objects.all()
@@ -359,18 +349,13 @@ class AggregateView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class AggregateCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_aggregate'
+class AggregateEditView(ObjectEditView):
     queryset = Aggregate.objects.all()
     queryset = Aggregate.objects.all()
     model_form = forms.AggregateForm
     model_form = forms.AggregateForm
     template_name = 'ipam/aggregate_edit.html'
     template_name = 'ipam/aggregate_edit.html'
     default_return_url = 'ipam:aggregate_list'
     default_return_url = 'ipam:aggregate_list'
 
 
 
 
-class AggregateEditView(AggregateCreateView):
-    permission_required = 'ipam.change_aggregate'
-
-
 class AggregateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class AggregateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'ipam.delete_aggregate'
     permission_required = 'ipam.delete_aggregate'
     queryset = Aggregate.objects.all()
     queryset = Aggregate.objects.all()
@@ -411,17 +396,12 @@ class RoleListView(ObjectListView):
     table = tables.RoleTable
     table = tables.RoleTable
 
 
 
 
-class RoleCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_role'
+class RoleEditView(ObjectEditView):
     queryset = Role.objects.all()
     queryset = Role.objects.all()
     model_form = forms.RoleForm
     model_form = forms.RoleForm
     default_return_url = 'ipam:role_list'
     default_return_url = 'ipam:role_list'
 
 
 
 
-class RoleEditView(RoleCreateView):
-    permission_required = 'ipam.change_role'
-
-
 class RoleBulkImportView(PermissionRequiredMixin, BulkImportView):
 class RoleBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'ipam.add_role'
     permission_required = 'ipam.add_role'
     queryset = Role.objects.all()
     queryset = Role.objects.all()
@@ -585,18 +565,13 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class PrefixCreateView(ObjectPermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_prefix'
+class PrefixEditView(ObjectEditView):
     queryset = Prefix.objects.all()
     queryset = Prefix.objects.all()
     model_form = forms.PrefixForm
     model_form = forms.PrefixForm
     template_name = 'ipam/prefix_edit.html'
     template_name = 'ipam/prefix_edit.html'
     default_return_url = 'ipam:prefix_list'
     default_return_url = 'ipam:prefix_list'
 
 
 
 
-class PrefixEditView(PrefixCreateView):
-    permission_required = 'ipam.change_prefix'
-
-
 class PrefixDeleteView(ObjectPermissionRequiredMixin, ObjectDeleteView):
 class PrefixDeleteView(ObjectPermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'ipam.delete_prefix'
     permission_required = 'ipam.delete_prefix'
     queryset = Prefix.objects.all()
     queryset = Prefix.objects.all()
@@ -696,8 +671,7 @@ class IPAddressView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class IPAddressCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_ipaddress'
+class IPAddressEditView(ObjectEditView):
     queryset = IPAddress.objects.all()
     queryset = IPAddress.objects.all()
     model_form = forms.IPAddressForm
     model_form = forms.IPAddressForm
     template_name = 'ipam/ipaddress_edit.html'
     template_name = 'ipam/ipaddress_edit.html'
@@ -715,10 +689,6 @@ class IPAddressCreateView(PermissionRequiredMixin, ObjectEditView):
         return obj
         return obj
 
 
 
 
-class IPAddressEditView(IPAddressCreateView):
-    permission_required = 'ipam.change_ipaddress'
-
-
 class IPAddressAssignView(PermissionRequiredMixin, View):
 class IPAddressAssignView(PermissionRequiredMixin, View):
     """
     """
     Search for IPAddresses to be assigned to an Interface.
     Search for IPAddresses to be assigned to an Interface.
@@ -814,17 +784,13 @@ class VLANGroupListView(ObjectListView):
     table = tables.VLANGroupTable
     table = tables.VLANGroupTable
 
 
 
 
-class VLANGroupCreateView(PermissionRequiredMixin, ObjectEditView):
+class VLANGroupEditView(ObjectEditView):
     permission_required = 'ipam.add_vlangroup'
     permission_required = 'ipam.add_vlangroup'
     queryset = VLANGroup.objects.all()
     queryset = VLANGroup.objects.all()
     model_form = forms.VLANGroupForm
     model_form = forms.VLANGroupForm
     default_return_url = 'ipam:vlangroup_list'
     default_return_url = 'ipam:vlangroup_list'
 
 
 
 
-class VLANGroupEditView(VLANGroupCreateView):
-    permission_required = 'ipam.change_vlangroup'
-
-
 class VLANGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
 class VLANGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'ipam.add_vlangroup'
     permission_required = 'ipam.add_vlangroup'
     queryset = VLANGroup.objects.all()
     queryset = VLANGroup.objects.all()
@@ -930,18 +896,13 @@ class VLANMembersView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class VLANCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_vlan'
+class VLANEditView(ObjectEditView):
     queryset = VLAN.objects.all()
     queryset = VLAN.objects.all()
     model_form = forms.VLANForm
     model_form = forms.VLANForm
     template_name = 'ipam/vlan_edit.html'
     template_name = 'ipam/vlan_edit.html'
     default_return_url = 'ipam:vlan_list'
     default_return_url = 'ipam:vlan_list'
 
 
 
 
-class VLANEditView(VLANCreateView):
-    permission_required = 'ipam.change_vlan'
-
-
 class VLANDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class VLANDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'ipam.delete_vlan'
     permission_required = 'ipam.delete_vlan'
     queryset = VLAN.objects.all()
     queryset = VLAN.objects.all()
@@ -997,8 +958,7 @@ class ServiceView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class ServiceCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'ipam.add_service'
+class ServiceEditView(ObjectEditView):
     queryset = Service.objects.all()
     queryset = Service.objects.all()
     model_form = forms.ServiceForm
     model_form = forms.ServiceForm
     template_name = 'ipam/service_edit.html'
     template_name = 'ipam/service_edit.html'
@@ -1022,10 +982,6 @@ class ServiceBulkImportView(PermissionRequiredMixin, BulkImportView):
     default_return_url = 'ipam:service_list'
     default_return_url = 'ipam:service_list'
 
 
 
 
-class ServiceEditView(ServiceCreateView):
-    permission_required = 'ipam.change_service'
-
-
 class ServiceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class ServiceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'ipam.delete_service'
     permission_required = 'ipam.delete_service'
     queryset = Service.objects.all()
     queryset = Service.objects.all()

+ 1 - 1
netbox/secrets/urls.py

@@ -9,7 +9,7 @@ urlpatterns = [
 
 
     # Secret roles
     # Secret roles
     path('secret-roles/', views.SecretRoleListView.as_view(), name='secretrole_list'),
     path('secret-roles/', views.SecretRoleListView.as_view(), name='secretrole_list'),
-    path('secret-roles/add/', views.SecretRoleCreateView.as_view(), name='secretrole_add'),
+    path('secret-roles/add/', views.SecretRoleEditView.as_view(), name='secretrole_add'),
     path('secret-roles/import/', views.SecretRoleBulkImportView.as_view(), name='secretrole_import'),
     path('secret-roles/import/', views.SecretRoleBulkImportView.as_view(), name='secretrole_import'),
     path('secret-roles/delete/', views.SecretRoleBulkDeleteView.as_view(), name='secretrole_bulk_delete'),
     path('secret-roles/delete/', views.SecretRoleBulkDeleteView.as_view(), name='secretrole_bulk_delete'),
     path('secret-roles/<slug:slug>/edit/', views.SecretRoleEditView.as_view(), name='secretrole_edit'),
     path('secret-roles/<slug:slug>/edit/', views.SecretRoleEditView.as_view(), name='secretrole_edit'),

+ 1 - 6
netbox/secrets/views.py

@@ -35,17 +35,12 @@ class SecretRoleListView(ObjectListView):
     table = tables.SecretRoleTable
     table = tables.SecretRoleTable
 
 
 
 
-class SecretRoleCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'secrets.add_secretrole'
+class SecretRoleEditView(ObjectEditView):
     queryset = SecretRole.objects.all()
     queryset = SecretRole.objects.all()
     model_form = forms.SecretRoleForm
     model_form = forms.SecretRoleForm
     default_return_url = 'secrets:secretrole_list'
     default_return_url = 'secrets:secretrole_list'
 
 
 
 
-class SecretRoleEditView(SecretRoleCreateView):
-    permission_required = 'secrets.change_secretrole'
-
-
 class SecretRoleBulkImportView(PermissionRequiredMixin, BulkImportView):
 class SecretRoleBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'secrets.add_secretrole'
     permission_required = 'secrets.add_secretrole'
     queryset = SecretRole.objects.all()
     queryset = SecretRole.objects.all()

+ 2 - 2
netbox/tenancy/urls.py

@@ -9,7 +9,7 @@ urlpatterns = [
 
 
     # Tenant groups
     # Tenant groups
     path('tenant-groups/', views.TenantGroupListView.as_view(), name='tenantgroup_list'),
     path('tenant-groups/', views.TenantGroupListView.as_view(), name='tenantgroup_list'),
-    path('tenant-groups/add/', views.TenantGroupCreateView.as_view(), name='tenantgroup_add'),
+    path('tenant-groups/add/', views.TenantGroupEditView.as_view(), name='tenantgroup_add'),
     path('tenant-groups/import/', views.TenantGroupBulkImportView.as_view(), name='tenantgroup_import'),
     path('tenant-groups/import/', views.TenantGroupBulkImportView.as_view(), name='tenantgroup_import'),
     path('tenant-groups/delete/', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'),
     path('tenant-groups/delete/', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'),
     path('tenant-groups/<slug:slug>/edit/', views.TenantGroupEditView.as_view(), name='tenantgroup_edit'),
     path('tenant-groups/<slug:slug>/edit/', views.TenantGroupEditView.as_view(), name='tenantgroup_edit'),
@@ -17,7 +17,7 @@ urlpatterns = [
 
 
     # Tenants
     # Tenants
     path('tenants/', views.TenantListView.as_view(), name='tenant_list'),
     path('tenants/', views.TenantListView.as_view(), name='tenant_list'),
-    path('tenants/add/', views.TenantCreateView.as_view(), name='tenant_add'),
+    path('tenants/add/', views.TenantEditView.as_view(), name='tenant_add'),
     path('tenants/import/', views.TenantBulkImportView.as_view(), name='tenant_import'),
     path('tenants/import/', views.TenantBulkImportView.as_view(), name='tenant_import'),
     path('tenants/edit/', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'),
     path('tenants/edit/', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'),
     path('tenants/delete/', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'),
     path('tenants/delete/', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'),

+ 2 - 12
netbox/tenancy/views.py

@@ -29,17 +29,12 @@ class TenantGroupListView(ObjectListView):
     table = tables.TenantGroupTable
     table = tables.TenantGroupTable
 
 
 
 
-class TenantGroupCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'tenancy.add_tenantgroup'
+class TenantGroupEditView(ObjectEditView):
     queryset = TenantGroup.objects.all()
     queryset = TenantGroup.objects.all()
     model_form = forms.TenantGroupForm
     model_form = forms.TenantGroupForm
     default_return_url = 'tenancy:tenantgroup_list'
     default_return_url = 'tenancy:tenantgroup_list'
 
 
 
 
-class TenantGroupEditView(TenantGroupCreateView):
-    permission_required = 'tenancy.change_tenantgroup'
-
-
 class TenantGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
 class TenantGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'tenancy.add_tenantgroup'
     permission_required = 'tenancy.add_tenantgroup'
     queryset = TenantGroup.objects.all()
     queryset = TenantGroup.objects.all()
@@ -92,18 +87,13 @@ class TenantView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class TenantCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'tenancy.add_tenant'
+class TenantEditView(ObjectEditView):
     queryset = Tenant.objects.all()
     queryset = Tenant.objects.all()
     model_form = forms.TenantForm
     model_form = forms.TenantForm
     template_name = 'tenancy/tenant_edit.html'
     template_name = 'tenancy/tenant_edit.html'
     default_return_url = 'tenancy:tenant_list'
     default_return_url = 'tenancy:tenant_list'
 
 
 
 
-class TenantEditView(TenantCreateView):
-    permission_required = 'tenancy.change_tenant'
-
-
 class TenantDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class TenantDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'tenancy.delete_tenant'
     permission_required = 'tenancy.delete_tenant'
     queryset = Tenant.objects.all()
     queryset = Tenant.objects.all()

+ 7 - 1
netbox/utilities/views.py

@@ -278,7 +278,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
         return {}
         return {}
 
 
 
 
-class ObjectEditView(GetReturnURLMixin, View):
+class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
     """
     """
     Create or edit a single object.
     Create or edit a single object.
 
 
@@ -290,6 +290,12 @@ class ObjectEditView(GetReturnURLMixin, View):
     model_form = None
     model_form = None
     template_name = 'utilities/obj_edit.html'
     template_name = 'utilities/obj_edit.html'
 
 
+    def get_required_permission(self):
+        # Determine required permission based on whether we are editing an existing object
+        if self.obj.pk is None:
+            return get_permission_for_model(self.queryset.model, 'add')
+        return get_permission_for_model(self.queryset.model, 'change')
+
     def get_object(self, kwargs):
     def get_object(self, kwargs):
         # Look up an existing object by slug or PK, if provided.
         # Look up an existing object by slug or PK, if provided.
         if 'slug' in kwargs:
         if 'slug' in kwargs:

+ 6 - 6
netbox/virtualization/urls.py

@@ -1,7 +1,7 @@
 from django.urls import path
 from django.urls import path
 
 
 from extras.views import ObjectChangeLogView
 from extras.views import ObjectChangeLogView
-from ipam.views import ServiceCreateView
+from ipam.views import ServiceEditView
 from . import views
 from . import views
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
 
 
@@ -10,7 +10,7 @@ urlpatterns = [
 
 
     # Cluster types
     # Cluster types
     path('cluster-types/', views.ClusterTypeListView.as_view(), name='clustertype_list'),
     path('cluster-types/', views.ClusterTypeListView.as_view(), name='clustertype_list'),
-    path('cluster-types/add/', views.ClusterTypeCreateView.as_view(), name='clustertype_add'),
+    path('cluster-types/add/', views.ClusterTypeEditView.as_view(), name='clustertype_add'),
     path('cluster-types/import/', views.ClusterTypeBulkImportView.as_view(), name='clustertype_import'),
     path('cluster-types/import/', views.ClusterTypeBulkImportView.as_view(), name='clustertype_import'),
     path('cluster-types/delete/', views.ClusterTypeBulkDeleteView.as_view(), name='clustertype_bulk_delete'),
     path('cluster-types/delete/', views.ClusterTypeBulkDeleteView.as_view(), name='clustertype_bulk_delete'),
     path('cluster-types/<slug:slug>/edit/', views.ClusterTypeEditView.as_view(), name='clustertype_edit'),
     path('cluster-types/<slug:slug>/edit/', views.ClusterTypeEditView.as_view(), name='clustertype_edit'),
@@ -18,7 +18,7 @@ urlpatterns = [
 
 
     # Cluster groups
     # Cluster groups
     path('cluster-groups/', views.ClusterGroupListView.as_view(), name='clustergroup_list'),
     path('cluster-groups/', views.ClusterGroupListView.as_view(), name='clustergroup_list'),
-    path('cluster-groups/add/', views.ClusterGroupCreateView.as_view(), name='clustergroup_add'),
+    path('cluster-groups/add/', views.ClusterGroupEditView.as_view(), name='clustergroup_add'),
     path('cluster-groups/import/', views.ClusterGroupBulkImportView.as_view(), name='clustergroup_import'),
     path('cluster-groups/import/', views.ClusterGroupBulkImportView.as_view(), name='clustergroup_import'),
     path('cluster-groups/delete/', views.ClusterGroupBulkDeleteView.as_view(), name='clustergroup_bulk_delete'),
     path('cluster-groups/delete/', views.ClusterGroupBulkDeleteView.as_view(), name='clustergroup_bulk_delete'),
     path('cluster-groups/<slug:slug>/edit/', views.ClusterGroupEditView.as_view(), name='clustergroup_edit'),
     path('cluster-groups/<slug:slug>/edit/', views.ClusterGroupEditView.as_view(), name='clustergroup_edit'),
@@ -26,7 +26,7 @@ urlpatterns = [
 
 
     # Clusters
     # Clusters
     path('clusters/', views.ClusterListView.as_view(), name='cluster_list'),
     path('clusters/', views.ClusterListView.as_view(), name='cluster_list'),
-    path('clusters/add/', views.ClusterCreateView.as_view(), name='cluster_add'),
+    path('clusters/add/', views.ClusterEditView.as_view(), name='cluster_add'),
     path('clusters/import/', views.ClusterBulkImportView.as_view(), name='cluster_import'),
     path('clusters/import/', views.ClusterBulkImportView.as_view(), name='cluster_import'),
     path('clusters/edit/', views.ClusterBulkEditView.as_view(), name='cluster_bulk_edit'),
     path('clusters/edit/', views.ClusterBulkEditView.as_view(), name='cluster_bulk_edit'),
     path('clusters/delete/', views.ClusterBulkDeleteView.as_view(), name='cluster_bulk_delete'),
     path('clusters/delete/', views.ClusterBulkDeleteView.as_view(), name='cluster_bulk_delete'),
@@ -39,7 +39,7 @@ urlpatterns = [
 
 
     # Virtual machines
     # Virtual machines
     path('virtual-machines/', views.VirtualMachineListView.as_view(), name='virtualmachine_list'),
     path('virtual-machines/', views.VirtualMachineListView.as_view(), name='virtualmachine_list'),
-    path('virtual-machines/add/', views.VirtualMachineCreateView.as_view(), name='virtualmachine_add'),
+    path('virtual-machines/add/', views.VirtualMachineEditView.as_view(), name='virtualmachine_add'),
     path('virtual-machines/import/', views.VirtualMachineBulkImportView.as_view(), name='virtualmachine_import'),
     path('virtual-machines/import/', views.VirtualMachineBulkImportView.as_view(), name='virtualmachine_import'),
     path('virtual-machines/edit/', views.VirtualMachineBulkEditView.as_view(), name='virtualmachine_bulk_edit'),
     path('virtual-machines/edit/', views.VirtualMachineBulkEditView.as_view(), name='virtualmachine_bulk_edit'),
     path('virtual-machines/delete/', views.VirtualMachineBulkDeleteView.as_view(), name='virtualmachine_bulk_delete'),
     path('virtual-machines/delete/', views.VirtualMachineBulkDeleteView.as_view(), name='virtualmachine_bulk_delete'),
@@ -48,7 +48,7 @@ urlpatterns = [
     path('virtual-machines/<int:pk>/delete/', views.VirtualMachineDeleteView.as_view(), name='virtualmachine_delete'),
     path('virtual-machines/<int:pk>/delete/', views.VirtualMachineDeleteView.as_view(), name='virtualmachine_delete'),
     path('virtual-machines/<int:pk>/config-context/', views.VirtualMachineConfigContextView.as_view(), name='virtualmachine_configcontext'),
     path('virtual-machines/<int:pk>/config-context/', views.VirtualMachineConfigContextView.as_view(), name='virtualmachine_configcontext'),
     path('virtual-machines/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='virtualmachine_changelog', kwargs={'model': VirtualMachine}),
     path('virtual-machines/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='virtualmachine_changelog', kwargs={'model': VirtualMachine}),
-    path('virtual-machines/<int:virtualmachine>/services/assign/', ServiceCreateView.as_view(), name='virtualmachine_service_assign'),
+    path('virtual-machines/<int:virtualmachine>/services/assign/', ServiceEditView.as_view(), name='virtualmachine_service_assign'),
 
 
     # VM interfaces
     # VM interfaces
     path('interfaces/add/', views.InterfaceCreateView.as_view(), name='interface_add'),
     path('interfaces/add/', views.InterfaceCreateView.as_view(), name='interface_add'),

+ 5 - 26
netbox/virtualization/views.py

@@ -27,17 +27,12 @@ class ClusterTypeListView(ObjectListView):
     table = tables.ClusterTypeTable
     table = tables.ClusterTypeTable
 
 
 
 
-class ClusterTypeCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'virtualization.add_clustertype'
+class ClusterTypeEditView(ObjectEditView):
     queryset = ClusterType.objects.all()
     queryset = ClusterType.objects.all()
     model_form = forms.ClusterTypeForm
     model_form = forms.ClusterTypeForm
     default_return_url = 'virtualization:clustertype_list'
     default_return_url = 'virtualization:clustertype_list'
 
 
 
 
-class ClusterTypeEditView(ClusterTypeCreateView):
-    permission_required = 'virtualization.change_clustertype'
-
-
 class ClusterTypeBulkImportView(PermissionRequiredMixin, BulkImportView):
 class ClusterTypeBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'virtualization.add_clustertype'
     permission_required = 'virtualization.add_clustertype'
     queryset = ClusterType.objects.all()
     queryset = ClusterType.objects.all()
@@ -62,17 +57,12 @@ class ClusterGroupListView(ObjectListView):
     table = tables.ClusterGroupTable
     table = tables.ClusterGroupTable
 
 
 
 
-class ClusterGroupCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'virtualization.add_clustergroup'
+class ClusterGroupEditView(ObjectEditView):
     queryset = ClusterGroup.objects.all()
     queryset = ClusterGroup.objects.all()
     model_form = forms.ClusterGroupForm
     model_form = forms.ClusterGroupForm
     default_return_url = 'virtualization:clustergroup_list'
     default_return_url = 'virtualization:clustergroup_list'
 
 
 
 
-class ClusterGroupEditView(ClusterGroupCreateView):
-    permission_required = 'virtualization.change_clustergroup'
-
-
 class ClusterGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
 class ClusterGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
     permission_required = 'virtualization.add_clustergroup'
     permission_required = 'virtualization.add_clustergroup'
     queryset = ClusterGroup.objects.all()
     queryset = ClusterGroup.objects.all()
@@ -118,17 +108,12 @@ class ClusterView(PermissionRequiredMixin, View):
         })
         })
 
 
 
 
-class ClusterCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'virtualization.add_cluster'
+class ClusterEditView(ObjectEditView):
     template_name = 'virtualization/cluster_edit.html'
     template_name = 'virtualization/cluster_edit.html'
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
     model_form = forms.ClusterForm
     model_form = forms.ClusterForm
 
 
 
 
-class ClusterEditView(ClusterCreateView):
-    permission_required = 'virtualization.change_cluster'
-
-
 class ClusterDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class ClusterDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'virtualization.delete_cluster'
     permission_required = 'virtualization.delete_cluster'
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
@@ -278,18 +263,13 @@ class VirtualMachineConfigContextView(PermissionRequiredMixin, ObjectConfigConte
     base_template = 'virtualization/virtualmachine.html'
     base_template = 'virtualization/virtualmachine.html'
 
 
 
 
-class VirtualMachineCreateView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'virtualization.add_virtualmachine'
+class VirtualMachineEditView(ObjectEditView):
     queryset = VirtualMachine.objects.all()
     queryset = VirtualMachine.objects.all()
     model_form = forms.VirtualMachineForm
     model_form = forms.VirtualMachineForm
     template_name = 'virtualization/virtualmachine_edit.html'
     template_name = 'virtualization/virtualmachine_edit.html'
     default_return_url = 'virtualization:virtualmachine_list'
     default_return_url = 'virtualization:virtualmachine_list'
 
 
 
 
-class VirtualMachineEditView(VirtualMachineCreateView):
-    permission_required = 'virtualization.change_virtualmachine'
-
-
 class VirtualMachineDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 class VirtualMachineDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     permission_required = 'virtualization.delete_virtualmachine'
     permission_required = 'virtualization.delete_virtualmachine'
     queryset = VirtualMachine.objects.all()
     queryset = VirtualMachine.objects.all()
@@ -333,8 +313,7 @@ class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
     template_name = 'virtualization/virtualmachine_component_add.html'
     template_name = 'virtualization/virtualmachine_component_add.html'
 
 
 
 
-class InterfaceEditView(PermissionRequiredMixin, ObjectEditView):
-    permission_required = 'dcim.change_interface'
+class InterfaceEditView(ObjectEditView):
     queryset = Interface.objects.all()
     queryset = Interface.objects.all()
     model_form = forms.InterfaceForm
     model_form = forms.InterfaceForm
     template_name = 'virtualization/interface_edit.html'
     template_name = 'virtualization/interface_edit.html'