Coverage for extras/graphql/types.py: 89%
59 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from typing import TYPE_CHECKING, Annotated
3import strawberry
4from strawberry.scalars import JSON
5from strawberry.types import Info
7from core.graphql.mixins import SyncedDataMixin
8from extras import models
9from extras.graphql.mixins import CustomFieldsMixin, TagsMixin
10from netbox.graphql.types import BaseObjectType, ContentTypeType, ObjectType, PrimaryObjectType, register_type
11from users.graphql.mixins import OwnerMixin
13from .filters import *
15if TYPE_CHECKING: 15 ↛ 16line 15 didn't jump to line 16 because the condition on line 15 was never true
16 from dcim.graphql.types import (
17 DeviceRoleType,
18 DeviceType,
19 DeviceTypeType,
20 LocationType,
21 PlatformType,
22 RegionType,
23 SiteGroupType,
24 SiteType,
25 )
26 from tenancy.graphql.types import TenantGroupType, TenantType
27 from users.graphql.types import GroupType, UserType
28 from virtualization.graphql.types import ClusterGroupType, ClusterType, ClusterTypeType, VirtualMachineType
30__all__ = (
31 'ConfigContextProfileType',
32 'ConfigContextType',
33 'ConfigTemplateType',
34 'CustomFieldChoiceSetType',
35 'CustomFieldType',
36 'CustomLinkType',
37 'EventRuleType',
38 'ExportTemplateType',
39 'ImageAttachmentType',
40 'JournalEntryType',
41 'NotificationGroupType',
42 'NotificationType',
43 'SavedFilterType',
44 'SubscriptionType',
45 'TableConfigType',
46 'TagType',
47 'WebhookType',
48)
51class SharedObjectMixin:
52 """
53 Restrict the queryset to shared objects, or those owned by the current user, unless the user is a superuser.
54 This mirrors the visibility enforced in the UI (extras.utils.SharedObjectViewMixin) and the REST API.
55 """
56 @classmethod
57 def get_queryset(cls, queryset, info: Info, **kwargs):
58 queryset = super().get_queryset(queryset, info, **kwargs)
59 return queryset.restrict_to_shared(info.context.request.user)
62@register_type(
63 models.ConfigContextProfile,
64 fields='__all__',
65 filters=ConfigContextProfileFilter,
66 pagination=True
67)
68class ConfigContextProfileType(SyncedDataMixin, PrimaryObjectType):
69 pass
72@register_type(
73 models.ConfigContext,
74 fields='__all__',
75 filters=ConfigContextFilter,
76 pagination=True
77)
78class ConfigContextType(SyncedDataMixin, OwnerMixin, ObjectType):
79 profile: ConfigContextProfileType | None
80 roles: list[Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')]]
81 device_types: list[Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')]]
82 tags: list[Annotated["TagType", strawberry.lazy('extras.graphql.types')]]
83 platforms: list[Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')]]
84 regions: list[Annotated["RegionType", strawberry.lazy('dcim.graphql.types')]]
85 cluster_groups: list[Annotated["ClusterGroupType", strawberry.lazy('virtualization.graphql.types')]]
86 tenant_groups: list[Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')]]
87 cluster_types: list[Annotated["ClusterTypeType", strawberry.lazy('virtualization.graphql.types')]]
88 clusters: list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]
89 locations: list[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]]
90 sites: list[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]]
91 tenants: list[Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')]]
92 site_groups: list[Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')]]
95@register_type(
96 models.ConfigTemplate,
97 fields='__all__',
98 filters=ConfigTemplateFilter,
99 pagination=True
100)
101class ConfigTemplateType(SyncedDataMixin, OwnerMixin, TagsMixin, ObjectType):
102 virtualmachines: list[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]]
103 devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]]
104 platforms: list[Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')]]
105 device_roles: list[Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')]]
108@register_type(
109 models.CustomField,
110 fields='__all__',
111 filters=CustomFieldFilter,
112 pagination=True
113)
114class CustomFieldType(OwnerMixin, ObjectType):
115 related_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
116 choice_set: Annotated["CustomFieldChoiceSetType", strawberry.lazy('extras.graphql.types')] | None
119@register_type(
120 models.CustomFieldChoiceSet,
121 exclude=['extra_choices', 'choice_colors'],
122 filters=CustomFieldChoiceSetFilter,
123 pagination=True
124)
125class CustomFieldChoiceSetType(OwnerMixin, ObjectType):
127 choices_for: list[Annotated["CustomFieldType", strawberry.lazy('extras.graphql.types')]]
128 extra_choices: list[list[str]] | None
129 choice_colors: JSON
132@register_type(
133 models.CustomLink,
134 fields='__all__',
135 filters=CustomLinkFilter,
136 pagination=True
137)
138class CustomLinkType(OwnerMixin, ObjectType):
139 pass
142@register_type(
143 models.ExportTemplate,
144 fields='__all__',
145 filters=ExportTemplateFilter,
146 pagination=True
147)
148class ExportTemplateType(SyncedDataMixin, OwnerMixin, ObjectType):
149 pass
152@register_type(
153 models.ImageAttachment,
154 fields='__all__',
155 filters=ImageAttachmentFilter,
156 pagination=True
157)
158class ImageAttachmentType(BaseObjectType):
159 object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
162@register_type(
163 models.JournalEntry,
164 fields='__all__',
165 filters=JournalEntryFilter,
166 pagination=True
167)
168class JournalEntryType(CustomFieldsMixin, TagsMixin, ObjectType):
169 assigned_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
170 created_by: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
173@register_type(
174 models.Notification,
175 filters=NotificationFilter,
176 pagination=True
177)
178class NotificationType(ObjectType):
179 user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
182@register_type(
183 models.NotificationGroup,
184 filters=NotificationGroupFilter,
185 pagination=True
186)
187class NotificationGroupType(ObjectType):
188 users: list[Annotated["UserType", strawberry.lazy('users.graphql.types')]]
189 groups: list[Annotated["GroupType", strawberry.lazy('users.graphql.types')]]
192@register_type(
193 models.SavedFilter,
194 exclude=['content_types',],
195 filters=SavedFilterFilter,
196 pagination=True
197)
198class SavedFilterType(SharedObjectMixin, OwnerMixin, ObjectType):
199 user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
202@register_type(
203 models.Subscription,
204 filters=SubscriptionFilter,
205 pagination=True
206)
207class SubscriptionType(ObjectType):
208 user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
211@register_type(
212 models.TableConfig,
213 fields='__all__',
214 filters=TableConfigFilter,
215 pagination=True
216)
217class TableConfigType(SharedObjectMixin, ObjectType):
218 object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
219 user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
222@register_type(
223 models.Tag,
224 exclude=['extras_taggeditem_items', ],
225 filters=TagFilter,
226 pagination=True
227)
228class TagType(OwnerMixin, ObjectType):
229 color: str
231 object_types: list[ContentTypeType]
234@register_type(
235 models.Webhook,
236 exclude=['content_types',],
237 filters=WebhookFilter,
238 pagination=True
239)
240class WebhookType(OwnerMixin, CustomFieldsMixin, TagsMixin, ObjectType):
241 pass
244@register_type(
245 models.EventRule,
246 exclude=['content_types',],
247 filters=EventRuleFilter,
248 pagination=True
249)
250class EventRuleType(OwnerMixin, CustomFieldsMixin, TagsMixin, ObjectType):
251 action_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None