Add authroization with actual user

This commit is contained in:
philipp lang 2024-01-03 13:42:29 +01:00
parent 1b2b148af5
commit c00ee87082
8 changed files with 150 additions and 16 deletions

View File

@ -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: []

View File

@ -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'];

View File

@ -1,7 +1,11 @@
<?php
use Illuminate\Auth\Access\Gate;
use Illuminate\Support\Facades\Storage;
use Workbench\App\Models\Post;
use Workbench\App\Policies\PostPolicy;
uses(Zoomyboy\MedialibraryHelper\Tests\TestCase::class)->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');

View File

@ -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;
}

View File

@ -10,4 +10,8 @@ class User extends Authenticatable
use HasFactory;
public $guarded = [];
public $casts = [
'policies' => 'json',
];
}

View File

@ -0,0 +1,52 @@
<?php
namespace Workbench\App\Policies;
use Illuminate\Auth\Access\HandlesAuthorization;
use Spatie\MediaLibrary\HasMedia;
use Workbench\App\Models\User;
class PostPolicy
{
use HandlesAuthorization;
public function listMedia(User $user, HasMedia $model): bool
{
if (is_bool($user->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;
}
}

View File

@ -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,
]]);
}
}

View File

@ -0,0 +1,20 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email');
$table->string('name');
$table->string('password');
$table->json('policies');
$table->timestamps();
});
}
};