Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions config/access-control.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
],
];
2 changes: 1 addition & 1 deletion src/Console/PerimeterMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
];
}

Expand Down
2 changes: 1 addition & 1 deletion src/Console/stubs/control.stub
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class {{ class }} extends Control
* The model the control refers to.
* @var class-string<Model>
*/
protected string $model = {{ namespacedModel }}::class;
protected string $model = \{{ namespacedModel }}::class;

/**
* Retrieve the list of perimeter definitions for the current control.
Expand Down
11 changes: 7 additions & 4 deletions src/Controls/Control.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -131,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);
Expand Down Expand Up @@ -166,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; };
Expand Down
13 changes: 11 additions & 2 deletions tests/Feature/ControlsShouldTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});

Expand Down Expand Up @@ -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;
});

Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/PoliciesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/Console/MakeCommandsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand Down