|
|
@@ -35,8 +35,8 @@ from dcim.models import (
|
|
|
VirtualChassis,
|
|
|
)
|
|
|
from extras.choices import CustomFieldTypeChoices
|
|
|
-from extras.models import CustomField, TableConfig, Tag
|
|
|
-from ipam.models import RIR, Aggregate, IPAddress, Prefix
|
|
|
+from extras.models import CustomField, ExportTemplate, JournalEntry, TableConfig, Tag
|
|
|
+from ipam.models import RIR, VLAN, Aggregate, IPAddress, Prefix
|
|
|
from netbox.graphql.pagination import apply_distinct_window_pagination
|
|
|
from netbox.graphql.scalars import BigInt, BigIntScalar
|
|
|
from netbox.graphql.schema import Query, get_schema_extensions, schema
|
|
|
@@ -47,6 +47,8 @@ from netbox.tests.dummy_plugin.models import DummySiteAttachment
|
|
|
from users.models import ObjectPermission, User
|
|
|
from utilities.tables import get_table_for_model
|
|
|
from utilities.testing import APITestCase, APIViewTestCases, TestCase, disable_warnings
|
|
|
+from vpn.choices import L2VPNTypeChoices
|
|
|
+from vpn.models import L2VPN, L2VPNTermination
|
|
|
|
|
|
|
|
|
def count_primary_table_queries(queries, table):
|
|
|
@@ -455,6 +457,62 @@ class GraphQLAPITestCase(APITestCase):
|
|
|
self.assertNotIn('errors', data)
|
|
|
self.assertEqual(len(data['data']['device_list']), 3)
|
|
|
|
|
|
+ def test_graphql_64bit_object_ids(self):
|
|
|
+ """
|
|
|
+ Object IDs beyond the 32-bit range must be accepted by GraphQL output fields and filters. Regression test
|
|
|
+ for #23423.
|
|
|
+ """
|
|
|
+ self.add_permissions(
|
|
|
+ 'extras.view_journalentry',
|
|
|
+ 'extras.view_exporttemplate',
|
|
|
+ 'vpn.view_l2vpntermination',
|
|
|
+ )
|
|
|
+ url = reverse('graphql')
|
|
|
+ object_id = 3_000_000_000
|
|
|
+
|
|
|
+ site = Site.objects.create(id=object_id, name='Site 64-bit', slug='site-64-bit')
|
|
|
+ JournalEntry.objects.create(assigned_object=site, comments='Test')
|
|
|
+ vlan = VLAN.objects.create(id=object_id, vid=100, name='VLAN 100')
|
|
|
+ l2vpn = L2VPN.objects.create(name='L2VPN 1', slug='l2vpn-1', type=L2VPNTypeChoices.TYPE_VXLAN)
|
|
|
+ L2VPNTermination.objects.create(l2vpn=l2vpn, assigned_object=vlan)
|
|
|
+ data_source = DataSource.objects.create(id=object_id, name='Data Source 1', type='local', source_url='/tmp')
|
|
|
+ export_template = ExportTemplate.objects.create(
|
|
|
+ name='Export Template 1',
|
|
|
+ template_code='{{ queryset }}',
|
|
|
+ data_source=data_source,
|
|
|
+ )
|
|
|
+ export_template.object_types.set([ObjectType.objects.get_for_model(Site)])
|
|
|
+
|
|
|
+ # Output field (PositiveBigIntegerField)
|
|
|
+ query = '{ journal_entry_list { assigned_object_id } }'
|
|
|
+ response = self.client.post(url, data={'query': query}, format='json', **self.header)
|
|
|
+ self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
|
+ data = json.loads(response.content)
|
|
|
+ self.assertNotIn('errors', data)
|
|
|
+ self.assertEqual(data['data']['journal_entry_list'], [{'assigned_object_id': object_id}])
|
|
|
+
|
|
|
+ # Filter on a generic object ID
|
|
|
+ query = f"""
|
|
|
+ {{
|
|
|
+ l2vpn_termination_list(filters: {{assigned_object_id: {{filter_lookup: {{exact: {object_id}}}}}}}) {{
|
|
|
+ id
|
|
|
+ }}
|
|
|
+ }}
|
|
|
+ """
|
|
|
+ response = self.client.post(url, data={'query': query}, format='json', **self.header)
|
|
|
+ self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
|
+ data = json.loads(response.content)
|
|
|
+ self.assertNotIn('errors', data)
|
|
|
+ self.assertEqual(len(data['data']['l2vpn_termination_list']), 1)
|
|
|
+
|
|
|
+ # Filter on a related object ID
|
|
|
+ query = f'{{ export_template_list(filters: {{data_source_id: {{exact: {object_id}}}}}) {{ id }} }}'
|
|
|
+ response = self.client.post(url, data={'query': query}, format='json', **self.header)
|
|
|
+ self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
|
+ data = json.loads(response.content)
|
|
|
+ self.assertNotIn('errors', data)
|
|
|
+ self.assertEqual(data['data']['export_template_list'], [{'id': str(export_template.pk)}])
|
|
|
+
|
|
|
def test_graphql_array_length_lookup(self):
|
|
|
"""
|
|
|
The public GraphQL ``length`` array lookup must map to Django's ``len`` transform.
|
|
|
@@ -860,7 +918,11 @@ class GraphQLAPITestCase(APITestCase):
|
|
|
class PluginQuery:
|
|
|
platforms: list[PluginPlatformType] = strawberry_django.field()
|
|
|
|
|
|
- plugin_schema = strawberry.Schema(query=PluginQuery, extensions=[DjangoOptimizerExtension])
|
|
|
+ plugin_schema = strawberry.Schema(
|
|
|
+ query=PluginQuery,
|
|
|
+ config=StrawberryConfig(scalar_map={BigInt: BigIntScalar}),
|
|
|
+ extensions=[DjangoOptimizerExtension],
|
|
|
+ )
|
|
|
self.user.is_superuser = True
|
|
|
result = plugin_schema.execute_sync(
|
|
|
'{ platforms { name display } }',
|