diff --git a/config/access-control.php b/config/access-control.php index 3633039..4ecf74e 100644 --- a/config/access-control.php +++ b/config/access-control.php @@ -8,7 +8,8 @@ | */ 'queries' => [ - 'enabled_by_default' => false, - 'isolated' => true, // Isolate the control's logic by applying a parent where on the query + 'enabled_by_default' => false, + '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 ], ]; diff --git a/src/Controls/Control.php b/src/Controls/Control.php index 15b00fe..cf37252 100644 --- a/src/Controls/Control.php +++ b/src/Controls/Control.php @@ -81,7 +81,7 @@ public function queried(Builder $query, Model $user): Builder return $this->applyQueryControl($query, $user); }; - if (config('access-control.queries.isolated')) { + if (config('access-control.queries.isolate_parent_query')) { return $query->where(function (Builder $query) use ($user, $callback) { $callback($query, $user); }); @@ -119,7 +119,13 @@ protected function applyQueryControl(Builder $query, Model $user): Builder foreach ($this->perimeters() as $perimeter) { if ($perimeter->applyAllowedCallback($user, 'view')) { - $query = $perimeter->applyQueryCallback($query, $user); + if (config('access-control.queries.isolate_perimeter_queries')) { + $query = $query->orWhere(function (Builder $query) use ($user, $perimeter) { + $perimeter->applyQueryCallback($query, $user); + }); + } else { + $perimeter->applyQueryCallback($query, $user); + } $noResultCallback = function ($query) {return $query; }; diff --git a/tests/Feature/ControlsQueryTest.php b/tests/Feature/ControlsQueryTest.php index d827839..2f6e940 100644 --- a/tests/Feature/ControlsQueryTest.php +++ b/tests/Feature/ControlsQueryTest.php @@ -150,9 +150,9 @@ public function test_control_queried_isolated(): void $this->assertEquals(50, $query->count()); } - public function test_control_queried_not_isolated(): void + public function test_control_queried_not_parent_isolated(): void { - config(['access-control.queries.isolated' => false]); + config(['access-control.queries.isolate_parent_query' => false]); Gate::define('view shared models', function (User $user) { return true; @@ -180,4 +180,40 @@ public function test_control_queried_not_isolated(): void $this->assertEquals(150, $query->count()); } + + public function test_control_queried_not_perimeter_isolated(): void + { + config(['access-control.queries.isolate_perimeter_queries' => false]); + + Gate::define('view shared models', function (User $user) { + return true; + }); + Gate::define('view own models', function (User $user) { + return true; + }); + + Model::factory() + ->clientPerimeter() + ->count(50) + ->create(); + Model::factory() + ->clientPerimeter() + ->sharedPerimeter() + ->count(50) + ->create(); + Model::factory() + ->ownPerimeter() + ->sharedPerimeter() + ->count(50) + ->create(); + Model::factory() + ->ownPerimeter() + ->count(50) + ->create(); + + $query = Model::query(); + $query = (new \Lomkit\Access\Tests\Support\Access\Controls\ModelControl())->queried($query, Auth::user()); + + $this->assertEquals(50, $query->count()); + } } diff --git a/tests/Support/Access/Controls/ModelControl.php b/tests/Support/Access/Controls/ModelControl.php index 65314d1..ff48ff2 100644 --- a/tests/Support/Access/Controls/ModelControl.php +++ b/tests/Support/Access/Controls/ModelControl.php @@ -26,7 +26,7 @@ protected function perimeters(): array return $query->where('shared_with_users', $user->getKey()); }) ->query(function (Builder $query, Model $user) { - return $query->orWhereHas('sharedWithUsers', function (Builder $query) use ($user) { + return $query->whereHas('sharedWithUsers', function (Builder $query) use ($user) { return $query->where('id', $user->getKey()); }); }), @@ -54,7 +54,7 @@ protected function perimeters(): array return $query->where('client_id', $user->client->getKey()); }) ->query(function (Builder $query, Model $user) { - return $query->orWhere('client_id', $user->client->getKey()); + return $query->where('client_id', $user->client->getKey()); }), OwnPerimeter::new() ->allowed(function (Model $user, string $method) { @@ -67,7 +67,7 @@ protected function perimeters(): array return $query->where('author_id', $user->getKey()); }) ->query(function (Builder $query, Model $user) { - return $query->orWhere('author_id', $user->getKey()); + return $query->where('author_id', $user->getKey()); }), ]; }