Enforce view permissions for UI views

This commit is contained in:
Jeremy Stretch 2019-04-11 17:27:38 -04:00
parent ea6815b9bb
commit e710ccb0e6
16 changed files with 257 additions and 168 deletions

View File

@ -4,13 +4,15 @@ from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
from circuits.models import Circuit, CircuitType, Provider from circuits.models import Circuit, CircuitType, Provider
from utilities.testing import create_test_user
class ProviderTestCase(TestCase): class ProviderTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['circuits.view_provider'])
self.client = Client() self.client = Client()
self.client.force_login(user)
Provider.objects.bulk_create([ Provider.objects.bulk_create([
Provider(name='Provider 1', slug='provider-1', asn=65001), Provider(name='Provider 1', slug='provider-1', asn=65001),
@ -38,8 +40,9 @@ class ProviderTestCase(TestCase):
class CircuitTypeTestCase(TestCase): class CircuitTypeTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['circuits.view_circuittype'])
self.client = Client() self.client = Client()
self.client.force_login(user)
CircuitType.objects.bulk_create([ CircuitType.objects.bulk_create([
CircuitType(name='Circuit Type 1', slug='circuit-type-1'), CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
@ -58,8 +61,9 @@ class CircuitTypeTestCase(TestCase):
class CircuitTestCase(TestCase): class CircuitTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['circuits.view_circuit'])
self.client = Client() self.client = Client()
self.client.force_login(user)
provider = Provider(name='Provider 1', slug='provider-1', asn=65001) provider = Provider(name='Provider 1', slug='provider-1', asn=65001)
provider.save() provider.save()
@ -84,8 +88,8 @@ class CircuitTestCase(TestCase):
response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params))) response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_provider(self): def test_circuit(self):
provider = Provider.objects.first() circuit = Circuit.objects.first()
response = self.client.get(provider.get_absolute_url()) response = self.client.get(circuit.get_absolute_url())
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View File

@ -20,7 +20,8 @@ from .models import Circuit, CircuitTermination, CircuitType, Provider
# Providers # Providers
# #
class ProviderListView(ObjectListView): class ProviderListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'circuits.view_provider'
queryset = Provider.objects.annotate(count_circuits=Count('circuits')) queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
filter = filters.ProviderFilter filter = filters.ProviderFilter
filter_form = forms.ProviderFilterForm filter_form = forms.ProviderFilterForm
@ -28,7 +29,8 @@ class ProviderListView(ObjectListView):
template_name = 'circuits/provider_list.html' template_name = 'circuits/provider_list.html'
class ProviderView(View): class ProviderView(PermissionRequiredMixin, View):
permission_required = 'circuits.view_provider'
def get(self, request, slug): def get(self, request, slug):
@ -93,7 +95,8 @@ class ProviderBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Circuit Types # Circuit Types
# #
class CircuitTypeListView(ObjectListView): class CircuitTypeListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'circuits.view_circuittype'
queryset = CircuitType.objects.annotate(circuit_count=Count('circuits')) queryset = CircuitType.objects.annotate(circuit_count=Count('circuits'))
table = tables.CircuitTypeTable table = tables.CircuitTypeTable
template_name = 'circuits/circuittype_list.html' template_name = 'circuits/circuittype_list.html'
@ -128,7 +131,8 @@ class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Circuits # Circuits
# #
class CircuitListView(ObjectListView): class CircuitListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'circuits.view_circuit'
queryset = Circuit.objects.select_related( queryset = Circuit.objects.select_related(
'provider', 'type', 'tenant' 'provider', 'type', 'tenant'
).prefetch_related( ).prefetch_related(
@ -140,7 +144,8 @@ class CircuitListView(ObjectListView):
template_name = 'circuits/circuit_list.html' template_name = 'circuits/circuit_list.html'
class CircuitView(View): class CircuitView(PermissionRequiredMixin, View):
permission_required = 'circuits.view_circuit'
def get(self, request, pk): def get(self, request, pk):

View File

@ -1,6 +1,5 @@
import urllib.parse import urllib.parse
from django.contrib.auth import get_user_model
from django.test import Client, TestCase from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
@ -9,13 +8,15 @@ from dcim.models import (
Cable, Device, DeviceRole, DeviceType, Interface, InventoryItem, Manufacturer, Platform, Rack, RackGroup, Cable, Device, DeviceRole, DeviceType, Interface, InventoryItem, Manufacturer, Platform, Rack, RackGroup,
RackReservation, RackRole, Site, Region, VirtualChassis, RackReservation, RackRole, Site, Region, VirtualChassis,
) )
from utilities.testing import create_test_user
class RegionTestCase(TestCase): class RegionTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_region'])
self.client = Client() self.client = Client()
self.client.force_login(user)
# Create three Regions # Create three Regions
for i in range(1, 4): for i in range(1, 4):
@ -32,8 +33,9 @@ class RegionTestCase(TestCase):
class SiteTestCase(TestCase): class SiteTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_site'])
self.client = Client() self.client = Client()
self.client.force_login(user)
region = Region(name='Region 1', slug='region-1') region = Region(name='Region 1', slug='region-1')
region.save() region.save()
@ -64,8 +66,9 @@ class SiteTestCase(TestCase):
class RackGroupTestCase(TestCase): class RackGroupTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_rackgroup'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -84,11 +87,12 @@ class RackGroupTestCase(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
class RackTypeTestCase(TestCase): class RackRoleTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_rackrole'])
self.client = Client() self.client = Client()
self.client.force_login(user)
RackRole.objects.bulk_create([ RackRole.objects.bulk_create([
RackRole(name='Rack Role 1', slug='rack-role-1'), RackRole(name='Rack Role 1', slug='rack-role-1'),
@ -107,12 +111,9 @@ class RackTypeTestCase(TestCase):
class RackReservationTestCase(TestCase): class RackReservationTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_rackreservation'])
self.client = Client() self.client = Client()
self.client.force_login(user)
User = get_user_model()
user = User(username='testuser', email='testuser@example.com')
user.save()
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -137,8 +138,9 @@ class RackReservationTestCase(TestCase):
class RackTestCase(TestCase): class RackTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_rack'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -169,8 +171,9 @@ class RackTestCase(TestCase):
class ManufacturerTypeTestCase(TestCase): class ManufacturerTypeTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_manufacturer'])
self.client = Client() self.client = Client()
self.client.force_login(user)
Manufacturer.objects.bulk_create([ Manufacturer.objects.bulk_create([
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
@ -189,8 +192,9 @@ class ManufacturerTypeTestCase(TestCase):
class DeviceTypeTestCase(TestCase): class DeviceTypeTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_devicetype'])
self.client = Client() self.client = Client()
self.client.force_login(user)
manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1') manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
manufacturer.save() manufacturer.save()
@ -221,8 +225,9 @@ class DeviceTypeTestCase(TestCase):
class DeviceRoleTestCase(TestCase): class DeviceRoleTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_devicerole'])
self.client = Client() self.client = Client()
self.client.force_login(user)
DeviceRole.objects.bulk_create([ DeviceRole.objects.bulk_create([
DeviceRole(name='Device Role 1', slug='device-role-1'), DeviceRole(name='Device Role 1', slug='device-role-1'),
@ -241,8 +246,9 @@ class DeviceRoleTestCase(TestCase):
class PlatformTestCase(TestCase): class PlatformTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_platform'])
self.client = Client() self.client = Client()
self.client.force_login(user)
Platform.objects.bulk_create([ Platform.objects.bulk_create([
Platform(name='Platform 1', slug='platform-1'), Platform(name='Platform 1', slug='platform-1'),
@ -261,8 +267,9 @@ class PlatformTestCase(TestCase):
class DeviceTestCase(TestCase): class DeviceTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_device'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -303,8 +310,9 @@ class DeviceTestCase(TestCase):
class InventoryItemTestCase(TestCase): class InventoryItemTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_inventoryitem'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -337,18 +345,13 @@ class InventoryItemTestCase(TestCase):
response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params))) response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_inventoryitem(self):
inventoryitem = InventoryItem.objects.first()
response = self.client.get(inventoryitem.get_absolute_url())
self.assertEqual(response.status_code, 200)
class CableTestCase(TestCase): class CableTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_cable'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -401,11 +404,12 @@ class CableTestCase(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
class VirtualMachineTestCase(TestCase): class VirtualChassisTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['dcim.view_virtualchassis'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site.objects.create(name='Site 1', slug='site-1') site = Site.objects.create(name='Site 1', slug='site-1')
manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1') manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1')
@ -450,9 +454,3 @@ class VirtualMachineTestCase(TestCase):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_virtualchassis(self):
virtualchassis = VirtualChassis.objects.first()
response = self.client.get(virtualchassis.get_absolute_url())
self.assertEqual(response.status_code, 200)

View File

@ -138,7 +138,8 @@ class BulkDisconnectView(GetReturnURLMixin, View):
# Regions # Regions
# #
class RegionListView(ObjectListView): class RegionListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_region'
queryset = Region.objects.add_related_count( queryset = Region.objects.add_related_count(
Region.objects.all(), Region.objects.all(),
Site, Site,
@ -182,7 +183,8 @@ class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Sites # Sites
# #
class SiteListView(ObjectListView): class SiteListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_site'
queryset = Site.objects.select_related('region', 'tenant') queryset = Site.objects.select_related('region', 'tenant')
filter = filters.SiteFilter filter = filters.SiteFilter
filter_form = forms.SiteFilterForm filter_form = forms.SiteFilterForm
@ -190,7 +192,8 @@ class SiteListView(ObjectListView):
template_name = 'dcim/site_list.html' template_name = 'dcim/site_list.html'
class SiteView(View): class SiteView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_site'
def get(self, request, slug): def get(self, request, slug):
@ -254,7 +257,8 @@ class SiteBulkEditView(PermissionRequiredMixin, BulkEditView):
# Rack groups # Rack groups
# #
class RackGroupListView(ObjectListView): class RackGroupListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_rackgroup'
queryset = RackGroup.objects.select_related('site').annotate(rack_count=Count('racks')) queryset = RackGroup.objects.select_related('site').annotate(rack_count=Count('racks'))
filter = filters.RackGroupFilter filter = filters.RackGroupFilter
filter_form = forms.RackGroupFilterForm filter_form = forms.RackGroupFilterForm
@ -292,7 +296,8 @@ class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Rack roles # Rack roles
# #
class RackRoleListView(ObjectListView): class RackRoleListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_rackrole'
queryset = RackRole.objects.annotate(rack_count=Count('racks')) queryset = RackRole.objects.annotate(rack_count=Count('racks'))
table = tables.RackRoleTable table = tables.RackRoleTable
template_name = 'dcim/rackrole_list.html' template_name = 'dcim/rackrole_list.html'
@ -327,7 +332,8 @@ class RackRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Racks # Racks
# #
class RackListView(ObjectListView): class RackListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_rack'
queryset = Rack.objects.select_related( queryset = Rack.objects.select_related(
'site', 'group', 'tenant', 'role' 'site', 'group', 'tenant', 'role'
).prefetch_related( ).prefetch_related(
@ -341,10 +347,11 @@ class RackListView(ObjectListView):
template_name = 'dcim/rack_list.html' template_name = 'dcim/rack_list.html'
class RackElevationListView(View): class RackElevationListView(PermissionRequiredMixin, View):
""" """
Display a set of rack elevations side-by-side. Display a set of rack elevations side-by-side.
""" """
permission_required = 'dcim.view_rack'
def get(self, request): def get(self, request):
@ -382,7 +389,8 @@ class RackElevationListView(View):
}) })
class RackView(View): class RackView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_rack'
def get(self, request, pk): def get(self, request, pk):
@ -454,7 +462,8 @@ class RackBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Rack reservations # Rack reservations
# #
class RackReservationListView(ObjectListView): class RackReservationListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_rackreservation'
queryset = RackReservation.objects.all() queryset = RackReservation.objects.all()
filter = filters.RackReservationFilter filter = filters.RackReservationFilter
filter_form = forms.RackReservationFilterForm filter_form = forms.RackReservationFilterForm
@ -510,7 +519,8 @@ class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Manufacturers # Manufacturers
# #
class ManufacturerListView(ObjectListView): class ManufacturerListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_manufacturer'
queryset = Manufacturer.objects.annotate( queryset = Manufacturer.objects.annotate(
devicetype_count=Count('device_types', distinct=True), devicetype_count=Count('device_types', distinct=True),
platform_count=Count('platforms', distinct=True), platform_count=Count('platforms', distinct=True),
@ -548,7 +558,8 @@ class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Device types # Device types
# #
class DeviceTypeListView(ObjectListView): class DeviceTypeListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_devicetype'
queryset = DeviceType.objects.select_related('manufacturer').annotate(instance_count=Count('instances')) queryset = DeviceType.objects.select_related('manufacturer').annotate(instance_count=Count('instances'))
filter = filters.DeviceTypeFilter filter = filters.DeviceTypeFilter
filter_form = forms.DeviceTypeFilterForm filter_form = forms.DeviceTypeFilterForm
@ -556,7 +567,8 @@ class DeviceTypeListView(ObjectListView):
template_name = 'dcim/devicetype_list.html' template_name = 'dcim/devicetype_list.html'
class DeviceTypeView(View): class DeviceTypeView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_devicetype'
def get(self, request, pk): def get(self, request, pk):
@ -812,7 +824,8 @@ class DeviceBayTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Device roles # Device roles
# #
class DeviceRoleListView(ObjectListView): class DeviceRoleListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_devicerole'
queryset = DeviceRole.objects.all() queryset = DeviceRole.objects.all()
table = tables.DeviceRoleTable table = tables.DeviceRoleTable
template_name = 'dcim/devicerole_list.html' template_name = 'dcim/devicerole_list.html'
@ -847,7 +860,8 @@ class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Platforms # Platforms
# #
class PlatformListView(ObjectListView): class PlatformListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_platform'
queryset = Platform.objects.all() queryset = Platform.objects.all()
table = tables.PlatformTable table = tables.PlatformTable
template_name = 'dcim/platform_list.html' template_name = 'dcim/platform_list.html'
@ -882,7 +896,8 @@ class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Devices # Devices
# #
class DeviceListView(ObjectListView): class DeviceListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_device'
queryset = Device.objects.select_related( queryset = Device.objects.select_related(
'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6' 'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6'
) )
@ -892,7 +907,8 @@ class DeviceListView(ObjectListView):
template_name = 'dcim/device_list.html' template_name = 'dcim/device_list.html'
class DeviceView(View): class DeviceView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_device'
def get(self, request, pk): def get(self, request, pk):
@ -972,7 +988,8 @@ class DeviceView(View):
}) })
class DeviceInventoryView(View): class DeviceInventoryView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_device'
def get(self, request, pk): def get(self, request, pk):
@ -993,7 +1010,7 @@ class DeviceInventoryView(View):
class DeviceStatusView(PermissionRequiredMixin, View): class DeviceStatusView(PermissionRequiredMixin, View):
permission_required = 'dcim.napalm_read' permission_required = ('dcim.view_device', 'dcim.napalm_read')
def get(self, request, pk): def get(self, request, pk):
@ -1006,7 +1023,7 @@ class DeviceStatusView(PermissionRequiredMixin, View):
class DeviceLLDPNeighborsView(PermissionRequiredMixin, View): class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
permission_required = 'dcim.napalm_read' permission_required = ('dcim.view_device', 'dcim.napalm_read')
def get(self, request, pk): def get(self, request, pk):
@ -1023,7 +1040,7 @@ class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
class DeviceConfigView(PermissionRequiredMixin, View): class DeviceConfigView(PermissionRequiredMixin, View):
permission_required = 'dcim.napalm_read' permission_required = ('dcim.view_device', 'dcim.napalm_read')
def get(self, request, pk): def get(self, request, pk):
@ -1035,7 +1052,8 @@ class DeviceConfigView(PermissionRequiredMixin, View):
}) })
class DeviceConfigContextView(ObjectConfigContextView): class DeviceConfigContextView(PermissionRequiredMixin, ObjectConfigContextView):
permission_required = 'dcim.view_device'
object_class = Device object_class = Device
base_template = 'dcim/device.html' base_template = 'dcim/device.html'
@ -1258,7 +1276,8 @@ class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Interfaces # Interfaces
# #
class InterfaceView(View): class InterfaceView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_interface'
def get(self, request, pk): def get(self, request, pk):
@ -1639,7 +1658,8 @@ class DeviceBulkAddDeviceBayView(PermissionRequiredMixin, BulkComponentCreateVie
# Cables # Cables
# #
class CableListView(ObjectListView): class CableListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_cable'
queryset = Cable.objects.prefetch_related( queryset = Cable.objects.prefetch_related(
'termination_a', 'termination_b' 'termination_a', 'termination_b'
) )
@ -1649,7 +1669,8 @@ class CableListView(ObjectListView):
template_name = 'dcim/cable_list.html' template_name = 'dcim/cable_list.html'
class CableView(View): class CableView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_cable'
def get(self, request, pk): def get(self, request, pk):
@ -1660,10 +1681,11 @@ class CableView(View):
}) })
class CableTraceView(View): class CableTraceView(PermissionRequiredMixin, View):
""" """
Trace a cable path beginning from the given termination. Trace a cable path beginning from the given termination.
""" """
permission_required = 'dcim.view_cable'
def get(self, request, model, pk): def get(self, request, model, pk):
@ -1792,7 +1814,8 @@ class CableBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Connections # Connections
# #
class ConsoleConnectionsListView(ObjectListView): class ConsoleConnectionsListView(PermissionRequiredMixin, ObjectListView):
permission_required = ('dcim.view_consoleport', 'dcim.view_consoleserverport')
queryset = ConsolePort.objects.select_related( queryset = ConsolePort.objects.select_related(
'device', 'connected_endpoint__device' 'device', 'connected_endpoint__device'
).filter( ).filter(
@ -1822,7 +1845,8 @@ class ConsoleConnectionsListView(ObjectListView):
return csv_data return csv_data
class PowerConnectionsListView(ObjectListView): class PowerConnectionsListView(PermissionRequiredMixin, ObjectListView):
permission_required = ('dcim.view_powerport', 'dcim.view_poweroutlet')
queryset = PowerPort.objects.select_related( queryset = PowerPort.objects.select_related(
'device', '_connected_poweroutlet__device' 'device', '_connected_poweroutlet__device'
).filter( ).filter(
@ -1852,7 +1876,8 @@ class PowerConnectionsListView(ObjectListView):
return csv_data return csv_data
class InterfaceConnectionsListView(ObjectListView): class InterfaceConnectionsListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.interface'
queryset = Interface.objects.select_related( queryset = Interface.objects.select_related(
'device', 'cable', '_connected_interface__device' 'device', 'cable', '_connected_interface__device'
).filter( ).filter(
@ -1894,7 +1919,8 @@ class InterfaceConnectionsListView(ObjectListView):
# Inventory items # Inventory items
# #
class InventoryItemListView(ObjectListView): class InventoryItemListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_inventoryitem'
queryset = InventoryItem.objects.select_related('device', 'manufacturer') queryset = InventoryItem.objects.select_related('device', 'manufacturer')
filter = filters.InventoryItemFilter filter = filters.InventoryItemFilter
filter_form = forms.InventoryItemFilterForm filter_form = forms.InventoryItemFilterForm
@ -1949,7 +1975,8 @@ class InventoryItemBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Virtual chassis # Virtual chassis
# #
class VirtualChassisListView(ObjectListView): class VirtualChassisListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_virtualchassis'
queryset = VirtualChassis.objects.select_related('master').annotate(member_count=Count('members')) queryset = VirtualChassis.objects.select_related('master').annotate(member_count=Count('members'))
table = tables.VirtualChassisTable table = tables.VirtualChassisTable
filter = filters.VirtualChassisFilter filter = filters.VirtualChassisFilter
@ -2184,7 +2211,8 @@ class VirtualChassisRemoveMemberView(PermissionRequiredMixin, GetReturnURLMixin,
# Power panels # Power panels
# #
class PowerPanelListView(ObjectListView): class PowerPanelListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_powerpanel'
queryset = PowerPanel.objects.select_related( queryset = PowerPanel.objects.select_related(
'site', 'rack_group' 'site', 'rack_group'
).annotate( ).annotate(
@ -2196,7 +2224,8 @@ class PowerPanelListView(ObjectListView):
template_name = 'dcim/powerpanel_list.html' template_name = 'dcim/powerpanel_list.html'
class PowerPanelView(View): class PowerPanelView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_powerpanel'
def get(self, request, pk): def get(self, request, pk):
@ -2253,7 +2282,8 @@ class PowerPanelBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Power feeds # Power feeds
# #
class PowerFeedListView(ObjectListView): class PowerFeedListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'dcim.view_powerfeed'
queryset = PowerFeed.objects.select_related( queryset = PowerFeed.objects.select_related(
'power_panel', 'rack' 'power_panel', 'rack'
) )
@ -2263,7 +2293,8 @@ class PowerFeedListView(ObjectListView):
template_name = 'dcim/powerfeed_list.html' template_name = 'dcim/powerfeed_list.html'
class PowerFeedView(View): class PowerFeedView(PermissionRequiredMixin, View):
permission_required = 'dcim.view_powerfeed'
def get(self, request, pk): def get(self, request, pk):

View File

@ -7,6 +7,7 @@ from django.urls import reverse
from dcim.models import Site from dcim.models import Site
from extras.models import ConfigContext, ObjectChange, Tag from extras.models import ConfigContext, ObjectChange, Tag
from utilities.testing import create_test_user
class TagTestCase(TestCase): class TagTestCase(TestCase):
@ -35,8 +36,9 @@ class TagTestCase(TestCase):
class ConfigContextTestCase(TestCase): class ConfigContextTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['extras.view_configcontext'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -70,11 +72,9 @@ class ConfigContextTestCase(TestCase):
class ObjectChangeTestCase(TestCase): class ObjectChangeTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['extras.view_objectchange'])
self.client = Client() self.client = Client()
self.client.force_login(user)
user = User(username='testuser', email='testuser@example.com')
user.save()
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()

View File

@ -96,7 +96,8 @@ class TagBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Config contexts # Config contexts
# #
class ConfigContextListView(ObjectListView): class ConfigContextListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'extras.view_configcontext'
queryset = ConfigContext.objects.all() queryset = ConfigContext.objects.all()
filter = filters.ConfigContextFilter filter = filters.ConfigContextFilter
filter_form = ConfigContextFilterForm filter_form = ConfigContextFilterForm
@ -104,7 +105,8 @@ class ConfigContextListView(ObjectListView):
template_name = 'extras/configcontext_list.html' template_name = 'extras/configcontext_list.html'
class ConfigContextView(View): class ConfigContextView(PermissionRequiredMixin, View):
permission_required = 'extras.view_configcontext'
def get(self, request, pk): def get(self, request, pk):
@ -173,7 +175,8 @@ class ObjectConfigContextView(View):
# Change logging # Change logging
# #
class ObjectChangeListView(ObjectListView): class ObjectChangeListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'extras.view_objectchange'
queryset = ObjectChange.objects.select_related('user', 'changed_object_type') queryset = ObjectChange.objects.select_related('user', 'changed_object_type')
filter = filters.ObjectChangeFilter filter = filters.ObjectChangeFilter
filter_form = ObjectChangeFilterForm filter_form = ObjectChangeFilterForm
@ -181,7 +184,8 @@ class ObjectChangeListView(ObjectListView):
template_name = 'extras/objectchange_list.html' template_name = 'extras/objectchange_list.html'
class ObjectChangeView(View): class ObjectChangeView(PermissionRequiredMixin, View):
permission_required = 'extras.view_objectchange'
def get(self, request, pk): def get(self, request, pk):
@ -272,10 +276,11 @@ class ImageAttachmentDeleteView(PermissionRequiredMixin, ObjectDeleteView):
# Reports # Reports
# #
class ReportListView(View): class ReportListView(PermissionRequiredMixin, View):
""" """
Retrieve all of the available reports from disk and the recorded ReportResult (if any) for each. Retrieve all of the available reports from disk and the recorded ReportResult (if any) for each.
""" """
permission_required = 'extras.view_reportresult'
def get(self, request): def get(self, request):
@ -295,10 +300,11 @@ class ReportListView(View):
}) })
class ReportView(View): class ReportView(PermissionRequiredMixin, View):
""" """
Display a single Report and its associated ReportResult (if any). Display a single Report and its associated ReportResult (if any).
""" """
permission_required = 'extras.view_reportresult'
def get(self, request, name): def get(self, request, name):

View File

@ -7,13 +7,15 @@ from django.urls import reverse
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
from ipam.constants import IP_PROTOCOL_TCP from ipam.constants import IP_PROTOCOL_TCP
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from utilities.testing import create_test_user
class VRFTestCase(TestCase): class VRFTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_vrf'])
self.client = Client() self.client = Client()
self.client.force_login(user)
VRF.objects.bulk_create([ VRF.objects.bulk_create([
VRF(name='VRF 1', rd='65000:1'), VRF(name='VRF 1', rd='65000:1'),
@ -41,8 +43,9 @@ class VRFTestCase(TestCase):
class RIRTestCase(TestCase): class RIRTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_rir'])
self.client = Client() self.client = Client()
self.client.force_login(user)
RIR.objects.bulk_create([ RIR.objects.bulk_create([
RIR(name='RIR 1', slug='rir-1'), RIR(name='RIR 1', slug='rir-1'),
@ -57,18 +60,13 @@ class RIRTestCase(TestCase):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_rir(self):
rir = RIR.objects.first()
response = self.client.get(rir.get_absolute_url())
self.assertEqual(response.status_code, 200)
class AggregateTestCase(TestCase): class AggregateTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_aggregate'])
self.client = Client() self.client = Client()
self.client.force_login(user)
rir = RIR(name='RIR 1', slug='rir-1') rir = RIR(name='RIR 1', slug='rir-1')
rir.save() rir.save()
@ -99,8 +97,9 @@ class AggregateTestCase(TestCase):
class RoleTestCase(TestCase): class RoleTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_role'])
self.client = Client() self.client = Client()
self.client.force_login(user)
Role.objects.bulk_create([ Role.objects.bulk_create([
Role(name='Role 1', slug='role-1'), Role(name='Role 1', slug='role-1'),
@ -119,8 +118,9 @@ class RoleTestCase(TestCase):
class PrefixTestCase(TestCase): class PrefixTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_prefix'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -151,8 +151,9 @@ class PrefixTestCase(TestCase):
class IPAddressTestCase(TestCase): class IPAddressTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_ipaddress'])
self.client = Client() self.client = Client()
self.client.force_login(user)
vrf = VRF(name='VRF 1', rd='65000:1') vrf = VRF(name='VRF 1', rd='65000:1')
vrf.save() vrf.save()
@ -183,8 +184,9 @@ class IPAddressTestCase(TestCase):
class VLANGroupTestCase(TestCase): class VLANGroupTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_vlangroup'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -209,8 +211,9 @@ class VLANGroupTestCase(TestCase):
class VLANTestCase(TestCase): class VLANTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_vlan'])
self.client = Client() self.client = Client()
self.client.force_login(user)
vlangroup = VLANGroup(name='VLAN Group 1', slug='vlan-group-1') vlangroup = VLANGroup(name='VLAN Group 1', slug='vlan-group-1')
vlangroup.save() vlangroup.save()
@ -241,8 +244,9 @@ class VLANTestCase(TestCase):
class ServiceTestCase(TestCase): class ServiceTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['ipam.view_service'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()

View File

@ -113,7 +113,8 @@ def add_available_vlans(vlan_group, vlans):
# VRFs # VRFs
# #
class VRFListView(ObjectListView): class VRFListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_vrf'
queryset = VRF.objects.select_related('tenant') queryset = VRF.objects.select_related('tenant')
filter = filters.VRFFilter filter = filters.VRFFilter
filter_form = forms.VRFFilterForm filter_form = forms.VRFFilterForm
@ -121,7 +122,8 @@ class VRFListView(ObjectListView):
template_name = 'ipam/vrf_list.html' template_name = 'ipam/vrf_list.html'
class VRFView(View): class VRFView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_vrf'
def get(self, request, pk): def get(self, request, pk):
@ -180,7 +182,8 @@ class VRFBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# RIRs # RIRs
# #
class RIRListView(ObjectListView): class RIRListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_rir'
queryset = RIR.objects.annotate(aggregate_count=Count('aggregates')) queryset = RIR.objects.annotate(aggregate_count=Count('aggregates'))
filter = filters.RIRFilter filter = filters.RIRFilter
filter_form = forms.RIRFilterForm filter_form = forms.RIRFilterForm
@ -286,7 +289,8 @@ class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Aggregates # Aggregates
# #
class AggregateListView(ObjectListView): class AggregateListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_aggregate'
queryset = Aggregate.objects.select_related('rir').extra(select={ queryset = Aggregate.objects.select_related('rir').extra(select={
'child_count': 'SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', 'child_count': 'SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix',
}) })
@ -312,7 +316,8 @@ class AggregateListView(ObjectListView):
} }
class AggregateView(View): class AggregateView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_aggregate'
def get(self, request, pk): def get(self, request, pk):
@ -398,7 +403,8 @@ class AggregateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Prefix/VLAN roles # Prefix/VLAN roles
# #
class RoleListView(ObjectListView): class RoleListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_role'
queryset = Role.objects.all() queryset = Role.objects.all()
table = tables.RoleTable table = tables.RoleTable
template_name = 'ipam/role_list.html' template_name = 'ipam/role_list.html'
@ -433,7 +439,8 @@ class RoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Prefixes # Prefixes
# #
class PrefixListView(ObjectListView): class PrefixListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_prefix'
queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role') queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
filter = filters.PrefixFilter filter = filters.PrefixFilter
filter_form = forms.PrefixFilterForm filter_form = forms.PrefixFilterForm
@ -446,7 +453,8 @@ class PrefixListView(ObjectListView):
return self.queryset.annotate_depth(limit=limit) return self.queryset.annotate_depth(limit=limit)
class PrefixView(View): class PrefixView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_prefix'
def get(self, request, pk): def get(self, request, pk):
@ -489,7 +497,8 @@ class PrefixView(View):
}) })
class PrefixPrefixesView(View): class PrefixPrefixesView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_prefix'
def get(self, request, pk): def get(self, request, pk):
@ -531,7 +540,8 @@ class PrefixPrefixesView(View):
}) })
class PrefixIPAddressesView(View): class PrefixIPAddressesView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_prefix'
def get(self, request, pk): def get(self, request, pk):
@ -617,7 +627,8 @@ class PrefixBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# IP addresses # IP addresses
# #
class IPAddressListView(ObjectListView): class IPAddressListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_ipaddress'
queryset = IPAddress.objects.select_related( queryset = IPAddress.objects.select_related(
'vrf__tenant', 'tenant', 'nat_inside' 'vrf__tenant', 'tenant', 'nat_inside'
).prefetch_related( ).prefetch_related(
@ -629,7 +640,8 @@ class IPAddressListView(ObjectListView):
template_name = 'ipam/ipaddress_list.html' template_name = 'ipam/ipaddress_list.html'
class IPAddressView(View): class IPAddressView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_ipaddress'
def get(self, request, pk): def get(self, request, pk):
@ -788,7 +800,8 @@ class IPAddressBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# VLAN groups # VLAN groups
# #
class VLANGroupListView(ObjectListView): class VLANGroupListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_vlangroup'
queryset = VLANGroup.objects.select_related('site').annotate(vlan_count=Count('vlans')) queryset = VLANGroup.objects.select_related('site').annotate(vlan_count=Count('vlans'))
filter = filters.VLANGroupFilter filter = filters.VLANGroupFilter
filter_form = forms.VLANGroupFilterForm filter_form = forms.VLANGroupFilterForm
@ -822,7 +835,9 @@ class VLANGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
default_return_url = 'ipam:vlangroup_list' default_return_url = 'ipam:vlangroup_list'
class VLANGroupVLANsView(View): class VLANGroupVLANsView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_vlangroup'
def get(self, request, pk): def get(self, request, pk):
vlan_group = get_object_or_404(VLANGroup.objects.all(), pk=pk) vlan_group = get_object_or_404(VLANGroup.objects.all(), pk=pk)
@ -861,7 +876,8 @@ class VLANGroupVLANsView(View):
# VLANs # VLANs
# #
class VLANListView(ObjectListView): class VLANListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_vlan'
queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role').prefetch_related('prefixes') queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role').prefetch_related('prefixes')
filter = filters.VLANFilter filter = filters.VLANFilter
filter_form = forms.VLANFilterForm filter_form = forms.VLANFilterForm
@ -869,7 +885,8 @@ class VLANListView(ObjectListView):
template_name = 'ipam/vlan_list.html' template_name = 'ipam/vlan_list.html'
class VLANView(View): class VLANView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_vlan'
def get(self, request, pk): def get(self, request, pk):
@ -886,7 +903,8 @@ class VLANView(View):
}) })
class VLANMembersView(View): class VLANMembersView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_vlan'
def get(self, request, pk): def get(self, request, pk):
@ -954,7 +972,8 @@ class VLANBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Services # Services
# #
class ServiceListView(ObjectListView): class ServiceListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'ipam.view_service'
queryset = Service.objects.select_related('device', 'virtual_machine') queryset = Service.objects.select_related('device', 'virtual_machine')
filter = filters.ServiceFilter filter = filters.ServiceFilter
filter_form = forms.ServiceFilterForm filter_form = forms.ServiceFilterForm
@ -962,7 +981,8 @@ class ServiceListView(ObjectListView):
template_name = 'ipam/service_list.html' template_name = 'ipam/service_list.html'
class ServiceView(View): class ServiceView(PermissionRequiredMixin, View):
permission_required = 'ipam.view_service'
def get(self, request, pk): def get(self, request, pk):

View File

@ -1,25 +1,19 @@
import urllib.parse import urllib.parse
from django.contrib.auth import get_user_model
from django.test import Client, TestCase from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
from secrets.models import Secret, SecretRole from secrets.models import Secret, SecretRole
from utilities.testing import create_test_user
class SecretRoleTestCase(TestCase): class SecretRoleTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['secrets.view_secretrole'])
TEST_USERNAME = 'testuser'
TEST_PASSWORD = 'testpassword'
User = get_user_model()
User.objects.create(username=TEST_USERNAME, email='testuser@example.com', password=TEST_PASSWORD)
self.client = Client() self.client = Client()
self.client.login(username=TEST_USERNAME, password=TEST_PASSWORD) self.client.force_login(user)
SecretRole.objects.bulk_create([ SecretRole.objects.bulk_create([
SecretRole(name='Secret Role 1', slug='secret-role-1'), SecretRole(name='Secret Role 1', slug='secret-role-1'),
@ -29,7 +23,7 @@ class SecretRoleTestCase(TestCase):
def test_secretrole_list(self): def test_secretrole_list(self):
url = reverse('secrets:secret_list') url = reverse('secrets:secretrole_list')
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -38,8 +32,9 @@ class SecretRoleTestCase(TestCase):
class SecretTestCase(TestCase): class SecretTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['secrets.view_secret'])
self.client = Client() self.client = Client()
self.client.force_login(user)
site = Site(name='Site 1', slug='site-1') site = Site(name='Site 1', slug='site-1')
site.save() site.save()
@ -75,7 +70,7 @@ class SecretTestCase(TestCase):
response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)), follow=True) response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)), follow=True)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_configcontext(self): def test_secret(self):
secret = Secret.objects.first() secret = Secret.objects.first()
response = self.client.get(secret.get_absolute_url(), follow=True) response = self.client.get(secret.get_absolute_url(), follow=True)

View File

@ -32,7 +32,8 @@ def get_session_key(request):
# Secret roles # Secret roles
# #
class SecretRoleListView(ObjectListView): class SecretRoleListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'secrets.view_secretrole'
queryset = SecretRole.objects.annotate(secret_count=Count('secrets')) queryset = SecretRole.objects.annotate(secret_count=Count('secrets'))
table = tables.SecretRoleTable table = tables.SecretRoleTable
template_name = 'secrets/secretrole_list.html' template_name = 'secrets/secretrole_list.html'
@ -67,8 +68,8 @@ class SecretRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Secrets # Secrets
# #
@method_decorator(login_required, name='dispatch') class SecretListView(PermissionRequiredMixin, ObjectListView):
class SecretListView(ObjectListView): permission_required = 'secrets.view_secret'
queryset = Secret.objects.select_related('role', 'device') queryset = Secret.objects.select_related('role', 'device')
filter = filters.SecretFilter filter = filters.SecretFilter
filter_form = forms.SecretFilterForm filter_form = forms.SecretFilterForm
@ -76,8 +77,8 @@ class SecretListView(ObjectListView):
template_name = 'secrets/secret_list.html' template_name = 'secrets/secret_list.html'
@method_decorator(login_required, name='dispatch') class SecretView(PermissionRequiredMixin, View):
class SecretView(View): permission_required = 'secrets.view_secret'
def get(self, request, pk): def get(self, request, pk):
@ -198,7 +199,7 @@ class SecretDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class SecretBulkImportView(BulkImportView): class SecretBulkImportView(BulkImportView):
permission_required = 'ipam.add_vlan' permission_required = 'secrets.add_secret'
model_form = forms.SecretCSVForm model_form = forms.SecretCSVForm
table = tables.SecretTable table = tables.SecretTable
template_name = 'secrets/secret_import.html' template_name = 'secrets/secret_import.html'

View File

@ -4,13 +4,15 @@ from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from utilities.testing import create_test_user
class TenantGroupTestCase(TestCase): class TenantGroupTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['tenancy.view_tenantgroup'])
self.client = Client() self.client = Client()
self.client.force_login(user)
TenantGroup.objects.bulk_create([ TenantGroup.objects.bulk_create([
TenantGroup(name='Tenant Group 1', slug='tenant-group-1'), TenantGroup(name='Tenant Group 1', slug='tenant-group-1'),
@ -29,8 +31,9 @@ class TenantGroupTestCase(TestCase):
class TenantTestCase(TestCase): class TenantTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['tenancy.view_tenant'])
self.client = Client() self.client = Client()
self.client.force_login(user)
tenantgroup = TenantGroup(name='Tenant Group 1', slug='tenant-group-1') tenantgroup = TenantGroup(name='Tenant Group 1', slug='tenant-group-1')
tenantgroup.save() tenantgroup.save()

View File

@ -18,7 +18,8 @@ from .models import Tenant, TenantGroup
# Tenant groups # Tenant groups
# #
class TenantGroupListView(ObjectListView): class TenantGroupListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'tenancy.view_tenantgroup'
queryset = TenantGroup.objects.annotate(tenant_count=Count('tenants')) queryset = TenantGroup.objects.annotate(tenant_count=Count('tenants'))
table = tables.TenantGroupTable table = tables.TenantGroupTable
template_name = 'tenancy/tenantgroup_list.html' template_name = 'tenancy/tenantgroup_list.html'
@ -53,7 +54,8 @@ class TenantGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Tenants # Tenants
# #
class TenantListView(ObjectListView): class TenantListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'tenancy.view_tenant'
queryset = Tenant.objects.select_related('group') queryset = Tenant.objects.select_related('group')
filter = filters.TenantFilter filter = filters.TenantFilter
filter_form = forms.TenantFilterForm filter_form = forms.TenantFilterForm
@ -61,7 +63,8 @@ class TenantListView(ObjectListView):
template_name = 'tenancy/tenant_list.html' template_name = 'tenancy/tenant_list.html'
class TenantView(View): class TenantView(PermissionRequiredMixin, View):
permission_required = 'tenancy.view_tenant'
def get(self, request, slug): def get(self, request, slug):

View File

@ -1,6 +1,5 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import login as auth_login, logout as auth_logout, update_session_auth_hash from django.contrib.auth import login as auth_login, logout as auth_logout, update_session_auth_hash
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.http import HttpResponseForbidden, HttpResponseRedirect from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
@ -74,8 +73,7 @@ class LogoutView(View):
# User profiles # User profiles
# #
@method_decorator(login_required, name='dispatch') class ProfileView(LoginRequiredMixin, View):
class ProfileView(View):
template_name = 'users/profile.html' template_name = 'users/profile.html'
def get(self, request): def get(self, request):
@ -85,8 +83,7 @@ class ProfileView(View):
}) })
@method_decorator(login_required, name='dispatch') class ChangePasswordView(LoginRequiredMixin, View):
class ChangePasswordView(View):
template_name = 'users/change_password.html' template_name = 'users/change_password.html'
def get(self, request): def get(self, request):
@ -111,8 +108,7 @@ class ChangePasswordView(View):
}) })
@method_decorator(login_required, name='dispatch') class UserKeyView(LoginRequiredMixin, View):
class UserKeyView(View):
template_name = 'users/userkey.html' template_name = 'users/userkey.html'
def get(self, request): def get(self, request):
@ -127,10 +123,9 @@ class UserKeyView(View):
}) })
class UserKeyEditView(View): class UserKeyEditView(LoginRequiredMixin, View):
template_name = 'users/userkey_edit.html' template_name = 'users/userkey_edit.html'
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try: try:
self.userkey = UserKey.objects.get(user=request.user) self.userkey = UserKey.objects.get(user=request.user)
@ -164,7 +159,6 @@ class UserKeyEditView(View):
}) })
@method_decorator(login_required, name='dispatch')
class SessionKeyDeleteView(LoginRequiredMixin, View): class SessionKeyDeleteView(LoginRequiredMixin, View):
def get(self, request): def get(self, request):

View File

@ -1,4 +1,4 @@
from django.contrib.auth.models import User from django.contrib.auth.models import Permission, User
from rest_framework.test import APITestCase as _APITestCase from rest_framework.test import APITestCase as _APITestCase
from users.models import Token from users.models import Token
@ -22,3 +22,16 @@ class APITestCase(_APITestCase):
self.assertEqual(response.status_code, expected_status, err_message.format( self.assertEqual(response.status_code, expected_status, err_message.format(
expected_status, response.status_code, response.data expected_status, response.status_code, response.data
)) ))
def create_test_user(username='testuser', permissions=list()):
"""
Create a User with the given permissions.
"""
user = User.objects.create_user(username=username)
for perm_name in permissions:
app, codename = perm_name.split('.')
perm = Permission.objects.get(content_type__app_label=app, codename=codename)
user.user_permissions.add(perm)
return user

View File

@ -3,14 +3,16 @@ import urllib.parse
from django.test import Client, TestCase from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
from utilities.testing import create_test_user
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
class ClusterGroupTestCase(TestCase): class ClusterGroupTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['virtualization.view_clustergroup'])
self.client = Client() self.client = Client()
self.client.force_login(user)
ClusterGroup.objects.bulk_create([ ClusterGroup.objects.bulk_create([
ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'), ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
@ -29,8 +31,9 @@ class ClusterGroupTestCase(TestCase):
class ClusterTypeTestCase(TestCase): class ClusterTypeTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['virtualization.view_clustertype'])
self.client = Client() self.client = Client()
self.client.force_login(user)
ClusterType.objects.bulk_create([ ClusterType.objects.bulk_create([
ClusterType(name='Cluster Type 1', slug='cluster-type-1'), ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
@ -49,8 +52,9 @@ class ClusterTypeTestCase(TestCase):
class ClusterTestCase(TestCase): class ClusterTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['virtualization.view_cluster'])
self.client = Client() self.client = Client()
self.client.force_login(user)
clustergroup = ClusterGroup(name='Cluster Group 1', slug='cluster-group-1') clustergroup = ClusterGroup(name='Cluster Group 1', slug='cluster-group-1')
clustergroup.save() clustergroup.save()
@ -85,8 +89,9 @@ class ClusterTestCase(TestCase):
class VirtualMachineTestCase(TestCase): class VirtualMachineTestCase(TestCase):
def setUp(self): def setUp(self):
user = create_test_user(permissions=['virtualization.view_virtualmachine'])
self.client = Client() self.client = Client()
self.client.force_login(user)
clustertype = ClusterType(name='Cluster Type 1', slug='cluster-type-1') clustertype = ClusterType(name='Cluster Type 1', slug='cluster-type-1')
clustertype.save() clustertype.save()

View File

@ -22,7 +22,8 @@ from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
# Cluster types # Cluster types
# #
class ClusterTypeListView(ObjectListView): class ClusterTypeListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'virtualization.view_clustertype'
queryset = ClusterType.objects.annotate(cluster_count=Count('clusters')) queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
table = tables.ClusterTypeTable table = tables.ClusterTypeTable
template_name = 'virtualization/clustertype_list.html' template_name = 'virtualization/clustertype_list.html'
@ -57,7 +58,8 @@ class ClusterTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Cluster groups # Cluster groups
# #
class ClusterGroupListView(ObjectListView): class ClusterGroupListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'virtualization.view_clustergroup'
queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters')) queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
table = tables.ClusterGroupTable table = tables.ClusterGroupTable
template_name = 'virtualization/clustergroup_list.html' template_name = 'virtualization/clustergroup_list.html'
@ -92,7 +94,8 @@ class ClusterGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# Clusters # Clusters
# #
class ClusterListView(ObjectListView): class ClusterListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'virtualization.view_cluster'
queryset = Cluster.objects.select_related('type', 'group', 'site') queryset = Cluster.objects.select_related('type', 'group', 'site')
table = tables.ClusterTable table = tables.ClusterTable
filter = filters.ClusterFilter filter = filters.ClusterFilter
@ -100,7 +103,8 @@ class ClusterListView(ObjectListView):
template_name = 'virtualization/cluster_list.html' template_name = 'virtualization/cluster_list.html'
class ClusterView(View): class ClusterView(PermissionRequiredMixin, View):
permission_required = 'virtualization.view_cluster'
def get(self, request, pk): def get(self, request, pk):
@ -247,7 +251,8 @@ class ClusterRemoveDevicesView(PermissionRequiredMixin, View):
# Virtual machines # Virtual machines
# #
class VirtualMachineListView(ObjectListView): class VirtualMachineListView(PermissionRequiredMixin, ObjectListView):
permission_required = 'virtualization.view_virtualmachine'
queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'role', 'primary_ip4', 'primary_ip6') queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'role', 'primary_ip4', 'primary_ip6')
filter = filters.VirtualMachineFilter filter = filters.VirtualMachineFilter
filter_form = forms.VirtualMachineFilterForm filter_form = forms.VirtualMachineFilterForm
@ -255,7 +260,8 @@ class VirtualMachineListView(ObjectListView):
template_name = 'virtualization/virtualmachine_list.html' template_name = 'virtualization/virtualmachine_list.html'
class VirtualMachineView(View): class VirtualMachineView(PermissionRequiredMixin, View):
permission_required = 'virtualization.view_virtualmachine'
def get(self, request, pk): def get(self, request, pk):
@ -270,7 +276,8 @@ class VirtualMachineView(View):
}) })
class VirtualMachineConfigContextView(ObjectConfigContextView): class VirtualMachineConfigContextView(PermissionRequiredMixin, ObjectConfigContextView):
permission_required = 'virtualization.view_virtualmachine'
object_class = VirtualMachine object_class = VirtualMachine
base_template = 'virtualization/virtualmachine.html' base_template = 'virtualization/virtualmachine.html'