netbox-plugin-dns 0.21.4__py3-none-any.whl → 1.4.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. netbox_dns/__init__.py +106 -41
  2. netbox_dns/api/field_serializers.py +25 -0
  3. netbox_dns/api/nested_serializers.py +95 -52
  4. netbox_dns/api/serializers.py +14 -296
  5. netbox_dns/api/serializers_/__init__.py +0 -0
  6. netbox_dns/api/serializers_/dnssec_key_template.py +69 -0
  7. netbox_dns/api/serializers_/dnssec_policy.py +165 -0
  8. netbox_dns/api/serializers_/nameserver.py +56 -0
  9. netbox_dns/api/serializers_/prefix.py +18 -0
  10. netbox_dns/api/serializers_/record.py +105 -0
  11. netbox_dns/api/serializers_/record_template.py +71 -0
  12. netbox_dns/api/serializers_/registrar.py +45 -0
  13. netbox_dns/api/serializers_/registration_contact.py +50 -0
  14. netbox_dns/api/serializers_/view.py +81 -0
  15. netbox_dns/api/serializers_/zone.py +247 -0
  16. netbox_dns/api/serializers_/zone_template.py +157 -0
  17. netbox_dns/api/urls.py +13 -2
  18. netbox_dns/api/views.py +96 -58
  19. netbox_dns/choices/__init__.py +4 -0
  20. netbox_dns/choices/dnssec_key_template.py +67 -0
  21. netbox_dns/choices/dnssec_policy.py +40 -0
  22. netbox_dns/choices/record.py +104 -0
  23. netbox_dns/choices/utilities.py +4 -0
  24. netbox_dns/choices/zone.py +119 -0
  25. netbox_dns/fields/__init__.py +4 -0
  26. netbox_dns/fields/address.py +22 -16
  27. netbox_dns/fields/choice_array.py +33 -0
  28. netbox_dns/fields/ipam.py +15 -0
  29. netbox_dns/fields/network.py +42 -18
  30. netbox_dns/fields/rfc2317.py +97 -0
  31. netbox_dns/fields/timeperiod.py +33 -0
  32. netbox_dns/filters.py +7 -0
  33. netbox_dns/filtersets/__init__.py +12 -0
  34. netbox_dns/filtersets/dnssec_key_template.py +57 -0
  35. netbox_dns/filtersets/dnssec_policy.py +101 -0
  36. netbox_dns/filtersets/nameserver.py +46 -0
  37. netbox_dns/filtersets/record.py +135 -0
  38. netbox_dns/filtersets/record_template.py +59 -0
  39. netbox_dns/{filters → filtersets}/registrar.py +8 -1
  40. netbox_dns/{filters/contact.py → filtersets/registration_contact.py} +9 -3
  41. netbox_dns/filtersets/view.py +45 -0
  42. netbox_dns/filtersets/zone.py +254 -0
  43. netbox_dns/filtersets/zone_template.py +165 -0
  44. netbox_dns/forms/__init__.py +5 -1
  45. netbox_dns/forms/dnssec_key_template.py +250 -0
  46. netbox_dns/forms/dnssec_policy.py +654 -0
  47. netbox_dns/forms/nameserver.py +121 -27
  48. netbox_dns/forms/record.py +215 -104
  49. netbox_dns/forms/record_template.py +285 -0
  50. netbox_dns/forms/registrar.py +108 -31
  51. netbox_dns/forms/registration_contact.py +282 -0
  52. netbox_dns/forms/view.py +331 -20
  53. netbox_dns/forms/zone.py +769 -373
  54. netbox_dns/forms/zone_template.py +463 -0
  55. netbox_dns/graphql/__init__.py +25 -22
  56. netbox_dns/graphql/enums.py +41 -0
  57. netbox_dns/graphql/filter_lookups.py +13 -0
  58. netbox_dns/graphql/filters/__init__.py +12 -0
  59. netbox_dns/graphql/filters/dnssec_key_template.py +63 -0
  60. netbox_dns/graphql/filters/dnssec_policy.py +124 -0
  61. netbox_dns/graphql/filters/nameserver.py +32 -0
  62. netbox_dns/graphql/filters/record.py +89 -0
  63. netbox_dns/graphql/filters/record_template.py +55 -0
  64. netbox_dns/graphql/filters/registrar.py +30 -0
  65. netbox_dns/graphql/filters/registration_contact.py +27 -0
  66. netbox_dns/graphql/filters/view.py +28 -0
  67. netbox_dns/graphql/filters/zone.py +147 -0
  68. netbox_dns/graphql/filters/zone_template.py +97 -0
  69. netbox_dns/graphql/schema.py +89 -7
  70. netbox_dns/graphql/types.py +355 -0
  71. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  72. netbox_dns/locale/en/LC_MESSAGES/django.mo +0 -0
  73. netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
  74. netbox_dns/management/commands/cleanup_database.py +175 -156
  75. netbox_dns/management/commands/cleanup_rrset_ttl.py +64 -0
  76. netbox_dns/management/commands/rebuild_dnssync.py +23 -0
  77. netbox_dns/management/commands/setup_dnssync.py +140 -0
  78. netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py +0 -27
  79. netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +557 -0
  80. netbox_dns/migrations/{0013_add_nameserver_zone_record_description.py → 0002_contact_description_registrar_description.py} +4 -9
  81. netbox_dns/migrations/0003_default_view.py +15 -0
  82. netbox_dns/migrations/0004_create_and_assign_default_view.py +26 -0
  83. netbox_dns/migrations/0005_alter_zone_view_not_null.py +18 -0
  84. netbox_dns/migrations/0006_templating.py +172 -0
  85. netbox_dns/migrations/0007_alter_ordering_options.py +25 -0
  86. netbox_dns/migrations/0008_view_prefixes.py +18 -0
  87. netbox_dns/migrations/0009_rename_contact_registrationcontact.py +36 -0
  88. netbox_dns/migrations/0010_view_ip_address_filter.py +18 -0
  89. netbox_dns/migrations/0011_rename_related_fields.py +63 -0
  90. netbox_dns/migrations/0012_natural_ordering.py +88 -0
  91. netbox_dns/migrations/0013_zonetemplate_soa_mname_zonetemplate_soa_rname.py +30 -0
  92. netbox_dns/migrations/0014_alter_unique_constraints_lowercase.py +42 -0
  93. netbox_dns/migrations/0015_dnssec.py +168 -0
  94. netbox_dns/migrations/{0015_add_record_status.py → 0016_dnssec_policy_status.py} +5 -4
  95. netbox_dns/migrations/0017_dnssec_policy_zone_zone_template.py +41 -0
  96. netbox_dns/migrations/0018_zone_domain_status_zone_expiration_date.py +23 -0
  97. netbox_dns/migrations/0019_dnssecpolicy_parental_agents.py +25 -0
  98. netbox_dns/migrations/0020_netbox_3_4.py +1 -1
  99. netbox_dns/migrations/0020_remove_dnssecpolicy_parental_agents_and_more.py +29 -0
  100. netbox_dns/migrations/0021_alter_record_ptr_record.py +25 -0
  101. netbox_dns/migrations/0021_record_ip_address.py +1 -1
  102. netbox_dns/migrations/0022_alter_record_ipam_ip_address.py +26 -0
  103. netbox_dns/migrations/0023_disable_ptr_false.py +27 -0
  104. netbox_dns/migrations/0024_zonetemplate_parental_agents.py +25 -0
  105. netbox_dns/migrations/0025_remove_zone_inline_signing_and_more.py +22 -0
  106. netbox_dns/migrations/0026_alter_dnssecpolicy_nsec3_opt_out.py +18 -0
  107. netbox_dns/migrations/0026_domain_registration.py +1 -1
  108. netbox_dns/migrations/0027_zone_comments.py +18 -0
  109. netbox_dns/migrations/0028_alter_zone_default_ttl_alter_zone_soa_minimum_and_more.py +54 -0
  110. netbox_dns/migrations/0028_rfc2317_fields.py +44 -0
  111. netbox_dns/migrations/0029_alter_registrationcontact_street.py +18 -0
  112. netbox_dns/migrations/0029_record_fqdn.py +30 -0
  113. netbox_dns/mixins/__init__.py +1 -0
  114. netbox_dns/mixins/object_modification.py +57 -0
  115. netbox_dns/models/__init__.py +5 -1
  116. netbox_dns/models/dnssec_key_template.py +114 -0
  117. netbox_dns/models/dnssec_policy.py +203 -0
  118. netbox_dns/models/nameserver.py +61 -30
  119. netbox_dns/models/record.py +781 -234
  120. netbox_dns/models/record_template.py +198 -0
  121. netbox_dns/models/registrar.py +34 -15
  122. netbox_dns/models/{contact.py → registration_contact.py} +72 -43
  123. netbox_dns/models/view.py +129 -9
  124. netbox_dns/models/zone.py +806 -242
  125. netbox_dns/models/zone_template.py +209 -0
  126. netbox_dns/navigation.py +176 -76
  127. netbox_dns/signals/__init__.py +0 -0
  128. netbox_dns/signals/dnssec.py +32 -0
  129. netbox_dns/signals/ipam_dnssync.py +216 -0
  130. netbox_dns/tables/__init__.py +5 -1
  131. netbox_dns/tables/dnssec_key_template.py +49 -0
  132. netbox_dns/tables/dnssec_policy.py +140 -0
  133. netbox_dns/tables/ipam_dnssync.py +12 -0
  134. netbox_dns/tables/nameserver.py +14 -17
  135. netbox_dns/tables/record.py +117 -59
  136. netbox_dns/tables/record_template.py +91 -0
  137. netbox_dns/tables/registrar.py +20 -10
  138. netbox_dns/tables/{contact.py → registration_contact.py} +22 -11
  139. netbox_dns/tables/view.py +47 -3
  140. netbox_dns/tables/zone.py +62 -31
  141. netbox_dns/tables/zone_template.py +78 -0
  142. netbox_dns/template_content.py +124 -38
  143. netbox_dns/templates/netbox_dns/dnsseckeytemplate.html +70 -0
  144. netbox_dns/templates/netbox_dns/dnssecpolicy.html +163 -0
  145. netbox_dns/templates/netbox_dns/nameserver.html +31 -28
  146. netbox_dns/templates/netbox_dns/record/managed.html +2 -1
  147. netbox_dns/templates/netbox_dns/record/related.html +17 -6
  148. netbox_dns/templates/netbox_dns/record.html +140 -93
  149. netbox_dns/templates/netbox_dns/recordtemplate.html +96 -0
  150. netbox_dns/templates/netbox_dns/registrar.html +41 -34
  151. netbox_dns/templates/netbox_dns/registrationcontact.html +76 -0
  152. netbox_dns/templates/netbox_dns/view/button.html +10 -0
  153. netbox_dns/templates/netbox_dns/view/prefix.html +44 -0
  154. netbox_dns/templates/netbox_dns/view/related.html +33 -0
  155. netbox_dns/templates/netbox_dns/view.html +62 -18
  156. netbox_dns/templates/netbox_dns/zone/base.html +6 -3
  157. netbox_dns/templates/netbox_dns/zone/child.html +6 -5
  158. netbox_dns/templates/netbox_dns/zone/child_zone.html +18 -0
  159. netbox_dns/templates/netbox_dns/zone/delegation_record.html +18 -0
  160. netbox_dns/templates/netbox_dns/zone/managed_record.html +1 -1
  161. netbox_dns/templates/netbox_dns/zone/record.html +6 -5
  162. netbox_dns/templates/netbox_dns/zone/registration.html +43 -24
  163. netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html +18 -0
  164. netbox_dns/templates/netbox_dns/zone.html +178 -119
  165. netbox_dns/templates/netbox_dns/zonetemplate/child.html +46 -0
  166. netbox_dns/templates/netbox_dns/zonetemplate.html +124 -0
  167. netbox_dns/templatetags/netbox_dns.py +10 -0
  168. netbox_dns/urls.py +50 -210
  169. netbox_dns/utilities/__init__.py +3 -0
  170. netbox_dns/{utilities.py → utilities/conversions.py} +55 -7
  171. netbox_dns/utilities/dns.py +11 -0
  172. netbox_dns/utilities/ipam_dnssync.py +370 -0
  173. netbox_dns/validators/__init__.py +4 -0
  174. netbox_dns/validators/dns_name.py +116 -0
  175. netbox_dns/validators/dns_value.py +147 -0
  176. netbox_dns/validators/dnssec.py +148 -0
  177. netbox_dns/validators/rfc2317.py +28 -0
  178. netbox_dns/views/__init__.py +5 -1
  179. netbox_dns/views/dnssec_key_template.py +78 -0
  180. netbox_dns/views/dnssec_policy.py +146 -0
  181. netbox_dns/views/nameserver.py +34 -15
  182. netbox_dns/views/record.py +156 -15
  183. netbox_dns/views/record_template.py +93 -0
  184. netbox_dns/views/registrar.py +32 -13
  185. netbox_dns/views/registration_contact.py +101 -0
  186. netbox_dns/views/view.py +58 -14
  187. netbox_dns/views/zone.py +130 -33
  188. netbox_dns/views/zone_template.py +82 -0
  189. netbox_plugin_dns-1.4.7.dist-info/METADATA +132 -0
  190. netbox_plugin_dns-1.4.7.dist-info/RECORD +201 -0
  191. {netbox_plugin_dns-0.21.4.dist-info → netbox_plugin_dns-1.4.7.dist-info}/WHEEL +2 -1
  192. {netbox_plugin_dns-0.21.4.dist-info → netbox_plugin_dns-1.4.7.dist-info/licenses}/LICENSE +2 -1
  193. netbox_plugin_dns-1.4.7.dist-info/top_level.txt +1 -0
  194. netbox_dns/filters/__init__.py +0 -6
  195. netbox_dns/filters/nameserver.py +0 -18
  196. netbox_dns/filters/record.py +0 -53
  197. netbox_dns/filters/view.py +0 -18
  198. netbox_dns/filters/zone.py +0 -112
  199. netbox_dns/forms/contact.py +0 -211
  200. netbox_dns/graphql/contact.py +0 -19
  201. netbox_dns/graphql/nameserver.py +0 -19
  202. netbox_dns/graphql/record.py +0 -19
  203. netbox_dns/graphql/registrar.py +0 -19
  204. netbox_dns/graphql/view.py +0 -19
  205. netbox_dns/graphql/zone.py +0 -19
  206. netbox_dns/management/commands/setup_coupling.py +0 -75
  207. netbox_dns/management/commands/update_soa.py +0 -22
  208. netbox_dns/middleware.py +0 -226
  209. netbox_dns/migrations/0001_initial.py +0 -115
  210. netbox_dns/migrations/0002_zone_default_ttl.py +0 -18
  211. netbox_dns/migrations/0003_soa_managed_records.py +0 -112
  212. netbox_dns/migrations/0004_create_ptr_for_a_aaaa_records.py +0 -80
  213. netbox_dns/migrations/0005_update_ns_records.py +0 -41
  214. netbox_dns/migrations/0006_zone_soa_serial_auto.py +0 -29
  215. netbox_dns/migrations/0007_alter_zone_soa_serial_auto.py +0 -17
  216. netbox_dns/migrations/0008_zone_status_names.py +0 -21
  217. netbox_dns/migrations/0009_netbox32.py +0 -71
  218. netbox_dns/migrations/0010_update_soa_records.py +0 -58
  219. netbox_dns/migrations/0011_add_view_model.py +0 -70
  220. netbox_dns/migrations/0012_adjust_zone_and_record.py +0 -17
  221. netbox_dns/migrations/0014_add_view_description.py +0 -16
  222. netbox_dns/migrations/0016_cleanup_ptr_records.py +0 -38
  223. netbox_dns/migrations/0017_alter_record_ttl.py +0 -17
  224. netbox_dns/migrations/0018_zone_arpa_network.py +0 -51
  225. netbox_dns/migrations/0019_update_ns_ttl.py +0 -19
  226. netbox_dns/templates/netbox_dns/contact.html +0 -71
  227. netbox_dns/templates/netbox_dns/related_dns_objects.html +0 -21
  228. netbox_dns/templatetags/view_helpers.py +0 -15
  229. netbox_dns/validators.py +0 -57
  230. netbox_dns/views/contact.py +0 -83
  231. netbox_plugin_dns-0.21.4.dist-info/METADATA +0 -101
  232. netbox_plugin_dns-0.21.4.dist-info/RECORD +0 -110
@@ -0,0 +1,209 @@
1
+ from dns import name as dns_name
2
+ from dns.exception import DNSException
3
+
4
+ from django.db import models
5
+ from django.utils.translation import gettext_lazy as _
6
+ from django.core.exceptions import ValidationError
7
+ from django.contrib.postgres.fields import ArrayField
8
+
9
+ from netbox.models import NetBoxModel
10
+ from netbox.search import SearchIndex, register_search
11
+
12
+ from netbox_dns.validators import validate_rname
13
+
14
+
15
+ __all__ = (
16
+ "ZoneTemplate",
17
+ "ZoneTemplateIndex",
18
+ )
19
+
20
+
21
+ class ZoneTemplate(NetBoxModel):
22
+ class Meta:
23
+ verbose_name = _("Zone Template")
24
+ verbose_name_plural = _("Zone Templates")
25
+
26
+ ordering = ("name",)
27
+
28
+ clone_fields = (
29
+ "description",
30
+ "nameservers",
31
+ "record_templates",
32
+ "soa_mname",
33
+ "soa_rname",
34
+ "dnssec_policy",
35
+ "parental_agents",
36
+ "registrar",
37
+ "registrant",
38
+ "admin_c",
39
+ "tech_c",
40
+ "billing_c",
41
+ "tenant",
42
+ )
43
+
44
+ template_fields = (
45
+ "soa_mname",
46
+ "soa_rname",
47
+ "dnssec_policy",
48
+ "parental_agents",
49
+ "registrar",
50
+ "registrant",
51
+ "admin_c",
52
+ "tech_c",
53
+ "billing_c",
54
+ "tenant",
55
+ )
56
+
57
+ def __str__(self):
58
+ return str(self.name)
59
+
60
+ name = models.CharField(
61
+ verbose_name=_("Template Name"),
62
+ unique=True,
63
+ max_length=200,
64
+ db_collation="natural_sort",
65
+ )
66
+ description = models.CharField(
67
+ verbose_name=_("Description"),
68
+ max_length=200,
69
+ blank=True,
70
+ )
71
+ nameservers = models.ManyToManyField(
72
+ verbose_name=_("Nameservers"),
73
+ to="NameServer",
74
+ related_name="+",
75
+ blank=True,
76
+ )
77
+ soa_mname = models.ForeignKey(
78
+ verbose_name=_("SOA MName"),
79
+ to="NameServer",
80
+ related_name="+",
81
+ on_delete=models.PROTECT,
82
+ blank=True,
83
+ null=True,
84
+ )
85
+ soa_rname = models.CharField(
86
+ verbose_name=_("SOA RName"),
87
+ max_length=255,
88
+ blank=True,
89
+ )
90
+ record_templates = models.ManyToManyField(
91
+ verbose_name=_("Record Templates"),
92
+ to="RecordTemplate",
93
+ related_name="zone_templates",
94
+ blank=True,
95
+ )
96
+ dnssec_policy = models.ForeignKey(
97
+ verbose_name=_("DNSSEC Policy"),
98
+ to="DNSSECPolicy",
99
+ on_delete=models.SET_NULL,
100
+ related_name="zone_templates",
101
+ blank=True,
102
+ null=True,
103
+ )
104
+ parental_agents = ArrayField(
105
+ base_field=models.GenericIPAddressField(
106
+ protocol="both",
107
+ ),
108
+ blank=True,
109
+ null=True,
110
+ default=list,
111
+ )
112
+ registrar = models.ForeignKey(
113
+ verbose_name=_("Registrar"),
114
+ to="Registrar",
115
+ on_delete=models.SET_NULL,
116
+ related_name="+",
117
+ blank=True,
118
+ null=True,
119
+ )
120
+ registrant = models.ForeignKey(
121
+ verbose_name=_("Registrant"),
122
+ to="RegistrationContact",
123
+ on_delete=models.SET_NULL,
124
+ related_name="+",
125
+ blank=True,
126
+ null=True,
127
+ )
128
+ admin_c = models.ForeignKey(
129
+ verbose_name=_("Administrative Contact"),
130
+ to="RegistrationContact",
131
+ on_delete=models.SET_NULL,
132
+ related_name="+",
133
+ blank=True,
134
+ null=True,
135
+ )
136
+ tech_c = models.ForeignKey(
137
+ verbose_name=_("Technical Contact"),
138
+ to="RegistrationContact",
139
+ on_delete=models.SET_NULL,
140
+ related_name="+",
141
+ blank=True,
142
+ null=True,
143
+ )
144
+ billing_c = models.ForeignKey(
145
+ verbose_name=_("Billing Contact"),
146
+ to="RegistrationContact",
147
+ on_delete=models.SET_NULL,
148
+ related_name="+",
149
+ blank=True,
150
+ null=True,
151
+ )
152
+ tenant = models.ForeignKey(
153
+ verbose_name=_("Tenant"),
154
+ to="tenancy.Tenant",
155
+ on_delete=models.SET_NULL,
156
+ related_name="+",
157
+ blank=True,
158
+ null=True,
159
+ )
160
+
161
+ def apply_to_zone_data(self, data):
162
+ fields_changed = False
163
+ for field in self.template_fields:
164
+ if data.get(field) in (None, "") and getattr(self, field) not in (None, ""):
165
+ fields_changed = True
166
+ data[field] = getattr(self, field)
167
+
168
+ return fields_changed
169
+
170
+ def apply_to_zone_relations(self, zone):
171
+ if not zone.nameservers.all() and self.nameservers.all():
172
+ zone.nameservers.set(self.nameservers.all())
173
+
174
+ if not zone.tags.all() and self.tags.all():
175
+ zone.tags.set(self.tags.all())
176
+
177
+ self.create_records(zone)
178
+
179
+ def create_records(self, zone):
180
+ for record_template in self.record_templates.all():
181
+ record_template.create_record(zone=zone)
182
+
183
+ def clean(self, *args, **kwargs):
184
+ if self.soa_rname:
185
+ try:
186
+ dns_name.from_text(self.soa_rname, origin=dns_name.root)
187
+ validate_rname(self.soa_rname)
188
+ except (DNSException, ValidationError) as exc:
189
+ raise ValidationError(
190
+ {
191
+ "soa_rname": exc,
192
+ }
193
+ )
194
+
195
+
196
+ @register_search
197
+ class ZoneTemplateIndex(SearchIndex):
198
+ model = ZoneTemplate
199
+
200
+ fields = (
201
+ ("name", 100),
202
+ ("tenant", 300),
203
+ ("registrar", 300),
204
+ ("registrant", 300),
205
+ ("admin_c", 300),
206
+ ("tech_c", 300),
207
+ ("billing_c", 300),
208
+ ("description", 500),
209
+ )
netbox_dns/navigation.py CHANGED
@@ -1,165 +1,265 @@
1
- from extras.plugins import PluginMenuButton, PluginMenuItem
2
- from extras.plugins import PluginMenu
3
- from utilities.choices import ButtonColorChoices
1
+ from django.utils.translation import gettext_lazy as _
2
+
3
+ from netbox.plugins import PluginMenuButton, PluginMenuItem, PluginMenu
4
+ from netbox.plugins.utils import get_plugin_config
5
+
6
+ menu_name = get_plugin_config("netbox_dns", "menu_name")
7
+ top_level_menu = get_plugin_config("netbox_dns", "top_level_menu")
4
8
 
5
9
  view_menu_item = PluginMenuItem(
6
10
  link="plugins:netbox_dns:view_list",
7
- link_text="Views",
11
+ link_text=_("Views"),
8
12
  permissions=["netbox_dns.view_view"],
9
13
  buttons=(
10
14
  PluginMenuButton(
11
15
  "plugins:netbox_dns:view_add",
12
- "Add",
16
+ _("Add"),
13
17
  "mdi mdi-plus-thick",
14
- ButtonColorChoices.GREEN,
15
18
  permissions=["netbox_dns.add_view"],
16
19
  ),
17
20
  PluginMenuButton(
18
- "plugins:netbox_dns:view_import",
19
- "Import",
21
+ "plugins:netbox_dns:view_bulk_import",
22
+ _("Import"),
20
23
  "mdi mdi-upload",
21
- ButtonColorChoices.CYAN,
22
24
  permissions=["netbox_dns.add_view"],
23
25
  ),
24
26
  ),
25
27
  )
26
28
 
27
- zone_menu_item = PluginMenuItem(
28
- link="plugins:netbox_dns:zone_list",
29
- link_text="Zones",
30
- permissions=["netbox_dns.view_zone"],
29
+ nameserver_menu_item = PluginMenuItem(
30
+ link="plugins:netbox_dns:nameserver_list",
31
+ link_text=_("Nameservers"),
32
+ permissions=["netbox_dns.view_nameserver"],
31
33
  buttons=(
32
34
  PluginMenuButton(
33
- "plugins:netbox_dns:zone_add",
34
- "Add",
35
+ "plugins:netbox_dns:nameserver_add",
36
+ _("Add"),
35
37
  "mdi mdi-plus-thick",
36
- ButtonColorChoices.GREEN,
37
- permissions=["netbox_dns.add_zone"],
38
+ permissions=["netbox_dns.add_nameserver"],
38
39
  ),
39
40
  PluginMenuButton(
40
- "plugins:netbox_dns:zone_import",
41
- "Import",
41
+ "plugins:netbox_dns:nameserver_bulk_import",
42
+ _("Import"),
42
43
  "mdi mdi-upload",
43
- ButtonColorChoices.CYAN,
44
- permissions=["netbox_dns.add_zone"],
44
+ permissions=["netbox_dns.add_nameserver"],
45
45
  ),
46
46
  ),
47
47
  )
48
48
 
49
- nameserver_menu_item = PluginMenuItem(
50
- link="plugins:netbox_dns:nameserver_list",
51
- link_text="Nameservers",
52
- permissions=["netbox_dns.view_nameserver"],
49
+ zone_menu_item = PluginMenuItem(
50
+ link="plugins:netbox_dns:zone_list",
51
+ link_text=_("Zones"),
52
+ permissions=["netbox_dns.view_zone"],
53
53
  buttons=(
54
54
  PluginMenuButton(
55
- "plugins:netbox_dns:nameserver_add",
56
- "Add",
55
+ "plugins:netbox_dns:zone_add",
56
+ _("Add"),
57
57
  "mdi mdi-plus-thick",
58
- ButtonColorChoices.GREEN,
59
- permissions=["netbox_dns.add_nameserver"],
58
+ permissions=["netbox_dns.add_zone"],
60
59
  ),
61
60
  PluginMenuButton(
62
- "plugins:netbox_dns:nameserver_import",
63
- "Import",
61
+ "plugins:netbox_dns:zone_bulk_import",
62
+ _("Import"),
64
63
  "mdi mdi-upload",
65
- ButtonColorChoices.CYAN,
66
- permissions=["netbox_dns.add_nameserver"],
64
+ permissions=["netbox_dns.add_zone"],
67
65
  ),
68
66
  ),
69
67
  )
70
68
 
71
69
  record_menu_item = PluginMenuItem(
72
70
  link="plugins:netbox_dns:record_list",
73
- link_text="Records",
71
+ link_text=_("Records"),
74
72
  permissions=["netbox_dns.view_record"],
75
73
  buttons=(
76
74
  PluginMenuButton(
77
75
  "plugins:netbox_dns:record_add",
78
- "Add",
76
+ _("Add"),
79
77
  "mdi mdi-plus-thick",
80
- ButtonColorChoices.GREEN,
81
78
  permissions=["netbox_dns.add_record"],
82
79
  ),
83
80
  PluginMenuButton(
84
- "plugins:netbox_dns:record_import",
85
- "Import",
81
+ "plugins:netbox_dns:record_bulk_import",
82
+ _("Import"),
86
83
  "mdi mdi-upload",
87
- ButtonColorChoices.CYAN,
88
84
  permissions=["netbox_dns.add_record"],
89
85
  ),
90
86
  ),
91
87
  )
92
88
 
93
89
  managed_record_menu_item = PluginMenuItem(
94
- link="plugins:netbox_dns:managed_record_list",
95
- link_text="Managed Records",
90
+ link="plugins:netbox_dns:record_list_managed",
91
+ link_text=_("Managed Records"),
96
92
  permissions=["netbox_dns.view_record"],
97
93
  )
98
94
 
95
+ zonetemplate_menu_item = PluginMenuItem(
96
+ link="plugins:netbox_dns:zonetemplate_list",
97
+ link_text=_("Zone Templates"),
98
+ permissions=["netbox_dns.view_zonetemplate"],
99
+ buttons=(
100
+ PluginMenuButton(
101
+ "plugins:netbox_dns:zonetemplate_add",
102
+ _("Add"),
103
+ "mdi mdi-plus-thick",
104
+ permissions=["netbox_dns.add_zonetemplate"],
105
+ ),
106
+ PluginMenuButton(
107
+ "plugins:netbox_dns:zonetemplate_bulk_import",
108
+ _("Import"),
109
+ "mdi mdi-upload",
110
+ permissions=["netbox_dns.add_zonetemplate"],
111
+ ),
112
+ ),
113
+ )
114
+
115
+ recordtemplate_menu_item = PluginMenuItem(
116
+ link="plugins:netbox_dns:recordtemplate_list",
117
+ link_text=_("Record Templates"),
118
+ permissions=["netbox_dns.view_recordtemplate"],
119
+ buttons=(
120
+ PluginMenuButton(
121
+ "plugins:netbox_dns:recordtemplate_add",
122
+ _("Add"),
123
+ "mdi mdi-plus-thick",
124
+ permissions=["netbox_dns.add_recordtemplate"],
125
+ ),
126
+ PluginMenuButton(
127
+ "plugins:netbox_dns:recordtemplate_bulk_import",
128
+ _("Import"),
129
+ "mdi mdi-upload",
130
+ permissions=["netbox_dns.add_recordtemplate"],
131
+ ),
132
+ ),
133
+ )
134
+
135
+ dnsseckeytemplate_menu_item = PluginMenuItem(
136
+ link="plugins:netbox_dns:dnsseckeytemplate_list",
137
+ link_text=_("DNSSEC Key Templates"),
138
+ permissions=["netbox_dns.view_dnsseckeytemplate"],
139
+ buttons=(
140
+ PluginMenuButton(
141
+ "plugins:netbox_dns:dnsseckeytemplate_add",
142
+ _("Add"),
143
+ "mdi mdi-plus-thick",
144
+ permissions=["netbox_dns.add_dnsseckeytemplate"],
145
+ ),
146
+ PluginMenuButton(
147
+ "plugins:netbox_dns:dnsseckeytemplate_bulk_import",
148
+ _("Import"),
149
+ "mdi mdi-upload",
150
+ permissions=["netbox_dns.add_dnsseckeytemplate"],
151
+ ),
152
+ ),
153
+ )
154
+
155
+ dnssecpolicy_menu_item = PluginMenuItem(
156
+ link="plugins:netbox_dns:dnssecpolicy_list",
157
+ link_text=_("DNSSEC Policies"),
158
+ permissions=["netbox_dns.view_dnssecpolicy"],
159
+ buttons=(
160
+ PluginMenuButton(
161
+ "plugins:netbox_dns:dnssecpolicy_add",
162
+ _("Add"),
163
+ "mdi mdi-plus-thick",
164
+ permissions=["netbox_dns.add_dnssecpolicy"],
165
+ ),
166
+ PluginMenuButton(
167
+ "plugins:netbox_dns:dnssecpolicy_bulk_import",
168
+ _("Import"),
169
+ "mdi mdi-upload",
170
+ permissions=["netbox_dns.add_dnssecpolicy"],
171
+ ),
172
+ ),
173
+ )
174
+
99
175
  registrar_menu_item = PluginMenuItem(
100
176
  link="plugins:netbox_dns:registrar_list",
101
- link_text="Registrars",
177
+ link_text=_("Registrars"),
102
178
  permissions=["netbox_dns.view_registrar"],
103
179
  buttons=(
104
180
  PluginMenuButton(
105
181
  "plugins:netbox_dns:registrar_add",
106
- "Add",
182
+ _("Add"),
107
183
  "mdi mdi-plus-thick",
108
- ButtonColorChoices.GREEN,
109
184
  permissions=["netbox_dns.add_registrar"],
110
185
  ),
111
186
  PluginMenuButton(
112
- "plugins:netbox_dns:registrar_import",
113
- "Import",
187
+ "plugins:netbox_dns:registrar_bulk_import",
188
+ _("Import"),
114
189
  "mdi mdi-upload",
115
- ButtonColorChoices.CYAN,
116
190
  permissions=["netbox_dns.add_registrar"],
117
191
  ),
118
192
  ),
119
193
  )
120
194
 
121
195
  contact_menu_item = PluginMenuItem(
122
- link="plugins:netbox_dns:contact_list",
123
- link_text="Contacts",
124
- permissions=["netbox_dns.view_contact"],
196
+ link="plugins:netbox_dns:registrationcontact_list",
197
+ link_text=_("Registration Contacts"),
198
+ permissions=["netbox_dns.view_registrationcontact"],
125
199
  buttons=(
126
200
  PluginMenuButton(
127
- "plugins:netbox_dns:contact_add",
128
- "Add",
201
+ "plugins:netbox_dns:registrationcontact_add",
202
+ _("Add"),
129
203
  "mdi mdi-plus-thick",
130
- ButtonColorChoices.GREEN,
131
- permissions=["netbox_dns.add_contact"],
204
+ permissions=["netbox_dns.add_registrationcontact"],
132
205
  ),
133
206
  PluginMenuButton(
134
- "plugins:netbox_dns:contact_import",
135
- "Import",
207
+ "plugins:netbox_dns:registrationcontact_bulk_import",
208
+ _("Import"),
136
209
  "mdi mdi-upload",
137
- ButtonColorChoices.CYAN,
138
- permissions=["netbox_dns.add_contact"],
210
+ permissions=["netbox_dns.add_registrationcontact"],
139
211
  ),
140
212
  ),
141
213
  )
142
214
 
143
- menu = PluginMenu(
144
- label="NetBox DNS",
145
- groups=(
146
- (
147
- "DNS Configuration",
215
+
216
+ if top_level_menu:
217
+ menu = PluginMenu(
218
+ label=menu_name,
219
+ groups=(
148
220
  (
149
- view_menu_item,
150
- zone_menu_item,
151
- nameserver_menu_item,
152
- record_menu_item,
153
- managed_record_menu_item,
221
+ _("DNS Configuration"),
222
+ (
223
+ view_menu_item,
224
+ nameserver_menu_item,
225
+ zone_menu_item,
226
+ record_menu_item,
227
+ managed_record_menu_item,
228
+ ),
229
+ ),
230
+ (
231
+ _("Templates"),
232
+ (
233
+ zonetemplate_menu_item,
234
+ recordtemplate_menu_item,
235
+ ),
154
236
  ),
155
- ),
156
- (
157
- "Domain Registration",
158
237
  (
159
- registrar_menu_item,
160
- contact_menu_item,
238
+ _("DNSSEC"),
239
+ (
240
+ dnsseckeytemplate_menu_item,
241
+ dnssecpolicy_menu_item,
242
+ ),
243
+ ),
244
+ (
245
+ _("Domain Registration"),
246
+ (
247
+ registrar_menu_item,
248
+ contact_menu_item,
249
+ ),
161
250
  ),
162
251
  ),
163
- ),
164
- icon_class="mdi mdi-dns",
165
- )
252
+ icon_class="mdi mdi-dns",
253
+ )
254
+ else:
255
+ menu_items = (
256
+ view_menu_item,
257
+ zone_menu_item,
258
+ nameserver_menu_item,
259
+ record_menu_item,
260
+ managed_record_menu_item,
261
+ dnsseckeytemplate_menu_item,
262
+ dnssecpolicy_menu_item,
263
+ registrar_menu_item,
264
+ contact_menu_item,
265
+ )
File without changes
@@ -0,0 +1,32 @@
1
+ from django.dispatch import receiver
2
+ from django.db.models.signals import m2m_changed
3
+ from django.core.exceptions import ValidationError
4
+
5
+ from netbox.context import current_request
6
+ from utilities.exceptions import AbortRequest
7
+
8
+ from netbox_dns.validators import validate_key_template_assignment
9
+
10
+ from netbox_dns.models import DNSSECPolicy, DNSSECKeyTemplate
11
+
12
+
13
+ @receiver(m2m_changed, sender=DNSSECPolicy.key_templates.through)
14
+ def dnssec_policy_key_templates_changed(action, instance, pk_set, **kwargs):
15
+ request = current_request.get()
16
+
17
+ key_templates = instance.key_templates.all()
18
+ match action:
19
+ case "pre_remove":
20
+ key_templates = key_templates.exclude(pk__in=pk_set)
21
+ case "pre_add":
22
+ key_templates |= DNSSECKeyTemplate.objects.filter(pk__in=pk_set)
23
+ case _:
24
+ return
25
+
26
+ try:
27
+ validate_key_template_assignment(key_templates)
28
+ except ValidationError as exc:
29
+ if request is not None:
30
+ raise AbortRequest(exc)
31
+ else:
32
+ raise exc