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,119 @@
1
+ from django.utils.translation import gettext_lazy as _
2
+
3
+ from utilities.choices import ChoiceSet
4
+
5
+
6
+ __all__ = (
7
+ "ZoneStatusChoices",
8
+ "ZoneEPPStatusChoices",
9
+ )
10
+
11
+
12
+ class ZoneStatusChoices(ChoiceSet):
13
+ key = "Zone.status"
14
+
15
+ STATUS_ACTIVE = "active"
16
+ STATUS_RESERVED = "reserved"
17
+ STATUS_DEPRECATED = "deprecated"
18
+ STATUS_PARKED = "parked"
19
+ STATUS_DYNAMIC = "dynamic"
20
+
21
+ CHOICES = [
22
+ (STATUS_ACTIVE, _("Active"), "blue"),
23
+ (STATUS_RESERVED, _("Reserved"), "cyan"),
24
+ (STATUS_DEPRECATED, _("Deprecated"), "red"),
25
+ (STATUS_PARKED, _("Parked"), "gray"),
26
+ (STATUS_DYNAMIC, _("Dynamic"), "orange"),
27
+ ]
28
+
29
+
30
+ class ZoneEPPStatusChoices(ChoiceSet):
31
+ """
32
+ Reflects the EPP status of a zone registered as a domain. See
33
+ https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en
34
+ for details.
35
+ """
36
+
37
+ key = "Zone.epp_status"
38
+
39
+ EPP_STATUS_ADD_PERIOD = "addPeriod"
40
+ EPP_STATUS_AUTO_RENEW_PERIOD = "autoRenewPeriod"
41
+ EPP_STATUS_INACTIVE = "inactive"
42
+ EPP_STATUS_OK = "ok"
43
+ EPP_STATUS_PENDING_CREATE = "pendingCreate"
44
+ EPP_STATUS_PENDING_DELETE = "pendingDelete"
45
+ EPP_STATUS_PENDING_RENEW = "pendingRenew"
46
+ EPP_STATUS_PENDING_RESTORE = "pendingRestore"
47
+ EPP_STATUS_PENDING_TRANSFER = "pendingTransfer"
48
+ EPP_STATUS_PENDING_UPDATE = "pendingUpdate"
49
+ EPP_STATUS_REDEMPTION_PERIOD = "redemptionPeriod"
50
+ EPP_STATUS_RENEW_PERIOD = "renewPeriod"
51
+ EPP_STATUS_SERVER_DELETE_PROHIBITED = "serverDeleteProhibited"
52
+ EPP_STATUS_SERVER_HOLD = "serverHold"
53
+ EPP_STATUS_SERVER_RENER_PROHIBITED = "serverRenewProhibited"
54
+ EPP_STATUS_SERVER_TRANSFER_PROHIBITED = "serverTransferProhibited"
55
+ EPP_STATUS_SERVER_UPDATE_PROHIBITED = "serverUpdateProhibited"
56
+ EPP_STATUS_TRANSFER_PERIOD = "transferPeriod"
57
+ EPP_STATUS_CLIENT_DELETE_PROHIBITED = "clientDeleteProhibited"
58
+ EPP_STATUS_CLIENT_HOLD = "clientHold"
59
+ EPP_STATUS_CLIENT_RENEW_PROHIBITED = "clientRenewProhibited"
60
+ EPP_STATUS_CLIENT_TRANSFER_PROHIBITED = "clientTransferProhibited"
61
+ EPP_STATUS_CLIENT_UPDATE_PROHIBITED = "clientUpdateProhibited"
62
+
63
+ CHOICES = [
64
+ (EPP_STATUS_ADD_PERIOD, EPP_STATUS_ADD_PERIOD, "blue"),
65
+ (EPP_STATUS_AUTO_RENEW_PERIOD, EPP_STATUS_AUTO_RENEW_PERIOD, "blue"),
66
+ (EPP_STATUS_INACTIVE, EPP_STATUS_INACTIVE, "blue"),
67
+ (EPP_STATUS_OK, EPP_STATUS_OK, "blue"),
68
+ (EPP_STATUS_PENDING_CREATE, EPP_STATUS_PENDING_CREATE, "blue"),
69
+ (EPP_STATUS_PENDING_DELETE, EPP_STATUS_PENDING_DELETE, "blue"),
70
+ (EPP_STATUS_PENDING_RENEW, EPP_STATUS_PENDING_RENEW, "blue"),
71
+ (EPP_STATUS_PENDING_RESTORE, EPP_STATUS_PENDING_RESTORE, "blue"),
72
+ (EPP_STATUS_PENDING_TRANSFER, EPP_STATUS_PENDING_TRANSFER, "blue"),
73
+ (EPP_STATUS_PENDING_UPDATE, EPP_STATUS_PENDING_UPDATE, "blue"),
74
+ (EPP_STATUS_REDEMPTION_PERIOD, EPP_STATUS_REDEMPTION_PERIOD, "blue"),
75
+ (EPP_STATUS_RENEW_PERIOD, EPP_STATUS_RENEW_PERIOD, "blue"),
76
+ (
77
+ EPP_STATUS_SERVER_DELETE_PROHIBITED,
78
+ EPP_STATUS_SERVER_DELETE_PROHIBITED,
79
+ "blue",
80
+ ),
81
+ (EPP_STATUS_SERVER_HOLD, EPP_STATUS_SERVER_HOLD, "blue"),
82
+ (
83
+ EPP_STATUS_SERVER_RENER_PROHIBITED,
84
+ EPP_STATUS_SERVER_RENER_PROHIBITED,
85
+ "blue",
86
+ ),
87
+ (
88
+ EPP_STATUS_SERVER_TRANSFER_PROHIBITED,
89
+ EPP_STATUS_SERVER_TRANSFER_PROHIBITED,
90
+ "blue",
91
+ ),
92
+ (
93
+ EPP_STATUS_SERVER_UPDATE_PROHIBITED,
94
+ EPP_STATUS_SERVER_UPDATE_PROHIBITED,
95
+ "blue",
96
+ ),
97
+ (EPP_STATUS_TRANSFER_PERIOD, EPP_STATUS_TRANSFER_PERIOD, "blue"),
98
+ (
99
+ EPP_STATUS_CLIENT_DELETE_PROHIBITED,
100
+ EPP_STATUS_CLIENT_DELETE_PROHIBITED,
101
+ "cyan",
102
+ ),
103
+ (EPP_STATUS_CLIENT_HOLD, EPP_STATUS_CLIENT_HOLD, "cyan"),
104
+ (
105
+ EPP_STATUS_CLIENT_RENEW_PROHIBITED,
106
+ EPP_STATUS_CLIENT_RENEW_PROHIBITED,
107
+ "cyan",
108
+ ),
109
+ (
110
+ EPP_STATUS_CLIENT_TRANSFER_PROHIBITED,
111
+ EPP_STATUS_CLIENT_TRANSFER_PROHIBITED,
112
+ "cyan",
113
+ ),
114
+ (
115
+ EPP_STATUS_CLIENT_UPDATE_PROHIBITED,
116
+ EPP_STATUS_CLIENT_UPDATE_PROHIBITED,
117
+ "cyan",
118
+ ),
119
+ ]
@@ -1,2 +1,6 @@
1
1
  from .network import *
2
2
  from .address import *
3
+ from .rfc2317 import *
4
+ from .ipam import *
5
+ from .choice_array import *
6
+ from .timeperiod import *
@@ -1,28 +1,18 @@
1
- from django import forms
2
1
  from django.db import models
2
+ from django.db.models import Lookup
3
3
  from django.core.exceptions import ValidationError
4
+ from django.utils.translation import gettext_lazy as _
4
5
 
5
6
  from netaddr import AddrFormatError, IPAddress
6
7
 
8
+ from ipam.formfields import IPAddressFormField
7
9
 
8
- class AddressFormField(forms.Field):
9
- def to_python(self, value):
10
- if not value:
11
- return None
12
-
13
- if isinstance(value, IPAddress):
14
- return value
15
-
16
- try:
17
- ip_address = IPAddress(value)
18
- except AddrFormatError as exc:
19
- raise ValidationError(exc)
20
10
 
21
- return ip_address
11
+ __all__ = ("AddressField",)
22
12
 
23
13
 
24
14
  class AddressField(models.Field):
25
- description = "IPv4/v6 address"
15
+ description = _("IPv4/v6 address")
26
16
 
27
17
  def python_type(self):
28
18
  return IPAddress
@@ -51,7 +41,7 @@ class AddressField(models.Field):
51
41
  return str(self.to_python(value))
52
42
 
53
43
  def form_class(self):
54
- return AddressFormField
44
+ return IPAddressFormField
55
45
 
56
46
  def formfield(self, **kwargs):
57
47
  defaults = {"form_class": self.form_class()}
@@ -61,3 +51,19 @@ class AddressField(models.Field):
61
51
 
62
52
  def db_type(self, connection):
63
53
  return "inet"
54
+
55
+
56
+ class AddressContained(Lookup):
57
+ lookup_name = "contained"
58
+
59
+ def get_prep_lookup(self):
60
+ return str(self.rhs)
61
+
62
+ def as_sql(self, compiler, connection):
63
+ lhs, lhs_params = self.process_lhs(compiler, connection)
64
+ rhs, rhs_params = self.process_rhs(compiler, connection)
65
+ params = lhs_params + rhs_params
66
+ return f"CAST(HOST({lhs}) AS INET) <<= {rhs}", params
67
+
68
+
69
+ AddressField.register_lookup(AddressContained)
@@ -0,0 +1,33 @@
1
+ from django import forms
2
+ from django.contrib.postgres.fields import ArrayField
3
+ from django.db.models import Transform, IntegerField
4
+
5
+
6
+ class ArrayLength(Transform):
7
+ lookup_name = "length"
8
+ function = "cardinality"
9
+
10
+ @property
11
+ def output_field(self):
12
+ return IntegerField()
13
+
14
+
15
+ class _TypedMultipleChoiceField(forms.TypedMultipleChoiceField):
16
+ def __init__(self, *args, **kwargs):
17
+ kwargs.pop("base_field", None)
18
+ kwargs.pop("max_length", None)
19
+
20
+ super().__init__(*args, **kwargs)
21
+
22
+
23
+ class ChoiceArrayField(ArrayField):
24
+ def formfield(self, **kwargs):
25
+ return super().formfield(
26
+ form_class=_TypedMultipleChoiceField,
27
+ choices=self.base_field.choices,
28
+ coerce=self.base_field.to_python,
29
+ **kwargs,
30
+ )
31
+
32
+
33
+ ChoiceArrayField.register_lookup(ArrayLength)
@@ -0,0 +1,15 @@
1
+ from utilities.forms.fields import DynamicModelMultipleChoiceField
2
+ from utilities.forms.widgets import APISelectMultiple
3
+
4
+
5
+ __all__ = ("PrefixDynamicModelMultipleChoiceField",)
6
+
7
+
8
+ class PrefixDynamicModelMultipleChoiceField(DynamicModelMultipleChoiceField):
9
+ widget = APISelectMultiple(api_url="/api/plugins/netbox-dns/prefixes")
10
+
11
+ def label_from_instance(self, obj):
12
+ if obj.vrf:
13
+ return f"{str(obj.prefix)} [{obj.vrf.name}]"
14
+
15
+ return str(obj.prefix)
@@ -1,49 +1,63 @@
1
1
  from django import forms
2
2
  from django.db import models
3
- from django.db.models import Lookup
3
+ from django.db.models import Lookup, Transform, IntegerField
4
4
  from django.core.exceptions import ValidationError
5
+ from django.utils.translation import gettext_lazy as _
5
6
 
6
7
  from netaddr import AddrFormatError, IPNetwork
7
8
 
8
9
 
10
+ __all__ = ("NetworkField",)
11
+
12
+
9
13
  class NetContains(Lookup):
10
14
  lookup_name = "net_contains"
11
15
 
12
- def as_sql(self, qn, connection):
13
- lhs, lhs_params = self.process_lhs(qn, connection)
14
- rhs, rhs_params = self.process_rhs(qn, connection)
16
+ def as_sql(self, compiler, connection):
17
+ lhs, lhs_params = self.process_lhs(compiler, connection)
18
+ rhs, rhs_params = self.process_rhs(compiler, connection)
15
19
  params = lhs_params + rhs_params
16
- return "%s >> %s" % (lhs, rhs), params
20
+ return f"{lhs} >> {rhs}", params
17
21
 
18
22
 
19
23
  class NetContainsOrEquals(Lookup):
20
24
  lookup_name = "net_contains_or_equals"
21
25
 
22
- def as_sql(self, qn, connection):
23
- lhs, lhs_params = self.process_lhs(qn, connection)
24
- rhs, rhs_params = self.process_rhs(qn, connection)
26
+ def as_sql(self, compiler, connection):
27
+ lhs, lhs_params = self.process_lhs(compiler, connection)
28
+ rhs, rhs_params = self.process_rhs(compiler, connection)
25
29
  params = lhs_params + rhs_params
26
- return "%s >>= %s" % (lhs, rhs), params
30
+ return f"{lhs} >>= {rhs}", params
27
31
 
28
32
 
29
33
  class NetContained(Lookup):
30
34
  lookup_name = "net_contained"
31
35
 
32
- def as_sql(self, qn, connection):
33
- lhs, lhs_params = self.process_lhs(qn, connection)
34
- rhs, rhs_params = self.process_rhs(qn, connection)
36
+ def as_sql(self, compiler, connection):
37
+ lhs, lhs_params = self.process_lhs(compiler, connection)
38
+ rhs, rhs_params = self.process_rhs(compiler, connection)
35
39
  params = lhs_params + rhs_params
36
- return "%s << %s" % (lhs, rhs), params
40
+ return f"{lhs} << {rhs}", params
37
41
 
38
42
 
39
43
  class NetContainedOrEqual(Lookup):
40
44
  lookup_name = "net_contained_or_equal"
41
45
 
42
- def as_sql(self, qn, connection):
43
- lhs, lhs_params = self.process_lhs(qn, connection)
44
- rhs, rhs_params = self.process_rhs(qn, connection)
46
+ def as_sql(self, compiler, connection):
47
+ lhs, lhs_params = self.process_lhs(compiler, connection)
48
+ rhs, rhs_params = self.process_rhs(compiler, connection)
45
49
  params = lhs_params + rhs_params
46
- return "%s <<= %s" % (lhs, rhs), params
50
+ return f"{lhs} <<= {rhs}", params
51
+
52
+
53
+ class NetOverlap(Lookup):
54
+ lookup_name = "net_overlap"
55
+
56
+ def as_sql(self, compiler, connection):
57
+ lhs, lhs_params = self.process_lhs(compiler, connection)
58
+ rhs, rhs_params = self.process_rhs(compiler, connection)
59
+ params = lhs_params + rhs_params
60
+ return f"{lhs} && {rhs}", params
47
61
 
48
62
 
49
63
  class NetworkFormField(forms.Field):
@@ -63,7 +77,7 @@ class NetworkFormField(forms.Field):
63
77
 
64
78
 
65
79
  class NetworkField(models.Field):
66
- description = "IPv4/v6 network associated with a reverse lookup zone"
80
+ description = _("IPv4/v6 network associated with a reverse lookup zone")
67
81
 
68
82
  def python_type(self):
69
83
  return IPNetwork
@@ -104,7 +118,17 @@ class NetworkField(models.Field):
104
118
  return "cidr"
105
119
 
106
120
 
121
+ class NetMaskLength(Transform):
122
+ function = "MASKLEN"
123
+ lookup_name = "net_mask_length"
124
+
125
+ def output_field(self):
126
+ return IntegerField()
127
+
128
+
107
129
  NetworkField.register_lookup(NetContains)
108
130
  NetworkField.register_lookup(NetContained)
109
131
  NetworkField.register_lookup(NetContainsOrEquals)
110
132
  NetworkField.register_lookup(NetContainedOrEqual)
133
+ NetworkField.register_lookup(NetOverlap)
134
+ NetworkField.register_lookup(NetMaskLength)
@@ -0,0 +1,97 @@
1
+ from netaddr import IPNetwork, AddrFormatError
2
+
3
+ from django import forms
4
+ from django.db import models
5
+ from django.core.exceptions import ValidationError
6
+ from django.utils.translation import gettext_lazy as _
7
+
8
+ from netbox_dns.validators import validate_ipv4, validate_prefix, validate_rfc2317
9
+ from .network import NetContains, NetContained, NetOverlap, NetMaskLength
10
+
11
+ INVALID_RFC2317 = _(
12
+ "RFC2317 requires an IPv4 prefix with a length of at least 25 bits."
13
+ )
14
+
15
+
16
+ __all__ = (
17
+ "RFC2317NetworkField",
18
+ "RFC2317NetworkFormField",
19
+ )
20
+
21
+
22
+ class RFC2317NetworkFormField(forms.Field):
23
+ def to_python(self, value):
24
+ if not value:
25
+ return None
26
+
27
+ if isinstance(value, IPNetwork):
28
+ if value.version == 4 and value.prefixlen > 24:
29
+ return value
30
+
31
+ raise ValidationError(INVALID_RFC2317)
32
+
33
+ if len(value.split("/")) != 2:
34
+ raise ValidationError(_("Please specify the prefix length"))
35
+
36
+ try:
37
+ ip_network = IPNetwork(value)
38
+ except AddrFormatError as exc:
39
+ raise ValidationError(exc)
40
+
41
+ if ip_network.version != 4 or ip_network.prefixlen <= 24:
42
+ raise ValidationError(INVALID_RFC2317)
43
+
44
+ return ip_network
45
+
46
+
47
+ class RFC2317NetworkField(models.Field):
48
+ description = _("PostgreSQL CIDR field for an RFC2317 prefix")
49
+
50
+ default_validators = [validate_ipv4, validate_prefix, validate_rfc2317]
51
+
52
+ def python_type(self):
53
+ return IPNetwork
54
+
55
+ def from_db_value(self, value, expression, connection):
56
+ return self.to_python(value)
57
+
58
+ def to_python(self, value):
59
+ if not value:
60
+ return value
61
+
62
+ try:
63
+ ip_network = IPNetwork(value)
64
+ except (AddrFormatError, TypeError, ValueError) as exc:
65
+ raise ValidationError(exc)
66
+
67
+ if ip_network.version != 4:
68
+ raise ValidationError(INVALID_RFC2317)
69
+
70
+ return ip_network
71
+
72
+ def get_prep_value(self, value):
73
+ if not value:
74
+ return None
75
+
76
+ if isinstance(value, list):
77
+ return [str(self.to_python(v)) for v in value]
78
+
79
+ return str(self.to_python(value))
80
+
81
+ def form_class(self):
82
+ return RFC2317NetworkFormField
83
+
84
+ def formfield(self, **kwargs):
85
+ defaults = {"form_class": self.form_class()}
86
+ defaults.update(kwargs)
87
+
88
+ return super().formfield(**defaults)
89
+
90
+ def db_type(self, connection):
91
+ return "cidr"
92
+
93
+
94
+ RFC2317NetworkField.register_lookup(NetContains)
95
+ RFC2317NetworkField.register_lookup(NetContained)
96
+ RFC2317NetworkField.register_lookup(NetOverlap)
97
+ RFC2317NetworkField.register_lookup(NetMaskLength)
@@ -0,0 +1,33 @@
1
+ from django.forms import Field, TextInput
2
+ from django.core.exceptions import ValidationError
3
+
4
+ from netbox_dns.utilities import iso8601_to_int
5
+
6
+ __all__ = ("TimePeriodField",)
7
+
8
+
9
+ class TimePeriodField(Field):
10
+ def __init__(self, *args, **kwargs):
11
+ placeholder = kwargs.pop("placeholder", None)
12
+
13
+ if placeholder is not None:
14
+ self.widget = TextInput(attrs={"placeholder": placeholder})
15
+
16
+ return super().__init__(*args, **kwargs)
17
+
18
+ def to_python(self, value):
19
+ if not value:
20
+ return None
21
+
22
+ try:
23
+ return iso8601_to_int(value)
24
+ except TypeError:
25
+ raise ValidationError(
26
+ "Enter a valid integer or ISO 8601 duration (W, M and Y are not supported)"
27
+ )
28
+
29
+ def validate(self, value):
30
+ super().validate(value)
31
+
32
+ if value is not None and value < 0:
33
+ raise ValidationError("A time period cannot be negative.")
netbox_dns/filters.py ADDED
@@ -0,0 +1,7 @@
1
+ from django_filters import NumberFilter
2
+
3
+ from netbox_dns.fields import TimePeriodField
4
+
5
+
6
+ class TimePeriodFilter(NumberFilter):
7
+ field_class = TimePeriodField
@@ -0,0 +1,12 @@
1
+ from .view import *
2
+ from .zone import *
3
+ from .nameserver import *
4
+ from .record import *
5
+ from .registration_contact import *
6
+ from .registrar import *
7
+
8
+ from .zone_template import *
9
+ from .record_template import *
10
+
11
+ from .dnssec_key_template import *
12
+ from .dnssec_policy import *
@@ -0,0 +1,57 @@
1
+ import django_filters
2
+ from django.db.models import Q
3
+ from django.utils.translation import gettext as _
4
+
5
+ from netbox.filtersets import NetBoxModelFilterSet
6
+ from tenancy.filtersets import TenancyFilterSet
7
+
8
+ from netbox_dns.models import DNSSECKeyTemplate, DNSSECPolicy
9
+ from netbox_dns.choices import (
10
+ DNSSECKeyTemplateTypeChoices,
11
+ DNSSECKeyTemplateAlgorithmChoices,
12
+ DNSSECKeyTemplateKeySizeChoices,
13
+ )
14
+ from netbox_dns.filters import TimePeriodFilter
15
+
16
+
17
+ __all__ = ("DNSSECKeyTemplateFilterSet",)
18
+
19
+
20
+ class DNSSECKeyTemplateFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
21
+ class Meta:
22
+ model = DNSSECKeyTemplate
23
+
24
+ fields = (
25
+ "id",
26
+ "name",
27
+ "description",
28
+ )
29
+
30
+ type = django_filters.MultipleChoiceFilter(
31
+ choices=DNSSECKeyTemplateTypeChoices,
32
+ )
33
+ algorithm = django_filters.MultipleChoiceFilter(
34
+ choices=DNSSECKeyTemplateAlgorithmChoices,
35
+ )
36
+ key_size = django_filters.MultipleChoiceFilter(
37
+ choices=DNSSECKeyTemplateKeySizeChoices,
38
+ )
39
+ lifetime = TimePeriodFilter()
40
+ policy_id = django_filters.ModelMultipleChoiceFilter(
41
+ field_name="policies",
42
+ queryset=DNSSECPolicy.objects.all(),
43
+ to_field_name="id",
44
+ label=_("DNSSEC Policy IDs"),
45
+ )
46
+ policy = django_filters.ModelMultipleChoiceFilter(
47
+ field_name="policies__name",
48
+ queryset=DNSSECPolicy.objects.all(),
49
+ to_field_name="name",
50
+ label=_("DNSSEC Policies"),
51
+ )
52
+
53
+ def search(self, queryset, name, value):
54
+ if not value.strip():
55
+ return queryset
56
+ qs_filter = Q(Q(name__icontains=value) | Q(description__icontains=value))
57
+ return queryset.filter(qs_filter)
@@ -0,0 +1,101 @@
1
+ import django_filters
2
+
3
+ from django.db.models import Q
4
+ from django.utils.translation import gettext as _
5
+
6
+ from netbox.filtersets import NetBoxModelFilterSet
7
+ from tenancy.filtersets import TenancyFilterSet
8
+ from utilities.filters import MultiValueCharFilter
9
+
10
+ from netbox_dns.models import DNSSECPolicy, DNSSECKeyTemplate, Zone, ZoneTemplate
11
+ from netbox_dns.choices import DNSSECPolicyStatusChoices
12
+ from netbox_dns.filters import TimePeriodFilter
13
+
14
+
15
+ __all__ = ("DNSSECPolicyFilterSet",)
16
+
17
+
18
+ class DNSSECPolicyFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
19
+ class Meta:
20
+ model = DNSSECPolicy
21
+
22
+ fields = (
23
+ "id",
24
+ "name",
25
+ "description",
26
+ "status",
27
+ "inline_signing",
28
+ "create_cdnskey",
29
+ "use_nsec3",
30
+ "nsec3_iterations",
31
+ "nsec3_opt_out",
32
+ "nsec3_salt_size",
33
+ )
34
+
35
+ status = django_filters.MultipleChoiceFilter(
36
+ choices=DNSSECPolicyStatusChoices,
37
+ )
38
+ cds_digest_types = MultiValueCharFilter(
39
+ method="filter_cds_digest_types",
40
+ label=_("CDS Digest Types"),
41
+ )
42
+ key_template = django_filters.ModelMultipleChoiceFilter(
43
+ field_name="key_templates__name",
44
+ queryset=DNSSECKeyTemplate.objects.all(),
45
+ to_field_name="name",
46
+ label=_("DNSSEC Key Templates"),
47
+ )
48
+ key_template_id = django_filters.ModelMultipleChoiceFilter(
49
+ field_name="key_templates",
50
+ queryset=DNSSECKeyTemplate.objects.all(),
51
+ to_field_name="id",
52
+ label=_("DNSSEC Key Template IDs"),
53
+ )
54
+ dnskey_ttl = TimePeriodFilter()
55
+ purge_keys = TimePeriodFilter()
56
+ publish_safety = TimePeriodFilter()
57
+ retire_safety = TimePeriodFilter()
58
+ signatures_jitter = TimePeriodFilter()
59
+ signatures_refresh = TimePeriodFilter()
60
+ signatures_validity = TimePeriodFilter()
61
+ signatures_validity_dnskey = TimePeriodFilter()
62
+ max_zone_ttl = TimePeriodFilter()
63
+ zone_propagation_delay = TimePeriodFilter()
64
+ parent_ds_ttl = TimePeriodFilter()
65
+ parent_propagation_delay = TimePeriodFilter()
66
+ zone = django_filters.ModelMultipleChoiceFilter(
67
+ field_name="zones__name",
68
+ queryset=Zone.objects.all(),
69
+ to_field_name="name",
70
+ label=_("Zones"),
71
+ )
72
+ zone_id = django_filters.ModelMultipleChoiceFilter(
73
+ field_name="zones",
74
+ queryset=Zone.objects.all(),
75
+ to_field_name="id",
76
+ label=_("Zone IDs"),
77
+ )
78
+ zone_template = django_filters.ModelMultipleChoiceFilter(
79
+ field_name="zone_templates__name",
80
+ queryset=ZoneTemplate.objects.all(),
81
+ to_field_name="name",
82
+ label=_("Zone Templates"),
83
+ )
84
+ zone_template_id = django_filters.ModelMultipleChoiceFilter(
85
+ field_name="zone_templates",
86
+ queryset=ZoneTemplate.objects.all(),
87
+ to_field_name="id",
88
+ label=_("Zone Template IDs"),
89
+ )
90
+
91
+ def filter_cds_digest_types(self, queryset, name, value):
92
+ if not value:
93
+ return queryset
94
+
95
+ return queryset.filter(cds_digest_types__overlap=value)
96
+
97
+ def search(self, queryset, name, value):
98
+ if not value.strip():
99
+ return queryset
100
+ qs_filter = Q(Q(name__icontains=value) | Q(description__icontains=value))
101
+ return queryset.filter(qs_filter)