Skip to content
This repository has been archived by the owner on Feb 17, 2022. It is now read-only.

Commit

Permalink
Merge pull request #48 from DarkGhostHunter/master
Browse files Browse the repository at this point in the history
Minor fix
  • Loading branch information
DarkGhostHunter authored Dec 21, 2021
2 parents 30526e2 + 39aeb29 commit df43d89
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 258 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ To declare the middleware, use the `ReCaptcha` helper to ease your development p
* `ReCaptcha::checkbox()` for explicitly rendered checkbox challenges.
* `ReCaptcha::invisible()` for invisible challenges.
* `ReCaptcha::android()` for Android app challenges.
*

```php
use App\Http\Controllers\Auth\LoginController;
use DarkGhostHunter\Captchavel\ReCaptcha;
Expand All @@ -69,13 +69,13 @@ Route::post('login', [LoginController::class, 'login'])
->middleware(ReCaptcha::checkbox());
```

> [Laravel 8.70 or below](https://github.com/laravel/framework/releases/tag/v8.70.0) need to cast the object as a string.
> [Laravel 8.69 or below](https://github.com/laravel/framework/releases/tag/v8.70.0) need to cast the object as a string.
#### Remembering challenges

To avoid a form asking for challenges over and over again, you can "remember" the challenge for a given set of minutes. This can be [enabled globally](#remember), but you may prefer to do it in a per-route basis.

Simple use the `remember()` method to use the config defaults. It accepts the number of minutes to override the amount of time to remember the challenge. Alternatively, `rememberForever()` will remember the challenge forever.
Simple use the `remember()` method to use the config defaults. It accepts the number of minutes to override the [global parameter](#remember). Alternatively, `rememberForever()` will remember the challenge forever.

```php
use App\Http\Controllers\Auth\LoginController;
Expand All @@ -100,11 +100,11 @@ You should use this in conjunction with the `@unlesschallenged` directive in you
@endchallenged
```

Good places to remember a challenge for some minutes are forms which are expected to fail, or when you have multiple forms the user may jump between.
> Good places to remember a challenge for some minutes are forms which are expected to fail, or when you have multiple forms the user may jump between.
#### Changing the input name

You can change the input name from `g-recaptcha-response`, which is the default, with `input()`.
You can change the input name from `g-recaptcha-response`, which is the default, to anything using `input()`.

```php
use App\Http\Controllers\Auth\LoginController;
Expand All @@ -116,7 +116,7 @@ Route::post('login', [LoginController::class, 'login'])

### Score-driven challenge

The reCAPTCHA v3 middleware works differently from v2. This is a score-driven response is _always_ a success, but the challenge scores between `0.0` and `1.0`. Human-like interaction will be higher, while robots will score lower. The default threshold is `0.5`, but this can be changed globally or per-route.
The reCAPTCHA v3 middleware works differently from v2. This response is _always_ a success, but the challenge scores between `0.0` and `1.0`. Human-like interaction will be higher, while robots will score lower. The default threshold is `0.5`, but this can be changed globally or per-route.

To start using it, simply use the `ReCaptcha::score()` method to your route.

Expand Down Expand Up @@ -179,7 +179,7 @@ Route::post('comment', [CommentController::class, 'create'])
#### Bypassing on authenticated users

Sometimes you may want to bypass reCAPTCHA checks on authenticated user, or automatically receive it as a "human" on score-driven challenges. While in your frontend you can programmatically disable reCAPTCHA when the user is authenticated, on the backend you can specify the guards using `except()`.
Sometimes you may want to bypass reCAPTCHA checks when there is an authenticated user, or automatically receive it as a "human" on score-driven challenges. While in your frontend you can programmatically disable reCAPTCHA when the user is authenticated, on the routes you can specify the guards to bypass using `except()`.

```php
use App\Http\Controllers\CommentController;
Expand All @@ -196,7 +196,7 @@ Route::post('comment/store', [CommentController::class, 'store'])

#### Faking reCAPTCHA scores

You can easily fake a reCAPTCHA response scores in your local development by setting `CAPTCHAVEL_FAKE` to `true`.
You can easily fake a reCAPTCHA response score in your local development by setting `CAPTCHAVEL_FAKE` to `true`.

```dotenv
CAPTCHAVEL_FAKE=true
Expand Down Expand Up @@ -333,11 +333,11 @@ return [
];
```

This allows (or disables) remembering the user once a v2 challenge is successful. It's disabled by default.
Remembering the user once a V2 challenge is successful is disabled by default.

It's recommended to [use a per-route basis "remember"](#remembering-challenges) if you expect only some routes to remember challenges.
It's recommended to [use a per-route basis "remember"](#remembering-challenges) if you expect only some routes to remember challenges, instead of the whole application.

This also control how many minutes to set the "remember". When zero, the "remember" will last until the session is destroyed or no longer valid.
This also control how many minutes to set the "remember". When zero, the "remember" will last until the session is destroyed or no longer valid.

### Credentials

Expand Down
3 changes: 1 addition & 2 deletions src/Http/Middleware/VerificationHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

use function auth;
use function back;
use function trans;
Expand Down Expand Up @@ -54,7 +53,7 @@ protected function isAuth(array $guards): bool
*/
protected function ensureChallengeIsPresent(Request $request, string $input): void
{
if ($request->missing($input)) {
if ($request->isNotFilled($input)) {
throw ValidationException::withMessages([
$input => trans('captchavel::validation.missing')
])->redirectTo(back()->getTargetUrl());
Expand Down
14 changes: 9 additions & 5 deletions src/Http/Middleware/VerifyReCaptchaV2.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,18 @@ protected function shouldCheckRemember(string $remember): bool
*/
protected function hasRemember(): bool
{
$timestamp = session()->get($this->config->get('recaptcha.remember.key', '_recaptcha'));
$timestamp = session($key = $this->config->get('recaptcha.remember.key', '_recaptcha'));

if ($timestamp === null) {
return false;
if (is_numeric($timestamp)) {
if (!$timestamp || now()->timestamp < $timestamp) {
return true;
}

// Dispose of the session key if we have the opportunity when invalid.
session()->forget($key);
}

// Check the session has a "forever" expiration, or is not expired.
return !$timestamp || now()->timestamp < $timestamp;
return false;
}

/**
Expand Down
37 changes: 18 additions & 19 deletions tests/CaptchavelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use LogicException;
use Mockery;
use Orchestra\Testbench\TestCase;

use function app;

class CaptchavelTest extends TestCase
Expand All @@ -22,10 +21,10 @@ public function test_returns_response()
{
$mock = $this->mock(Factory::class);

$mock->shouldReceive('asForm')->withNoArgs()->once()->andReturnSelf();
$mock->shouldReceive('async')->withNoArgs()->once()->andReturnSelf();
$mock->shouldReceive('withOptions')->with(['version' => 2.0])->once()->andReturnSelf();
$mock->shouldReceive('post')
$mock->expects('asForm')->withNoArgs()->once()->andReturnSelf();
$mock->expects('async')->withNoArgs()->once()->andReturnSelf();
$mock->expects('withOptions')->with(['version' => 2.0])->once()->andReturnSelf();
$mock->expects('post')
->with(
Captchavel::RECAPTCHA_ENDPOINT,
[
Expand Down Expand Up @@ -53,10 +52,10 @@ public function test_uses_v2_test_credentials_by_default(): void
{
$mock = $this->mock(Factory::class);

$mock->shouldReceive('asForm')->withNoArgs()->times(3)->andReturnSelf();
$mock->shouldReceive('async')->withNoArgs()->times(3)->andReturnSelf();
$mock->shouldReceive('withOptions')->with(['version' => 2.0])->times(3)->andReturnSelf();
$mock->shouldReceive('post')
$mock->expects('asForm')->withNoArgs()->times(3)->andReturnSelf();
$mock->expects('async')->withNoArgs()->times(3)->andReturnSelf();
$mock->expects('withOptions')->with(['version' => 2.0])->times(3)->andReturnSelf();
$mock->expects('post')
->with(
Captchavel::RECAPTCHA_ENDPOINT,
[
Expand Down Expand Up @@ -109,11 +108,11 @@ public function test_uses_v2_custom_credentials(): void

$mock = $this->mock(Factory::class);

$mock->shouldReceive('asForm')->withNoArgs()->times(3)->andReturnSelf();
$mock->shouldReceive('async')->withNoArgs()->times(3)->andReturnSelf();
$mock->shouldReceive('withOptions')->with(['version' => 2.0])->times(3)->andReturnSelf();
$mock->expects('asForm')->withNoArgs()->times(3)->andReturnSelf();
$mock->expects('async')->withNoArgs()->times(3)->andReturnSelf();
$mock->expects('withOptions')->with(['version' => 2.0])->times(3)->andReturnSelf();

$mock->shouldReceive('post')
$mock->expects('post')
->with(
Captchavel::RECAPTCHA_ENDPOINT,
[
Expand All @@ -130,7 +129,7 @@ public function test_uses_v2_custom_credentials(): void
])
);

$mock->shouldReceive('post')
$mock->expects('post')
->with(
Captchavel::RECAPTCHA_ENDPOINT,
[
Expand All @@ -147,7 +146,7 @@ public function test_uses_v2_custom_credentials(): void
])
);

$mock->shouldReceive('post')
$mock->expects('post')
->with(
Captchavel::RECAPTCHA_ENDPOINT,
[
Expand Down Expand Up @@ -202,10 +201,10 @@ public function test_receives_v3_secret(): void

$mock = $this->mock(Factory::class);

$mock->shouldReceive('asForm')->withNoArgs()->once()->andReturnSelf();
$mock->shouldReceive('async')->withNoArgs()->once()->andReturnSelf();
$mock->shouldReceive('withOptions')->with(['version' => 2.0])->once()->andReturnSelf();
$mock->shouldReceive('post')
$mock->expects('asForm')->withNoArgs()->once()->andReturnSelf();
$mock->expects('async')->withNoArgs()->once()->andReturnSelf();
$mock->expects('withOptions')->with(['version' => 2.0])->once()->andReturnSelf();
$mock->expects('post')
->with(Captchavel::RECAPTCHA_ENDPOINT, [
'secret' => 'secret',
'response' => 'token',
Expand Down
Loading

0 comments on commit df43d89

Please sign in to comment.