validators.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import re
  2. from django.core.exceptions import ValidationError
  3. from django.core.validators import _lazy_re_compile, BaseValidator, URLValidator
  4. from netbox.config import get_config
  5. class EnhancedURLValidator(URLValidator):
  6. """
  7. Extends Django's built-in URLValidator to permit the use of hostnames with no domain extension and enforce allowed
  8. schemes specified in the configuration.
  9. """
  10. fqdn_re = URLValidator.hostname_re + URLValidator.domain_re + URLValidator.tld_re
  11. host_res = [URLValidator.ipv4_re, URLValidator.ipv6_re, fqdn_re, URLValidator.hostname_re]
  12. regex = _lazy_re_compile(
  13. r'^(?:[a-z0-9\.\-\+]*)://' # Scheme (enforced separately)
  14. r'(?:\S+(?::\S*)?@)?' # HTTP basic authentication
  15. r'(?:' + '|'.join(host_res) + ')' # IPv4, IPv6, FQDN, or hostname
  16. r'(?::\d{2,5})?' # Port number
  17. r'(?:[/?#][^\s]*)?' # Path
  18. r'\Z', re.IGNORECASE)
  19. schemes = None
  20. def __call__(self, value):
  21. if self.schemes is None:
  22. # We can't load the allowed schemes until the configuration has been initialized
  23. self.schemes = get_config().ALLOWED_URL_SCHEMES
  24. return super().__call__(value)
  25. class ExclusionValidator(BaseValidator):
  26. """
  27. Ensure that a field's value is not equal to any of the specified values.
  28. """
  29. message = 'This value may not be %(show_value)s.'
  30. def compare(self, a, b):
  31. return a in b
  32. def validate_regex(value):
  33. """
  34. Checks that the value is a valid regular expression. (Don't confuse this with RegexValidator, which *uses* a regex
  35. to validate a value.)
  36. """
  37. try:
  38. re.compile(value)
  39. except re.error:
  40. raise ValidationError(f"{value} is not a valid regular expression.")