From c00ee870823fd1282b28eb0ba33b89dae7a5badd Mon Sep 17 00:00:00 2001 From: philipp lang Date: Wed, 3 Jan 2024 13:42:29 +0100 Subject: [PATCH] Add authroization with actual user --- testbench.yaml | 13 +++++ tests/Feature/UploadTest.php | 48 +++++++++++++++-- tests/Pest.php | 4 ++ tests/TestCase.php | 13 +---- tests/workbench/app/Models/User.php | 4 ++ tests/workbench/app/Policies/PostPolicy.php | 52 +++++++++++++++++++ .../database/factories/Models/UserFactory.php | 12 +++++ .../2023_03_08_000000_create_users_table.php | 20 +++++++ 8 files changed, 150 insertions(+), 16 deletions(-) create mode 100644 tests/workbench/app/Policies/PostPolicy.php create mode 100644 tests/workbench/database/migrations/2023_03_08_000000_create_users_table.php diff --git a/testbench.yaml b/testbench.yaml index d495615..d9461a4 100644 --- a/testbench.yaml +++ b/testbench.yaml @@ -5,3 +5,16 @@ providers: migrations: - tests/workbench/database/migrations + +workbench: + start: '/' + install: false + discovers: + web: false + api: false + commands: false + components: false + views: false + build: [] + assets: [] + sync: [] diff --git a/tests/Feature/UploadTest.php b/tests/Feature/UploadTest.php index 04d1377..2b43439 100644 --- a/tests/Feature/UploadTest.php +++ b/tests/Feature/UploadTest.php @@ -214,15 +214,56 @@ test('it returns 403 when not authorized', function () { $this->auth(['storeMedia' => false])->registerModel(); $post = $this->newPost(); - $response = $this->postJson('/mediaupload', [ + $this->postJson('/mediaupload', [ 'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id], 'payload' => [ 'content' => base64_encode($this->pdfFile()->getContent()), 'name' => 'beispiel bild.jpg', ], - ]); + ])->assertStatus(403); +}); - $response->assertStatus(403); +test('it checks for model when running authorization', function () { + $otherPost = $this->newPost(); + $post = $this->newPost(); + $this->auth(['storeMedia' => ['id' => $post->id, 'collection' => 'defaultSingleFile']])->registerModel(); + + $this->postJson('/mediaupload', [ + 'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id], + 'payload' => [ + 'content' => base64_encode($this->pdfFile()->getContent()), + 'name' => 'beispiel bild.jpg', + ], + ])->assertStatus(201); + + $this->postJson('/mediaupload', [ + 'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $otherPost->id], + 'payload' => [ + 'content' => base64_encode($this->pdfFile()->getContent()), + 'name' => 'beispiel bild.jpg', + ], + ])->assertStatus(403); +}); + +test('it checks for collection when running authorization', function () { + $post = $this->newPost(); + $this->auth(['storeMedia' => ['id' => $post->id, 'collection' => 'defaultSingleFile']])->registerModel(); + + $this->postJson('/mediaupload', [ + 'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id], + 'payload' => [ + 'content' => base64_encode($this->pdfFile()->getContent()), + 'name' => 'beispiel bild.jpg', + ], + ])->assertStatus(201); + + $this->postJson('/mediaupload', [ + 'parent' => ['model' => 'post', 'collection' => 'singleWithEvent', 'id' => $post->id], + 'payload' => [ + 'content' => base64_encode($this->pdfFile()->getContent()), + 'name' => 'beispiel bild.jpg', + ], + ])->assertStatus(403); }); test('it needs validation for single files', function (array $payloadOverwrites, string $invalidFieldName) { @@ -293,7 +334,6 @@ test('it needs validation for multiple files', function (array $payloadOverwrite yield [['payload' => 'lalal'], 'payload']; yield [['payload' => []], 'payload']; yield [['payload' => 1], 'payload']; - yield [['payload' => [['name' => 'AAA', 'content' => []]]], 'payload.0.content']; yield [['payload' => [['name' => 'AAA', 'content' => ['UU']]]], 'payload.0.content']; yield [['payload' => [['name' => 'AAA', 'content' => null]]], 'payload.0.content']; diff --git a/tests/Pest.php b/tests/Pest.php index 165e502..9d2a6ec 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,7 +1,11 @@ in('Feature'); uses(Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Feature'); uses()->beforeEach(fn () => Storage::fake('media'))->in('Feature'); +uses()->beforeEach(fn () => Gate::policy(Post::class, PostPolicy::class))->in('Feature'); diff --git a/tests/TestCase.php b/tests/TestCase.php index c47890d..7211518 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -50,18 +50,7 @@ class TestCase extends BaseTestCase protected function auth(array $policies = []): self { - $this->be(User::factory()->create()); - $policies = [ - 'storeMedia' => true, - 'updateMedia' => true, - 'destroyMedia' => true, - 'listMedia' => true, - ...$policies, - ]; - - foreach ($policies as $ability => $result) { - Gate::define($ability, fn (?string $user, string $collectionName) => $result); - } + $this->be(User::factory()->policies($policies)->create()); return $this; } diff --git a/tests/workbench/app/Models/User.php b/tests/workbench/app/Models/User.php index f236a54..242c27c 100644 --- a/tests/workbench/app/Models/User.php +++ b/tests/workbench/app/Models/User.php @@ -10,4 +10,8 @@ class User extends Authenticatable use HasFactory; public $guarded = []; + + public $casts = [ + 'policies' => 'json', + ]; } diff --git a/tests/workbench/app/Policies/PostPolicy.php b/tests/workbench/app/Policies/PostPolicy.php new file mode 100644 index 0000000..e1e33a4 --- /dev/null +++ b/tests/workbench/app/Policies/PostPolicy.php @@ -0,0 +1,52 @@ +policies['listMedia'])) { + return $user->policies['listMedia'] === true; + } + + return data_get($user->policies, 'listMedia.id') === $model->id + && data_get($user->policies, 'listMedia.collection') === $collection; + } + + public function storeMedia(User $user, HasMedia $model, string $collection): bool + { + if (is_bool($user->policies['storeMedia'])) { + return $user->policies['storeMedia'] === true; + } + + return data_get($user->policies, 'storeMedia.id') === $model->id + && data_get($user->policies, 'storeMedia.collection') === $collection; + } + + public function updateMedia(User $user, HasMedia $model, string $collection): bool + { + if (is_bool($user->policies['updateMedia'])) { + return $user->policies['updateMedia'] === true; + } + + return data_get($user->policies, 'updateMedia.id') === $model->id + && data_get($user->policies, 'updateMedia.collection') === $collection; + } + + public function destroyMedia(User $user, HasMedia $model, string $collection): bool + { + if (is_bool($user->policies['destroyMedia'])) { + return $user->policies['destroyMedia'] === true; + } + + return data_get($user->policies, 'destroyMedia.id') === $model->id + && data_get($user->policies, 'destroyMedia.collection') === $collection; + } +} diff --git a/tests/workbench/database/factories/Models/UserFactory.php b/tests/workbench/database/factories/Models/UserFactory.php index 583e2f8..8eb64f8 100644 --- a/tests/workbench/database/factories/Models/UserFactory.php +++ b/tests/workbench/database/factories/Models/UserFactory.php @@ -24,6 +24,18 @@ class UserFactory extends Factory 'email' => $this->faker->safeEmail, 'password' => Hash::make('password'), 'name' => $this->faker->firstName, + 'policies' => [], ]; } + + public function policies(array $policies): self + { + return $this->state(['policies' => [ + 'storeMedia' => true, + 'updateMedia' => true, + 'destroyMedia' => true, + 'listMedia' => true, + ...$policies, + ]]); + } } diff --git a/tests/workbench/database/migrations/2023_03_08_000000_create_users_table.php b/tests/workbench/database/migrations/2023_03_08_000000_create_users_table.php new file mode 100644 index 0000000..d756954 --- /dev/null +++ b/tests/workbench/database/migrations/2023_03_08_000000_create_users_table.php @@ -0,0 +1,20 @@ +id(); + $table->string('email'); + $table->string('name'); + $table->string('password'); + $table->json('policies'); + $table->timestamps(); + }); + } +};