From 41a0853670b0c54eef3c405dcc0b19c001957127 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 20:32:37 +0200 Subject: [PATCH 1/7] wip --- .gitignore | 1 + src/Exceptions/RestifyHandler.php | 4 +- .../RepositoryUpdateControllerTest.php | 54 +++++++++++++++++++ tests/Fixtures/PostPolicy.php | 5 ++ 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 tests/Controllers/RepositoryUpdateControllerTest.php diff --git a/.gitignore b/.gitignore index 081dddebd..15c88373a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ html output docs/node_modules docs/.vuepress/dist +.phpunit.result.cache diff --git a/src/Exceptions/RestifyHandler.php b/src/Exceptions/RestifyHandler.php index 233d9c9f4..9cc237efc 100644 --- a/src/Exceptions/RestifyHandler.php +++ b/src/Exceptions/RestifyHandler.php @@ -94,13 +94,13 @@ public function render($request, $exception) case $exception instanceof ValidationUnauthorized: case $exception instanceof UnauthorizedHttpException: case $exception instanceof UnauthenticateException: - case $exception instanceof ActionUnauthorizedException: - case $exception instanceof AuthorizationException: case $exception instanceof GatePolicy: case $exception instanceof AuthenticationException: $response->addError($exception->getMessage())->auth(); break; + case $exception instanceof AuthorizationException: + case $exception instanceof ActionUnauthorizedException: case $exception instanceof AccessDeniedHttpException: case $exception instanceof InvalidSignatureException: $response->addError($exception->getMessage())->forbidden(); diff --git a/tests/Controllers/RepositoryUpdateControllerTest.php b/tests/Controllers/RepositoryUpdateControllerTest.php new file mode 100644 index 000000000..fb6149937 --- /dev/null +++ b/tests/Controllers/RepositoryUpdateControllerTest.php @@ -0,0 +1,54 @@ + + */ +class RepositoryUpdateControllerTest extends IntegrationTest +{ + protected function setUp(): void + { + parent::setUp(); + $this->authenticate(); + } + + public function test_basic_update_works() + { + $post = factory(Post::class)->create(['user_id' => 1]); + + $this->withoutExceptionHandling()->patch('/restify-api/posts/' . $post->id, [ + 'title' => 'Updated title', + ]) + ->assertStatus(200); + + $updatedPost = Post::find($post->id); + + $this->assertEquals($updatedPost->title, 'Updated title'); + } + + public function test_unathorized_to_update() + { + $this->app->bind(ExceptionHandler::class, RestifyHandler::class); + + Gate::policy(Post::class, PostPolicy::class); + + $post = factory(Post::class)->create(['user_id' => 1]); + + $_SERVER['restify.post.updateable'] = false; + + $this->patch('/restify-api/posts/' . $post->id, [ + 'title' => 'Updated title', + ])->assertStatus(403) + ->assertJson([ + 'errors' => ['This action is unauthorized.'], + ]); + } +} diff --git a/tests/Fixtures/PostPolicy.php b/tests/Fixtures/PostPolicy.php index 85c78af7d..ccc895be5 100644 --- a/tests/Fixtures/PostPolicy.php +++ b/tests/Fixtures/PostPolicy.php @@ -22,4 +22,9 @@ public function store($user) { return $_SERVER['restify.post.creatable'] ?? true; } + + public function update($user, $post) + { + return $_SERVER['restify.post.updateable'] ?? true; + } } From 10e9fffd7fb5d841540ae8656be2816396951061 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 20:32:56 +0200 Subject: [PATCH 2/7] Apply fixes from StyleCI (#140) --- tests/Controllers/RepositoryUpdateControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Controllers/RepositoryUpdateControllerTest.php b/tests/Controllers/RepositoryUpdateControllerTest.php index fb6149937..26e15d329 100644 --- a/tests/Controllers/RepositoryUpdateControllerTest.php +++ b/tests/Controllers/RepositoryUpdateControllerTest.php @@ -24,7 +24,7 @@ public function test_basic_update_works() { $post = factory(Post::class)->create(['user_id' => 1]); - $this->withoutExceptionHandling()->patch('/restify-api/posts/' . $post->id, [ + $this->withoutExceptionHandling()->patch('/restify-api/posts/'.$post->id, [ 'title' => 'Updated title', ]) ->assertStatus(200); @@ -44,7 +44,7 @@ public function test_unathorized_to_update() $_SERVER['restify.post.updateable'] = false; - $this->patch('/restify-api/posts/' . $post->id, [ + $this->patch('/restify-api/posts/'.$post->id, [ 'title' => 'Updated title', ])->assertStatus(403) ->assertJson([ From 74300095d6ef1eaf0a3aff75c0712ea7b7a3a647 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 20:51:02 +0200 Subject: [PATCH 3/7] wip --- routes/api.php | 1 + src/Exceptions/RestifyHandler.php | 7 +-- .../RepositoryDestroyControllerTest.php | 55 +++++++++++++++++++ .../RepositoryUpdateControllerTest.php | 14 +++++ tests/Fixtures/PostPolicy.php | 5 ++ tests/HandlerTest.php | 13 +++++ 6 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 tests/Controllers/RepositoryDestroyControllerTest.php diff --git a/routes/api.php b/routes/api.php index ed6150abb..1c4808627 100644 --- a/routes/api.php +++ b/routes/api.php @@ -4,4 +4,5 @@ Route::post('/{repository}', 'RepositoryStoreController@handle'); Route::get('/{repository}/{repositoryId}', 'RepositoryShowController@handle'); Route::patch('/{repository}/{repositoryId}', 'RepositoryUpdateController@handle'); +Route::put('/{repository}/{repositoryId}', 'RepositoryUpdateController@handle'); Route::delete('/{repository}/{repositoryId}', 'RepositoryDestroyController@handle'); diff --git a/src/Exceptions/RestifyHandler.php b/src/Exceptions/RestifyHandler.php index 9cc237efc..c8b1ec8b0 100644 --- a/src/Exceptions/RestifyHandler.php +++ b/src/Exceptions/RestifyHandler.php @@ -9,7 +9,6 @@ use Binaryk\LaravelRestify\Exceptions\UnauthorizedException as ActionUnauthorizedException; use Binaryk\LaravelRestify\Restify; use Closure; -use Exception; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Auth\AuthenticationException; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -54,8 +53,8 @@ class RestifyHandler extends ExceptionHandler /** * Render an exception into an HTTP response. * - * @param Request $request - * @param \Exception|Throwable $exception + * @param Request $request + * @param \Exception|Throwable $exception * * @return Response|\Symfony\Component\HttpFoundation\Response * @throws \Illuminate\Contracts\Container\BindingResolutionException @@ -121,7 +120,7 @@ public function render($request, $exception) /** * Report or log an exception. * - * @param \Exception|Throwable $e + * @param \Exception|Throwable $e * @return mixed * * @throws \Exception diff --git a/tests/Controllers/RepositoryDestroyControllerTest.php b/tests/Controllers/RepositoryDestroyControllerTest.php new file mode 100644 index 000000000..39d47e6f2 --- /dev/null +++ b/tests/Controllers/RepositoryDestroyControllerTest.php @@ -0,0 +1,55 @@ + + */ +class RepositoryDestroyControllerTest extends IntegrationTest +{ + protected function setUp(): void + { + parent::setUp(); + $this->authenticate(); + $this->app->bind(ExceptionHandler::class, RestifyHandler::class); + } + + public function test_destroy_works() + { + $post = factory(Post::class)->create(['user_id' => 1]); + + $this->assertInstanceOf(Post::class, Post::find($post->id)); + + $this->withoutExceptionHandling()->delete('/restify-api/posts/' . $post->id, [ + 'title' => 'Updated title', + ]) + ->assertStatus(204); + + $this->assertNull(Post::find($post->id)); + } + + public function test_unathorized_to_destroy() + { + Gate::policy(Post::class, PostPolicy::class); + + $post = factory(Post::class)->create(['user_id' => 1]); + + $_SERVER['restify.post.deletable'] = false; + + $this->delete('/restify-api/posts/' . $post->id, [ + 'title' => 'Updated title', + ])->assertStatus(403) + ->assertJson([ + 'errors' => ['This action is unauthorized.'], + ]); + + $this->assertInstanceOf(Post::class, $post->refresh()); + } +} diff --git a/tests/Controllers/RepositoryUpdateControllerTest.php b/tests/Controllers/RepositoryUpdateControllerTest.php index fb6149937..bdec75318 100644 --- a/tests/Controllers/RepositoryUpdateControllerTest.php +++ b/tests/Controllers/RepositoryUpdateControllerTest.php @@ -34,6 +34,20 @@ public function test_basic_update_works() $this->assertEquals($updatedPost->title, 'Updated title'); } + public function test_put_works() + { + $post = factory(Post::class)->create(['user_id' => 1]); + + $this->withoutExceptionHandling()->put('/restify-api/posts/' . $post->id, [ + 'title' => 'Updated title', + ]) + ->assertStatus(200); + + $updatedPost = Post::find($post->id); + + $this->assertEquals($updatedPost->title, 'Updated title'); + } + public function test_unathorized_to_update() { $this->app->bind(ExceptionHandler::class, RestifyHandler::class); diff --git a/tests/Fixtures/PostPolicy.php b/tests/Fixtures/PostPolicy.php index ccc895be5..161b1a02e 100644 --- a/tests/Fixtures/PostPolicy.php +++ b/tests/Fixtures/PostPolicy.php @@ -27,4 +27,9 @@ public function update($user, $post) { return $_SERVER['restify.post.updateable'] ?? true; } + + public function delete($user, $post) + { + return $_SERVER['restify.post.deletable'] ?? true; + } } diff --git a/tests/HandlerTest.php b/tests/HandlerTest.php index 1def7bac5..aca2d87a8 100644 --- a/tests/HandlerTest.php +++ b/tests/HandlerTest.php @@ -7,6 +7,7 @@ use Binaryk\LaravelRestify\Exceptions\Guard\GatePolicy; use Binaryk\LaravelRestify\Exceptions\RestifyHandler; use Binaryk\LaravelRestify\Exceptions\UnauthenticateException; +use Binaryk\LaravelRestify\Restify; use Illuminate\Auth\AuthenticationException; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Foundation\Testing\Concerns\InteractsWithContainer; @@ -150,4 +151,16 @@ public function test_default_unhandled_exception_production() $this->assertObjectHasAttribute('errors', $response->getData()); $this->assertEquals($response->getData()->errors[0], __('messages.something_went_wrong')); } + + public function test_can_inject_custom_handler_but_handler_will_continue_handle() + { + Restify::exceptionHandler(function ($request, $exception) { + $this->assertInstanceOf(NotFoundHttpException::class, $exception); + }); + + $response = $this->handler->render($this->request, new NotFoundHttpException('This message is not visible')); + $this->assertInstanceOf(JsonResponse::class, $response); + $this->assertEquals($response->getData()->errors[0], __('messages.not_found')); + $this->assertEquals($response->getStatusCode(), 404); + } } From 8dd6061207b73609a955e9e2f30f70f749290aba Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 20:51:38 +0200 Subject: [PATCH 4/7] Apply fixes from StyleCI (#142) --- tests/Controllers/RepositoryDestroyControllerTest.php | 4 ++-- tests/Controllers/RepositoryUpdateControllerTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Controllers/RepositoryDestroyControllerTest.php b/tests/Controllers/RepositoryDestroyControllerTest.php index 39d47e6f2..f229dab53 100644 --- a/tests/Controllers/RepositoryDestroyControllerTest.php +++ b/tests/Controllers/RepositoryDestroyControllerTest.php @@ -27,7 +27,7 @@ public function test_destroy_works() $this->assertInstanceOf(Post::class, Post::find($post->id)); - $this->withoutExceptionHandling()->delete('/restify-api/posts/' . $post->id, [ + $this->withoutExceptionHandling()->delete('/restify-api/posts/'.$post->id, [ 'title' => 'Updated title', ]) ->assertStatus(204); @@ -43,7 +43,7 @@ public function test_unathorized_to_destroy() $_SERVER['restify.post.deletable'] = false; - $this->delete('/restify-api/posts/' . $post->id, [ + $this->delete('/restify-api/posts/'.$post->id, [ 'title' => 'Updated title', ])->assertStatus(403) ->assertJson([ diff --git a/tests/Controllers/RepositoryUpdateControllerTest.php b/tests/Controllers/RepositoryUpdateControllerTest.php index e41c5ba31..625938b59 100644 --- a/tests/Controllers/RepositoryUpdateControllerTest.php +++ b/tests/Controllers/RepositoryUpdateControllerTest.php @@ -38,7 +38,7 @@ public function test_put_works() { $post = factory(Post::class)->create(['user_id' => 1]); - $this->withoutExceptionHandling()->put('/restify-api/posts/' . $post->id, [ + $this->withoutExceptionHandling()->put('/restify-api/posts/'.$post->id, [ 'title' => 'Updated title', ]) ->assertStatus(200); From b370f601c1043791c023a2852db795abd2460aaf Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 21:08:01 +0200 Subject: [PATCH 5/7] wip --- tests/RepositoryWithRoutesTest.php | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tests/RepositoryWithRoutesTest.php b/tests/RepositoryWithRoutesTest.php index 53c0f0503..2b70abd96 100644 --- a/tests/RepositoryWithRoutesTest.php +++ b/tests/RepositoryWithRoutesTest.php @@ -21,6 +21,7 @@ protected function setUp(): void WithCustomPrefix::class, WithCustomMiddleware::class, WithCustomNamespace::class, + WithoutGroup::class, ]); parent::setUp(); @@ -28,7 +29,7 @@ protected function setUp(): void public function test_can_add_custom_routes() { - $this->get(Restify::path(RepositoryWithRoutes::uriKey()).'/main-testing')->assertStatus(200) + $this->get(Restify::path(RepositoryWithRoutes::uriKey()) . '/main-testing')->assertStatus(200) ->assertJson([ 'success' => true, ]); @@ -62,6 +63,18 @@ public function test_can_use_custom_namespace() ], ]); } + + public function test_routes_default_wrapped() + { + $this->withoutExceptionHandling()->getJson(route('no.group.default.options')) + ->assertStatus(200) + ->assertJson([ + 'meta' => [ + 'message' => 'From the sayHello method', + ], + ]); + + } } class RepositoryWithRoutes extends Repository @@ -69,8 +82,9 @@ class RepositoryWithRoutes extends Repository /** * @param Router $router * @param array $attributes + * @param bool $wrap */ - public static function routes(Router $router, $attributes) + public static function routes(Router $router, $attributes, $wrap = false) { $router->group($attributes, function ($router) { $router->get('/main-testing', function () { @@ -89,7 +103,7 @@ public static function uriKey() class WithCustomPrefix extends RepositoryWithRoutes { - public static function routes(Router $router, $attributes) + public static function routes(Router $router, $attributes, $wrap = false) { $attributes['prefix'] = 'custom-prefix'; @@ -115,7 +129,7 @@ public function handle($request, $next) class WithCustomMiddleware extends RepositoryWithRoutes { - public static function routes(Router $router, $options) + public static function routes(Router $router, $options, $wrap = false) { $options['middleware'] = [MiddlewareFail::class]; @@ -131,7 +145,7 @@ public static function routes(Router $router, $options) class WithCustomNamespace extends RepositoryWithRoutes { - public static function routes(Router $router, $options) + public static function routes(Router $router, $options, $wrap = false) { $options['namespace'] = 'Binaryk\LaravelRestify\Tests'; @@ -141,6 +155,14 @@ public static function routes(Router $router, $options) } } +class WithoutGroup extends RepositoryWithRoutes +{ + public static function routes(Router $router, $options = [], $wrap = true) + { + $router->get('default-options', '\\' . HandleController::class . '@sayHello')->name('no.group.default.options'); + } +} + class HandleController extends RestController { /** From 5bfbb2c08f05196abe9c7ce1613d3ecc399b9227 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 21:08:33 +0200 Subject: [PATCH 6/7] Apply fixes from StyleCI (#143) --- tests/RepositoryWithRoutesTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/RepositoryWithRoutesTest.php b/tests/RepositoryWithRoutesTest.php index 2b70abd96..b433df6ae 100644 --- a/tests/RepositoryWithRoutesTest.php +++ b/tests/RepositoryWithRoutesTest.php @@ -29,7 +29,7 @@ protected function setUp(): void public function test_can_add_custom_routes() { - $this->get(Restify::path(RepositoryWithRoutes::uriKey()) . '/main-testing')->assertStatus(200) + $this->get(Restify::path(RepositoryWithRoutes::uriKey()).'/main-testing')->assertStatus(200) ->assertJson([ 'success' => true, ]); @@ -73,7 +73,6 @@ public function test_routes_default_wrapped() 'message' => 'From the sayHello method', ], ]); - } } @@ -159,7 +158,7 @@ class WithoutGroup extends RepositoryWithRoutes { public static function routes(Router $router, $options = [], $wrap = true) { - $router->get('default-options', '\\' . HandleController::class . '@sayHello')->name('no.group.default.options'); + $router->get('default-options', '\\'.HandleController::class.'@sayHello')->name('no.group.default.options'); } } From 5102e8035d0d524703593a7ecb6a11c105d70332 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Sun, 8 Mar 2020 21:12:28 +0200 Subject: [PATCH 7/7] wip --- src/Fields/Field.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 85bc20742..29173609b 100644 --- a/src/Fields/Field.php +++ b/src/Fields/Field.php @@ -153,7 +153,7 @@ public function getAttribute() /** * Validation rules for store. - * @param callable|array|string $rules + * @param $rules * @return Field */ public function storingRules($rules) @@ -166,7 +166,7 @@ public function storingRules($rules) /** * Validation rules for update. * - * @param callable|array|string $rules + * @param $rules * @return Field */ public function updatingRules($rules) @@ -178,7 +178,7 @@ public function updatingRules($rules) /** * Validation rules for store. - * @param callable|array|string $rules + * @param $rules * @return Field */ public function rules($rules)