Skip to content

Commit

Permalink
feat: add error codes and score to RecaptchaV3 constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain committed Jun 26, 2024
1 parent 9c8cfcd commit 8371e15
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 9 deletions.
4 changes: 4 additions & 0 deletions docs/validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ error message should be displayed in debug mode when validating.

#[LeaptAssert\RecaptchaV3(message: 'Invalid captcha.')]
public $recaptcha;

// Or if you need technical details about why the captcha is invalid:
#[LeaptAssert\RecaptchaV3(message: LeaptAssert\RecaptchaV3::$technicalMessage)]
public $recaptcha;
```

??? info "Options"
Expand Down
2 changes: 2 additions & 0 deletions src/Validator/Constraints/RecaptchaV3.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class RecaptchaV3 extends Recaptcha
{
public string $message = 'The submitted captcha is invalid.';

public static string $technicalMessage = 'The submitted captcha is invalid. Error codes: {{ errorCodes }}. Score: {{ score }}.';

public function validatedBy(): string
{
return RecaptchaV3Validator::class;
Expand Down
22 changes: 13 additions & 9 deletions src/Validator/Constraints/RecaptchaV3Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Psr\Log\LoggerInterface;
use ReCaptcha\ReCaptcha;
use ReCaptcha\Response;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
Expand Down Expand Up @@ -50,24 +51,27 @@ public function validate(mixed $value, Constraint $constraint): void
throw new UnexpectedTypeException($value, 'string');
}

if (!$this->isTokenValid($value)) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ string }}', $value)
->addViolation();
$response = $this->verifyToken($value);
if ($response?->isSuccess()) {
return;
}

$this->context->buildViolation($constraint->message)
->setParameter('{{ string }}', $this->formatValue($value))
->setParameter('{{ score }}', $this->formatValue($response?->getScore()))
->setParameter('{{ errorCodes }}', $this->formatValues($response?->getErrorCodes() ?? []))
->addViolation();
}

private function isTokenValid(string $token): bool
private function verifyToken(string $token): ?Response
{
try {
$remoteIp = $this->requestStack->getCurrentRequest()->getClientIp();
$recaptcha = new ReCaptcha($this->secretKey);

$response = $recaptcha
return $recaptcha
->setScoreThreshold($this->scoreThreshold)
->verify($token, $remoteIp);

return $response->isSuccess();
} catch (\Exception $exception) {
$this->logger->error(
'reCAPTCHA validator error: ' . $exception->getMessage(),
Expand All @@ -76,7 +80,7 @@ private function isTokenValid(string $token): bool
],
);

return false;
return null;
}
}
}
1 change: 1 addition & 0 deletions translations/validators.en.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"This value is not a valid captcha.": This value is not a valid captcha.
"The captcha was not resolved on the right domain.": The captcha was not resolved on the right domain.
"The submitted captcha is invalid.": The submitted captcha is invalid.
"The submitted captcha is invalid. Error codes: {{ errorCodes }}. Score: {{ score }}.": "The submitted captcha is invalid. Error codes: {{ errorCodes }}. Score: {{ score }}."
"A slug can only contain lowercase letters, numbers and hyphens.": A slug can only contain lowercase letters, numbers and hyphens.
"This password is not strong enough.": This password is not strong enough.
"This password is too short. It should have {{ limit }} characters or more.": This password is too short. It should have {{ limit }} characters or more.
Expand Down
1 change: 1 addition & 0 deletions translations/validators.fr.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"This value is not a valid captcha.": Vous devez cocher la case "Je ne suis pas un robot".
"The captcha was not resolved on the right domain.": Le captcha est rempli sur un domaine inconnu.
"The submitted captcha is invalid.": Le captcha envoyé est invalide, veuillez réessayer.
"The submitted captcha is invalid. Error codes: {{ errorCodes }}. Score: {{ score }}.": "Le captcha envoyé est invalide. Codes d'erreur : {{ errorCodes }}. Score : {{ score }}."
"A slug can only contain lowercase letters, numbers and hyphens.": Un slug ne peut contenir que des lettres minuscules sans accents, des chiffres et des tirets.
"This password is not strong enough.": Le mot de passe n'est pas assez fort.
"This password is too short. It should have {{ limit }} characters or more.": Le mot de passe est trop court et doit contenir au moins {{ limit }} caractères.
Expand Down

0 comments on commit 8371e15

Please sign in to comment.