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

1from typing import TYPE_CHECKING, Annotated 

2 

3import strawberry 

4from strawberry.scalars import JSON 

5from strawberry.types import Info 

6 

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 

12 

13from .filters import * 

14 

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 

29 

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) 

49 

50 

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) 

60 

61 

62@register_type( 

63 models.ConfigContextProfile, 

64 fields='__all__', 

65 filters=ConfigContextProfileFilter, 

66 pagination=True 

67) 

68class ConfigContextProfileType(SyncedDataMixin, PrimaryObjectType): 

69 pass 

70 

71 

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')]] 

93 

94 

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')]] 

106 

107 

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 

117 

118 

119@register_type( 

120 models.CustomFieldChoiceSet, 

121 exclude=['extra_choices', 'choice_colors'], 

122 filters=CustomFieldChoiceSetFilter, 

123 pagination=True 

124) 

125class CustomFieldChoiceSetType(OwnerMixin, ObjectType): 

126 

127 choices_for: list[Annotated["CustomFieldType", strawberry.lazy('extras.graphql.types')]] 

128 extra_choices: list[list[str]] | None 

129 choice_colors: JSON 

130 

131 

132@register_type( 

133 models.CustomLink, 

134 fields='__all__', 

135 filters=CustomLinkFilter, 

136 pagination=True 

137) 

138class CustomLinkType(OwnerMixin, ObjectType): 

139 pass 

140 

141 

142@register_type( 

143 models.ExportTemplate, 

144 fields='__all__', 

145 filters=ExportTemplateFilter, 

146 pagination=True 

147) 

148class ExportTemplateType(SyncedDataMixin, OwnerMixin, ObjectType): 

149 pass 

150 

151 

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 

160 

161 

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 

171 

172 

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 

180 

181 

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')]] 

190 

191 

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 

200 

201 

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 

209 

210 

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 

220 

221 

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 

230 

231 object_types: list[ContentTypeType] 

232 

233 

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 

242 

243 

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