Skip to content

Latest commit

 

History

History
233 lines (193 loc) · 8.61 KB

File metadata and controls

233 lines (193 loc) · 8.61 KB

Captcha

With the release of 1.6.0 InformationCollectionBundle provides ReCaptcha integration. Captcha settings can be configured globally or per content type.

Global configuration

This configuration example enables captcha globally for all forms generated by InformationCollectionController with some additional options like hostname, action, and score_threshold.

netgen_information_collection:
    system:
        default:
            captcha:
                enabled: true
                options:
                    hostname: 'www.example.com'
                    action: 'global'
                    score_threshold: 0.4
                secret: 'secret'
                site_key: 'sitekey'
            action_config:
                email:
                    templates:
                        default: "@ezdesign/info_collection/email.html.twig"
                    default_variables:
                        sender: "[email protected]"
                        recipient: "[email protected]"
            actions:
                default:
                    - database
                    - email

Content Type overrides

This example disables captcha globally, but enables it on for ng_feedback_form content type and overrides site_key value, plus sets action option to feedback.

netgen_information_collection:
    system:
        default:
            captcha:
                enabled: false
                override_by_type:
                    ng_feedback_form:
                        enabled: true
                        site_key: 'mycustomsitekey'
                        options:
                            action: 'feedback'            
                options:
                    hostname: 'www.example.com'
                    score_threshold: 0.4
                    challenge_timeout: 54
                secret: 'secret'
                site_key: 'sitekey'
            action_config:
                email:
                    templates:
                        default: "@ezdesign/info_collection/email.html.twig"
                    default_variables:
                        sender: "[email protected]"
                        recipient: "[email protected]"
            actions:
                default:
                    - database
                    - email

All available options under options configuration are:

  • hostname
  • apk_package_name
  • action
  • score_threshold
  • challenge_timeout

Template

This bundle does not provides frontend/template integration with captcha, rather leave's end implementation to developer. Backend supports both visible and invisible captcha's.

To help with frontend implementation bundle provides two Twig functions:

  • info_collection_captcha_is_enabled()
  • info_collection_captcha_get_site_key()

Both accepts eZ Location value object as argument.

Example template implementation for ng_feedback_form would be something like this (visible captcha):

{% block content %}
    <div class="view-type view-type-{{ view_type }} ng-feedback-form">
        <div class="full-form-content">
            {% if not is_valid %}
                {% if not content.fields.body.empty %}
                    {{ ng_render_field(content.fields.body) }}
                {% endif %}

                {{ form_start(form) }}
                    {{ form_errors(form) }}

                    <fieldset>
                        {{ form_row(form.sender_name, {attr: {class: 'form-control'}}) }}
                        {{ form_row(form.email, {attr: {class: 'form-control'}}) }}
                        {{ form_row(form.subject, {attr: {class: 'form-control'}}) }}
                        {{ form_row(form.message, {attr: {class: 'form-control'}}) }}

                        <button type="submit" class="btn btn-primary">Send</button>
                    </fieldset>

                    {{ form_rest(form) }}
                {{ form_end(form) }}


                {% if info_collection_captcha_is_enabled(location.innerLocation) %}
                    <div class="info-collector-captcha">
                        <script src='https://www.google.com/recaptcha/api.js'></script>
                        {% set captcha = info_collection_captcha_get_site_key(location) %}
                        <div class="g-recaptcha" data-sitekey="{{ captcha }}"></div>
                    </div>
                {% endif %}

            {% else %}
                {{ block('success') }}
            {% endif %}
        </div>
    </div>
{% endblock %}

Or, using captcha v3:

{% block content %}
    <div class="view-type view-type-{{ view_type }} ng-feedback-form">
        <div class="full-form-content">
            {% if not is_valid %}
                {% if not content.fields.body.empty %}
                    {{ ng_render_field(content.fields.body) }}
                {% endif %}

                {{ form_start(form) }}
                {{ form_errors(form) }}

                <fieldset>
                    {{ form_row(form.sender_name, {attr: {class: 'form-control'}}) }}
                    {{ form_row(form.email, {attr: {class: 'form-control'}}) }}
                    {{ form_row(form.subject, {attr: {class: 'form-control'}}) }}
                    {{ form_row(form.message, {attr: {class: 'form-control'}}) }}
                    
                    <input name="g-recaptcha-response" hidden>
                    <button type="submit" class="btn btn-primary">Send</button>
                </fieldset>

                {{ form_rest(form) }}
                {{ form_end(form) }}


                {% if info_collection_captcha_is_enabled(location.innerLocation) %}
                    {% set captcha = info_collection_captcha_get_site_key(location.innerLocation) %}
                    <div class="info-collector-captcha">
                        <script src="https://www.google.com/recaptcha/api.js?render={{ captcha }}"></script>
                        <script>
                            grecaptcha.ready(function () {
                                grecaptcha.execute('{{ captcha }}', {action: 'feedback'}).then(function (token) {
                                    $('[name="g-recaptcha-response"]').val(token);
                                });
                            });
                        </script>
                    </div>
                {% endif %}

            {% else %}
                {{ block('success') }}
            {% endif %}
        </div>
    </div>
{% endblock %}

Or, using invisible captcha:

{% block content %}
    <div class="view-type view-type-{{ view_type }} ng-feedback-form">
        <div class="full-form-content">
            {% if not is_valid %}
                {% if not content.fields.body.empty %}
                    {{ ng_render_field(content.fields.body) }}
                {% endif %}

                {{ form_start(form, { 'attr': { 'id': 'ng_feedback_form'} } ) }}) }}
                {{ form_errors(form) }}

                <fieldset>
                    {{ form_row(form.sender_name, {attr: {class: 'form-control'}}) }}
                    {{ form_row(form.email, {attr: {class: 'form-control'}}) }}
                    {{ form_row(form.subject, {attr: {class: 'form-control'}}) }}
                    {{ form_row(form.message, {attr: {class: 'form-control'}}) }}
                    
                    <input name="g-recaptcha-response" hidden>
                    <button type="submit" class="btn btn-primary g-recaptcha" data-sitekey={{info_collection_captcha_get_site_key(location.innerLocation)}} data-callback='onSubmit'>Send</button>
                </fieldset>

                {{ form_rest(form) }}
                {{ form_end(form) }}


                {% if info_collection_captcha_is_enabled(location.innerLocation) %}
                    <div class="info-collector-captcha">
                        <script src="https://www.google.com/recaptcha/api.js" async defer></script>
                        <script>
                            function onSubmit(token) {
                                document.getElementById("ng_feedback_form").submit();
                            }
                        </script>
                    </div>
                {% endif %}

            {% else %}
                {{ block('success') }}
            {% endif %}
        </div>
    </div>
{% endblock %}

If captcha validation results in error with code missing-input-response you probably did not send reCAPTCHA token in variable g-recaptcha-response. Another error you might encounter is action-mismatch. In this case make sure that the action you specified in captcha config (globally or per content type) is the same as the one you use when executing captcha check.