Skip to content

Commit

Permalink
Improving the recaptcha (feature).
Browse files Browse the repository at this point in the history
  • Loading branch information
vihuvac committed Aug 10, 2016
1 parent 62cc6a9 commit de87e22
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 231 deletions.
24 changes: 23 additions & 1 deletion DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Vihuvac\Bundle\RecaptchaBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

Expand All @@ -33,12 +34,33 @@ public function getConfigTreeBuilder()
->children()
->scalarNode("site_key")->isRequired()->end()
->scalarNode("secret_key")->isRequired()->end()
->booleanNode("secure")->defaultFalse()->end()
->booleanNode("enabled")->defaultTrue()->end()
->booleanNode("ajax")->defaultFalse()->end()
->scalarNode("locale_key")->defaultValue("%kernel.default_locale%")->end()
->end()
;

$this->addHttpClientConfiguration($rootNode);

return $treeBuilder;
}

/**
* {@inheritDoc}
*/
private function addHttpClientConfiguration(ArrayNodeDefinition $node)
{
$node
->children()
->arrayNode("http_proxy")
->addDefaultsIfNotSet()
->children()
->scalarNode("host")->defaultValue(null)->end()
->scalarNode("port")->defaultValue(null)->end()
->scalarNode("auth")->defaultValue(null)->end()
->end()
->end()
->end()
;
}
}
75 changes: 40 additions & 35 deletions Form/Type/VihuvacRecaptchaType.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

namespace Vihuvac\Bundle\RecaptchaBundle\Form\Type;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
Expand All @@ -24,10 +23,10 @@
class VihuvacRecaptchaType extends AbstractType
{
/**
* The reCAPTCHA server URL's
* The reCAPTCHA Server URL's
*/
const RECAPTCHA_API_SERVER = "http://www.google.com/recaptcha/api";
const RECAPTCHA_API_SECURE_SERVER = "https://www.google.com/recaptcha/api";
const RECAPTCHA_API_SERVER = "https://www.google.com/recaptcha/api";
const RECAPTCHA_API_JS_SERVER = "https://www.google.com/recaptcha/api/js/recaptcha_ajax.js";

/**
* The public key
Expand All @@ -36,12 +35,12 @@ class VihuvacRecaptchaType extends AbstractType
*/
protected $siteKey;

/**
* Use secure url?
*
* @var Boolean
*/
protected $secure;
/**
* Use AJAX API
*
* @var Boolean
*/
protected $ajax;

/**
* Enable recaptcha?
Expand All @@ -62,47 +61,47 @@ class VihuvacRecaptchaType extends AbstractType
* Construct.
*
* @param string $siteKey Recaptcha site key
* @param string $secure Recaptcha securey api url
* @param Boolean $enabled Recaptcha status
* @param Boolean $ajax Ajax status
* @param string $language Language or locale code
*/
public function __construct(ContainerInterface $container)
public function __construct($siteKey, $enabled, $ajax, $language)
{
$this->siteKey = $container->getParameter("vihuvac_recaptcha.site_key");
$this->secure = $container->getParameter("vihuvac_recaptcha.secure");
$this->enabled = $container->getParameter("vihuvac_recaptcha.enabled");
$this->language = $container->getParameter("vihuvac_recaptcha.locale_key");
$this->siteKey = $siteKey;
$this->enabled = $enabled;
$this->ajax = $ajax;
$this->language = $language;
}

/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars = array_replace(
$view->vars,
array(
"vihuvac_recaptcha_enabled" => $this->enabled
)
);
$view->vars = array_replace($view->vars, array(
"vihuvac_recaptcha_enabled" => $this->enabled,
"vihuvac_recaptcha_ajax" => $this->ajax
));

if (!$this->enabled) {
return;
}

if ($this->secure) {
$server = self::RECAPTCHA_API_SECURE_SERVER;
if (!isset($options["language"])) {
$options["language"] = $this->language;
}

if (!$this->ajax) {
$view->vars = array_replace($view->vars, array(
"url_challenge" => sprintf("%s.js?hl=%s", self::RECAPTCHA_API_SERVER, $options["language"]),
"site_key" => $this->siteKey
));
} else {
$server = self::RECAPTCHA_API_SERVER;
$view->vars = array_replace($view->vars, array(
"url_api" => self::RECAPTCHA_API_JS_SERVER,
"site_key" => $this->siteKey
));
}

$view->vars = array_replace(
$view->vars,
array(
"url_challenge" => sprintf("%s.js?hl=%s", $server, $this->language),
"site_key" => $this->siteKey
)
);
}

/**
Expand All @@ -113,12 +112,18 @@ public function configureOptions(OptionsResolver $resolver)
$resolver->setDefaults(
array(
"compound" => false,
"language" => $this->language,
"site_key" => null,
"url_challenge" => null,
"url_noscript" => null,
"attr" => array(
"options" => array(
"theme" => null,
"type" => null
"theme" => "light",
"type" => "image",
"size" => "normal",
"expiredCallback" => null,
"defer" => false,
"async" => false,
)
)
)
Expand Down
84 changes: 73 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,45 @@ Add the following to your config file:
vihuvac_recaptcha:
site_key: here_is_your_site_key
secret_key: here_is_your_secret_key
secure: true
enabled: true
locale_key: kernel.default_locale
```
> **NOTE**:
>
> If you want to use the secure URL for the reCAPTCHA, just set ```true``` as value in the secure parameter (__false is the default value__).
> This bundle uses a secure API (**HTTPS Protocol**). **Google API** solves the requests by the Browser (**Client**).
>
> The ```site_key``` parameter is the same than the ```public_key``` parameter and the ```secret_key``` parameter is the same than the ```private_key``` parameter (parameters used in the previous versions).

You can easily disable reCAPTCHA (for example in a local or test environment):
You can easily **enable** and **disable** the reCAPTCHA feature using any one of the booleans ```true``` or ```false``` through the **enabled** parameter, e.g:

``` yaml
# app/config/config.yml
vihuvac_recaptcha:
// ...
enabled: false
enabled: true
```

You can load the reCAPTCHA using the Ajax API (**optional**):

``` yaml
# app/config/config.yml
vihuvac_recaptcha:
// ...
ajax: true
```

Additionally you can add HTTP Proxy configuration (**optional**):

``` yaml
# app/config/config.yml
vihuvac_recaptcha:
// ...
host: proxy.your-domain.com
port: 3128
auth: proxy_username:proxy_password
```

Congratulations! You're ready!
Expand All @@ -83,10 +103,14 @@ public function buildForm(FormBuilder $builder, array $options)

You can pass extra options to reCAPTCHA with the ```attr > options``` option, e.g:

| Tag attribute | Render parameter | Value | Default | Description |
| ------------- | :--------------: | :-----------: | :-----: | ---------------------------------------: |
| data-theme | theme | dark / light | light | Optional. The color theme of the widget. |
| data-type | type | audio / image | image | Optional. The type of CAPTCHA to serve. |
| Tag attribute | Render parameter | Value | Default | Description |
| --------------------- | :--------------: | :--------------: | :-----: | ---------------------------------------: |
| data-theme | theme | dark / light | light | Optional. The color theme of the widget. |
| data-type | type | audio / image | image | Optional. The type of CAPTCHA to serve. |
| data-size | size | compact / normal | normal | Optional. The size of the widget. |
| data-expired-callback | expiredCallback | | | Optional. The name of your callback function to be executed when the recaptcha response expires and the user needs to solve a new CAPTCHA. |
| | defer | true / false | false | Optional for the Ajax API. |
| | async | true / false | false | Optional for the Ajax API. |

``` php
<?php
Expand All @@ -101,7 +125,8 @@ public function buildForm(FormBuilder $builder, array $options)
"attr" => array(
"options" => array(
"theme" => "light",
"type" => "audio"
"type" => "audio",
"size" => "normal"
)
)
)
Expand Down Expand Up @@ -141,7 +166,8 @@ public function buildForm(FormBuilder $builder, array $options)
"attr" => array(
"options" => array(
"theme" => "light",
"type" => "audio"
"type" => "audio",
"size" => "normal"
)
),
"mapped" => false,
Expand Down Expand Up @@ -227,4 +253,40 @@ using JavaScript:
</script>
```

**Customization**:

If you want to use a custom theme, put your chunk of code before setting the theme:

```
<div id="recaptcha_widget">
<div id="recaptcha_image"></div>
<div class="recaptcha_only_if_incorrect_sol" style="color:red">Incorrect please try again</div>
<span class="recaptcha_only_if_image">Enter the words above:</span>
<span class="recaptcha_only_if_audio">Enter the numbers you hear:</span>
<input type="text" id="recaptcha_response_field" name="recaptcha_response_field" />
<div><a href="javascript:Recaptcha.reload()">Get another CAPTCHA</a></div>
<div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type("audio")">Get an audio CAPTCHA</a></div>
<div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type("image")">Get an image CAPTCHA</a></div>
<div><a href="javascript:Recaptcha.showhelp()">Help</a></div>
</div>
{% form_theme form "VihuvacRecaptchaBundle:Form:vihuvac_recaptcha_widget.html.twig %}
{{
form_widget(
form.recaptcha, {
"attr": {
"options" : {
"theme" : "custom",
},
}
}
)
}}
```

**Further reading**: [Google Official Documentation](https://developers.google.com/recaptcha/docs/start)
7 changes: 4 additions & 3 deletions Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ services:
vihuvac_recaptcha.form.type:
class: "%vihuvac_recaptcha.form.type.class%"
arguments:
- "@service_container"
- "%vihuvac_recaptcha.site_key%"
- "%vihuvac_recaptcha.enabled%"
- "%vihuvac_recaptcha.ajax%"
- "%vihuvac_recaptcha.locale_key%"
tags:
- { name: form.type, alias: vihuvac_recaptcha }

vihuvac_recaptcha.validator.true:
class: "%vihuvac_recaptcha.validator.true.class%"
arguments:
- "@service_container"
- "%vihuvac_recaptcha.secret_key%"
- "%vihuvac_recaptcha.enabled%"
- "%vihuvac_recaptcha.secret_key%"
- "@request_stack"
- "%vihuvac_recaptcha.http_proxy%"
tags:
- { name: validator.constraint_validator, alias: vihuvac_recaptcha.true }
15 changes: 0 additions & 15 deletions Resources/translations/validators.en.xliff

This file was deleted.

4 changes: 4 additions & 0 deletions Resources/translations/validators.en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vihuvac_recaptcha:
validator:
message: Please, don't forget to tick the checkbox in the reCAPTCHA field.
remote_ip: For security reasons, you must pass the Remote IP to reCAPTCHA.
15 changes: 0 additions & 15 deletions Resources/translations/validators.es.xliff

This file was deleted.

4 changes: 4 additions & 0 deletions Resources/translations/validators.es.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vihuvac_recaptcha:
validator:
message: Por favor, no olvides de marcar la casilla de verificación en el campo de reCAPTCHA.
remote_ip: Por razones de seguridad, debes pasar la IP Remota al reCAPTCHA.
15 changes: 0 additions & 15 deletions Resources/translations/validators.fr.xliff

This file was deleted.

4 changes: 4 additions & 0 deletions Resources/translations/validators.fr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vihuvac_recaptcha:
validator:
message: Veuillez cliquez sur la case à cocher du reCAPTCHA.
remote_ip: Pour des raisons de sécurité, vous devez passer l'IP Distante à reCAPTCHA.
Loading

0 comments on commit de87e22

Please sign in to comment.