Skip to content

Commit 4fead1c

Browse files
authored
Fixes: #17310 - Properly restrict GraphQL related object queries (#17312)
* Fixes: #17310 - Fix GraphQL restriction of related objects * Fix some failing tests * Fix test
1 parent 91ad3f2 commit 4fead1c

File tree

10 files changed

+53
-2
lines changed

10 files changed

+53
-2
lines changed

netbox/circuits/tests/test_api.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class CircuitTest(APIViewTestCases.APIViewTestCase):
9696
bulk_update_data = {
9797
'status': 'planned',
9898
}
99+
user_permissions = ('circuits.view_provider', 'circuits.view_circuittype')
99100

100101
@classmethod
101102
def setUpTestData(cls):
@@ -150,6 +151,7 @@ def setUpTestData(cls):
150151
class CircuitTerminationTest(APIViewTestCases.APIViewTestCase):
151152
model = CircuitTermination
152153
brief_fields = ['_occupied', 'cable', 'circuit', 'description', 'display', 'id', 'term_side', 'url']
154+
user_permissions = ('circuits.view_circuit', )
153155

154156
@classmethod
155157
def setUpTestData(cls):
@@ -209,6 +211,7 @@ def setUpTestData(cls):
209211
class ProviderAccountTest(APIViewTestCases.APIViewTestCase):
210212
model = ProviderAccount
211213
brief_fields = ['account', 'description', 'display', 'id', 'name', 'url']
214+
user_permissions = ('circuits.view_provider', )
212215

213216
@classmethod
214217
def setUpTestData(cls):
@@ -252,6 +255,7 @@ def setUpTestData(cls):
252255
class ProviderNetworkTest(APIViewTestCases.APIViewTestCase):
253256
model = ProviderNetwork
254257
brief_fields = ['description', 'display', 'id', 'name', 'url']
258+
user_permissions = ('circuits.view_provider', )
255259

256260
@classmethod
257261
def setUpTestData(cls):

netbox/core/tests/test_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class DataFileTest(
5757
):
5858
model = DataFile
5959
brief_fields = ['display', 'id', 'path', 'url']
60+
user_permissions = ('core.view_datasource', )
6061

6162
@classmethod
6263
def setUpTestData(cls):

netbox/dcim/tests/test_api.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ class LocationTest(APIViewTestCases.APIViewTestCase):
195195
bulk_update_data = {
196196
'description': 'New description',
197197
}
198+
user_permissions = ('dcim.view_site', )
198199

199200
@classmethod
200201
def setUpTestData(cls):
@@ -280,6 +281,7 @@ class RackTest(APIViewTestCases.APIViewTestCase):
280281
bulk_update_data = {
281282
'status': 'planned',
282283
}
284+
user_permissions = ('dcim.view_site', )
283285

284286
@classmethod
285287
def setUpTestData(cls):
@@ -368,6 +370,7 @@ class RackReservationTest(APIViewTestCases.APIViewTestCase):
368370
bulk_update_data = {
369371
'description': 'New description',
370372
}
373+
user_permissions = ('dcim.view_rack', 'users.view_user')
371374

372375
@classmethod
373376
def setUpTestData(cls):
@@ -447,6 +450,7 @@ class DeviceTypeTest(APIViewTestCases.APIViewTestCase):
447450
bulk_update_data = {
448451
'part_number': 'ABC123',
449452
}
453+
user_permissions = ('dcim.view_manufacturer', )
450454

451455
@classmethod
452456
def setUpTestData(cls):
@@ -492,6 +496,7 @@ class ModuleTypeTest(APIViewTestCases.APIViewTestCase):
492496
bulk_update_data = {
493497
'part_number': 'ABC123',
494498
}
499+
user_permissions = ('dcim.view_manufacturer', )
495500

496501
@classmethod
497502
def setUpTestData(cls):
@@ -663,6 +668,7 @@ class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase):
663668
bulk_update_data = {
664669
'description': 'New description',
665670
}
671+
user_permissions = ('dcim.view_devicetype', )
666672

667673
@classmethod
668674
def setUpTestData(cls):
@@ -768,6 +774,7 @@ class FrontPortTemplateTest(APIViewTestCases.APIViewTestCase):
768774
bulk_update_data = {
769775
'description': 'New description',
770776
}
777+
user_permissions = ('dcim.view_rearporttemplate', )
771778

772779
@classmethod
773780
def setUpTestData(cls):
@@ -905,6 +912,7 @@ class ModuleBayTemplateTest(APIViewTestCases.APIViewTestCase):
905912
bulk_update_data = {
906913
'description': 'New description',
907914
}
915+
user_permissions = ('dcim.view_devicetype', )
908916

909917
@classmethod
910918
def setUpTestData(cls):
@@ -945,6 +953,7 @@ class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase):
945953
bulk_update_data = {
946954
'description': 'New description',
947955
}
956+
user_permissions = ('dcim.view_devicetype', )
948957

949958
@classmethod
950959
def setUpTestData(cls):
@@ -985,6 +994,7 @@ class InventoryItemTemplateTest(APIViewTestCases.APIViewTestCase):
985994
bulk_update_data = {
986995
'description': 'New description',
987996
}
997+
user_permissions = ('dcim.view_devicetype', 'dcim.view_manufacturer',)
988998

989999
@classmethod
9901000
def setUpTestData(cls):
@@ -1103,6 +1113,10 @@ class DeviceTest(APIViewTestCases.APIViewTestCase):
11031113
bulk_update_data = {
11041114
'status': 'failed',
11051115
}
1116+
user_permissions = (
1117+
'dcim.view_site', 'dcim.view_rack', 'dcim.view_location', 'dcim.view_devicerole', 'dcim.view_devicetype',
1118+
'extras.view_configtemplate',
1119+
)
11061120

11071121
@classmethod
11081122
def setUpTestData(cls):
@@ -1293,6 +1307,7 @@ class ModuleTest(APIViewTestCases.APIViewTestCase):
12931307
bulk_update_data = {
12941308
'serial': '1234ABCD',
12951309
}
1310+
user_permissions = ('dcim.view_modulebay', 'dcim.view_moduletype', 'dcim.view_device')
12961311

12971312
@classmethod
12981313
def setUpTestData(cls):
@@ -1358,6 +1373,7 @@ class ConsolePortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCa
13581373
'description': 'New description',
13591374
}
13601375
peer_termination_type = ConsoleServerPort
1376+
user_permissions = ('dcim.view_device', )
13611377

13621378
@classmethod
13631379
def setUpTestData(cls):
@@ -1400,6 +1416,7 @@ class ConsoleServerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIView
14001416
'description': 'New description',
14011417
}
14021418
peer_termination_type = ConsolePort
1419+
user_permissions = ('dcim.view_device', )
14031420

14041421
@classmethod
14051422
def setUpTestData(cls):
@@ -1442,6 +1459,7 @@ class PowerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
14421459
'description': 'New description',
14431460
}
14441461
peer_termination_type = PowerOutlet
1462+
user_permissions = ('dcim.view_device', )
14451463

14461464
@classmethod
14471465
def setUpTestData(cls):
@@ -1481,6 +1499,7 @@ class PowerOutletTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCa
14811499
'description': 'New description',
14821500
}
14831501
peer_termination_type = PowerPort
1502+
user_permissions = ('dcim.view_device', )
14841503

14851504
@classmethod
14861505
def setUpTestData(cls):
@@ -1529,6 +1548,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
15291548
'description': 'New description',
15301549
}
15311550
peer_termination_type = Interface
1551+
user_permissions = ('dcim.view_device', )
15321552

15331553
@classmethod
15341554
def setUpTestData(cls):
@@ -1663,6 +1683,7 @@ class FrontPortTest(APIViewTestCases.APIViewTestCase):
16631683
'description': 'New description',
16641684
}
16651685
peer_termination_type = Interface
1686+
user_permissions = ('dcim.view_device', 'dcim.view_rearport')
16661687

16671688
@classmethod
16681689
def setUpTestData(cls):
@@ -1721,6 +1742,7 @@ class RearPortTest(APIViewTestCases.APIViewTestCase):
17211742
'description': 'New description',
17221743
}
17231744
peer_termination_type = Interface
1745+
user_permissions = ('dcim.view_device', )
17241746

17251747
@classmethod
17261748
def setUpTestData(cls):
@@ -1762,6 +1784,7 @@ class ModuleBayTest(APIViewTestCases.APIViewTestCase):
17621784
bulk_update_data = {
17631785
'description': 'New description',
17641786
}
1787+
user_permissions = ('dcim.view_device', )
17651788

17661789
@classmethod
17671790
def setUpTestData(cls):
@@ -1801,6 +1824,7 @@ class DeviceBayTest(APIViewTestCases.APIViewTestCase):
18011824
bulk_update_data = {
18021825
'description': 'New description',
18031826
}
1827+
user_permissions = ('dcim.view_device', )
18041828

18051829
@classmethod
18061830
def setUpTestData(cls):
@@ -1864,6 +1888,7 @@ class InventoryItemTest(APIViewTestCases.APIViewTestCase):
18641888
bulk_update_data = {
18651889
'description': 'New description',
18661890
}
1891+
user_permissions = ('dcim.view_device', 'dcim.view_manufacturer')
18671892

18681893
@classmethod
18691894
def setUpTestData(cls):
@@ -2160,6 +2185,7 @@ def setUpTestData(cls):
21602185
class PowerPanelTest(APIViewTestCases.APIViewTestCase):
21612186
model = PowerPanel
21622187
brief_fields = ['description', 'display', 'id', 'name', 'powerfeed_count', 'url']
2188+
user_permissions = ('dcim.view_site', )
21632189

21642190
@classmethod
21652191
def setUpTestData(cls):
@@ -2212,6 +2238,7 @@ class PowerFeedTest(APIViewTestCases.APIViewTestCase):
22122238
bulk_update_data = {
22132239
'status': 'planned',
22142240
}
2241+
user_permissions = ('dcim.view_powerpanel', )
22152242

22162243
@classmethod
22172244
def setUpTestData(cls):

netbox/ipam/tests/test_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ class FHRPGroupAssignmentTest(APIViewTestCases.APIViewTestCase):
767767
bulk_update_data = {
768768
'priority': 100,
769769
}
770+
user_permissions = ('ipam.view_fhrpgroup', )
770771

771772
@classmethod
772773
def setUpTestData(cls):

netbox/netbox/graphql/schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ class Query(
3636
query=Query,
3737
config=StrawberryConfig(auto_camel_case=False),
3838
extensions=[
39-
DjangoOptimizerExtension,
39+
DjangoOptimizerExtension(prefetch_custom_queryset=True),
4040
]
4141
)

netbox/netbox/tests/test_graphql.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from core.models import ObjectType
88
from dcim.models import Site, Location
9+
from ipam.models import ASN, RIR
910
from users.models import ObjectPermission
1011
from utilities.testing import disable_warnings, APITestCase, TestCase
1112

@@ -45,7 +46,6 @@ def test_graphiql_interface(self):
4546
class GraphQLAPITestCase(APITestCase):
4647

4748
@override_settings(LOGIN_REQUIRED=True)
48-
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*', 'auth.user'])
4949
def test_graphql_filter_objects(self):
5050
"""
5151
Test the operation of filters for GraphQL API requests.
@@ -66,6 +66,7 @@ def test_graphql_filter_objects(self):
6666
obj_perm.save()
6767
obj_perm.users.add(self.user)
6868
obj_perm.object_types.add(ObjectType.objects.get_for_model(Location))
69+
obj_perm.object_types.add(ObjectType.objects.get_for_model(Site))
6970

7071
# A valid request should return the filtered list
7172
url = reverse('graphql')
@@ -75,10 +76,20 @@ def test_graphql_filter_objects(self):
7576
data = json.loads(response.content)
7677
self.assertNotIn('errors', data)
7778
self.assertEqual(len(data['data']['location_list']), 1)
79+
self.assertIsNotNone(data['data']['location_list'][0]['site'])
7880

7981
# An invalid request should return an empty list
8082
query = '{location_list(filters: {site_id: "99999"}) {id site {id}}}' # Invalid site ID
8183
response = self.client.post(url, data={'query': query}, format="json", **self.header)
8284
self.assertHttpStatus(response, status.HTTP_200_OK)
8385
data = json.loads(response.content)
8486
self.assertEqual(len(data['data']['location_list']), 0)
87+
88+
# Removing the permissions from location should result in an empty locations list
89+
obj_perm.object_types.remove(ObjectType.objects.get_for_model(Location))
90+
query = '{site(id: ' + str(sites[0].pk) + ') {id locations {id}}}'
91+
response = self.client.post(url, data={'query': query}, format="json", **self.header)
92+
self.assertHttpStatus(response, status.HTTP_200_OK)
93+
data = json.loads(response.content)
94+
self.assertNotIn('errors', data)
95+
self.assertEqual(len(data['data']['site']['locations']), 0)

netbox/tenancy/tests/test_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ class ContactAssignmentTest(APIViewTestCases.APIViewTestCase):
210210
bulk_update_data = {
211211
'priority': ContactPriorityChoices.PRIORITY_INACTIVE,
212212
}
213+
user_permissions = ('tenancy.view_contact', )
213214

214215
@classmethod
215216
def setUpTestData(cls):

netbox/virtualization/tests/test_api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
253253
'description': 'New description',
254254
}
255255
graphql_base_name = 'vm_interface'
256+
user_permissions = ('virtualization.view_virtualmachine', )
256257

257258
@classmethod
258259
def setUpTestData(cls):
@@ -342,6 +343,7 @@ class VirtualDiskTest(APIViewTestCases.APIViewTestCase):
342343
'size': 888,
343344
}
344345
graphql_base_name = 'virtual_disk'
346+
user_permissions = ('virtualization.view_virtualmachine', )
345347

346348
@classmethod
347349
def setUpTestData(cls):

netbox/vpn/tests/test_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class TunnelTerminationTest(APIViewTestCases.APIViewTestCase):
116116
bulk_update_data = {
117117
'role': TunnelTerminationRoleChoices.ROLE_PEER,
118118
}
119+
user_permissions = ('vpn.view_tunnel', )
119120

120121
@classmethod
121122
def setUpTestData(cls):
@@ -430,6 +431,7 @@ def setUpTestData(cls):
430431
class IPSecProfileTest(APIViewTestCases.APIViewTestCase):
431432
model = IPSecProfile
432433
brief_fields = ['description', 'display', 'id', 'name', 'url']
434+
user_permissions = ('vpn.view_ikepolicy', 'vpn.view_ipsecpolicy')
433435

434436
@classmethod
435437
def setUpTestData(cls):
@@ -558,6 +560,7 @@ def setUpTestData(cls):
558560
class L2VPNTerminationTest(APIViewTestCases.APIViewTestCase):
559561
model = L2VPNTermination
560562
brief_fields = ['display', 'id', 'l2vpn', 'url']
563+
user_permissions = ('dcim.view_location', 'vpn.view_l2vpn')
561564

562565
@classmethod
563566
def setUpTestData(cls):

netbox/wireless/tests/test_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class WirelessLinkTest(APIViewTestCases.APIViewTestCase):
114114
bulk_update_data = {
115115
'status': 'planned',
116116
}
117+
user_permissions = ('dcim.view_interface', )
117118

118119
@classmethod
119120
def setUpTestData(cls):

0 commit comments

Comments
 (0)