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,78 @@
1
+ import django_tables2 as tables
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+ from netbox.tables import NetBoxTable, TagColumn, ActionsColumn
5
+ from tenancy.tables import TenancyColumnsMixin
6
+
7
+ from netbox_dns.models import ZoneTemplate
8
+
9
+
10
+ __all__ = (
11
+ "ZoneTemplateTable",
12
+ "ZoneTemplateDisplayTable",
13
+ )
14
+
15
+
16
+ class ZoneTemplateTable(TenancyColumnsMixin, NetBoxTable):
17
+ class Meta(NetBoxTable.Meta):
18
+ model = ZoneTemplate
19
+
20
+ fields = (
21
+ "soa_rname",
22
+ "description",
23
+ )
24
+
25
+ default_columns = (
26
+ "name",
27
+ "tags",
28
+ )
29
+
30
+ name = tables.Column(
31
+ verbose_name=_("Name"),
32
+ linkify=True,
33
+ )
34
+ soa_mname = tables.Column(
35
+ verbose_name=_("SOA MName"),
36
+ linkify=True,
37
+ )
38
+ tags = TagColumn(
39
+ url_name="plugins:netbox_dns:zonetemplate_list",
40
+ )
41
+ dnssec_policy = tables.Column(
42
+ verbose_name=_("DNSSEC Policy"),
43
+ linkify=True,
44
+ )
45
+ registrar = tables.Column(
46
+ verbose_name=_("Registrar"),
47
+ linkify=True,
48
+ )
49
+ registrant = tables.Column(
50
+ verbose_name=_("Registrant"),
51
+ linkify=True,
52
+ )
53
+ admin_c = tables.Column(
54
+ verbose_name=_("Administrative Contact"),
55
+ linkify=True,
56
+ )
57
+ tech_c = tables.Column(
58
+ verbose_name=_("Technical Contact"),
59
+ linkify=True,
60
+ )
61
+ billing_c = tables.Column(
62
+ verbose_name=_("Billing Contact"),
63
+ linkify=True,
64
+ )
65
+
66
+
67
+ class ZoneTemplateDisplayTable(ZoneTemplateTable):
68
+ class Meta(NetBoxTable.Meta):
69
+ model = ZoneTemplate
70
+
71
+ fields = ("description",)
72
+
73
+ default_columns = (
74
+ "name",
75
+ "description",
76
+ )
77
+
78
+ actions = ActionsColumn(actions="")
@@ -1,20 +1,26 @@
1
- try:
2
- # NetBox 3.5.0 - 3.5.7, 3.5.9+
3
- from extras.plugins import get_plugin_config
4
- except ImportError:
5
- # NetBox 3.5.8
6
- from extras.plugins.utils import get_plugin_config
7
- from extras.plugins import PluginTemplateExtension
1
+ import django_tables2 as tables
8
2
 
9
- from netbox_dns.models import Record, Zone, View, NameServer
10
- from netbox_dns.tables import RelatedRecordTable
3
+ from django.conf import settings
4
+ from django.urls import reverse
5
+ from django.utils.translation import gettext_lazy as _
6
+
7
+ from netbox.plugins.utils import get_plugin_config
8
+ from netbox.plugins import PluginTemplateExtension
9
+ from utilities.tables import register_table_column
10
+ from ipam.tables import IPAddressTable
11
+
12
+ from netbox_dns.models import Record
13
+ from netbox_dns.choices import RecordTypeChoices
14
+ from netbox_dns.tables import RelatedRecordTable, RelatedViewTable
15
+ from netbox_dns.utilities import get_views_by_prefix
11
16
 
12
17
 
13
18
  class RelatedDNSRecords(PluginTemplateExtension):
14
- model = "ipam.ipaddress"
19
+ models = ("ipam.ipaddress",)
15
20
 
16
21
  def right_page(self):
17
22
  ip_address = self.context.get("object")
23
+ request = self.context.get("request")
18
24
 
19
25
  address_records = ip_address.netbox_dns_records.all()
20
26
  pointer_records = [
@@ -27,6 +33,7 @@ class RelatedDNSRecords(PluginTemplateExtension):
27
33
  address_record_table = RelatedRecordTable(
28
34
  data=address_records,
29
35
  )
36
+ address_record_table.configure(request)
30
37
  else:
31
38
  address_record_table = None
32
39
 
@@ -34,52 +41,131 @@ class RelatedDNSRecords(PluginTemplateExtension):
34
41
  pointer_record_table = RelatedRecordTable(
35
42
  data=pointer_records,
36
43
  )
44
+ pointer_record_table.configure(request)
37
45
  else:
38
46
  pointer_record_table = None
39
47
 
40
48
  return self.render(
41
49
  "netbox_dns/record/related.html",
42
50
  extra_context={
43
- "related_address_records": address_record_table,
44
- "related_pointer_records": pointer_record_table,
51
+ "address_card_title": (
52
+ _("Synchronized Address Records")
53
+ if len(address_records) > 1
54
+ else _("Synchronized Address Record")
55
+ ),
56
+ "address_record_table": address_record_table,
57
+ "pointer_card_title": (
58
+ _("Synchronized Pointer Records")
59
+ if len(pointer_records) > 1
60
+ else _("Synchronized Pointer Record")
61
+ ),
62
+ "pointer_record_table": pointer_record_table,
45
63
  },
46
64
  )
47
65
 
48
66
 
49
- class RelatedDNSObjects(PluginTemplateExtension):
50
- model = "tenancy.tenant"
67
+ class RelatedDNSViews(PluginTemplateExtension):
68
+ models = ("ipam.prefix",)
51
69
 
52
- def left_page(self):
53
- obj = self.context.get("object")
70
+ def right_page(self):
71
+ prefix = self.context.get("object")
54
72
  request = self.context.get("request")
55
73
 
56
- related_dns_models = (
57
- (
58
- View.objects.restrict(request.user, "view").filter(tenant=obj),
59
- "tenant_id",
60
- ),
61
- (
62
- NameServer.objects.restrict(request.user, "view").filter(tenant=obj),
63
- "tenant_id",
64
- ),
65
- (
66
- Zone.objects.restrict(request.user, "view").filter(tenant=obj),
67
- "tenant_id",
68
- ),
69
- (
70
- Record.objects.restrict(request.user, "view").filter(tenant=obj),
71
- "tenant_id",
72
- ),
74
+ if assigned_views := prefix.netbox_dns_views.all():
75
+ assigned_views_table = RelatedViewTable(data=assigned_views)
76
+ assigned_views_table.configure(request)
77
+ context = {"assigned_views": assigned_views_table}
78
+ elif inherited_views := get_views_by_prefix(prefix):
79
+ inherited_views_table = RelatedViewTable(data=inherited_views)
80
+ inherited_views_table.configure(request)
81
+ context = {"inherited_views": inherited_views_table}
82
+ else:
83
+ context = {}
84
+
85
+ return self.render(
86
+ "netbox_dns/view/related.html",
87
+ extra_context=context,
88
+ )
89
+
90
+ def buttons(self):
91
+ return self.render(
92
+ "netbox_dns/view/button.html",
93
+ extra_context={
94
+ "url": reverse(
95
+ "ipam:prefix_views",
96
+ kwargs={"pk": self.context.get("object").pk},
97
+ ),
98
+ },
73
99
  )
74
100
 
101
+
102
+ class IPRelatedDNSRecords(PluginTemplateExtension):
103
+ models = ("ipam.ipaddress",)
104
+
105
+ def right_page(self):
106
+ ip_address = self.context.get("object")
107
+ request = self.context.get("request")
108
+
109
+ address_records = Record.objects.filter(
110
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
111
+ ip_address=ip_address.address.ip,
112
+ ).exclude(ipam_ip_address=ip_address)
113
+ pointer_records = Record.objects.filter(
114
+ type=RecordTypeChoices.PTR,
115
+ ip_address=ip_address.address.ip,
116
+ ).exclude(address_records__ipam_ip_address__in=[ip_address])
117
+
118
+ if address_records:
119
+ address_record_table = RelatedRecordTable(
120
+ data=address_records,
121
+ )
122
+ address_record_table.configure(request)
123
+ else:
124
+ address_record_table = None
125
+
126
+ if pointer_records:
127
+ pointer_record_table = RelatedRecordTable(
128
+ data=pointer_records,
129
+ )
130
+ pointer_record_table.configure(request)
131
+ else:
132
+ pointer_record_table = None
133
+
75
134
  return self.render(
76
- "netbox_dns/related_dns_objects.html",
135
+ "netbox_dns/record/related.html",
77
136
  extra_context={
78
- "related_dns_models": related_dns_models,
137
+ "address_card_title": (
138
+ _("Related Address Records")
139
+ if len(address_records) > 1
140
+ else _("Related Address Record")
141
+ ),
142
+ "address_record_table": address_record_table,
143
+ "pointer_card_title": (
144
+ _("Related Pointer Records")
145
+ if len(pointer_records) > 1
146
+ else _("Related Pointer Record")
147
+ ),
148
+ "pointer_record_table": pointer_record_table,
79
149
  },
80
150
  )
81
151
 
82
152
 
83
- template_extensions = [RelatedDNSObjects]
84
- if get_plugin_config("netbox_dns", "feature_ipam_coupling"):
85
- template_extensions.append(RelatedDNSRecords)
153
+ address_records = tables.ManyToManyColumn(
154
+ verbose_name=_("DNS Address Records"),
155
+ accessor="netbox_dns_records",
156
+ linkify_item=True,
157
+ transform=lambda obj: (
158
+ obj.fqdn.rstrip(".")
159
+ if obj.zone.view.default_view
160
+ else f"[{obj.zone.view.name}] {obj.fqdn.rstrip('.')}"
161
+ ),
162
+ )
163
+
164
+ if not settings.PLUGINS_CONFIG["netbox_dns"].get("dnssync_disabled"):
165
+ template_extensions = [RelatedDNSRecords, RelatedDNSViews]
166
+ register_table_column(address_records, "address_records", IPAddressTable)
167
+ else:
168
+ template_extensions = []
169
+
170
+ if get_plugin_config("netbox_dns", "feature_ipam_dns_info"):
171
+ template_extensions.append(IPRelatedDNSRecords)
@@ -0,0 +1,70 @@
1
+ {% extends 'generic/object.html' %}
2
+ {% load render_table from django_tables2 %}
3
+ {% load i18n %}
4
+
5
+ {% block content %}
6
+ <div class="row">
7
+ <div class="col col-md-6">
8
+ <div class="card">
9
+ <h5 class="card-header">{% trans "DNSSEC Key" %}</h5>
10
+ <table class="table table-hover attr-table">
11
+ <tr>
12
+ <th scope="row">{% trans "Name" %}</th>
13
+ <td>{{ object.name }}</td>
14
+ </tr>
15
+ {% if object.description %}
16
+ <tr>
17
+ <th scope="row">{% trans "Description" %}</th>
18
+ <td style="word-break:break-all;">{{ object.description }}</td>
19
+ </tr>
20
+ {% endif %}
21
+ <tr>
22
+ <th scope="row">{% trans "Type" %}</th>
23
+ <td>{% badge object.get_type_display bg_color=object.get_type_color %}</td>
24
+ </tr>
25
+ <tr>
26
+ <th scope="row">{% trans "Lifetime" %}</th>
27
+ <td>{{ object.lifetime|placeholder }}</td>
28
+ </tr>
29
+ <tr>
30
+ <th scope="row">{% trans "Algorithm" %}</th>
31
+ <td>{% badge object.get_algorithm_display %}</td>
32
+ </tr>
33
+ <tr>
34
+ <th scope="row">{% trans "Key Size" %}</th>
35
+ <td>{% badge object.get_key_size_display %}</td>
36
+ </tr>
37
+ {% if object.tenant %}
38
+ <tr>
39
+ <th scope="row">{% trans "Tenant" %}</th>
40
+ <td>
41
+ {% if object.tenant.group %}
42
+ {{ object.tenant.group|linkify }} /
43
+ {% endif %}
44
+ {{ object.tenant|linkify|placeholder }}
45
+ </td>
46
+ </tr>
47
+ {% endif %}
48
+ </table>
49
+ </div>
50
+ {% include 'inc/panels/custom_fields.html' %}
51
+ </div>
52
+ <div class="col col-md-6">
53
+ {% include 'inc/panels/tags.html' %}
54
+ </div>
55
+ </div>
56
+ {% if policy_table %}
57
+ <div class="col col-md-12">
58
+ <div class="card">
59
+ {% if policy_table.rows|length == 1 %}
60
+ <h2 class="card-header">{% trans "Policy" %}</h2>
61
+ {% else %}
62
+ <h2 class="card-header">{% trans "Policies" %}</h2>
63
+ {% endif %}
64
+ <div class="table-responsive">
65
+ {% render_table policy_table 'inc/table.html' %}
66
+ </div>
67
+ </div>
68
+ </div>
69
+ {% endif %}
70
+ {% endblock %}
@@ -0,0 +1,163 @@
1
+ {% extends 'generic/object.html' %}
2
+ {% load i18n %}
3
+
4
+ {% block content %}
5
+ <div class="row">
6
+ <div class="col col-md-6">
7
+ <div class="card">
8
+ <h5 class="card-header">{% trans "DNSSEC Policy" %}</h5>
9
+ <table class="table table-hover attr-table">
10
+ {% if object.description %}
11
+ <tr>
12
+ <th scope="row">{% trans "Description" %}</th>
13
+ <td style="word-break:break-all;">{{ object.description }}</td>
14
+ </tr>
15
+ {% endif %}
16
+ <tr>
17
+ <th scope="row">{% trans "Status" %}</th>
18
+ <td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
19
+ </tr>
20
+ <tr>
21
+ <th scope="row">{% trans "Use Inline Signing" %}</th>
22
+ <td>{% checkmark object.inline_signing %}</td>
23
+ </tr>
24
+ <tr>
25
+ <th scope="row">{% trans "Key Templates" %}</th>
26
+ <td>
27
+ <table>
28
+ {% for key_template in object.key_templates.all %}
29
+ <tr><td>{{ key_template|linkify }}</td></tr>
30
+ {% for template_id, errors in key_template_errors.items %}
31
+ {% if template_id == key_template.pk %}
32
+ {% for error in errors %}
33
+ <tr><td class="text-danger">{{ error }}</td></tr>
34
+ {% endfor %}
35
+ {% endif %}
36
+ {% endfor %}
37
+ {% endfor %}
38
+ </table>
39
+ </td>
40
+ </tr>
41
+ {% if policy_warning %}
42
+ <tr><td class="text-danger">{{ policy_warning }}</td></tr>
43
+ {% endif %}
44
+ {% if object.tenant %}
45
+ <tr>
46
+ <th scope="row">{% trans "Tenant" %}</th>
47
+ <td>
48
+ {% if object.tenant.group %}
49
+ {{ object.tenant.group|linkify }} /
50
+ {% endif %}
51
+ {{ object.tenant|linkify|placeholder }}
52
+ </td>
53
+ </tr>
54
+ {% endif %}
55
+ </table>
56
+ </div>
57
+ <div class="card">
58
+ <h5 class="card-header">{% trans "Timing" %}</h5>
59
+ <table class="table table-hover attr-table">
60
+ <tr>
61
+ <th scope="row">{% trans "DNSKEY TTL" %}</th>
62
+ <td>{{ object.dnskey_ttl|placeholder }}</td>
63
+ </tr>
64
+ <tr>
65
+ <th scope="row">{% trans "Publish Safety" %}</th>
66
+ <td>{{ object.publish_safety|placeholder }}</td>
67
+ </tr>
68
+ <tr>
69
+ <th scope="row">{% trans "Purge Keys" %}</th>
70
+ <td>{{ object.purge_keys|placeholder }}</td>
71
+ </tr>
72
+ <tr>
73
+ <th scope="row">{% trans "Retire Safety" %}</th>
74
+ <td>{{ object.retire_safety|placeholder }}</td>
75
+ </tr>
76
+ <tr>
77
+ <th scope="row">{% trans "Signatures Jitter" %}</th>
78
+ <td>{{ object.signatures_jitter|placeholder }}</td>
79
+ </tr>
80
+ <tr>
81
+ <th scope="row">{% trans "Signatures Refresh" %}</th>
82
+ <td>{{ object.signatures_refresh|placeholder }}</td>
83
+ </tr>
84
+ <tr>
85
+ <th scope="row">{% trans "Signatures Validity" %}</th>
86
+ <td>{{ object.signatures_validity|placeholder }}</td>
87
+ </tr>
88
+ <tr>
89
+ <th scope="row">{% trans "Signatures Validity (DNSKEY)" %}</th>
90
+ <td>{{ object.signatures_validity_dnskey|placeholder }}</td>
91
+ </tr>
92
+ <tr>
93
+ <th scope="row">{% trans "Max Zone TTL" %}</th>
94
+ <td>{{ object.max_zone_ttl|placeholder }}</td>
95
+ </tr>
96
+ <tr>
97
+ <th scope="row">{% trans "Zone Propagation Delay" %}</th>
98
+ <td>{{ object.zone_propagation_delay|placeholder }}</td>
99
+ </tr>
100
+ </table>
101
+ </div>
102
+ {% include 'inc/panels/custom_fields.html' %}
103
+ </div>
104
+ <div class="col col-md-6">
105
+ {% include 'inc/panels/tags.html' %}
106
+ <div class="card">
107
+ <h5 class="card-header">{% trans "Parent Delegation" %}</h5>
108
+ <table class="table table-hover attr-table">
109
+ <tr>
110
+ <th scope="row">{% trans "Create CDNSKEY" %}</th>
111
+ <td>{% checkmark object.create_cdnskey %}</td>
112
+ </tr>
113
+ <tr>
114
+ <th scope="row">{% trans "CDS Digest Types" %}</th>
115
+ <td>{% if object.cds_digest_types %}{% for digest_type in object.cds_digest_types %}{% badge digest_type %}{% endfor %}{% else %}{{ object_cds_digest_types|placeholder }}{% endif %}</td>
116
+ </tr>
117
+ <tr>
118
+ <th scope="row">{% trans "Parent DS TTL" %}</th>
119
+ <td>{{ object.parent_ds_ttl|placeholder }}</td>
120
+ </tr>
121
+ <tr>
122
+ <th scope="row">{% trans "Parent Propagation Delay" %}</th>
123
+ <td>{{ object.parent_propagation_delay|placeholder }}</td>
124
+ </tr>
125
+ </table>
126
+ </div>
127
+ <div class="card">
128
+ <h5 class="card-header">{% trans "Proof of Non-Existence" %}</h5>
129
+ <table class="table table-hover attr-table">
130
+ <tr>
131
+ <th scope="row">{% trans "Use NSEC3" %}</th>
132
+ <td>{% checkmark object.use_nsec3 %}</td>
133
+ </tr>
134
+ {% if object.use_nsec3 %}
135
+ <tr>
136
+ <th scope="row">{% trans "NSEC3 Iterations" %}</th>
137
+ <td>{{ object.nsec3_iterations|placeholder }}</td>
138
+ </tr>
139
+ <tr>
140
+ <th scope="row">{% trans "NSEC3 Opt Out" %}</th>
141
+ {% if object.nsec3_opt_out is None %}
142
+ <td>{{ ''|placeholder }}</td>
143
+ {% else %}
144
+ <td>{% checkmark object.nsec3_opt_out %}</td>
145
+ {% endif %}
146
+ </tr>
147
+ <tr>
148
+ <th scope="row">{% trans "NSEC3 Salt Size" %}</th>
149
+ <td>{{ object.nsec3_salt_size|placeholder }}</td>
150
+ </tr>
151
+ {% if object.nsec3_iterations or object.nsec3_opt_out or object.nsec3_salt_size %}
152
+ <tr>
153
+ <th class="text-warning">
154
+ {% blocktrans with link='<a href="https://datatracker.ietf.org/doc/html/rfc9276.html#section-3.1">RFC 9276, Section 3.1</a>' %}Using NSEC3 options is not recommended (see {{ link }}){% endblocktrans %}
155
+ </th>
156
+ </tr>
157
+ {% endif %}
158
+ {% endif %}
159
+ </table>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ {% endblock %}
@@ -1,37 +1,40 @@
1
1
  {% extends 'generic/object.html' %}
2
+ {% load i18n %}
2
3
 
3
4
  {% block content %}
4
5
  <div class="row">
5
6
  <div class="col col-md-6">
6
7
  <div class="card">
7
- <h5 class="card-header">Name Server</h5>
8
- <div class="card-body">
9
- <table class="table table-hover attr-table">
10
- <tr>
11
- <th scope="row">Name</th>
12
- <td>{{ object.name }}</td>
13
- </tr>
14
- {% if unicode_name %}
15
- <tr>
16
- <th scope="row">IDN</th>
17
- <td>{{ unicode_name }}</td>
18
- </tr>
19
- {% endif %}
20
- <tr>
21
- <th scope="row">Tenant</th>
22
- <td>
23
- {% if object.tenant.group %}
24
- {{ object.tenant.group|linkify }} /
25
- {% endif %}
26
- {{ object.tenant|linkify|placeholder }}
27
- </td>
28
- </tr>
29
- <tr>
30
- <th scope="row">Description</th>
31
- <td>{{ object.description }}</td>
32
- </tr>
33
- </table>
34
- </div>
8
+ <h5 class="card-header">{% trans "Nameserver" %}</h5>
9
+ <table class="table table-hover attr-table">
10
+ <tr>
11
+ <th scope="row">{% trans "Name" %}</th>
12
+ <td>{{ object.name }}</td>
13
+ </tr>
14
+ {% if unicode_name %}
15
+ <tr>
16
+ <th scope="row">{% trans "IDN" %}</th>
17
+ <td>{{ unicode_name }}</td>
18
+ </tr>
19
+ {% endif %}
20
+ {% if object.description %}
21
+ <tr>
22
+ <th scope="row">{% trans "Description" %}</th>
23
+ <td style="word-break:break-all;">{{ object.description }}</td>
24
+ </tr>
25
+ {% endif %}
26
+ {% if object.tenant %}
27
+ <tr>
28
+ <th scope="row">{% trans "Tenant" %}</th>
29
+ <td>
30
+ {% if object.tenant.group %}
31
+ {{ object.tenant.group|linkify }} /
32
+ {% endif %}
33
+ {{ object.tenant|linkify|placeholder }}
34
+ </td>
35
+ </tr>
36
+ {% endif %}
37
+ </table>
35
38
  </div>
36
39
  {% include 'inc/panels/custom_fields.html' %}
37
40
  </div>
@@ -1,3 +1,4 @@
1
1
  {% extends 'generic/object_list.html' %}
2
+ {% load i18n %}
2
3
 
3
- {% block title %}Managed Records{% endblock %}
4
+ {% block title %}{% trans "Managed Records" %}{% endblock %}
@@ -1,10 +1,21 @@
1
+ {% load render_table from django_tables2 %}
1
2
  {% load perms %}
2
3
 
3
4
  {% if perms.netbox_dns.view_record %}
4
- {% if related_address_records %}
5
- {% include 'inc/panel_table.html' with table=related_address_records heading='Related DNS Address Record' %}
6
- {% endif %}
7
- {% if related_pointer_records %}
8
- {% include 'inc/panel_table.html' with table=related_pointer_records heading='Related DNS Pointer Record' %}
9
- {% endif %}
5
+ {% if address_record_table %}
6
+ <div class="card">
7
+ <h2 class="card-header">{{ address_card_title }}</h2>
8
+ <div class="table-responsive">
9
+ {% render_table address_record_table 'inc/table.html' %}
10
+ </div>
11
+ </div>
12
+ {% endif %}
13
+ {% if pointer_record_table %}
14
+ <div class="card">
15
+ <h2 class="card-header">{{ pointer_card_title }}</h2>
16
+ <div class="table-responsive">
17
+ {% render_table pointer_record_table 'inc/table.html' %}
18
+ </div>
19
+ </div>
20
+ {% endif %}
10
21
  {% endif %}