captcha.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from recaptcha.client.captcha import displayhtml, submit as submit_recaptcha
  2. from django.utils.translation import ugettext_lazy as _
  3. from misago.conf import settings
  4. from misago.core import forms
  5. def add_captcha_to_form(FormType, request):
  6. captcha_type = settings.captcha_on_registration
  7. test_passed = session_already_passed_test(request.session)
  8. captcha_attrs = {}
  9. if captcha_type == 'recaptcha':
  10. captcha_attrs.update(add_recaptcha_to_form(request, test_passed))
  11. elif captcha_type == 'qa':
  12. captcha_attrs.update(add_qa_test_to_form(request, test_passed))
  13. if captcha_attrs:
  14. captcha_attrs['session'] = request.session
  15. return type('FinalRegisterForm', (FormType,), captcha_attrs)
  16. """
  17. reCaptcha
  18. """
  19. def clean_recaptcha(self):
  20. if not self.data.get('recaptcha_response_field'):
  21. raise forms.ValidationError(_("This field is required."))
  22. api_response = submit_recaptcha(
  23. self.data.get('recaptcha_challenge_field'),
  24. self.data.get('recaptcha_response_field'),
  25. settings.recaptcha_private_api_key,
  26. self._misago_real_ip)
  27. if api_response.is_valid:
  28. self.has_recaptcha = False
  29. mark_session_as_passing(self.session)
  30. else:
  31. raise forms.ValidationError(_("Text from image is incorrect."))
  32. return ''
  33. def add_recaptcha_to_form(request, test_passed):
  34. recaptcha_field = forms.CharField(label=_('Security image'),
  35. required=False)
  36. field_html = displayhtml(settings.recaptcha_public_api_key,
  37. request.is_secure())
  38. extra_fields = {
  39. 'passed_recaptcha': test_passed,
  40. 'has_recaptcha': True,
  41. 'recaptcha': recaptcha_field,
  42. 'recaptcha_html': field_html,
  43. '_misago_real_ip': request._misago_real_ip,
  44. 'clean_recaptcha': clean_recaptcha,
  45. }
  46. if test_passed:
  47. extra_fields['has_recaptcha'] = False
  48. extra_fields.pop('clean_recaptcha')
  49. return extra_fields
  50. """
  51. Q&A
  52. """
  53. def clean_qa_answer(self):
  54. answer = self.cleaned_data['qa_answer'].lower()
  55. for predefined_answer in settings.qa_answers.lower().splitlines():
  56. predefined_answer = predefined_answer.strip().lower()
  57. if answer == predefined_answer:
  58. self.has_qa_captcha = False
  59. mark_session_as_passing(self.session)
  60. return self.cleaned_data['qa_answer']
  61. else:
  62. raise forms.ValidationError(_("Entered answer is incorrect."))
  63. def add_qa_test_to_form(request, test_passed):
  64. qa_answer_field = forms.CharField(label=settings.qa_question,
  65. help_text=settings.qa_help_text,
  66. required=(not test_passed))
  67. extra_fields = {
  68. 'passed_qa_captcha': test_passed,
  69. 'has_qa_captcha': True,
  70. 'qa_answer': qa_answer_field,
  71. 'clean_qa_answer': clean_qa_answer,
  72. }
  73. if test_passed:
  74. extra_fields['has_qa_captcha'] = False
  75. extra_fields.pop('clean_qa_answer')
  76. return extra_fields
  77. """
  78. Session utils
  79. """
  80. def session_already_passed_test(session):
  81. return session.get('passes_captcha')
  82. def mark_session_as_passing(session):
  83. session['passes_captcha'] = True