From 7458761d11112417443c7e92eac5ee3d6e4b06d7 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 26 Mar 2025 20:47:52 +0100 Subject: [PATCH 1/7] Dynamic binding gates --- src/Http/Response.php | 9 +++------ src/Rules/SearchRules.php | 7 ++++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index cef1aea..44f4005 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -32,12 +32,9 @@ public function resource(Resource $resource) protected function buildGatesForModel(Model $model, Resource $resource, array $gates) { - return array_merge( - in_array('view', $gates) ? [config('rest.gates.names.authorized_to_view') => $resource->authorizedTo('view', $model)] : [], - in_array('update', $gates) ? [config('rest.gates.names.authorized_to_update') => $resource->authorizedTo('update', $model)] : [], - in_array('delete', $gates) ? [config('rest.gates.names.authorized_to_delete') => $resource->authorizedTo('delete', $model)] : [], - in_array('restore', $gates) ? [config('rest.gates.names.authorized_to_restore') => $resource->authorizedTo('restore', $model)] : [], - in_array('forceDelete', $gates) ? [config('rest.gates.names.authorized_to_force_delete') => $resource->authorizedTo('forceDelete', $model)] : [], + return array_combine( + array_map(fn($gate) => config("rest.gates.names.authorized_to_{$gate}", "authorized_to_{$gate}"), $gates), + array_map(fn($gate) => $resource->authorizedTo($gate, $model), $gates) ); } diff --git a/src/Rules/SearchRules.php b/src/Rules/SearchRules.php index d1033af..de735be 100644 --- a/src/Rules/SearchRules.php +++ b/src/Rules/SearchRules.php @@ -9,6 +9,7 @@ use Illuminate\Http\Client\Request; use Illuminate\Validation\Rule; use Illuminate\Validation\Validator; +use Illuminate\Support\Facades\Gate; use Lomkit\Rest\Http\Requests\RestRequest; use Lomkit\Rest\Http\Resource; @@ -68,6 +69,10 @@ public function validate(string $attribute, mixed $value, Closure $fail): void $attribute .= '.'; } + $policy = Gate::getPolicyFor($this->resource::$model); + $validGates = $policy ? get_class_methods($policy) : []; + $validGates = array_filter($validGates, fn($method) => !in_array($method, ['before', 'after'])); + $this ->validator ->setRules( @@ -89,7 +94,7 @@ public function validate(string $attribute, mixed $value, Closure $fail): void [ $attribute.'limit' => ['sometimes', 'integer', Rule::in($this->resource->getLimits($this->request))], $attribute.'page' => ['sometimes', 'integer'], - $attribute.'gates' => ['sometimes', 'array', Rule::in(['viewAny', 'view', 'create', 'update', 'delete', 'restore', 'forceDelete'])], + $attribute.'gates' => ['sometimes', 'array', Rule::in($validGates)], ], $this->isRootSearchRules ? [$attribute.'includes' => ['sometimes', 'array']] : [], $this->isRootSearchRules ? $this->includesRules($this->resource, $attribute.'includes') : [], From ed74e0afb67f230af33fb4e4ccdbe7313b53acc3 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 26 Mar 2025 20:49:15 +0100 Subject: [PATCH 2/7] Exclude __call and __construct Policy method --- src/Rules/SearchRules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rules/SearchRules.php b/src/Rules/SearchRules.php index de735be..9db8f1d 100644 --- a/src/Rules/SearchRules.php +++ b/src/Rules/SearchRules.php @@ -71,7 +71,7 @@ public function validate(string $attribute, mixed $value, Closure $fail): void $policy = Gate::getPolicyFor($this->resource::$model); $validGates = $policy ? get_class_methods($policy) : []; - $validGates = array_filter($validGates, fn($method) => !in_array($method, ['before', 'after'])); + $validGates = array_filter($validGates, fn($method) => !in_array($method, ['before', 'after', '__call', '__construct'])); $this ->validator From 9810d55ae988508df772f6e6a25e5b82aa9f6d96 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 26 Mar 2025 20:57:10 +0100 Subject: [PATCH 3/7] Exclude __call and __construct Policy method --- src/Http/Response.php | 4 ++-- src/Rules/SearchRules.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 44f4005..35e35f9 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -33,8 +33,8 @@ public function resource(Resource $resource) protected function buildGatesForModel(Model $model, Resource $resource, array $gates) { return array_combine( - array_map(fn($gate) => config("rest.gates.names.authorized_to_{$gate}", "authorized_to_{$gate}"), $gates), - array_map(fn($gate) => $resource->authorizedTo($gate, $model), $gates) + array_map(fn ($gate) => config("rest.gates.names.authorized_to_{$gate}", "authorized_to_{$gate}"), $gates), + array_map(fn ($gate) => $resource->authorizedTo($gate, $model), $gates) ); } diff --git a/src/Rules/SearchRules.php b/src/Rules/SearchRules.php index 9db8f1d..f1a777a 100644 --- a/src/Rules/SearchRules.php +++ b/src/Rules/SearchRules.php @@ -7,9 +7,9 @@ use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Contracts\Validation\ValidatorAwareRule; use Illuminate\Http\Client\Request; +use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rule; use Illuminate\Validation\Validator; -use Illuminate\Support\Facades\Gate; use Lomkit\Rest\Http\Requests\RestRequest; use Lomkit\Rest\Http\Resource; @@ -71,7 +71,7 @@ public function validate(string $attribute, mixed $value, Closure $fail): void $policy = Gate::getPolicyFor($this->resource::$model); $validGates = $policy ? get_class_methods($policy) : []; - $validGates = array_filter($validGates, fn($method) => !in_array($method, ['before', 'after', '__call', '__construct'])); + $validGates = array_filter($validGates, fn ($method) => !in_array($method, ['before', 'after', '__call', '__construct'])); $this ->validator From 27ec3bbe4e20a844798809085062be36b3143cec Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 26 Mar 2025 21:02:06 +0100 Subject: [PATCH 4/7] Exclude __call and __construct Policy method --- src/Http/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 35e35f9..47e016e 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -50,7 +50,7 @@ protected function buildGatesForModel(Model $model, Resource $resource, array $g * * @return array The structured array representation of the model, including attributes and recursively processed relations. */ - public function modelToResponse(Model $model, Resource $resource, array $requestArray, Relation $relation = null) + public function modelToResponse(Model $model, Resource $resource, array $requestArray, ?Relation $relation = null) { $currentRequestArray = $relation === null ? $requestArray : collect($requestArray['includes'] ?? []) ->first(function ($include) use ($relation) { From 972c5008e6df2f00cd7221e2cd400ccf07784d3c Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 30 Mar 2025 20:02:35 +0200 Subject: [PATCH 5/7] Fix tests --- src/Http/Response.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 47e016e..939b50e 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -32,12 +32,15 @@ public function resource(Resource $resource) protected function buildGatesForModel(Model $model, Resource $resource, array $gates) { + $filteredGates = array_filter($gates, fn ($gate) => $gate !== 'create'); + return array_combine( - array_map(fn ($gate) => config("rest.gates.names.authorized_to_{$gate}", "authorized_to_{$gate}"), $gates), - array_map(fn ($gate) => $resource->authorizedTo($gate, $model), $gates) + array_map(fn ($gate) => config('rest.gates.names.authorized_to_' . Str::snake($gate), 'authorized_to_' . Str::snake($gate)), $filteredGates), + array_map(fn ($gate) => $resource->authorizedTo($gate, $model), $filteredGates) ); } + /** * Convert an Eloquent model into an array representation for the HTTP response. * From 4a0b5e1b4faf875a3b2f7bb7bf999cbf1a5edaed Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 30 Mar 2025 20:07:53 +0200 Subject: [PATCH 6/7] Fix styleCI --- src/Http/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 939b50e..7f1724f 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -35,7 +35,7 @@ protected function buildGatesForModel(Model $model, Resource $resource, array $g $filteredGates = array_filter($gates, fn ($gate) => $gate !== 'create'); return array_combine( - array_map(fn ($gate) => config('rest.gates.names.authorized_to_' . Str::snake($gate), 'authorized_to_' . Str::snake($gate)), $filteredGates), + array_map(fn ($gate) => config('rest.gates.names.authorized_to_'.Str::snake($gate), 'authorized_to_'.Str::snake($gate)), $filteredGates), array_map(fn ($gate) => $resource->authorizedTo($gate, $model), $filteredGates) ); } From b605fd3d94be5757a370b8168ed7f6304ff30fae Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 30 Mar 2025 20:09:21 +0200 Subject: [PATCH 7/7] Fix styleCI --- src/Http/Response.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 7f1724f..40f6f2b 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -40,7 +40,6 @@ protected function buildGatesForModel(Model $model, Resource $resource, array $g ); } - /** * Convert an Eloquent model into an array representation for the HTTP response. *