validators.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. from importlib import import_module
  2. import json
  3. import re
  4. import requests
  5. from django.core.exceptions import PermissionDenied, ValidationError
  6. from django.core.validators import validate_email as validate_email_content
  7. from django.utils.translation import ungettext, ugettext_lazy as _
  8. from django.contrib.auth import get_user_model
  9. from misago.conf import settings
  10. from misago.users.bans import get_email_ban, get_username_ban
  11. USERNAME_RE = re.compile(r'^[0-9a-z]+$', re.IGNORECASE)
  12. """
  13. Email validators
  14. """
  15. def validate_email_available(value, exclude=None):
  16. User = get_user_model()
  17. try:
  18. user = User.objects.get_by_email(value)
  19. if not exclude or user.pk != exclude.pk:
  20. raise ValidationError(_("This e-mail address is not available."))
  21. except User.DoesNotExist:
  22. pass
  23. def validate_email_banned(value):
  24. ban = get_email_ban(value)
  25. if ban:
  26. if ban.user_message:
  27. raise ValidationError(ban.user_message)
  28. else:
  29. raise ValidationError(_("This e-mail address is not allowed."))
  30. def validate_email(value, exclude=None):
  31. """shortcut function that does complete validation of email"""
  32. validate_email_content(value)
  33. validate_email_available(value, exclude)
  34. validate_email_banned(value)
  35. """
  36. Password validators
  37. """
  38. def validate_password(value):
  39. if len(value) < settings.password_length_min:
  40. message = ungettext(
  41. 'Valid password must be at least %(limit)s character long.',
  42. 'Valid password must be at least %(limit)s characters long.',
  43. settings.password_length_min)
  44. message = message % {'limit': settings.password_length_min}
  45. raise ValidationError(message)
  46. """
  47. Username validators
  48. """
  49. def validate_username_available(value, exclude=None):
  50. User = get_user_model()
  51. try:
  52. user = User.objects.get_by_username(value)
  53. if not exclude or user.pk != exclude.pk:
  54. raise ValidationError(_("This username is not available."))
  55. except User.DoesNotExist:
  56. pass
  57. def validate_username_banned(value):
  58. ban = get_username_ban(value)
  59. if ban:
  60. if ban.user_message:
  61. raise ValidationError(ban.user_message)
  62. else:
  63. raise ValidationError(_("This username is not allowed."))
  64. def validate_username_content(value):
  65. if not USERNAME_RE.match(value):
  66. raise ValidationError(
  67. _("Username can only contain latin alphabet letters and digits."))
  68. def validate_username_length(value):
  69. if len(value) < settings.username_length_min:
  70. message = ungettext(
  71. "Username must be at least %(limit)s character long.",
  72. "Username must be at least %(limit)s characters long.",
  73. settings.username_length_min)
  74. message = message % {'limit': settings.username_length_min}
  75. raise ValidationError(message)
  76. if len(value) > settings.username_length_max:
  77. message = ungettext(
  78. "Username cannot be longer than %(limit)s characters.",
  79. "Username cannot be longer than %(limit)s characters.",
  80. settings.username_length_max)
  81. message = message % {'limit': settings.username_length_max}
  82. raise ValidationError(message)
  83. def validate_username(value, exclude=None):
  84. """shortcut function that does complete validation of username"""
  85. validate_username_length(value)
  86. validate_username_content(value)
  87. validate_username_available(value, exclude)
  88. validate_username_banned(value)
  89. """
  90. New account validators
  91. """
  92. SFS_API_URL = 'http://api.stopforumspam.org/api?email=%(email)s&ip=%(ip)s&f=json&confidence' # noqa
  93. def validate_with_sfs(ip, username, email):
  94. if settings.MISAGO_STOP_FORUM_SPAM_USE:
  95. _real_validate_with_sfs(ip, email)
  96. def _real_validate_with_sfs(ip, email):
  97. try:
  98. r = requests.get(SFS_API_URL % {'email': email, 'ip': ip},
  99. timeout=3)
  100. api_response = json.loads(r.content)
  101. ip_score = api_response.get('ip', {}).get('confidence', 0)
  102. email_score = api_response.get('email', {}).get('confidence', 0)
  103. api_score = max((ip_score, email_score))
  104. if api_score > settings.MISAGO_STOP_FORUM_SPAM_MIN_CONFIDENCE:
  105. raise PermissionDenied()
  106. except requests.exceptions.RequestException:
  107. pass # todo: log those somewhere
  108. def validate_gmail_email(ip, username, email):
  109. username, domain = email.split('@')
  110. if domain == 'gmail.com' and username.count('.') > 6:
  111. raise PermissionDenied()
  112. """
  113. Registration validation
  114. """
  115. def load_registration_validators(validators_list):
  116. loaded_validators = []
  117. for path in validators_list:
  118. module = import_module('.'.join(path.split('.')[:-1]))
  119. loaded_validators.append(getattr(module, path.split('.')[-1]))
  120. return loaded_validators
  121. validators_list = settings.MISAGO_NEW_REGISTRATIONS_VALIDATORS
  122. REGISTRATION_VALIDATORS = load_registration_validators(validators_list)
  123. def validate_new_registration(ip, username, email, validators=None):
  124. validators = validators or REGISTRATION_VALIDATORS
  125. for validator in validators:
  126. validator(ip, username, email)