Browse Source

Beginnings of captcha implementation

Rafał Pitoń 11 years ago
parent
commit
9d6cf6f472
2 changed files with 144 additions and 0 deletions
  1. 68 0
      misago/core/captcha.py
  2. 76 0
      misago/core/migrations/0002_basic_settings.py

+ 68 - 0
misago/core/captcha.py

@@ -0,0 +1,68 @@
+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):
+    if session_already_passed_test(request.session):
+        return FormType
+    else:
+        captcha_attrs = {}
+
+        captcha_type = getattr(settings, FormType.captcha_setting)
+        if captcha_type == 'recaptcha':
+            captcha_attrs['has_recaptcha'] = True
+            captcha_attrs.update(add_recaptcha_to_form(request))
+        elif captcha_type == 'qa':
+            captcha_attrs['has_qa_captcha'] = True
+            captcha_attrs.update(add_qa_test_to_form(request))
+
+        if captcha_attrs:
+            captcha_attrs['session'] = request.session
+        return type('FinalRegisterForm', (FormType,), captcha_attrs)
+
+
+"""
+reCaptcha
+"""
+def add_recaptcha_to_form(request):
+    extra_fields = {}
+    return extra_fields
+
+
+"""
+Q&A
+"""
+def clean_qa_answer(self):
+    answer = self.cleaned_data['qa_answer']
+
+    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 answer
+    else:
+        raise forms.ValidationError(_("Entered answer is invalid."))
+
+
+def add_qa_test_to_form(request):
+    qa_answer_field = forms.CharField(label=settings.qa_question,
+                                      help_text=settings.qa_help_text)
+
+    extra_fields = {
+        'qa_answer': qa_answer_field,
+        'clean_qa_answer': 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

+ 76 - 0
misago/core/migrations/0002_basic_settings.py

@@ -59,6 +59,82 @@ def create_basic_settings_group(apps, schema_editor):
             )
         })
 
+    migrate_settings_group(
+        apps,
+        {
+            'key': 'captcha',
+            'name': _("CAPTCHA"),
+            'description': _("Those settings allow you to combat automatic "
+                             "registrations and spam messages on your forum."),
+            'settings': (
+                {
+                    'setting': 'captcha_on_registration',
+                    'name': _("CAPTCHA on registration"),
+                    'legend': _("CAPTCHA types"),
+                    'value': 'no',
+                    'form_field': 'select',
+                    'field_extra': {
+                        'choices': (
+                            ('no', _("No protection")),
+                            ('recaptcha', _("reCaptcha")),
+                            ('qa', _("Question and answer")),
+                        ),
+                    },
+                },
+                {
+                    'setting': 'recaptcha_public_api_key',
+                    'name': _("Public API key"),
+                    'legend': _("reCAPTCHA"),
+                    'value': '',
+                    'field_extra': {
+                        'required': False,
+                        'max_length': 100,
+                    },
+                },
+                {
+                    'setting': 'recaptcha_private_api_key',
+                    'name': _("Private API key"),
+                    'value': '',
+                    'field_extra': {
+                        'required': False,
+                        'max_length': 100,
+                    },
+                },
+                {
+                    'setting': 'qa_question',
+                    'name': _("Test question"),
+                    'legend': _("Question and answer"),
+                    'value': '',
+                    'field_extra': {
+                        'required': False,
+                        'max_length': 250,
+                    },
+                },
+                {
+                    'setting': 'qa_help_text',
+                    'name': _("Question help text"),
+                    'value': '',
+                    'field_extra': {
+                        'required': False,
+                        'max_length': 250,
+                    },
+                },
+                {
+                    'setting': 'qa_answers',
+                    'name': _("Valid answers"),
+                    'description': _("Enter each answer in new line. "
+                                     "Answers are case-insensitive."),
+                    'value': '',
+                    'form_field': 'textarea',
+                    'field_extra': {
+                        'rows': 4,
+                        'required': False,
+                        'max_length': 250,
+                    },
+                },
+            )
+        })
+
 
 class Migration(migrations.Migration):