validators.py 2.1 KB

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