Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from passioneight/dev
improvement: re-implement the bundle
- Loading branch information
Showing
39 changed files
with
514 additions
and
376 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Upgrade Notes | ||
## 2.0.0 | ||
- Namespace changed from `Passioneight\Bundle\PimcoreGoogleRecaptchaBundle` to | ||
`Passioneight\PimcoreGoogleRecaptcha`. Use your IDE to replace namespaces. | ||
|
||
- Requirements changed to `pimcore/pimcore ^10.5`, which means PHP 8 is used. | ||
|
||
- `google-recaptcha.js` is now a class. You'll have to transpile the file. For example, | ||
you may want to use [Webpack Encore](https://github.com/symfony/webpack-encore) (see docs). | ||
|
||
- `google-recaptcha.js` does not load Google's script by default anymore. Instead, call the `loadScript` method explicitly. | ||
This ensures GDPR compliance, unless you call the method without user consent. | ||
|
||
- Added some `Trait`s to ease dependency injection of services. | ||
|
||
## 1.0.0 | ||
No upgrade notes available, because `v1.0.0` was the first version. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# Installation | ||
To use Google reCAPTCHA and, therefore, this bundle, you'll need to | ||
[register a reCAPTCHA-key](https://www.google.com/recaptcha/admin/create). | ||
Google requires you to [register a reCAPTCHA-key](https://www.google.com/recaptcha/admin/create). The reCAPTCHA-key | ||
will also be needed as part of the configuration of this bundle. | ||
|
||
### [Next Chapter: Installation](/documentation/10_installation.md) | ||
### [Next Chapter: Installation](/documentation/10_installation.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
# Installation | ||
|
||
Execute the following commands, and you are ready to go: | ||
Execute the following commands to install and enable this bundle: | ||
|
||
``` | ||
COMPOSER_MEMORY_LIMIT=-1 composer require passioneight/pimcore-google-recaptcha | ||
php bin/console pimcore:bundle:enable PimcoreGoogleRecaptchaBundle | ||
composer require passioneight/pimcore-google-recaptcha | ||
bin/console pimcore:bundle:enable PimcoreGoogleRecaptchaBundle | ||
``` | ||
|
||
### [Next Chapter: Configuration](/documentation/20_configuration.md) | ||
### [Next Chapter: Configuration](/documentation/20_configuration.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,86 @@ | ||
# Usage | ||
After configuring the bundle, you'll need some JavaScript in your HTML-Code. | ||
|
||
> Note that the `recpatcha.js` only supports **V3**. | ||
```html | ||
<script> | ||
var _config = _config || {}; | ||
_config.googleRecaptcha = { | ||
debug: {{ google_recaptcha_debug() }}, | ||
publicKey: "{{ google_recaptcha_public_key() }}", | ||
querySelector: ".google-recaptcha", | ||
defaultAction: "{{ google_recaptcha_default_action() }}", | ||
}; | ||
</script> | ||
<script src="{{ asset('bundles/googlerecaptcha/js/recaptcha.js') }}"></script> | ||
After [configuring the bundle]((/documentation/20_configuration.md)), the JavaScript needs to become aware of the bundle's | ||
configuration. Include the following template to achieve this: | ||
|
||
```twig | ||
{% include '@PimcoreGoogleRecaptcha/google-recaptcha.html.twig' %} | ||
``` | ||
|
||
> No need to change the JavaScript, as you can simply change the bundle's configuration to alter the `_config` variable. | ||
> You can also pass a `nonce` parameter to the template to improve security | ||
> (see [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src) for more information). | ||
Next, add a hidden form field to your form, like so: | ||
```html | ||
<input type="hidden" name="google-recaptcha" class="google-recaptcha" /> | ||
``` | ||
### Including the Script | ||
Import the script in your main script (e.g., `app.js`) and call the `loadScript` method once you have the user's | ||
consent to load Google reCAPTCHA: | ||
|
||
> If you want to customize the `action` that is sent to Google, add a `data-action="myCustomAction"` attribute to the form field. | ||
```js | ||
let recaptcha = new PassioneightGoogleRecaptcha() | ||
|
||
The script will automatically detect any elements with the `google-recaptcha` class and try to find a parent form. | ||
If a parent form was found, _any_ corresponding submit buttons (i.e., `<input type="submit" ...>`) will be used to trigger | ||
Google's `grecaptcha.execute` method before the form is actually submitted. | ||
// Omitted: asking for the user's permission | ||
let userConsent = true | ||
|
||
> The reCAPTCHA is executed on each click, since Google states: _reCAPTCHA tokens expire after two minutes. If you're | ||
> protecting an action with reCAPTCHA, make sure to call execute when the user takes the action_. | ||
if(userConsent) { | ||
recaptcha.loadScript() | ||
} | ||
``` | ||
|
||
Once the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) resolves, | ||
a token will be added to the hidden input field. Afterwards the form will be submitted. | ||
> You may want to use a custom callback when the `grecaptcha` is ready. You can pass the callback to the `loadScript` | ||
> method, like so: `recaptcha.loadScript(() => { recaptcha.fetchRecaptchaToken(event) })`. | ||
Finally, you'll need to verify that the user is human. Various, extendable services are provided for this: | ||
- `TokenDecoderInterface` | ||
- `ResponseParserInterface` | ||
- `ResponseValidatorInterface` | ||
The script will automatically detect any form fields with the defined `querySelector` (i.e., `.google-recaptcha` by default) | ||
and try to find a parent form. If the user submits the form, the reCAPTCHA-token is loaded first, so it is submitted too. | ||
|
||
Inject both the `TokenDecoderInterface` and `ResponseValidatorInterface` into your class, which handles the form submission | ||
and add the following code: | ||
```php | ||
$recaptchaToken = "theSubmittedToken"; | ||
$recaptchaResponse = $this->responseDecoder->decodeToken($recaptchaToken); | ||
$this->responseValidator->validate($recaptchaResponse); // Throws an exception if invalid | ||
``` | ||
> To avoid timeouts, the reCAPTCHA is executed **on click**, since Google states: _reCAPTCHA tokens expire after two | ||
> minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action_. | ||
Alternatively, you can trigger a `ValidationEvent` using Symfony's `EventDispatcherInterface`. If the token is invalid, | ||
a `ValidationException` is thrown. | ||
### Implementing the Form | ||
While the script is loaded, it won't find any forms to protect just yet. You'll need to add a hidden form field, which | ||
will be used to submit the token that was loaded from Google. | ||
|
||
Conveniently, you can add this field as follows: | ||
```php | ||
try{ | ||
$this->eventDispacther->dispatch(new ValidationEvent("theSubmittedToken")); | ||
} catch (ValidationException $e) { | ||
// Do some error handling | ||
|
||
namespace App\Form\Authentication; | ||
|
||
use Symfony\Component\Form\AbstractType; | ||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | ||
use Symfony\Component\Form\FormBuilderInterface; | ||
use Passioneight\PimcoreGoogleRecaptcha\Form\Field\GoogleRecaptchaField; | ||
|
||
class RegistrationForm extends AbstractType | ||
{ | ||
const FIELD_GOOGLE_RECAPTCHA = "google-recaptcha"; | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public function buildForm(FormBuilderInterface $builder, array $options) | ||
{ | ||
parent::buildForm($builder, $options); | ||
|
||
// Omitted: any other fields of the form | ||
|
||
$builder->add(self::FIELD_GOOGLE_RECAPTCHA, GoogleRecaptchaField::class); | ||
|
||
$builder->add('submit', SubmitType::class, [ | ||
'label_format' => 'form.registration.submit' | ||
]); | ||
} | ||
} | ||
``` | ||
|
||
> You may want to checkout our [Form Builder Bundle](https://github.com/passioneight/form-builder) for an even easier integration. | ||
> You'll only have to include the JS and add a `GoogleRecaptcha` field to your form. | ||
> If you want to customize the `action` that is sent to Google, add a `data-action="myCustomAction"` to the `SubmitType`. | ||
Using the `GoogleRecaptchaField`, the token will be validated automatically, because it contains the `GoogleRecaptchaConstraint`. | ||
|
||
### Explicit Token Validation | ||
If you want to validate the token yourself, dispatch a `ValidationEvent`: | ||
```php | ||
try{ | ||
$this->eventDispacther->dispatch(new ValidationEvent($token)); | ||
} catch (ValidationException $e) { | ||
// Do some error handling | ||
} | ||
``` | ||
|
||
### [Next Chapter: Extending the bundle](/documentation/40_extending_the_bundle.md) | ||
### [Next Chapter: Extending the bundle](/documentation/40_extending_the_bundle.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,18 @@ | ||
# Extending the Bundle | ||
If, for some reason, the provided code is not sufficient, you may extend the provided services like so: | ||
If the provided code is not sufficient for your use case, you can extend the provided services like so: | ||
|
||
```yaml | ||
Passioneight\Bundle\PimcoreGoogleRecaptchaBundle\Service\Decoder\TokenDecoderInterface: | ||
Passioneight\PimcoreGoogleRecaptcha\Service\Decoder\TokenDecoderInterface: | ||
class: AppBundle\Service\GoogleRecaptcha\Decoder\TokenDecoder | ||
|
||
Passioneight\Bundle\PimcoreGoogleRecaptchaBundle\Service\Parser\ResponseParserInterface: | ||
Passioneight\PimcoreGoogleRecaptcha\Service\Parser\ResponseParserInterface: | ||
class: AppBundle\Service\GoogleRecaptcha\Parser\ResponseParser | ||
|
||
Passioneight\Bundle\PimcoreGoogleRecaptchaBundle\Service\Validator\ResponseValidatorInterface: | ||
Passioneight\PimcoreGoogleRecaptcha\Service\Validator\ResponseValidatorInterface: | ||
class: AppBundle\Service\GoogleRecaptcha\Validator\ResponseValidator | ||
``` | ||
|
||
> Your custom classes should extend from the provided abstract classes: | ||
> - `Passioneight\Bundle\PimcoreGoogleRecaptchaBundle\Service\Decoder\AbstractTokenDecoder` | ||
> - `Passioneight\Bundle\PimcoreGoogleRecaptchaBundle\Service\Parser\AbstractResponseParser` | ||
> - `Passioneight\Bundle\PimcoreGoogleRecaptchaBundle\Service\Validator\AbstractResponseValidator` | ||
> Consider extending the following classes instead of starting from scratch: | ||
> - `Passioneight\PimcoreGoogleRecaptcha\Service\Decoder\AbstractTokenDecoder` | ||
> - `Passioneight\PimcoreGoogleRecaptcha\Service\Parser\AbstractResponseParser` | ||
> - `Passioneight\PimcoreGoogleRecaptcha\Service\Validator\AbstractResponseValidator` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.