validators.py 2.0 KB

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