from recaptcha.client.captcha import displayhtml, submit as submit_recaptcha from django.utils.translation import ugettext_lazy as _ from misago.conf import settings from misago.core import forms def add_captcha_to_form(FormType, request): captcha_type = settings.captcha_on_registration test_passed = session_already_passed_test(request.session) captcha_attrs = {} if captcha_type == 'recaptcha': captcha_attrs.update(add_recaptcha_to_form(request, test_passed)) elif captcha_type == 'qa': captcha_attrs.update(add_qa_test_to_form(request, test_passed)) if captcha_attrs: captcha_attrs['session'] = request.session return type('FinalRegisterForm', (FormType,), captcha_attrs) """ reCaptcha """ def clean_recaptcha(self): if not self.data.get('recaptcha_response_field'): raise forms.ValidationError(_("This field is required.")) api_response = submit_recaptcha( self.data.get('recaptcha_challenge_field'), self.data.get('recaptcha_response_field'), settings.recaptcha_private_api_key, self._misago_real_ip) if api_response.is_valid: self.has_recaptcha = False mark_session_as_passing(self.session) else: raise forms.ValidationError(_("Text from image is incorrect.")) return '' def add_recaptcha_to_form(request, test_passed): recaptcha_field = forms.CharField(label=_('Security image'), required=False) field_html = displayhtml(settings.recaptcha_public_api_key, request.is_secure()) extra_fields = { 'passed_recaptcha': test_passed, 'has_recaptcha': True, 'recaptcha': recaptcha_field, 'recaptcha_html': field_html, '_misago_real_ip': request._misago_real_ip, 'clean_recaptcha': clean_recaptcha, } if test_passed: extra_fields['has_recaptcha'] = False extra_fields.pop('clean_recaptcha') return extra_fields """ Q&A """ def clean_qa_answer(self): answer = self.cleaned_data['qa_answer'].lower() for predefined_answer in settings.qa_answers.lower().splitlines(): predefined_answer = predefined_answer.strip().lower() if answer == predefined_answer: self.has_qa_captcha = False mark_session_as_passing(self.session) return self.cleaned_data['qa_answer'] else: raise forms.ValidationError(_("Entered answer is incorrect.")) def add_qa_test_to_form(request, test_passed): qa_answer_field = forms.CharField(label=settings.qa_question, help_text=settings.qa_help_text, required=(not test_passed)) extra_fields = { 'passed_qa_captcha': test_passed, 'has_qa_captcha': True, 'qa_answer': qa_answer_field, 'clean_qa_answer': clean_qa_answer, } if test_passed: extra_fields['has_qa_captcha'] = False extra_fields.pop('clean_qa_answer') return extra_fields """ Session utils """ def session_already_passed_test(session): return session.get('passes_captcha') def mark_session_as_passing(session): session['passes_captcha'] = True