Add authroization with actual user
This commit is contained in:
parent
1b2b148af5
commit
c00ee87082
|
@ -5,3 +5,16 @@ providers:
|
||||||
|
|
||||||
migrations:
|
migrations:
|
||||||
- tests/workbench/database/migrations
|
- tests/workbench/database/migrations
|
||||||
|
|
||||||
|
workbench:
|
||||||
|
start: '/'
|
||||||
|
install: false
|
||||||
|
discovers:
|
||||||
|
web: false
|
||||||
|
api: false
|
||||||
|
commands: false
|
||||||
|
components: false
|
||||||
|
views: false
|
||||||
|
build: []
|
||||||
|
assets: []
|
||||||
|
sync: []
|
||||||
|
|
|
@ -214,15 +214,56 @@ test('it returns 403 when not authorized', function () {
|
||||||
$this->auth(['storeMedia' => false])->registerModel();
|
$this->auth(['storeMedia' => false])->registerModel();
|
||||||
$post = $this->newPost();
|
$post = $this->newPost();
|
||||||
|
|
||||||
$response = $this->postJson('/mediaupload', [
|
$this->postJson('/mediaupload', [
|
||||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||||
'payload' => [
|
'payload' => [
|
||||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||||
'name' => 'beispiel bild.jpg',
|
'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) {
|
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' => 'lalal'], 'payload'];
|
||||||
yield [['payload' => []], 'payload'];
|
yield [['payload' => []], 'payload'];
|
||||||
yield [['payload' => 1], 'payload'];
|
yield [['payload' => 1], 'payload'];
|
||||||
|
|
||||||
yield [['payload' => [['name' => 'AAA', 'content' => []]]], 'payload.0.content'];
|
yield [['payload' => [['name' => 'AAA', 'content' => []]]], 'payload.0.content'];
|
||||||
yield [['payload' => [['name' => 'AAA', 'content' => ['UU']]]], 'payload.0.content'];
|
yield [['payload' => [['name' => 'AAA', 'content' => ['UU']]]], 'payload.0.content'];
|
||||||
yield [['payload' => [['name' => 'AAA', 'content' => null]]], 'payload.0.content'];
|
yield [['payload' => [['name' => 'AAA', 'content' => null]]], 'payload.0.content'];
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Auth\Access\Gate;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Workbench\App\Models\Post;
|
||||||
|
use Workbench\App\Policies\PostPolicy;
|
||||||
|
|
||||||
uses(Zoomyboy\MedialibraryHelper\Tests\TestCase::class)->in('Feature');
|
uses(Zoomyboy\MedialibraryHelper\Tests\TestCase::class)->in('Feature');
|
||||||
uses(Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Feature');
|
uses(Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Feature');
|
||||||
uses()->beforeEach(fn () => Storage::fake('media'))->in('Feature');
|
uses()->beforeEach(fn () => Storage::fake('media'))->in('Feature');
|
||||||
|
uses()->beforeEach(fn () => Gate::policy(Post::class, PostPolicy::class))->in('Feature');
|
||||||
|
|
|
@ -50,18 +50,7 @@ class TestCase extends BaseTestCase
|
||||||
|
|
||||||
protected function auth(array $policies = []): self
|
protected function auth(array $policies = []): self
|
||||||
{
|
{
|
||||||
$this->be(User::factory()->create());
|
$this->be(User::factory()->policies($policies)->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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,8 @@ class User extends Authenticatable
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
public $guarded = [];
|
public $guarded = [];
|
||||||
|
|
||||||
|
public $casts = [
|
||||||
|
'policies' => 'json',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,18 @@ class UserFactory extends Factory
|
||||||
'email' => $this->faker->safeEmail,
|
'email' => $this->faker->safeEmail,
|
||||||
'password' => Hash::make('password'),
|
'password' => Hash::make('password'),
|
||||||
'name' => $this->faker->firstName,
|
'name' => $this->faker->firstName,
|
||||||
|
'policies' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function policies(array $policies): self
|
||||||
|
{
|
||||||
|
return $this->state(['policies' => [
|
||||||
|
'storeMedia' => true,
|
||||||
|
'updateMedia' => true,
|
||||||
|
'destroyMedia' => true,
|
||||||
|
'listMedia' => true,
|
||||||
|
...$policies,
|
||||||
|
]]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue