diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index 537a4968d..313a84f20 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -21,6 +21,7 @@ A new `PluginMenu` class has been introduced, which enables a plugin to inject a * [#9654](https://github.com/netbox-community/netbox/issues/9654) - Add `weight` field to racks, device types, and module types * [#9892](https://github.com/netbox-community/netbox/issues/9892) - Add optional `name` field for FHRP groups * [#10348](https://github.com/netbox-community/netbox/issues/10348) - Add decimal custom field type +* [#10556](https://github.com/netbox-community/netbox/issues/10556) - Include a `display` field in all GraphQL object types ### Plugins API @@ -46,3 +47,7 @@ A new `PluginMenu` class has been introduced, which enables a plugin to inject a * Added optional `weight` and `weight_unit` fields * ipam.FHRPGroup * Added optional `name` field + +### GraphQL API Changes + +* All object types now include a `display` field diff --git a/netbox/netbox/graphql/scalars.py b/netbox/netbox/graphql/scalars.py index 7d14189dd..8fc186b4d 100644 --- a/netbox/netbox/graphql/scalars.py +++ b/netbox/netbox/graphql/scalars.py @@ -1,6 +1,6 @@ from graphene import Scalar from graphql.language import ast -from graphql.type.scalars import MAX_INT, MIN_INT +from graphene.types.scalars import MAX_INT, MIN_INT class BigInt(Scalar): diff --git a/netbox/netbox/graphql/schema.py b/netbox/netbox/graphql/schema.py index f0bc8559c..084ac3607 100644 --- a/netbox/netbox/graphql/schema.py +++ b/netbox/netbox/graphql/schema.py @@ -12,12 +12,12 @@ from wireless.graphql.schema import WirelessQuery class Query( + UsersQuery, CircuitsQuery, DCIMQuery, ExtrasQuery, IPAMQuery, TenancyQuery, - UsersQuery, VirtualizationQuery, WirelessQuery, *registry['plugins']['graphql_schemas'], # Append plugin schemas diff --git a/netbox/netbox/graphql/types.py b/netbox/netbox/graphql/types.py index 9c50e980b..10847742b 100644 --- a/netbox/netbox/graphql/types.py +++ b/netbox/netbox/graphql/types.py @@ -1,4 +1,5 @@ import graphene + from django.contrib.contenttypes.models import ContentType from extras.graphql.mixins import ( ChangelogMixin, @@ -24,6 +25,7 @@ class BaseObjectType(DjangoObjectType): """ Base GraphQL object type for all NetBox objects. Restricts the model queryset to enforce object permissions. """ + display = graphene.String() class_type = graphene.String() class Meta: @@ -34,6 +36,9 @@ class BaseObjectType(DjangoObjectType): # Enforce object permissions on the queryset return queryset.restrict(info.context.user, 'view') + def resolve_display(parent, info, **kwargs): + return str(parent) + def resolve_class_type(parent, info, **kwargs): return parent.__class__.__name__ diff --git a/netbox/utilities/testing/api.py b/netbox/utilities/testing/api.py index b3fa5704f..f26e5fffc 100644 --- a/netbox/utilities/testing/api.py +++ b/netbox/utilities/testing/api.py @@ -467,6 +467,7 @@ class APIViewTestCases: return query @override_settings(LOGIN_REQUIRED=True) + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*', 'auth.user']) def test_graphql_get_object(self): url = reverse('graphql') field_name = self._get_graphql_base_name() @@ -492,6 +493,7 @@ class APIViewTestCases: self.assertNotIn('errors', data) @override_settings(LOGIN_REQUIRED=True) + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*', 'auth.user']) def test_graphql_list_objects(self): url = reverse('graphql') field_name = f'{self._get_graphql_base_name()}_list' diff --git a/requirements.txt b/requirements.txt index 16c55462f..5b2a1141f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ django-taggit==3.0.0 django-timezone-field==5.0 djangorestframework==3.14.0 drf-yasg[validation]==1.21.4 -graphene-django==2.15.0 +graphene-django==3.0.0 gunicorn==20.1.0 Jinja2==3.1.2 Markdown==3.3.7