You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

validators.py 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. from django.core import validators
  2. from django.core.exceptions import ValidationError
  3. from django.core.urlresolvers import resolve
  4. from oscar.core.loading import get_model
  5. from django.http import Http404
  6. from django.utils.translation import ugettext_lazy as _
  7. class ExtendedURLValidator(validators.URLValidator):
  8. def __init__(self, *args, **kwargs):
  9. # 'verify_exists' has been removed in Django 1.5 and so we no longer
  10. # pass it up to the core validator class
  11. self.is_local_url = False
  12. verify_exists = kwargs.pop('verify_exists', False)
  13. super(ExtendedURLValidator, self).__init__(*args, **kwargs)
  14. self.verify_exists = verify_exists
  15. def __call__(self, value):
  16. try:
  17. super(ExtendedURLValidator, self).__call__(value)
  18. except ValidationError:
  19. # The parent validator will raise an exception if the URL does not
  20. # exist and so we test here to see if the value is a local URL.
  21. if value:
  22. self.validate_local_url(value)
  23. else:
  24. raise
  25. def validate_local_url(self, value):
  26. value = self.clean_url(value)
  27. try:
  28. resolve(value)
  29. except Http404:
  30. # We load flatpages here as it causes a circular reference problem
  31. # sometimes. FlatPages is None if not installed
  32. FlatPage = get_model('flatpages', 'FlatPage')
  33. if FlatPage is not None:
  34. try:
  35. FlatPage.objects.get(url=value)
  36. except FlatPage.DoesNotExist:
  37. self.is_local_url = True
  38. else:
  39. return
  40. raise ValidationError(_('The URL "%s" does not exist') % value)
  41. else:
  42. self.is_local_url = True
  43. def clean_url(self, value):
  44. """
  45. Ensure url has a preceding slash and no query string
  46. """
  47. if value != '/':
  48. value = '/' + value.lstrip('/')
  49. q_index = value.find('?')
  50. if q_index > 0:
  51. value = value[:q_index]
  52. return value
  53. class URLDoesNotExistValidator(ExtendedURLValidator):
  54. def __call__(self, value):
  55. """
  56. Validate that the URLdoes not already exist.
  57. The URL will be verified first and raises ``ValidationError`` when
  58. it is invalid. A valid URL is checked for existance and raises
  59. ``ValidationError`` if the URL already exists. Setting attribute
  60. ``verify_exists`` has no impact on validation.
  61. This validation uses two calls to ExtendedURLValidator which can
  62. be slow. Be aware of this, when you use it.
  63. Returns ``None`` if URL is valid and does not exist.
  64. """
  65. try:
  66. self.validate_local_url(value)
  67. except ValidationError:
  68. # Page exists - that is what we want
  69. return
  70. raise ValidationError(
  71. _('Specified page already exists!'), code='invalid')
  72. def non_whitespace(value):
  73. stripped = value.strip()
  74. if not stripped:
  75. raise ValidationError(
  76. _("This field is required"))
  77. return stripped
  78. class CommonPasswordValidator(validators.BaseValidator):
  79. # See
  80. # http://www.smartplanet.com/blog/business-brains/top-20-most-common-passwords-of-all-time-revealed-8216123456-8216princess-8216qwerty/4519 # noqa
  81. forbidden_passwords = [
  82. 'password',
  83. '1234',
  84. '12345'
  85. '123456',
  86. '123456y',
  87. '123456789',
  88. 'iloveyou',
  89. 'princess',
  90. 'monkey',
  91. 'rockyou',
  92. 'babygirl',
  93. 'monkey',
  94. 'qwerty',
  95. '654321',
  96. 'dragon',
  97. 'pussy',
  98. 'baseball',
  99. 'football',
  100. 'letmein',
  101. 'monkey',
  102. '696969',
  103. 'abc123',
  104. 'qwe123',
  105. 'qweasd',
  106. 'mustang',
  107. 'michael',
  108. 'shadow',
  109. 'master',
  110. 'jennifer',
  111. '111111',
  112. '2000',
  113. 'jordan',
  114. 'superman'
  115. 'harley'
  116. ]
  117. message = _("Please choose a less common password")
  118. code = 'password'
  119. def __init__(self, password_file=None):
  120. self.limit_value = password_file
  121. def clean(self, value):
  122. return value.strip()
  123. def compare(self, value, limit):
  124. return value in self.forbidden_passwords
  125. def get_forbidden_passwords(self):
  126. if self.limit_value is None:
  127. return self.forbidden_passwords
  128. # List all requirements for password, site wide
  129. password_validators = [
  130. validators.MinLengthValidator(6),
  131. CommonPasswordValidator(),
  132. ]