Skip to content

Commit

Permalink
feat: Add captcha
Browse files Browse the repository at this point in the history
  • Loading branch information
famoser committed Oct 14, 2024
1 parent c6292a6 commit 987d3c2
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ [email protected]
SUPPORT_EMAIL=[email protected]
BASE_URI=https://localhost:8000

NEED_CAPTCHA=0

# determines wether an accounts is allowed to login or not, and wheter it can create / join other construction sites.
# Possible values are:
# - default_allow_self_association (by default, users can create / join construction sites)
Expand Down
1 change: 1 addition & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ services:
$environment: '%kernel.environment%'
$publicDir: '%kernel.project_dir%/public'
$reportAssetDir: '%kernel.project_dir%/assets/report'
$needCaptcha: '%env(NEED_CAPTCHA)%'

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
Expand Down
6 changes: 5 additions & 1 deletion src/Controller/SecurityController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use App\Controller\Base\BaseController;
use App\Entity\ConstructionManager;
use App\Form\CaptchaType;
use App\Form\ConstructionManager\RegisterConfirmType;
use App\Form\UserTrait\LoginType;
use App\Form\UserTrait\OnlyEmailType;
Expand Down Expand Up @@ -87,12 +88,15 @@ public function token(): Response
}

#[Route(path: '/register', name: 'register')]
public function register(Request $request, TranslatorInterface $translator, UserServiceInterface $userService): \Symfony\Component\HttpFoundation\RedirectResponse|Response
public function register(Request $request, TranslatorInterface $translator, UserServiceInterface $userService, string $needCaptcha): \Symfony\Component\HttpFoundation\RedirectResponse|Response
{
$constructionManager = new ConstructionManager();
$constructionManager->setEmail($request->query->get('email'));

$form = $this->createForm(OnlyEmailType::class, $constructionManager);
if ($needCaptcha) {
$form->add('captcha', CaptchaType::class);
}
$form->add('submit', SubmitType::class, ['translation_domain' => 'security', 'label' => 'register.title']);

$form->handleRequest($request);
Expand Down
83 changes: 83 additions & 0 deletions src/Form/CaptchaType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/*
* This file is part of the baupen project.
*
* (c) Florian Moser <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;

class CaptchaType extends AbstractType
{
public const CAPTCHA_CHALLENGE_SESSION_KEY = '_captcha_challenge';

public function __construct(private readonly RequestStack $requestStack, private readonly TranslatorInterface $translator)
{
}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addEventListener(FormEvents::POST_SUBMIT, [$this, 'validate']);
}

public function buildView(FormView $view, FormInterface $form, array $options): void
{
$challenge = rand(1, 9);

$session = $this->requestStack->getSession();
$session->set(self::CAPTCHA_CHALLENGE_SESSION_KEY, $challenge);

$view->vars = array_merge($view->vars, ['challenge' => $challenge]);
}

public function validate(FormEvent $event): void
{
$session = $this->requestStack->getSession();
$expectedChallenge = $session->get(self::CAPTCHA_CHALLENGE_SESSION_KEY, 0);

$form = $event->getForm();
$actualChallenge = $form->getData();

// see translation files: user always asked to sum up $expectedChallenge + 2
if (intval($actualChallenge) - 2 !== $expectedChallenge) {
$error = $this->translator->trans('captcha.invalid', [], 'security');
$form->addError(new FormError($error));
}
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(['mapped' => false]);
}

public function getParent(): string
{
return NumberType::class;
}

public function getName(): string
{
return $this->getBlockPrefix();
}

public function getBlockPrefix(): string
{
return 'captcha';
}
}
7 changes: 7 additions & 0 deletions templates/form/form_layout.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@
{{- parent() -}}
{%- endblock form_label -%}

{% block captcha_label -%}
{%- set label = 'captcha.label' -%}
{%- set translation_domain = 'security' -%}
{%- set label_translation_parameters = {'%challenge%': challenge} -%}

{{- block('form_label') -}}
{%- endblock captcha_label %}
3 changes: 3 additions & 0 deletions translations/security.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ register:
success:
welcome: 'Sie wurden erfolgreich registriert! Prüfen Sie Ihre E-Mails um den Account zu aktivieren.'
title: 'Account erstellen.'
captcha:
label: 'Was ergibt %challenge% + 2?'
invalid: 'Captcha ist falsch.'
3 changes: 3 additions & 0 deletions translations/security.it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ register:
success:
welcome: 'Sei stato registrato con successo! Controlla la tua e-mail per attivare il tuo account.'
title: 'Crea un account.'
captcha:
label: 'Cosa risulta in %challenge% + 2?'
invalid: 'Il captcha è sbagliato.'

0 comments on commit 987d3c2

Please sign in to comment.