From 82a68156444b091a731a296d8948b84f14ca1072 Mon Sep 17 00:00:00 2001 From: Italo Date: Mon, 15 Nov 2021 01:54:29 -0300 Subject: [PATCH 01/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8804a53..68b586f 100644 --- a/README.md +++ b/README.md @@ -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; From d053d85ea46d098a90572ecce963a3906dde9c3c Mon Sep 17 00:00:00 2001 From: Italo Date: Mon, 15 Nov 2021 01:55:37 -0300 Subject: [PATCH 02/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68b586f..fd6fe25 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ 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 From d9ba6cc920151ca929130e9390918d5589d847ff Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Mon, 15 Nov 2021 02:09:56 -0300 Subject: [PATCH 03/13] Added test to enforce check if remember expired. --- .../Middleware/ChallengeMiddlewareTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Http/Middleware/ChallengeMiddlewareTest.php b/tests/Http/Middleware/ChallengeMiddlewareTest.php index 2fcb043..577c8b3 100644 --- a/tests/Http/Middleware/ChallengeMiddlewareTest.php +++ b/tests/Http/Middleware/ChallengeMiddlewareTest.php @@ -872,6 +872,25 @@ public function test_doesnt_bypasses_check_if_session_has_not_remember(): void $this->post('v2/android')->assertSessionHasErrors(); } + public function test_doesnt_bypasses_check_if_remember_has_expired_and_deletes_key(): void + { + config([ + 'captchavel.remember.enabled' => true, + ]); + + $this->session(['_recaptcha' => now()->subSecond()->getTimestamp()]); + + $mock = $this->mock(Captchavel::class); + + $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); + $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->shouldNotReceive('getChallenge'); + + $this->post('v2/checkbox')->assertSessionHasErrors()->assertSessionMissing('_recaptcha'); + $this->post('v2/invisible')->assertSessionHasErrors()->assertSessionMissing('_recaptcha'); + $this->post('v2/android')->assertSessionHasErrors()->assertSessionMissing('_recaptcha'); + } + public function test_doesnt_bypasses_check_if_remember_disabled_when_config_overridden(): void { config([ From 45334ce077f174c9e62fc7a7c3e6d2b4fab565f3 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Mon, 15 Nov 2021 02:10:22 -0300 Subject: [PATCH 04/13] Removes key if expired. --- src/Http/Middleware/VerifyReCaptchaV2.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Http/Middleware/VerifyReCaptchaV2.php b/src/Http/Middleware/VerifyReCaptchaV2.php index 9d4de68..ad1ca3a 100644 --- a/src/Http/Middleware/VerifyReCaptchaV2.php +++ b/src/Http/Middleware/VerifyReCaptchaV2.php @@ -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; } /** From d0d03e89a96845b586953528c9092906ee80cd36 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Mon, 15 Nov 2021 02:11:31 -0300 Subject: [PATCH 05/13] Added test to check if key not deleted when not expired. --- tests/Http/Middleware/ChallengeMiddlewareTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Http/Middleware/ChallengeMiddlewareTest.php b/tests/Http/Middleware/ChallengeMiddlewareTest.php index 577c8b3..0f7e558 100644 --- a/tests/Http/Middleware/ChallengeMiddlewareTest.php +++ b/tests/Http/Middleware/ChallengeMiddlewareTest.php @@ -829,9 +829,9 @@ public function test_bypasses_check_if_session_has_remember_not_expired(): void $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); - $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk(); - $this->post('v2/invisible', [Captchavel::INPUT => 'token'])->assertOk(); - $this->post('v2/android', [Captchavel::INPUT => 'token'])->assertOk(); + $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk()->assertSessionHas('_recaptcha'); + $this->post('v2/invisible', [Captchavel::INPUT => 'token'])->assertOk()->assertSessionHas('_recaptcha'); + $this->post('v2/android', [Captchavel::INPUT => 'token'])->assertOk()->assertSessionHas('_recaptcha'); } public function test_bypasses_check_if_session_has_remember_forever(): void @@ -850,9 +850,9 @@ public function test_bypasses_check_if_session_has_remember_forever(): void $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); - $this->post('v2/checkbox')->assertOk(); - $this->post('v2/invisible')->assertOk(); - $this->post('v2/android')->assertOk(); + $this->post('v2/checkbox')->assertOk()->assertSessionHas('_recaptcha'); + $this->post('v2/invisible')->assertOk()->assertSessionHas('_recaptcha'); + $this->post('v2/android')->assertOk()->assertSessionHas('_recaptcha'); } public function test_doesnt_bypasses_check_if_session_has_not_remember(): void From 4bf992a8a5b59cdbe019b4208026077a8aac0660 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Mon, 15 Nov 2021 02:15:55 -0300 Subject: [PATCH 06/13] Multiple fixes. --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fd6fe25..96a6837 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Route::post('login', [LoginController::class, 'login']) 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; @@ -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; @@ -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. @@ -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; @@ -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 @@ -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 From 71003833916f980eea22b81c7c1201100f052556 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:29:19 -0300 Subject: [PATCH 07/13] Updates mockery legacy methods. --- tests/CaptchavelTest.php | 37 ++- .../Middleware/ChallengeMiddlewareTest.php | 215 +++++++++--------- tests/Http/Middleware/ScoreMiddlewareTest.php | 39 ++-- 3 files changed, 144 insertions(+), 147 deletions(-) diff --git a/tests/CaptchavelTest.php b/tests/CaptchavelTest.php index 6d88990..cbcb122 100644 --- a/tests/CaptchavelTest.php +++ b/tests/CaptchavelTest.php @@ -10,7 +10,6 @@ use LogicException; use Mockery; use Orchestra\Testbench\TestCase; - use function app; class CaptchavelTest extends TestCase @@ -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, [ @@ -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, [ @@ -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, [ @@ -130,7 +129,7 @@ public function test_uses_v2_custom_credentials(): void ]) ); - $mock->shouldReceive('post') + $mock->expects('post') ->with( Captchavel::RECAPTCHA_ENDPOINT, [ @@ -147,7 +146,7 @@ public function test_uses_v2_custom_credentials(): void ]) ); - $mock->shouldReceive('post') + $mock->expects('post') ->with( Captchavel::RECAPTCHA_ENDPOINT, [ @@ -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', diff --git a/tests/Http/Middleware/ChallengeMiddlewareTest.php b/tests/Http/Middleware/ChallengeMiddlewareTest.php index 0f7e558..383d822 100644 --- a/tests/Http/Middleware/ChallengeMiddlewareTest.php +++ b/tests/Http/Middleware/ChallengeMiddlewareTest.php @@ -8,7 +8,6 @@ use Orchestra\Testbench\TestCase; use Tests\CreatesFulfilledResponse; use Tests\RegistersPackage; - use function app; use function config; use function now; @@ -99,19 +98,19 @@ public function test_validates_if_real(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge')->once() + $mock->expects('getChallenge')->once() ->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge')->once() + $mock->expects('getChallenge')->once() ->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge')->once() + $mock->expects('getChallenge')->once() ->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk(); @@ -123,8 +122,8 @@ public function test_uses_custom_input(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -132,11 +131,11 @@ public function test_uses_custom_input(): void 'foo' => 'bar', ], 'bar'); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', 'bar')->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', 'bar')->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', 'bar')->andReturn($response); $this->post('v2/checkbox/input_bar', ['bar' => 'token'])->assertOk(); @@ -148,8 +147,8 @@ public function test_exception_when_token_absent(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(12)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(12)->andReturnFalse(); + $mock->expects('isDisabled')->times(12)->andReturnFalse(); + $mock->expects('shouldFake')->times(12)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); @@ -184,19 +183,19 @@ public function test_exception_when_response_failed(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(6)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(6)->andReturnFalse(); + $mock->expects('isDisabled')->times(6)->andReturnFalse(); + $mock->expects('shouldFake')->times(6)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => false, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -217,18 +216,18 @@ public function test_exception_when_response_invalid(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(6)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(6)->andReturnFalse(); + $mock->expects('isDisabled')->times(6)->andReturnFalse(); + $mock->expects('shouldFake')->times(6)->andReturnFalse(); $response = $this->fulfilledResponse([ 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -251,19 +250,19 @@ public function test_no_error_if_not_hostname_issued(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk(); @@ -277,8 +276,8 @@ public function test_no_error_if_not_hostname_same(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -286,11 +285,11 @@ public function test_no_error_if_not_hostname_same(): void 'hostname' => 'foo', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk(); @@ -304,8 +303,8 @@ public function test_exception_if_hostname_not_equal(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(6)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(6)->andReturnFalse(); + $mock->expects('isDisabled')->times(6)->andReturnFalse(); + $mock->expects('shouldFake')->times(6)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -313,11 +312,11 @@ public function test_exception_if_hostname_not_equal(): void 'hostname' => 'foo', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -340,8 +339,8 @@ public function test_no_error_if_no_apk_issued(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -349,11 +348,11 @@ public function test_no_error_if_no_apk_issued(): void 'apk_package_name' => 'foo', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk(); @@ -367,8 +366,8 @@ public function test_no_error_if_no_apk_same(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -376,11 +375,11 @@ public function test_no_error_if_no_apk_same(): void 'apk_package_name' => 'foo', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk(); @@ -394,8 +393,8 @@ public function test_exception_if_apk_not_equal(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(6)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(6)->andReturnFalse(); + $mock->expects('isDisabled')->times(6)->andReturnFalse(); + $mock->expects('shouldFake')->times(6)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -403,11 +402,11 @@ public function test_exception_if_apk_not_equal(): void 'apk_package_name' => 'foo', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->twice()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -428,8 +427,8 @@ public function test_challenge_is_not_remembered_by_default(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, @@ -437,11 +436,11 @@ public function test_challenge_is_not_remembered_by_default(): void 'apk_package_name' => 'foo', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -462,19 +461,19 @@ public function test_challenge_is_remembered_in_session(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -499,19 +498,19 @@ public function test_challenge_is_remembered_in_session_when_config_overridden() $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox/remember', [Captchavel::INPUT => 'token']) @@ -541,19 +540,19 @@ public function test_challenge_is_remembered_in_session_using_custom_key(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -582,19 +581,19 @@ public function test_challenge_is_remembered_in_session_with_custom_key_when_con $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox/remember', [Captchavel::INPUT => 'token']) @@ -620,19 +619,19 @@ public function test_challenge_is_remembered_forever(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->app['router']->post('v2/checkbox/forever', function () { @@ -672,19 +671,19 @@ public function test_challenge_is_remembered_forever_when_config_overridden(): v { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->app['router']->post('v2/checkbox/forever', function () { @@ -733,19 +732,19 @@ public function test_challenge_is_remembered_with_different_offset(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->post('v2/checkbox', [Captchavel::INPUT => 'token']) @@ -770,19 +769,19 @@ public function test_challenge_is_not_remembered_when_config_overridden(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $response = $this->fulfilledResponse([ 'success' => true, 'foo' => 'bar', ]); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'checkbox', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'invisible', Captchavel::INPUT)->andReturn($response); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->once()->with('token', '127.0.0.1', 'android', Captchavel::INPUT)->andReturn($response); $this->app['router']->post('v2/checkbox/dont-remember', function () { @@ -825,8 +824,8 @@ public function test_bypasses_check_if_session_has_remember_not_expired(): void '_recaptcha' => now()->addMinute()->getTimestamp() ]); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); $this->post('v2/checkbox', [Captchavel::INPUT => 'token'])->assertOk()->assertSessionHas('_recaptcha'); @@ -846,8 +845,8 @@ public function test_bypasses_check_if_session_has_remember_forever(): void '_recaptcha' => 0 ]); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); $this->post('v2/checkbox')->assertOk()->assertSessionHas('_recaptcha'); @@ -863,8 +862,8 @@ public function test_doesnt_bypasses_check_if_session_has_not_remember(): void $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); $this->post('v2/checkbox')->assertSessionHasErrors(); @@ -882,8 +881,8 @@ public function test_doesnt_bypasses_check_if_remember_has_expired_and_deletes_k $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); $this->post('v2/checkbox')->assertSessionHasErrors()->assertSessionMissing('_recaptcha'); @@ -899,8 +898,8 @@ public function test_doesnt_bypasses_check_if_remember_disabled_when_config_over $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->times(3)->andReturnFalse(); - $mock->shouldReceive('shouldFake')->times(3)->andReturnFalse(); + $mock->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('shouldFake')->times(3)->andReturnFalse(); $mock->shouldNotReceive('getChallenge'); $this->app['router']->post('v2/checkbox/dont-remember', function () { diff --git a/tests/Http/Middleware/ScoreMiddlewareTest.php b/tests/Http/Middleware/ScoreMiddlewareTest.php index 054e073..a7be717 100644 --- a/tests/Http/Middleware/ScoreMiddlewareTest.php +++ b/tests/Http/Middleware/ScoreMiddlewareTest.php @@ -14,7 +14,6 @@ use Orchestra\Testbench\TestCase; use Tests\CreatesFulfilledResponse; use Tests\RegistersPackage; - use function config; use function trans; @@ -74,10 +73,10 @@ public function test_validates_if_real(): void { $mock = $this->mock(Captchavel::class); - $mock->shouldReceive('isDisabled')->once()->andReturnFalse(); + $mock->expects('isDisabled')->once()->andReturnFalse(); - $mock->shouldReceive('shouldFake')->once()->andReturnFalse(); - $mock->shouldReceive('getChallenge') + $mock->expects('shouldFake')->once()->andReturnFalse(); + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse([ @@ -140,7 +139,7 @@ public function test_uses_custom_threshold(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'foo' => 'bar']) @@ -159,7 +158,7 @@ public function test_uses_custom_input(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, 'foo', null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'foo' => 'bar']) @@ -188,7 +187,7 @@ public function test_exception_when_response_invalid(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => false, 'score' => 0.7, 'foo' => 'bar']) @@ -208,7 +207,7 @@ public function test_no_error_if_not_hostname_issued(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'hostname' => 'foo']) @@ -227,7 +226,7 @@ public function test_no_error_if_hostname_same(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'hostname' => 'bar']) @@ -246,7 +245,7 @@ public function test_exception_if_hostname_not_equal(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'hostname' => 'foo']) @@ -266,7 +265,7 @@ public function test_no_error_if_no_apk_issued(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'apk_package_name' => 'foo']) @@ -285,7 +284,7 @@ public function test_no_error_if_apk_same(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'apk_package_name' => 'foo']) @@ -304,7 +303,7 @@ public function test_exception_if_apk_not_equal(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'apk_package_name' => null]) @@ -322,7 +321,7 @@ public function test_no_error_if_no_action(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) @@ -339,7 +338,7 @@ public function test_no_error_if_action_same(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, 'foo') ->andReturn( $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) @@ -356,7 +355,7 @@ public function test_exception_if_action_not_equal(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, 'bar') ->andReturn( $this->fulfilledResponse( @@ -387,10 +386,10 @@ public function test_checks_for_human_score(): void $mock = $this->mock(Factory::class); - $mock->shouldReceive('async')->withNoArgs()->times(4)->andReturnSelf(); - $mock->shouldReceive('asForm')->withNoArgs()->times(4)->andReturnSelf(); - $mock->shouldReceive('withOptions')->with(['version' => 2.0])->times(4)->andReturnSelf(); - $mock->shouldReceive('post') + $mock->expects('async')->withNoArgs()->times(4)->andReturnSelf(); + $mock->expects('asForm')->withNoArgs()->times(4)->andReturnSelf(); + $mock->expects('withOptions')->with(['version' => 2.0])->times(4)->andReturnSelf(); + $mock->expects('post') ->with( Captchavel::RECAPTCHA_ENDPOINT, [ From 7663b592b9d42dfe4e3b1d20cfc7187a734896d5 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:33:54 -0300 Subject: [PATCH 08/13] Fixes input filled with null values. #47 --- src/Http/Middleware/VerificationHelpers.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Http/Middleware/VerificationHelpers.php b/src/Http/Middleware/VerificationHelpers.php index aa2f1f8..2210509 100644 --- a/src/Http/Middleware/VerificationHelpers.php +++ b/src/Http/Middleware/VerificationHelpers.php @@ -4,7 +4,6 @@ use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; - use function auth; use function back; use function trans; @@ -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()); From eafab4b004464e0929ebd44f0b574dc2ea9dd162 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:35:01 -0300 Subject: [PATCH 09/13] Fixes expectations count. --- tests/Http/Middleware/ScoreMiddlewareTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/Http/Middleware/ScoreMiddlewareTest.php b/tests/Http/Middleware/ScoreMiddlewareTest.php index a7be717..8f742ba 100644 --- a/tests/Http/Middleware/ScoreMiddlewareTest.php +++ b/tests/Http/Middleware/ScoreMiddlewareTest.php @@ -208,6 +208,7 @@ public function test_no_error_if_not_hostname_issued(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'hostname' => 'foo']) @@ -227,6 +228,7 @@ public function test_no_error_if_hostname_same(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'hostname' => 'bar']) @@ -246,6 +248,7 @@ public function test_exception_if_hostname_not_equal(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'hostname' => 'foo']) @@ -266,6 +269,7 @@ public function test_no_error_if_no_apk_issued(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'apk_package_name' => 'foo']) @@ -285,6 +289,7 @@ public function test_no_error_if_apk_same(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'apk_package_name' => 'foo']) @@ -304,6 +309,7 @@ public function test_exception_if_apk_not_equal(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'apk_package_name' => null]) @@ -322,6 +328,7 @@ public function test_no_error_if_no_action(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) @@ -339,6 +346,7 @@ public function test_no_error_if_action_same(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, 'foo') ->andReturn( $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) @@ -356,6 +364,7 @@ public function test_exception_if_action_not_equal(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, 'bar') ->andReturn( $this->fulfilledResponse( From 255affa889d8d952f695fdc8edb7de1757823ca2 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:35:41 -0300 Subject: [PATCH 10/13] Add tests for null input. --- tests/Http/Middleware/ScoreMiddlewareTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Http/Middleware/ScoreMiddlewareTest.php b/tests/Http/Middleware/ScoreMiddlewareTest.php index 8f742ba..d97c9fb 100644 --- a/tests/Http/Middleware/ScoreMiddlewareTest.php +++ b/tests/Http/Middleware/ScoreMiddlewareTest.php @@ -183,6 +183,16 @@ public function test_exception_when_token_absent(): void ->assertJsonValidationErrors(Captchavel::INPUT); } + public function test_exception_when_token_null(): void + { + $this->post('v3/default', [Captchavel::INPUT => null]) + ->assertSessionHasErrors(Captchavel::INPUT, trans('captchavel::validation.error')) + ->assertRedirect('/'); + + $this->postJson('v3/default', [Captchavel::INPUT => null]) + ->assertJsonValidationErrors(Captchavel::INPUT); + } + public function test_exception_when_response_invalid(): void { $mock = $this->spy(Captchavel::class); From 62dc051eaf2c572fdb716afa9fb28ca38aea27b3 Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:35:59 -0300 Subject: [PATCH 11/13] Add tests for null input on non-score middleware. --- .../Middleware/ChallengeMiddlewareTest.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/Http/Middleware/ChallengeMiddlewareTest.php b/tests/Http/Middleware/ChallengeMiddlewareTest.php index 383d822..bf36a56 100644 --- a/tests/Http/Middleware/ChallengeMiddlewareTest.php +++ b/tests/Http/Middleware/ChallengeMiddlewareTest.php @@ -179,6 +179,42 @@ public function test_exception_when_token_absent(): void $this->postJson('v2/android/input_bar')->assertJsonValidationErrors('bar'); } + public function test_exception_when_token_null(): void + { + $mock = $this->mock(Captchavel::class); + + $mock->expects('isDisabled')->times(12)->andReturnFalse(); + $mock->expects('shouldFake')->times(12)->andReturnFalse(); + + $mock->allows('getChallenge')->never(); + + $this->post('v2/checkbox', [Captchavel::INPUT => null]) + ->assertSessionHasErrors(Captchavel::INPUT, trans('captchavel::validation.missing')) + ->assertRedirect('/'); + $this->postJson('v2/checkbox')->assertJsonValidationErrors(Captchavel::INPUT); + $this->post('v2/invisible', [Captchavel::INPUT => null]) + ->assertSessionHasErrors(Captchavel::INPUT, trans('captchavel::validation.missing')) + ->assertRedirect('/'); + $this->postJson('v2/invisible')->assertJsonValidationErrors(Captchavel::INPUT); + $this->post('v2/android', [Captchavel::INPUT => null]) + ->assertSessionHasErrors(Captchavel::INPUT, trans('captchavel::validation.missing')) + ->assertRedirect('/'); + $this->postJson('v2/android', [Captchavel::INPUT => null])->assertJsonValidationErrors(Captchavel::INPUT); + + $this->post('v2/checkbox/input_bar', ['bar' => null]) + ->assertSessionHasErrors('bar', trans('captchavel::validation.missing')) + ->assertRedirect('/'); + $this->postJson('v2/checkbox/input_bar')->assertJsonValidationErrors('bar'); + $this->post('v2/invisible/input_bar', ['bar' => null]) + ->assertSessionHasErrors('bar', trans('captchavel::validation.missing')) + ->assertRedirect('/'); + $this->postJson('v2/invisible/input_bar')->assertJsonValidationErrors('bar'); + $this->post('v2/android/input_bar', ['bar' => null]) + ->assertSessionHasErrors('bar', trans('captchavel::validation.missing')) + ->assertRedirect('/'); + $this->postJson('v2/android/input_bar', ['bar' => null])->assertJsonValidationErrors('bar'); + } + public function test_exception_when_response_failed(): void { $mock = $this->mock(Captchavel::class); From fcbe71053b6df5fb2a8dd29ff7f3b02c21bbc97a Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:45:34 -0300 Subject: [PATCH 12/13] Fixed expectation count. --- tests/Http/Middleware/ScoreMiddlewareTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Http/Middleware/ScoreMiddlewareTest.php b/tests/Http/Middleware/ScoreMiddlewareTest.php index d97c9fb..984c12d 100644 --- a/tests/Http/Middleware/ScoreMiddlewareTest.php +++ b/tests/Http/Middleware/ScoreMiddlewareTest.php @@ -338,7 +338,6 @@ public function test_no_error_if_no_action(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') - ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, null) ->andReturn( $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) @@ -356,7 +355,6 @@ public function test_no_error_if_action_same(): void $mock = $this->spy(Captchavel::class); $mock->expects('getChallenge') - ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, 'foo') ->andReturn( $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) From 39aeb29780a70563c927f28c058b3fbf11df254a Mon Sep 17 00:00:00 2001 From: DarkGhosthunter Date: Tue, 21 Dec 2021 14:52:03 -0300 Subject: [PATCH 13/13] Updated tests and removed redundant closures. --- tests/Http/Middleware/ScoreMiddlewareTest.php | 23 +---- .../Middleware/UsesRoutesWithMiddleware.php | 95 +++++-------------- 2 files changed, 29 insertions(+), 89 deletions(-) diff --git a/tests/Http/Middleware/ScoreMiddlewareTest.php b/tests/Http/Middleware/ScoreMiddlewareTest.php index 984c12d..0152d85 100644 --- a/tests/Http/Middleware/ScoreMiddlewareTest.php +++ b/tests/Http/Middleware/ScoreMiddlewareTest.php @@ -37,9 +37,7 @@ function (): void { public function test_fakes_response_if_authenticated_in_guard(): void { - $this->app['router']->post('v3/guarded', function (ReCaptchaResponse $response) { - return $response; - })->middleware(ReCaptcha::score()->except('web')->toString()); + $this->app['router']->post('v3/guarded', [__CLASS__, 'returnSameResponse'])->middleware(ReCaptcha::score()->except('web')->toString()); $this->actingAs(User::make(), 'web'); @@ -164,9 +162,7 @@ public function test_uses_custom_input(): void $this->fulfilledResponse(['success' => true, 'score' => 0.7, 'foo' => 'bar']) ); - $this->app['router']->post('test', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:null,null,foo'); + $this->app['router']->post('test', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:null,null,foo'); $this->post('test', ['foo' => 'token']) ->assertOk() @@ -343,9 +339,7 @@ public function test_no_error_if_no_action(): void $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) ); - $this->app['router']->post('test', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:null,null'); + $this->app['router']->post('test', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:null,null'); $this->post('test', [Captchavel::INPUT => 'token'])->assertOk(); } @@ -360,9 +354,7 @@ public function test_no_error_if_action_same(): void $this->fulfilledResponse(['success' => true, 'action' => 'foo', 'apk_package_name' => null]) ); - $this->app['router']->post('test', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:null,foo'); + $this->app['router']->post('test', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:null,foo'); $this->post('test', [Captchavel::INPUT => 'token'])->assertOk(); } @@ -382,12 +374,7 @@ public function test_exception_if_action_not_equal(): void ) ); - $this->app['router']->post( - 'test', - function (ReCaptchaResponse $response) { - return $response; - } - )->middleware('recaptcha.score:null,bar'); + $this->app['router']->post('test', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:null,bar'); $this->post('test', [Captchavel::INPUT => 'token']) ->assertSessionHasErrors(Captchavel::INPUT, trans('captchavel::validation.match')) diff --git a/tests/Http/Middleware/UsesRoutesWithMiddleware.php b/tests/Http/Middleware/UsesRoutesWithMiddleware.php index 1bd89ac..3844aef 100644 --- a/tests/Http/Middleware/UsesRoutesWithMiddleware.php +++ b/tests/Http/Middleware/UsesRoutesWithMiddleware.php @@ -3,6 +3,7 @@ namespace Tests\Http\Middleware; use DarkGhostHunter\Captchavel\Http\ReCaptchaResponse; +use function app; trait UsesRoutesWithMiddleware { @@ -10,78 +11,30 @@ protected function createsRoutes() { config(['captchavel.enable' => true]); - $this->app['router']->post('v3/default', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score'); - - $this->app['router']->post('v3/threshold_1', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:1.0'); - - $this->app['router']->post('v3/threshold_0', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:0'); - - $this->app['router']->post('v3/action_foo', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:null,foo'); - - $this->app['router']->post('v3/input_bar', function (ReCaptchaResponse $response) { - return $response; - })->middleware('recaptcha.score:null,null,bar'); - - $this->app['router']->post('v2/checkbox', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:checkbox'); - - $this->app['router']->post('v2/checkbox/input_bar', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:checkbox,null,bar'); - - $this->app['router']->post('v2/checkbox/remember', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:checkbox,10'); - - $this->app['router']->post('v2/invisible', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:invisible'); - - $this->app['router']->post('v2/invisible/input_bar', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:invisible,null,bar'); - - $this->app['router']->post('v2/invisible/remember', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:invisible,10'); - - $this->app['router']->post('v2/android', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:android'); + $this->app['router']->post('v3/default', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score'); + $this->app['router']->post('v3/threshold_1', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:1.0'); + $this->app['router']->post('v3/threshold_0', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:0'); + $this->app['router']->post('v3/action_foo', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:null,foo'); + $this->app['router']->post('v3/input_bar', [__CLASS__, 'returnSameResponse'])->middleware('recaptcha.score:null,null,bar'); + + $this->app['router']->post('v2/checkbox', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:checkbox'); + $this->app['router']->post('v2/checkbox/input_bar', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:checkbox,null,bar'); + $this->app['router']->post('v2/checkbox/remember', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:checkbox,10'); + $this->app['router']->post('v2/invisible', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:invisible'); + $this->app['router']->post('v2/invisible/input_bar', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:invisible,null,bar'); + $this->app['router']->post('v2/invisible/remember', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:invisible,10'); + $this->app['router']->post('v2/android', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:android'); + $this->app['router']->post('v2/android/input_bar', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:android,null,bar'); + $this->app['router']->post('v2/android/remember', [__CLASS__, 'returnResponseIfExists'])->middleware('recaptcha:android,10'); + } - $this->app['router']->post('v2/android/input_bar', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:android,null,bar'); + public static function returnSameResponse(ReCaptchaResponse $response): ReCaptchaResponse + { + return $response; + } - $this->app['router']->post('v2/android/remember', function () { - if (app()->has(ReCaptchaResponse::class)) { - return app(ReCaptchaResponse::class); - } - })->middleware('recaptcha:android,10'); + public static function returnResponseIfExists(): ?ReCaptchaResponse + { + return app()->has(ReCaptchaResponse::class) ? app(ReCaptchaResponse::class) : null; } }