Giter VIP home page Giter VIP logo

statamic-captcha's Introduction

Captcha

Protect your Statamic forms using a Captcha service.

This addon allows you to protect your Statamic forms from spam using Google reCAPTCHA v2 (v3 not supported), hCaptcha or Cloudflare Turnstile.

After the initial setup, all you need to do is add the {{ captcha }} tag inside your forms, easy peasy!

Installation

Install the addon via composer:

composer require aryehraber/statamic-captcha

Publish the config file:

 php please vendor:publish --tag=captcha-config

Alternately, you can manually setup the config file by creating captcha.php inside your project's config directory:

<?php

return [
    'service' => 'Recaptcha', // options: Recaptcha / Hcaptcha / Turnstile
    'sitekey' => env('CAPTCHA_SITEKEY', ''),
    'secret' => env('CAPTCHA_SECRET', ''),
    'forms' => [],
    'user_login' => false,
    'user_registration' => false,
    'disclaimer' => '',
    'invisible' => false,
    'hide_badge' => false,
    'enable_api_routes' => false,
];

Once the config file is in place, make sure to add your sitekey & secret from Recaptcha's Console, hCaptcha's Console or Cloudflare's Dashboard and add the handles of the Statamic Forms you'd like to protect:

<?php

return [
    'service' => 'Recaptcha', // options: Recaptcha / Hcaptcha / Turnstile
    'sitekey' => 'YOUR_SITEKEY_HERE', // Or add to .env
    'secret' => 'YOUR_SECRET_HERE', // Or add to .env
    'forms' => ['contact', 'newsletter'],
    // ...
];

If you would like Captcha to verify ALL forms without having to specify each one in the forms config array, you may use the all option instead.

Note: this should replace the array and be set as a string.

<?php

return [
    'forms' => 'all',
    // ...
];

Usage

<head>
    <title>My Awesome Site</title>

    {{ captcha:head }}
</head>
<body>
    {{ form:contact }}

        <!-- Add your fields like normal -->

        {{ captcha }}

        {{ if error:captcha }}
          <p>{{ error:captcha }}</p>
        {{ /if }}

    {{ /form:contact }}
</body>

This will automatically render the Captcha element on the page. After the form is submitted, the addon will temporarily halt the form from saving while the Captcha service verifies that the request checks out. If all is good, the form will save as normal, otherwise an error will be added to the {{ errors }} object.

Invisible Captcha

Simply set invisible to true inside Captcha's config (Turnstile handles invisibility from Cloudflares's Dashboard, so no Captcha config changes are needed). To hide the sticky Recaptcha badge, make sure to also set hide_badge to true.

Note: using Invisible Captcha will require you to display links to the Captcha service's Terms underneath the form, to make this easier use {{ captcha:disclaimer }}. This message can be customised using the disclaimer option inside Captcha's config, however sensible defaults have been added that will automatically switch depending on the Captcha service you're using.

User Registration & Login

Captcha can also verify User Registration & User Login form requests, simply set user_registration / user_login to true inside Captcha's config and use the {{ captcha }} tag as normal inside Statamic's {{ user:register_form }} / {{ user:login_form }} tags.

Data Attributes

Some of the Captcha services offer additional features, such as light/dark mode and sizing options, via data attributes. These can simply be added to the Captcha tag and will be passed through to the client-side widget.

{{ captcha data-theme="dark" data-size="compact" }}

Translations

This package is localized to English and German. If you need translations in another language, you can create them yourself:

  • Create the translations file in resources/lang/vendor/statamic-captcha/{language}/messages.php.
  • You can use the English translation file as a blueprint.
  • You are welcome to share your translations here by submitting a PR.

If you want to change existing messages, you can publish and override them:

php please vendor:publish --tag="captcha-translations"

statamic-captcha's People

Contributors

aryehraber avatar edalzell avatar fjahn avatar jacksleight avatar stoffelio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

statamic-captcha's Issues

Sitekey not found in local dev.

Popping this here in case anyone has the same issue I did.

Installed on a statamic v3 site not problem - but I saw getting a must supply sitekey error in the console.

The cause was that my local dev site is not on a secure domain.

The fix is to use switch to using ssl, or in my case I switched to using the google test keys for local dev instead.

Hcaptcha is not checking the form

Hello,

I am not sure, if i miss something. If I submit the form the success message appears. If I fill the captcha it counts up in the hcaptcha Dashboard.

captcha.php

<?php
return [
    'service' => 'Hcaptcha', // options: Recaptcha / Hcaptcha
    'sitekey' => env('CAPTCHA_SITEKEY', ''),
    'secret' => env('CAPTCHA_SECRET', ''),
    'collections' => [],
    'forms' => ['kontakt'],
    'error_message' => 'Captcha failed.',
    'disclaimer' => '',
    'invisible' => false,
    'hide_badge' => false,
    'enable_api_routes' => false,
];

kontakt.antlers.html

{{ form:kontakt }}
{{ captcha:head }}
{{ if success }}
    <div class="bg-green-300 text-white p-2">
        {{ success }}
    </div>
{{ else }}
    {{ if errors }}
        <div class="bg-red-300 text-white p-2">
            {{ errors }}
            {{ value }}<br>
            {{ /errors }}
        </div>
    {{ /if }}

    {{ fields }}
    <div class="p-2">
        <label class="block font-medium text-gray-700">{{ display }}</label>
        <div class="p-1">{{ field }}</div>
        {{ if error }}
            <p class="text-gray-500">{{ error }}</p>
        {{ /if }}
    </div>
    {{ /fields }}

    <div class="p-2">
        {{ captcha }}

        {{ if error:captcha }}
            <p>{{ error:captcha }}</p>
        {{ /if }}

    </div>

    <div class="p-2">
        <button class="primary" type="submit">Absenden</button>
    </div>
{{ /if }}

{{ /form:kontakt }}

composer.json

      "aryehraber/statamic-captcha": "^1.3",

composer.lock

        "name": "aryehraber/statamic-captcha",
            "version": "v1.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/aryehraber/statamic-captcha.git",
                "reference": "5a87dd626773125edd624daded40a74c33663151"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/aryehraber/statamic-captcha/zipball/5a87dd626773125edd624daded40a74c33663151",
                "reference": "5a87dd626773125edd624daded40a74c33663151",
                "shasum": ""
            },
            "require": {
                "statamic/cms": "^3.0"
            },
            "type": "statamic-addon",
            "extra": {
                "statamic": {
                    "name": "Captcha",
                    "slug": "captcha",
                    "description": "Protect your Statamic forms using a Captcha service",
                    "version": "1.3.0"
                },
                "laravel": {
                    "providers": [
                        "AryehRaber\\Captcha\\CaptchaServiceProvider"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "AryehRaber\\Captcha\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aryeh Raber",
                    "email": "[email protected]",
                    "homepage": "https://aryeh.dev",
                    "role": "Developer"
                }
            ],
            "description": "Protect your Statamic forms using a Captcha service",
            "homepage": "https://github.com/aryehraber/statamic-captcha",
            "keywords": [
                "Forms",
                "captcha",
                "hcaptcha",
                "recaptcha",
                "statamic"
            ],
            "support": {
                "issues": "https://github.com/aryehraber/statamic-captcha/issues",
                "source": "https://github.com/aryehraber/statamic-captcha/tree/v1.3.0"
            },
            "time": "2021-01-27T08:52:16+00:00"
        },

Usage with half method caching and nocache

release: dev-dev (also tried on latest)
statamic: v3.4.9

I have a form that I need to use a captcha on, and the client has asked for reCaptcha. The form HTML currently looks like this:

{{ nocache }}
    {{ form:set in="get_in_touch" }}
        {{ if form:errors }}
                {{ form:errors }}
                    {{ value }}<br>
                {{ /form:errors }}
        {{ /if }}
        {{ form:create  js="alpine" id="contactForm" redirect="/thank-you" }}  
            <div>
                {{ fields }}
                    <template x-if="{{ show_field }}">
                        <div>
                            <label for="form_{{ handle }}">{{ display }}</label>
                            {{ field }}
                        </div>
                    </template>
                {{ /fields }}
            </div>

            <input type="text" class="hidden" name="{{ honeypot ?? 'honeypot' }}">
            <div>
                <div class="captcha">
                    {{ if config:captcha:enabled }}
                        {{ captcha }}
                    {{ /if }}
                </div>
            </div>
            <button form="contactForm" type="submit">
                <i class="fa fa-spinner fa-spin hidden" id="loading-icon"></i>
                <span class="btn-text" id="btn-text">Submit Message</span>
            </button>
        {{ /form:create }}
    {{ /form:set }}
{{ /nocache }}

As you can see during debugging I've updated the config slightly to look like the one below, this was so I could easily check it was the captcha plugin causing the issue.

return [
    'enabled' => env('CAPTCHA_ENABLED', false), // true/false
    'service' => env('CAPTCHA_PROVIDER', 'Recaptcha'), // options: Recaptcha / Hcaptcha
    'sitekey' => env('CAPTCHA_SITEKEY', ''),
    'secret' => env('CAPTCHA_SECRET', ''),
    //'collections' => [],
    'forms' => env('CAPTCHA_ENABLED', false) == false ? [] : 'all',
    'user_login' => false,
    'user_registration' => false,
    'disclaimer' => '',
    'invisible' => false,
    'hide_badge' => false,
    'enable_api_routes' => false,
];

I've also updated the replacer to have the one mentioned in #45

    'replacers' => [
        Statamic\StaticCaching\Replacers\CsrfTokenReplacer::class,
        Statamic\StaticCaching\Replacers\NoCacheReplacer::class,
        \AryehRaber\Captcha\CaptchaReplacer::class
    ]

The response I get is simply "Captcha failed" and it reloads the page with the form.

Option to publish view file

Would it be possible to add an option to publish the view file (where the JS code is in)?

Background is, that I need to add certain attributes to the <script .. tag in order to make it work with https://www.consentmanager.de/

Or is there any other option to modify the JS code that loads the recaptcha?

No badge showing and failing every submit

Hey!

I'm using ReCaptcha V2, composer updated to the latest everything, added the form handle and doubled checked it is correct,]. I've added the tag to the form markup, site key and secret to env (and tested in the config) and I have even dd'd to make sure it is actually registering the addon. Every time I just get Captcha failed ๐Ÿค•

Side point I am not seeing the Badge...is this an indication of something?

Appreciate any help my man ๐Ÿ™‚

Captcha blocks `EntrySaving` event from propagating

Right now Captcha returns $entry and according to this code in EntrySaving::dispatch, the propagation stops on the first non-null value:

    /**
     * Dispatch the event with the given arguments, and halt on first non-null listener response.
     *
     * @return mixed
     */
    public static function dispatch()
    {
        return event(new static(...func_get_args()), [], true);
    }

This means if you have additional listeners, they don't get called when you return anything.

Confirmed that this code in handle fixes the issue, in the CP:

        if (Statamic::isCpRoute()) {
            return null;
        }

captcha:head stopped working with section

After the last update (1.0.3), when entering the contact page I get the error View [recaptcha.head] not found.
Contact template:

{{ section:script }}
{{ captcha:head }}
{{ /section:script }}
...

Layout template:

<head>
  {{ partial:partials/head }}
  {{ yield:script }}
</head>
...

If the captcha:head is in the layout template, the problem does not occur.

Can't get error message to show

When I leave the captcha unchecked the error never shows? All other validation errors show fine. Any ideas? Really appreciate everything!!!

{{ form:contact }}

    <label for="name">Full Name</label>
    <input id="name" name="name" type="text" placeholder="Name *" value="{{ old:name }}">    
    {{ error:name ensure_left="*" wrap="span.error" }}
	  
    {{ captcha }}
    {{ if error:captcha }}{{ error:captcha }}{{ /if }}
	  
    <button type="submit" name="submit_button"></button>

{{ /form:contact }}

My config:

<?php

return [
    'service' => 'Recaptcha', // options: Recaptcha / Hcaptcha
    'sitekey' => env('CAPTCHA_SITEKEY', 'xxx'),
    'secret' => env('CAPTCHA_SECRET', 'xxx'),
    'forms' => ['contact'],
    'error_message' => 'Captcha failed.',
    'disclaimer' => '',
    'invisible' => false,
    'hide_badge' => false,
    'enable_api_routes' => false,
    'user_registration' => true,
    'user_login' => true,
];

In composer.json:
"aryehraber/statamic-captcha": "^1.5",

Unfilled captcha doesn't fail form validation

Hi,

Thanks very much for this add-on. However, I cannot get it to work for love nor money.

I have the capture setup in my form show template as so:

{{ if show_captcha }}
        <div class="form-group{{ if error:captcha }} form-group--error{{ /if }}">
        {{ if error:captcha }}<span class="form-error">{{ error:captcha }}</span>{{ /if }}
        {{ captcha }}
        </div>
      {{ /if }}

Which works! The capture is shown (I've tested both Recaptcha and Hcaptcha)

and my config looks like:

return [
    'service' => 'Hcaptcha', // options: Recaptcha / Hcaptcha
    'sitekey' => env('CAPTCHA_SITEKEY', '[my key is here]'),
    'secret' => env('CAPTCHA_SECRET', '[my secret is here]'),
    'collections' => ['pages'],
    'forms' => ['contact-us'],
    'error_message' => 'Captcha failed.',
    'disclaimer' => '',
    'invisible' => false,
    'hide_badge' => false,
    'enable_api_routes' => false,
];

However, even without filling the captcha, the form is submitted without error.

Usage with Full Static Caching (and `nocache`)

๐Ÿ˜„ Been trying to wrap my head around an intermittent issue today - but turns out it's not intermittent!

When using the Captcha addon with Full Static Caching the first page load works fine, but subsequent page loads are missing the captcha widget. I've got the entire form wrapped in {{nocache}} tags.

Where the widget should be I just get <div class="cf-turnstile" data-sitekey="0x4AAAAAAACauAHbma0FeuPz"></div>

Theres nothing logged in the console. The call to <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script> seems to be correctly in there.

Is the addon compatible with nocache? Should I be including the javascript elsewhere somehow? ๐Ÿ˜‚ any ideas at all?

EDIT: Hmmmm, maybe it requires some sort of Replacer wangjangling https://statamic.dev/static-caching#replacers

Disclaimer not working in multisite

We want to display the disclaimer in 2 languages, but when we use __("disclaimer"); in the config file it returns a error saying target class [translator] does not exist

Captcha error checking via AJAX

Hey @aryehraber - this is definitely more a bug on my end rather than something specific to your script; but thought I'd file a bug to see if you might be able to point me in the right direction. ๐Ÿ˜‚

I'm trying to utilise Statamic Captcha with Statamic Peak - which does its form processing via Javascript. Essentially statamic peak works by processing the form via AJAX, which is super handy as you can have forms on statically cached pages.

For the relevant code see here: https://github.com/studio1902/statamic-peak/blob/main/resources/views/page_builder/_form.antlers.html#L79 - it requires that you handle errors external to the normal form error loop by displaying them client side via alpine.

Out of the box the captcha seems to work perfectly with the sole exception of not throwing errors. With a normal statamic install the Captcha errors come through within the normal error loop, but I just cannot seem to find them when going via the AJAX method.

Say for a simple form like this....
Screen Shot 2022-03-19 at 4 24 55 pm

I'd get back all fields except the Captcha in the errors array
Screen Shot 2022-03-19 at 4 24 39 pm

Just grabbing this via...
Screen Shot 2022-03-19 at 4 29 58 pm

Would you have any idea how I would be able to get access to Captcha validation via ajax, or is it likely something I'd have to do client-side? Had a cursory look around the code and it seems to hook into the normal Exception code... so feel like I'm missing something obvious?

Again, this isn't really a bug with Captcha (more with me!) so feel free to delete if you feel like this is out of scope!

๐Ÿ‘

Captcha still shows on forms not declared in `forms` config

Spent a while trying to figure out how I was having bots slip through and auto-submit one of my forms, even though it had a Captcha on the page. Turns out that although the page had the header code, and the Captcha displayed visually (and interactively) it wasn't actually added to my Captcha Forms Config (captcha.php). Which is definitely a mistake on my part ๐Ÿ˜‚ but it did get me thinking that it was unsual that everything displayed correctly even though I hadn't chosen that form to display the Captcha.

For many sites I use the same form template (and fields etc) for multiple different forms - so I can easily see how this slipped through on my part.

tldr; would it be possible to make it so captchas only display on forms that have actually been chosen in the config? It seems like the forms setting only dictates which forms require validation, rather than where it is displayed?

Error Message not localizable

The error_message that is configurable via captcha.php is not localized. This could be fixed by wrapping all references to config('captcha.error_message') in a call to the function __. See Laravel Localization docs for details.

I can also do a PR in a couple of days if you say that it would be merged.

Not verifying passed solutions

In my reCaptcha admin console, I get this warning on a site that uses this plugin:

We detected that your site is verifying reCAPTCHA passed solutions less than 50% of the time. This could indicate a problem with your integration with reCAPTCHA. Please see [our developer site](https://developers.google.com/recaptcha/docs/verify#api-request) for more information.

Support for statamic login form

Is it possible to support the out of the box login form too? there is already a setting for the user registration form, but wanted to add it to my login form too.

Get error when submitting the form

I get this error when submitting my form:

GuzzleHttp\Exception\ConnectException cURL error 35: OpenSSL SSL_connect: Connection reset by peer in connection to www.google.com:443 (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) http://swisstime.proto/!/forms/contact

Please note that the form submit works just fine without statamic-captcha

Details
Statamic 3.0.10 Pro
Laravel 7.26.1
PHP 7.4.6
aryehraber/statamic-captcha 1.0.3
statamic/migrator dev-master
statamic/ssg 0.2.0

image

image

image

image

Adding translations not working

When adding or publishing the translation messages the changes are not showing on the frontend when a validation error occurs.

Is it possible that this is not working a the moment in the current version?

Fields Reset on Captcha Fail

First, thanks for building this out, it's saved me a bunch of time.

I am running into a strange issue though which I'm not sure if it's expected or not. When I submit the form (all fields populated) but intentionally don't complete the captcha the page appears to be reloaded and then shows the captcha error but all form fields are now empty. As you can imagine this would definitely be annoying for someone!

My form looks like this:

{{ form:contact_us }}

    <div class="grid grid-cols-6 gap-6">
        {{ fields }}
            {{ if first || count == 2 }}
                <div class="col-span-6 sm:col-span-3">
                    <label for="contact-{{ handle }}" class="block text-sm font-medium text-gray-700">{{ display }}</label>
                    <input value="{{ old:{{ handle }} }}" type="text" name="{{ handle }}" id="contact-{{ handle }}" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
                    {{ if error }}
                        <p class="mt-2 text-sm text-red-300">{{ error }}</p>
                    {{ /if }}
                </div>
            {{ elseif handle == 'comment' }}
                <div class="col-span-6 ">
                    <label for="contact-{{ handle }}" class="block text-sm font-medium text-gray-700">{{ display }}</label>
                    <div class="mt-1">
                        <textarea value="{{ old:{{ handle }} }}" name="{{ handle }}" id="contact-{{ handle }}" rows="3" class="block w-full mt-1 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" placeholder="Message..."></textarea>
                        {{ if error }}
                            <p class="mt-2 text-sm text-red-300">{{ error }}</p>
                        {{ /if }}
                    </div>
                    <p class="mt-2 text-gray-500">
                        Let us know how we can help.
                    </p>
                </div>
            {{ else }}
                <div class="col-span-6 sm:col-span-6">
                    <label for="contact-{{ handle }}" class="block text-sm font-medium text-gray-700">{{ display }}</label>
                    <input value="{{ old:{{ handle }} }}" type="text" name="{{ handle }}" id="contact-{{ handle }}" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
                    {{ if error }}
                        <p class="mt-2 text-sm text-red-300">{{ error }}</p>
                    {{ /if }}
                </div>
            {{ /if }}
        {{ /fields }}

        
        <div class="col-span-6 sm:col-span-6">
            {{ captcha }}
            {{ if error:captcha }}
                <p class="mt-2 text-sm text-red-300">{{ error:captcha }}</p>
            {{ /if }}
        </div>
    </div>

    <button class="button" type="submit">Submit</button>

    {{ if success }}
        <div class="p-2 my-8 text-white bg-green-500 rounded-md shadow-sm">
            <h5 class="text-white ">Thank you for getting in touch!</h5>
            <p>We appreciate you contacting us. One of our staff will be in touch with you soon! Have a great day!</p>
        </div>
    {{ /if }}

{{ /form:contact_us }}

Any help is appreciated, I'm running the latest version of Statamic and Statamic Captcha on PHP 7.3.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.