mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-09 00:58:16 -06:00
Only accept networks for IPNetworkVar
This commit is contained in:
parent
7a83c0f79d
commit
6c905d4f00
@ -160,11 +160,14 @@ An uploaded file. Note that uploaded files are present in memory only for the du
|
|||||||
|
|
||||||
### IPAddressVar
|
### IPAddressVar
|
||||||
|
|
||||||
An IPv4 or IPv6 address (CIDR mask not allowed).
|
An IPv4 or IPv6 address. Returns an instance of `netaddr.IPNetwork`. Options include:
|
||||||
|
|
||||||
|
* `min_prefix_length` - Minimum length of the mask (default: none)
|
||||||
|
* `max_prefix_length` - Maximum length of the mask (default: none)
|
||||||
|
|
||||||
### IPNetworkVar
|
### IPNetworkVar
|
||||||
|
|
||||||
An IPv4 or IPv6 network with a mask. Options include:
|
Similar to `IPAddressVar` but will only accept networks (i.e. host-bits cannot be set). Options include:
|
||||||
|
|
||||||
* `min_prefix_length` - Minimum length of the mask (default: none)
|
* `min_prefix_length` - Minimum length of the mask (default: none)
|
||||||
* `max_prefix_length` - Maximum length of the mask (default: none)
|
* `max_prefix_length` - Maximum length of the mask (default: none)
|
||||||
|
@ -14,7 +14,8 @@ from django.db import transaction
|
|||||||
from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField
|
from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField
|
||||||
from mptt.models import MPTTModel
|
from mptt.models import MPTTModel
|
||||||
|
|
||||||
from ipam.formfields import IPAddressFormField, IPNetworkFormField
|
from ipam.fields import prefix_validator
|
||||||
|
from ipam.formfields import IPFormField
|
||||||
from utilities.exceptions import AbortTransaction
|
from utilities.exceptions import AbortTransaction
|
||||||
from utilities.validators import MaxPrefixLengthValidator, MinPrefixLengthValidator
|
from utilities.validators import MaxPrefixLengthValidator, MinPrefixLengthValidator
|
||||||
from .constants import LOG_DEFAULT, LOG_FAILURE, LOG_INFO, LOG_SUCCESS, LOG_WARNING
|
from .constants import LOG_DEFAULT, LOG_FAILURE, LOG_INFO, LOG_SUCCESS, LOG_WARNING
|
||||||
@ -201,14 +202,7 @@ class IPAddressVar(ScriptVariable):
|
|||||||
"""
|
"""
|
||||||
An IPv4 or IPv6 address.
|
An IPv4 or IPv6 address.
|
||||||
"""
|
"""
|
||||||
form_field = IPAddressFormField
|
form_field = IPFormField
|
||||||
|
|
||||||
|
|
||||||
class IPNetworkVar(ScriptVariable):
|
|
||||||
"""
|
|
||||||
An IPv4 or IPv6 prefix.
|
|
||||||
"""
|
|
||||||
form_field = IPNetworkFormField
|
|
||||||
|
|
||||||
def __init__(self, min_prefix_length=None, max_prefix_length=None, *args, **kwargs):
|
def __init__(self, min_prefix_length=None, max_prefix_length=None, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@ -226,6 +220,19 @@ class IPNetworkVar(ScriptVariable):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class IPNetworkVar(IPAddressVar):
|
||||||
|
"""
|
||||||
|
An IPv4 or IPv6 prefix.
|
||||||
|
"""
|
||||||
|
form_field = IPFormField
|
||||||
|
|
||||||
|
def __init__(self, min_prefix_length=None, max_prefix_length=None, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Reject prefixes with any host-bits set
|
||||||
|
self.field_attrs['validators'].append(prefix_validator)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Scripts
|
# Scripts
|
||||||
#
|
#
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from netaddr import IPAddress, IPNetwork
|
from netaddr import IPNetwork
|
||||||
|
|
||||||
from dcim.models import DeviceRole
|
from dcim.models import DeviceRole
|
||||||
from extras.scripts import *
|
from extras.scripts import *
|
||||||
@ -198,17 +198,11 @@ class ScriptVariablesTest(TestCase):
|
|||||||
self.assertFalse(form.is_valid())
|
self.assertFalse(form.is_valid())
|
||||||
self.assertIn('var1', form.errors)
|
self.assertIn('var1', form.errors)
|
||||||
|
|
||||||
# Subnet masks are not accepted
|
|
||||||
data = {'var1': '192.0.2.0/24'}
|
|
||||||
form = TestScript().as_form(data, None)
|
|
||||||
self.assertFalse(form.is_valid())
|
|
||||||
self.assertIn('var1', form.errors)
|
|
||||||
|
|
||||||
# Validate valid data
|
# Validate valid data
|
||||||
data = {'var1': '192.0.2.0'}
|
data = {'var1': '192.0.2.1/24'}
|
||||||
form = TestScript().as_form(data, None)
|
form = TestScript().as_form(data, None)
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
self.assertEqual(form.cleaned_data['var1'], IPAddress(data['var1']))
|
self.assertEqual(form.cleaned_data['var1'], IPNetwork(data['var1']))
|
||||||
|
|
||||||
def test_ipnetworkvar(self):
|
def test_ipnetworkvar(self):
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ from django.db import models
|
|||||||
from netaddr import AddrFormatError, IPNetwork, IPAddress
|
from netaddr import AddrFormatError, IPNetwork, IPAddress
|
||||||
|
|
||||||
from . import lookups
|
from . import lookups
|
||||||
from .formfields import IPNetworkFormField
|
from .formfields import IPFormField
|
||||||
|
|
||||||
|
|
||||||
def prefix_validator(prefix):
|
def prefix_validator(prefix):
|
||||||
@ -40,7 +40,7 @@ class BaseIPField(models.Field):
|
|||||||
return str(self.to_python(value))
|
return str(self.to_python(value))
|
||||||
|
|
||||||
def form_class(self):
|
def form_class(self):
|
||||||
return IPNetworkFormField
|
return IPFormField
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': self.form_class()}
|
defaults = {'form_class': self.form_class()}
|
||||||
|
@ -7,29 +7,7 @@ from netaddr import IPAddress, IPNetwork, AddrFormatError
|
|||||||
# Form fields
|
# Form fields
|
||||||
#
|
#
|
||||||
|
|
||||||
class IPAddressFormField(forms.Field):
|
class IPFormField(forms.Field):
|
||||||
default_error_messages = {
|
|
||||||
'invalid': "Enter a valid IPv4 or IPv6 address (without CIDR mask).",
|
|
||||||
}
|
|
||||||
|
|
||||||
def to_python(self, value):
|
|
||||||
if not value:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if isinstance(value, IPAddress):
|
|
||||||
return value
|
|
||||||
|
|
||||||
# Prevent CIDR masks; an IPAddress doesn't have one
|
|
||||||
if len(value.split('/')) != 1:
|
|
||||||
raise ValidationError('CIDR mask (e.g. /24) is not allowed.')
|
|
||||||
|
|
||||||
try:
|
|
||||||
return IPAddress(value)
|
|
||||||
except AddrFormatError:
|
|
||||||
raise ValidationError("Please specify a valid IPv4 or IPv6 address.")
|
|
||||||
|
|
||||||
|
|
||||||
class IPNetworkFormField(forms.Field):
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': "Enter a valid IPv4 or IPv6 address (with CIDR mask).",
|
'invalid': "Enter a valid IPv4 or IPv6 address (with CIDR mask).",
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user