Skip to content

Commit acf8050

Browse files
authored
🐛 destructive operations gates (#184)
1 parent 1163f71 commit acf8050

File tree

5 files changed

+188
-0
lines changed

5 files changed

+188
-0
lines changed

src/Concerns/PerformsRestOperations.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ public function destroy(DestroyRequest $request)
140140

141141
foreach ($models as $model) {
142142
self::newResource()->authorizeTo('delete', $model);
143+
}
143144

145+
foreach ($models as $model) {
144146
$resource->destroying($request, $model);
145147

146148
$resource->performDelete($request, $model);
@@ -177,7 +179,9 @@ public function restore(RestoreRequest $request)
177179

178180
foreach ($models as $model) {
179181
self::newResource()->authorizeTo('restore', $model);
182+
}
180183

184+
foreach ($models as $model) {
181185
$resource->restoring($request, $model);
182186

183187
$resource->performRestore($request, $model);
@@ -215,7 +219,9 @@ public function forceDelete(ForceDestroyRequest $request)
215219

216220
foreach ($models as $model) {
217221
self::newResource()->authorizeTo('forceDelete', $model);
222+
}
218223

224+
foreach ($models as $model) {
219225
$resource->forceDestroying($request, $model);
220226

221227
$resource->performForceDelete($request, $model);

tests/Feature/Controllers/DeleteOperationsTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Lomkit\Rest\Tests\Support\Models\SoftDeletedModel;
1111
use Lomkit\Rest\Tests\Support\Policies\GreenPolicy;
1212
use Lomkit\Rest\Tests\Support\Policies\RedPolicy;
13+
use Lomkit\Rest\Tests\Support\Policies\RedPolicyButForModel;
1314
use Lomkit\Rest\Tests\Support\Rest\Resources\ModelResource;
1415
use Lomkit\Rest\Tests\Support\Rest\Resources\SoftDeletedModelResource;
1516

@@ -33,6 +34,28 @@ public function test_deleting_a_non_authorized_model(): void
3334
$response->assertJson(['message' => 'This action is unauthorized.']);
3435
}
3536

37+
public function test_deleting_a_non_authorized_model_with_an_authorized_one(): void
38+
{
39+
$model = ModelFactory::new()->count(1)->createOne();
40+
$modelDeletable = ModelFactory::new()->count(1)->createOne();
41+
42+
RedPolicyButForModel::forModel($modelDeletable);
43+
Gate::policy(Model::class, RedPolicyButForModel::class);
44+
45+
$response = $this->delete(
46+
'/api/models',
47+
[
48+
'resources' => [$model->getKey(), $modelDeletable->getKey()],
49+
],
50+
['Accept' => 'application/json']
51+
);
52+
53+
$response->assertStatus(403);
54+
$response->assertJson(['message' => 'This action is unauthorized.']);
55+
$this->assertDatabaseHas('models', $model->only('id'));
56+
$this->assertDatabaseHas('models', $modelDeletable->only('id'));
57+
}
58+
3659
public function test_deleting_a_model(): void
3760
{
3861
$model = ModelFactory::new()->count(1)->createOne();

tests/Feature/Controllers/ForceDeleteOperationsTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Lomkit\Rest\Tests\Support\Models\SoftDeletedModel;
99
use Lomkit\Rest\Tests\Support\Policies\GreenPolicy;
1010
use Lomkit\Rest\Tests\Support\Policies\RedPolicy;
11+
use Lomkit\Rest\Tests\Support\Policies\RedPolicyButForModel;
1112
use Lomkit\Rest\Tests\Support\Rest\Resources\SoftDeletedModelResource;
1213

1314
class ForceDeleteOperationsTest extends TestCase
@@ -30,6 +31,28 @@ public function test_force_deleting_a_non_authorized_model(): void
3031
$response->assertJson(['message' => 'This action is unauthorized.']);
3132
}
3233

34+
public function test_force_deleting_a_non_authorized_model_with_an_authorized_one(): void
35+
{
36+
$model = SoftDeletedModelFactory::new()->count(1)->trashed()->createOne();
37+
$modelForceDeletable = SoftDeletedModelFactory::new()->count(1)->trashed()->createOne();
38+
39+
RedPolicyButForModel::forModel($modelForceDeletable);
40+
Gate::policy(SoftDeletedModel::class, RedPolicyButForModel::class);
41+
42+
$response = $this->delete(
43+
'/api/soft-deleted-models/force',
44+
[
45+
'resources' => [$model->getKey(), $modelForceDeletable->getKey()],
46+
],
47+
['Accept' => 'application/json']
48+
);
49+
50+
$response->assertStatus(403);
51+
$response->assertJson(['message' => 'This action is unauthorized.']);
52+
$this->assertSoftDeleted($model);
53+
$this->assertSoftDeleted($modelForceDeletable);
54+
}
55+
3356
public function test_force_deleting_a_soft_deleted_model(): void
3457
{
3558
$softDeletedModel = SoftDeletedModelFactory::new()->count(1)->trashed()->createOne();

tests/Feature/Controllers/RestoreOperationsTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Lomkit\Rest\Tests\Support\Models\SoftDeletedModel;
99
use Lomkit\Rest\Tests\Support\Policies\GreenPolicy;
1010
use Lomkit\Rest\Tests\Support\Policies\RedPolicy;
11+
use Lomkit\Rest\Tests\Support\Policies\RedPolicyButForModel;
1112
use Lomkit\Rest\Tests\Support\Rest\Resources\SoftDeletedModelResource;
1213

1314
class RestoreOperationsTest extends TestCase
@@ -30,6 +31,34 @@ public function test_restoring_a_non_authorized_model(): void
3031
$response->assertJson(['message' => 'This action is unauthorized.']);
3132
}
3233

34+
public function test_restoring_a_non_authorized_model_with_an_authorized_one(): void
35+
{
36+
$model = SoftDeletedModelFactory::new()->count(1)->trashed()->createOne();
37+
$modelRestorable = SoftDeletedModelFactory::new()->count(1)->trashed()->createOne();
38+
39+
RedPolicyButForModel::forModel($modelRestorable);
40+
Gate::policy(SoftDeletedModel::class, RedPolicyButForModel::class);
41+
42+
$response = $this->post(
43+
'/api/soft-deleted-models/restore',
44+
[
45+
'resources' => [$model->getKey(), $modelRestorable->getKey()],
46+
],
47+
['Accept' => 'application/json']
48+
);
49+
50+
$response->assertStatus(403);
51+
$response->assertJson(['message' => 'This action is unauthorized.']);
52+
$this->assertNotEquals(
53+
null,
54+
$modelRestorable->fresh()->deleted_at,
55+
);
56+
$this->assertNotEquals(
57+
null,
58+
$model->fresh()->deleted_at,
59+
);
60+
}
61+
3362
public function test_restoring_a_soft_deleted_model(): void
3463
{
3564
$softDeletedModel = SoftDeletedModelFactory::new()->count(1)->trashed()->createOne();
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace Lomkit\Rest\Tests\Support\Policies;
4+
5+
use Illuminate\Auth\Access\HandlesAuthorization;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class RedPolicyButForModel
9+
{
10+
use HandlesAuthorization;
11+
12+
public static Model $model;
13+
14+
public static function forModel(Model $model)
15+
{
16+
static::$model = $model;
17+
}
18+
19+
/**
20+
* Determine whether the user can view the list of models.
21+
*
22+
* @param $user
23+
*
24+
* @return bool
25+
*/
26+
public function viewAny($user)
27+
{
28+
return false;
29+
}
30+
31+
/**
32+
* Determine whether the user can view the model.
33+
*
34+
* @param $user
35+
* @param Model $model
36+
*
37+
* @return bool
38+
*/
39+
public function view($user, Model $model)
40+
{
41+
return static::$model->is($model);
42+
}
43+
44+
/**
45+
* Determine whether the user can create models.
46+
*
47+
* @param $user
48+
*
49+
* @return bool
50+
*/
51+
public function create($user)
52+
{
53+
return false;
54+
}
55+
56+
/**
57+
* Determine whether the user can update the model.
58+
*
59+
* @param $user
60+
* @param Model $model
61+
*
62+
* @return bool
63+
*/
64+
public function update($user, Model $model)
65+
{
66+
return static::$model->is($model);
67+
}
68+
69+
/**
70+
* Determine whether the user can delete the model.
71+
*
72+
* @param $user
73+
* @param Model $model
74+
*
75+
* @return bool
76+
*/
77+
public function delete($user, Model $model)
78+
{
79+
return static::$model->is($model);
80+
}
81+
82+
/**
83+
* Determine whether the user can restore the model.
84+
*
85+
* @param $user
86+
* @param Model $model
87+
*
88+
* @return bool
89+
*/
90+
public function restore($user, Model $model)
91+
{
92+
return static::$model->is($model);
93+
}
94+
95+
/**
96+
* Determine whether the user can permanently delete the model.
97+
*
98+
* @param $user
99+
* @param Model $model
100+
*
101+
* @return bool
102+
*/
103+
public function forceDelete($user, Model $model)
104+
{
105+
return static::$model->is($model);
106+
}
107+
}

0 commit comments

Comments
 (0)