From c926ad4fdc8b9ef8f8951ea3351b1e88cae25e8a Mon Sep 17 00:00:00 2001 From: Gautier DELEGLISE Date: Mon, 21 Jul 2025 19:45:22 +0200 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20small=20adjustments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/access-control.php | 16 ++++++++++++++++ src/Console/PerimeterMakeCommand.php | 2 +- src/Console/stubs/control.stub | 2 +- src/Controls/Control.php | 7 +++++-- tests/Feature/ControlsShouldTest.php | 13 +++++++++++-- tests/Feature/PoliciesTest.php | 2 +- tests/Unit/Console/MakeCommandsTest.php | 2 +- 7 files changed, 36 insertions(+), 8 deletions(-) diff --git a/config/access-control.php b/config/access-control.php index 4ecf74e..4e8b47c 100644 --- a/config/access-control.php +++ b/config/access-control.php @@ -12,4 +12,20 @@ 'isolate_parent_query' => true, // Isolate the control's logic by applying a parent where on the query 'isolate_perimeter_queries' => true, // Isolate every perimeter query by applying a default "orWhere" to prevent Overlayed Perimeters collapsing ], + + /* + |-------------------------------------------------------------------------- + | Access Control Methods + |-------------------------------------------------------------------------- + | + */ + 'methods' => [ + 'viewAny' => 'view', + 'view' => 'view', + 'create' => 'create', + 'update' => 'update', + 'delete' => 'delete', + 'restore' => 'restore', + 'forceDelete' => 'forceDelete', + ] ]; diff --git a/src/Console/PerimeterMakeCommand.php b/src/Console/PerimeterMakeCommand.php index c89f387..f2e1cf1 100644 --- a/src/Console/PerimeterMakeCommand.php +++ b/src/Console/PerimeterMakeCommand.php @@ -104,7 +104,7 @@ protected function buildClass($name) protected function getOptions() { return [ - ['overlay', 'o', InputOption::VALUE_OPTIONAL, 'Indicates if the perimeter overlays'], + ['overlay', 'o', InputOption::VALUE_NONE, 'Indicates if the perimeter overlays'], ]; } diff --git a/src/Console/stubs/control.stub b/src/Console/stubs/control.stub index dda0591..731a410 100644 --- a/src/Console/stubs/control.stub +++ b/src/Console/stubs/control.stub @@ -13,7 +13,7 @@ class {{ class }} extends Control * The model the control refers to. * @var class-string */ - protected string $model = {{ namespacedModel }}::class; + protected string $model = \{{ namespacedModel }}::class; /** * Retrieve the list of perimeter definitions for the current control. diff --git a/src/Controls/Control.php b/src/Controls/Control.php index 2439418..a2b6bf5 100644 --- a/src/Controls/Control.php +++ b/src/Controls/Control.php @@ -61,9 +61,12 @@ protected function perimeters(): array */ public function applies(Model $user, string $method, Model $model): bool { + // If the method is viewAny, we check instead if he has any 'view' right on different perimeters + $appliesMethod = config(sprintf('access-control.methods.%s', $method)) ?? $method; + foreach ($this->perimeters() as $perimeter) { - if ($perimeter->applyAllowedCallback($user, $method)) { - // If the model doesn't exists, it means the method is not related to a model + if ($perimeter->applyAllowedCallback($user, $appliesMethod)) { + // If the model doesn't exist, it means the method is not related to a model // so we don't need to activate the should result since we can't compare an existing model if (!$model->exists) { return true; diff --git a/tests/Feature/ControlsShouldTest.php b/tests/Feature/ControlsShouldTest.php index cb6a9de..6b4205b 100644 --- a/tests/Feature/ControlsShouldTest.php +++ b/tests/Feature/ControlsShouldTest.php @@ -14,9 +14,18 @@ public function test_control_with_no_perimeter_passing(): void $this->assertFalse((new \Lomkit\Access\Tests\Support\Access\Controls\ModelControl())->applies(Auth::user(), 'create', new Model())); } + public function test_control_should_view_any_using_client_perimeter_with_changed_view_any_method_configuration(): void + { + Gate::define('view client models', function (User $user) { + return true; + }); + + $this->assertTrue((new \Lomkit\Access\Tests\Support\Access\Controls\ModelControl())->applies(Auth::user(), 'viewAny', new Model())); + } + public function test_control_should_view_any_using_client_perimeter(): void { - Gate::define('viewAny client models', function (User $user) { + Gate::define('view client models', function (User $user) { return true; }); @@ -85,7 +94,7 @@ public function test_control_should_delete_using_client_perimeter(): void public function test_control_should_view_any_using_global_perimeter(): void { - Gate::define('viewAny global models', function (User $user) { + Gate::define('view global models', function (User $user) { return true; }); diff --git a/tests/Feature/PoliciesTest.php b/tests/Feature/PoliciesTest.php index 3f53f1a..e7ed951 100644 --- a/tests/Feature/PoliciesTest.php +++ b/tests/Feature/PoliciesTest.php @@ -24,7 +24,7 @@ public function test_policies_calls_view_method_properly(): void public function test_policies_calls_view_any_method_properly(): void { - Gate::define('viewAny global models', function (User $user) { + Gate::define('view global models', function (User $user) { return true; }); $user = \Illuminate\Support\Facades\Auth::user(); diff --git a/tests/Unit/Console/MakeCommandsTest.php b/tests/Unit/Console/MakeCommandsTest.php index 76f3973..dd345c6 100644 --- a/tests/Unit/Console/MakeCommandsTest.php +++ b/tests/Unit/Console/MakeCommandsTest.php @@ -109,7 +109,7 @@ public function test_make_control_with_model_command() $this->assertFileExists(app_path('Access/Controls/TestControl.php')); $this->assertStringContainsString('class TestControl', file_get_contents(app_path('Access/Controls/TestControl.php'))); - $this->assertStringContainsString('protected string $model = App\Models\User::class;', file_get_contents(app_path('Access/Controls/TestControl.php'))); + $this->assertStringContainsString('protected string $model = \App\Models\User::class;', file_get_contents(app_path('Access/Controls/TestControl.php'))); unlink(app_path('Models/User.php')); unlink(app_path('Models/Post.php')); From a17d5fe813dd9039817353bc37c06d2ca88edf74 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 21 Jul 2025 17:45:42 +0000 Subject: [PATCH 2/3] Apply fixes from StyleCI --- config/access-control.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/config/access-control.php b/config/access-control.php index 4e8b47c..ccb6be1 100644 --- a/config/access-control.php +++ b/config/access-control.php @@ -20,12 +20,12 @@ | */ 'methods' => [ - 'viewAny' => 'view', - 'view' => 'view', - 'create' => 'create', - 'update' => 'update', - 'delete' => 'delete', - 'restore' => 'restore', + 'viewAny' => 'view', + 'view' => 'view', + 'create' => 'create', + 'update' => 'update', + 'delete' => 'delete', + 'restore' => 'restore', 'forceDelete' => 'forceDelete', - ] + ], ]; From 01df53dbdd75d078261505c15af5321f078cf266 Mon Sep 17 00:00:00 2001 From: Gautier DELEGLISE Date: Mon, 21 Jul 2025 19:51:16 +0200 Subject: [PATCH 3/3] Update Control.php --- src/Controls/Control.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controls/Control.php b/src/Controls/Control.php index a2b6bf5..42ae3f5 100644 --- a/src/Controls/Control.php +++ b/src/Controls/Control.php @@ -134,7 +134,7 @@ protected function applyQueryControl(Builder $query, Model $user): Builder }; foreach ($this->perimeters() as $perimeter) { - if ($perimeter->applyAllowedCallback($user, 'view')) { + if ($perimeter->applyAllowedCallback($user, config('access-control.methods.view'))) { if (config('access-control.queries.isolate_perimeter_queries')) { $query = $query->orWhere(function (Builder $query) use ($user, $perimeter) { $perimeter->applyQueryCallback($query, $user); @@ -169,7 +169,7 @@ protected function applyScoutQueryControl(\Laravel\Scout\Builder $query, Model $ }; foreach ($this->perimeters() as $perimeter) { - if ($perimeter->applyAllowedCallback($user, 'view')) { + if ($perimeter->applyAllowedCallback($user, config('access-control.methods.view'))) { $query = $perimeter->applyScoutQueryCallback($query, $user); $noResultCallback = function ($query) {return $query; };