diff --git a/README.md b/README.md index 8804a53..96a6837 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; @@ -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; @@ -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 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()); 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; } /** 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 2fcb043..bf36a56 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'); @@ -180,23 +179,59 @@ 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); - $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 +252,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 +286,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 +312,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 +321,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 +339,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 +348,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 +375,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 +384,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 +402,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 +411,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 +429,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 +438,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 +463,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 +472,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 +497,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 +534,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 +576,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 +617,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 +655,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 +707,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 +768,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 +805,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,13 +860,13 @@ 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(); - $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 @@ -846,13 +881,13 @@ 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(); - $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 @@ -863,8 +898,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(); @@ -872,6 +907,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->expects('isDisabled')->times(3)->andReturnFalse(); + $mock->expects('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([ @@ -880,8 +934,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..0152d85 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; @@ -38,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'); @@ -74,10 +71,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 +137,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,15 +156,13 @@ 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']) ); - $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() @@ -184,11 +179,21 @@ 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); - $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 +213,8 @@ public function test_no_error_if_not_hostname_issued(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $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,7 +233,8 @@ public function test_no_error_if_hostname_same(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $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,7 +253,8 @@ public function test_exception_if_hostname_not_equal(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $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,7 +274,8 @@ public function test_no_error_if_no_apk_issued(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $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,7 +294,8 @@ public function test_no_error_if_apk_same(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $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,7 +314,8 @@ public function test_exception_if_apk_not_equal(): void $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $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,15 +333,13 @@ 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]) ); - $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(); } @@ -339,15 +348,13 @@ 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]) ); - $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(); } @@ -356,7 +363,8 @@ public function test_exception_if_action_not_equal(): void { $mock = $this->spy(Captchavel::class); - $mock->shouldReceive('getChallenge') + $mock->expects('getChallenge') + ->twice() ->with('token', '127.0.0.1', Captchavel::SCORE, Captchavel::INPUT, 'bar') ->andReturn( $this->fulfilledResponse( @@ -366,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')) @@ -387,10 +390,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, [ 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; } }