diff --git a/plugins/form/CHANGELOG.md b/plugins/form/CHANGELOG.md index 1b1f56d..7e3a478 100644 --- a/plugins/form/CHANGELOG.md +++ b/plugins/form/CHANGELOG.md @@ -1,3 +1,9 @@ +# v7.1.0 +## 11/16/2022 + +1. [](#new) + * Added Cloudflare's `turnstile` captcha integration [documentation](https://learn.getgrav.org/17/forms/forms/fields-available#turnstile-field-cloudflare) + # v7.0.2 ## 10/05/2022 diff --git a/plugins/form/blueprints.yaml b/plugins/form/blueprints.yaml index 3dea14d..776ee88 100644 --- a/plugins/form/blueprints.yaml +++ b/plugins/form/blueprints.yaml @@ -1,7 +1,7 @@ name: Form slug: form type: plugin -version: 7.0.2 +version: 7.1.0 description: Enables forms handling and processing icon: check-square author: diff --git a/plugins/form/form.php b/plugins/form/form.php index 3beff18..eb19d62 100644 --- a/plugins/form/form.php +++ b/plugins/form/form.php @@ -25,6 +25,7 @@ use Grav\Plugin\Form\BasicCaptcha; use Grav\Plugin\Form\Form; use Grav\Plugin\Form\Forms; use Grav\Plugin\Form\TwigExtension; +use Grav\Common\HTTP\Client; use ReCaptcha\ReCaptcha; use ReCaptcha\RequestMethod\CurlPost; use RecursiveArrayIterator; @@ -34,6 +35,7 @@ use RocketTheme\Toolbox\File\YamlFile; use RocketTheme\Toolbox\File\File; use RocketTheme\Toolbox\Event\Event; use RuntimeException; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Twig\Environment; use Twig\Extension\CoreExtension; use Twig\Extension\EscaperExtension; @@ -440,6 +442,7 @@ class FormPlugin extends Plugin * @param Event $event * @return void * @throws Exception + * @throws TransportExceptionInterface */ public function onFormProcessed(Event $event): void { @@ -526,6 +529,40 @@ class FormPlugin extends Plugin $event->stopPropagation(); return; } + break; + case 'turnstile': + /** @var Uri $uri */ + $uri = $this->grav['uri']; + + $turnstile_config = $this->config->get('plugins.form.turnstile'); + $secret = $turnstile_config['secret_key'] ?? null; + $token = $form->getValue('cf-turnstile-response') ?? null; + $ip = Uri::ip(); + + $client = Client::getClient(); + $response = $client->request('POST', 'https://challenges.cloudflare.com/turnstile/v0/siteverify', [ + 'body' => [ + 'secret' => $secret, + 'response' => $token, + 'remoteip' => $ip + ] + ]); + + $content = $response->toArray(); + + if (!$content['success']) { + $message = $params['message'] ?? $this->grav['language']->translate('PLUGIN_FORM.ERROR_BASIC_CAPTCHA'); + + $this->grav->fireEvent('onFormValidationError', new Event([ + 'form' => $form, + 'message' => $message + ])); + + $this->grav['log']->addWarning('Form Turnstile invalid: [' . $uri->route() . '] ' . json_encode($content)); + $event->stopPropagation(); + return; + } + break; case 'timestamp': $label = $params['label'] ?? 'Timestamp'; diff --git a/plugins/form/form.yaml b/plugins/form/form.yaml index 71e704f..ae8cecf 100644 --- a/plugins/form/form.yaml +++ b/plugins/form/form.yaml @@ -18,6 +18,12 @@ recaptcha: theme: light site_key: secret_key: +turnstile: + widget: managed # options: [managed | non-interactive | invisible] + theme: light # options: [light | dark] + site_key: + secret_key: + basic_captcha: type: characters # options: [characters | math] chars: @@ -33,4 +39,4 @@ basic_captcha: math: min: 1 # smallest digit max: 12 # largest digit - operators: ['+','-','*'] # operators that can be used in math \ No newline at end of file + operators: ['+','-','*'] # operators that can be used in math diff --git a/plugins/form/templates/forms/fields/basic-captcha/basic-captcha.html.twig b/plugins/form/templates/forms/fields/basic-captcha/basic-captcha.html.twig index e7dd890..68d9c7a 100644 --- a/plugins/form/templates/forms/fields/basic-captcha/basic-captcha.html.twig +++ b/plugins/form/templates/forms/fields/basic-captcha/basic-captcha.html.twig @@ -5,7 +5,7 @@ {% block prepend %}