Skip to content

Commit

Permalink
Add optional support for a simple CAPTCHA.
Browse files Browse the repository at this point in the history
  • Loading branch information
almet committed Oct 10, 2021
1 parent 60149cd commit 4c7e594
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 4 deletions.
5 changes: 5 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ Note: this setting is actually interpreted by Flask-Babel, see the

.. _Flask-Babel guide for formatting dates: https://pythonhosted.org/Flask-Babel/#formatting-dates

`ENABLE_CAPTCHA`
---------------

It is possible to add a simple captcha in order to filter out spammer bots on the form creation.
In order to do so, you just have to set `ENABLE_CAPTCHA = True`.

Configuring emails sending
--------------------------
Expand Down
4 changes: 4 additions & 0 deletions ihatemoney/conf-templates/ihatemoney.cfg.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ ACTIVATE_ADMIN_DASHBOARD = False
# You can change the timezone used to display time. By default it will be
#derived from the server OS.
#BABEL_DEFAULT_TIMEZONE = "Europe/Paris"

# You can activate an optional CAPTCHA if you want to. It can be helpful
# to filter spammer bots.
# ENABLE_CAPTCHA = True
1 change: 1 addition & 0 deletions ihatemoney/default_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@
"uk",
"zh_Hans",
]
ENABLE_CAPTCHA = True
16 changes: 15 additions & 1 deletion ihatemoney/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
from types import SimpleNamespace

import email_validator
from flask import request
from flask import current_app, request
from flask_babel import lazy_gettext as _
from flask_wtf.file import FileAllowed, FileField, FileRequired
from flask_wtf.form import FlaskForm
from markupsafe import Markup
from werkzeug.security import check_password_hash, generate_password_hash
from wtforms.fields import Field
from wtforms.fields.core import Label, SelectField, SelectMultipleField
from wtforms.fields.html5 import DateField, DecimalField, URLField
from wtforms.fields.simple import BooleanField, PasswordField, StringField, SubmitField
Expand Down Expand Up @@ -220,6 +221,19 @@ def validate_id(form, field):
)
raise ValidationError(Markup(message))

@classmethod
def enable_captcha(cls):
captchaField = StringField(
_("Which is a real currency: Euro or Petro dollar?")
)
setattr(cls, "captcha", captchaField)

def validate_captcha(form, field):
if not field.data.lower() == _("euro"):
message = _('Please, validate the captcha to proceed.')
raise ValidationError(Markup(message))



class DestructiveActionProjectForm(FlaskForm):
"""Used for any important "delete" action linked to a project:
Expand Down
5 changes: 4 additions & 1 deletion ihatemoney/templates/forms.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
{{ input(form.name) }}
{{ input(form.password) }}
{{ input(form.contact_email) }}
{% if config['ENABLE_CAPTCHA'] %}
{{ input(form.captcha) }}
{% endif %}
{{ input(form.default_currency) }}
{% if not home %}
{{ submit(form.submit, home=True) }}
Expand Down Expand Up @@ -171,7 +174,7 @@
</div>
</div>
</div>

<details class="mb-3">
<summary class="mb-2">{{ _("More options") }}</summary>
{% if g.project.default_currency != "XXX" %}
Expand Down
5 changes: 5 additions & 0 deletions ihatemoney/tests/budget_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def test_project_creation(self):
"password": "party",
"contact_email": "raclette@notmyidea.org",
"default_currency": "USD",
"captcha": "euro",
},
follow_redirects=True,
)
Expand Down Expand Up @@ -186,6 +187,7 @@ def test_project_creation(self):
"password": "party",
"contact_email": "raclette@notmyidea.org",
"default_currency": "USD",
"captcha" : "euro",
},
)

Expand All @@ -204,6 +206,7 @@ def test_project_creation_without_public_permissions(self):
"password": "party",
"contact_email": "raclette@notmyidea.org",
"default_currency": "USD",
"captcha" : "euro",
},
)

Expand All @@ -225,6 +228,7 @@ def test_project_creation_with_public_permissions(self):
"password": "party",
"contact_email": "raclette@notmyidea.org",
"default_currency": "USD",
"captcha" : "euro",
},
)

Expand All @@ -245,6 +249,7 @@ def test_project_deletion(self):
"password": "party",
"contact_email": "raclette@notmyidea.org",
"default_currency": "USD",
"captcha" : "euro",
},
)

Expand Down
1 change: 1 addition & 0 deletions ihatemoney/tests/common/ihatemoney_testcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def post_project(self, name, follow_redirects=True, default_currency="XXX"):
"password": name,
"contact_email": f"{name}@notmyidea.org",
"default_currency": default_currency,
"captcha" : "euro"
},
follow_redirects=follow_redirects,
)
Expand Down
11 changes: 9 additions & 2 deletions ihatemoney/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,16 @@ def authenticate(project_id=None):
return render_template("authenticate.html", form=form)


def get_project_form():
if current_app.config.get("ENABLE_CAPTCHA", False):
ProjectForm.enable_captcha()

return ProjectForm()


@main.route("/", strict_slashes=False)
def home():
project_form = ProjectForm()
project_form = get_project_form()
auth_form = AuthenticationForm()
is_demo_project_activated = current_app.config["ACTIVATE_DEMO_PROJECT"]
is_public_project_creation_allowed = current_app.config[
Expand All @@ -281,7 +288,7 @@ def mobile():
@main.route("/create", methods=["GET", "POST"])
@requires_admin(bypass=("ALLOW_PUBLIC_PROJECT_CREATION", True))
def create_project():
form = ProjectForm()
form = get_project_form()
if request.method == "GET" and "project_id" in request.values:
form.name.data = request.values["project_id"]

Expand Down

0 comments on commit 4c7e594

Please sign in to comment.