Do not require a captcha when using the API (#931)

* Do not require a captcha when using the API

This was trickier than expected, due to some side effects : when the
captcha is set to `True` via configuration, it doesn't change the
behavior directly of the ProjectForm class, but does so only when the
project form is used in the `web.py` module.

So, when just using the API (and not using the web.py module, for
instance during tests — manual or functional), no problem was shown,
and everything was working properly.

But at soon as somebody sees the "/" endpoint, the captcha was
required, by both the API and the `web.py` module.

This fixes it by adding a way to bypass the captcha with a new
`bypass_captcha` property on the form.

Prior to this commit, things were done by activating or deactivating a
"captcha" property on the class on-the-fly, which caused side-effects.

This is now using subclasses, which makes the code simpler to
understand, and less prone to side-effects.

Thanks @zorun for the idea.
This commit is contained in:
Alexis Metaireau 2021-11-25 00:44:21 +01:00 committed by GitHub
parent 05ac991a55
commit 1698841f6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 8 additions and 9 deletions

View file

@ -228,13 +228,11 @@ class ProjectForm(EditProjectForm):
)
raise ValidationError(Markup(message))
@classmethod
def enable_captcha(cls):
captchaField = StringField(
_("Which is a real currency: Euro or Petro dollar?"),
validators=[DataRequired()],
)
setattr(cls, "captcha", captchaField)
class ProjectFormWithCaptcha(ProjectForm):
captcha = StringField(
_("Which is a real currency: Euro or Petro dollar?"),
)
def validate_captcha(form, field):
if not field.data.lower() == _("euro"):

View file

@ -286,6 +286,7 @@ class CaptchaTestCase(IhatemoneyTestCase):
assert len(models.Project.query.all()) == 1
def test_api_project_creation_does_not_need_captcha(self):
self.client.get("/")
resp = self.client.post(
"/api/projects",
data={

View file

@ -47,6 +47,7 @@ from ihatemoney.forms import (
MemberForm,
PasswordReminder,
ProjectForm,
ProjectFormWithCaptcha,
ResetPasswordForm,
UploadForm,
get_billform_for,
@ -264,8 +265,7 @@ def authenticate(project_id=None):
def get_project_form():
if current_app.config.get("ENABLE_CAPTCHA", False):
ProjectForm.enable_captcha()
return ProjectFormWithCaptcha()
return ProjectForm()