From 0962506d86aa6a184f62cedb810bac8974c28fb9 Mon Sep 17 00:00:00 2001 From: Benjamin RS Date: Sat, 15 Mar 2025 13:23:24 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20Add=20Operatable=20trait=20to?= =?UTF-8?q?=20Resource=20and=20update=20operator=20rules=20in=20SearchRule?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Concerns/Resource/Operatable.php | 50 ++++++++++++++++++++++++++++ src/Http/Resource.php | 2 ++ src/Rules/SearchRules.php | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/Concerns/Resource/Operatable.php diff --git a/src/Concerns/Resource/Operatable.php b/src/Concerns/Resource/Operatable.php new file mode 100644 index 0000000..4fa03a8 --- /dev/null +++ b/src/Concerns/Resource/Operatable.php @@ -0,0 +1,50 @@ +', + '>=', + '<', + '<=', + 'like', + 'not like', + 'in', + 'not in' + ]; + } + + /** + * Get the resource's operators. + * + * @param \Lomkit\Rest\Http\Requests\RestRequest $request + * + * @return array + */ + public function getOperators(\Lomkit\Rest\Http\Requests\RestRequest $request): array + { + return $this->calculatedOperators ?? ($this->calculatedOperators = $this->operators($request)); + } +} diff --git a/src/Http/Resource.php b/src/Http/Resource.php index 9541529..a24e6cd 100644 --- a/src/Http/Resource.php +++ b/src/Http/Resource.php @@ -11,6 +11,7 @@ use Lomkit\Rest\Concerns\PerformsQueries; use Lomkit\Rest\Concerns\Resource\ConfiguresRestParameters; use Lomkit\Rest\Concerns\Resource\HasResourceHooks; +use Lomkit\Rest\Concerns\Resource\Operatable; use Lomkit\Rest\Concerns\Resource\Paginable; use Lomkit\Rest\Concerns\Resource\Relationable; use Lomkit\Rest\Concerns\Resource\Rulable; @@ -31,6 +32,7 @@ class Resource implements \JsonSerializable use Actionable; use Instructionable; use HasResourceHooks; + use Operatable; /** * The model the entry corresponds to. diff --git a/src/Rules/SearchRules.php b/src/Rules/SearchRules.php index d1033af..fbbd841 100644 --- a/src/Rules/SearchRules.php +++ b/src/Rules/SearchRules.php @@ -131,7 +131,7 @@ public function filtersRules(\Lomkit\Rest\Http\Resource $resource, string $prefi $operatorRules = $isScoutMode ? ['=', 'in', 'not in'] : - ['=', '!=', '>', '>=', '<', '<=', 'like', 'not like', 'in', 'not in']; + $resource->getOperators($this->request); $fieldValidation = $isScoutMode ? Rule::in($resource->getScoutFields($this->request)) : From 3fcbb53d928c001e929aa7a3e667ab86190c1161 Mon Sep 17 00:00:00 2001 From: Benjamin RS Date: Wed, 19 Mar 2025 09:33:29 +0100 Subject: [PATCH 2/3] tests for limited operators --- .../SearchFilteringOperationsTest.php | 50 +++++++++++++++++++ .../Controllers/LimitedModelController.php | 11 ++++ .../Rest/Resources/LimitedModelResource.php | 16 ++++++ tests/Support/Routes/api.php | 1 + 4 files changed, 78 insertions(+) create mode 100644 tests/Support/Http/Controllers/LimitedModelController.php create mode 100644 tests/Support/Rest/Resources/LimitedModelResource.php diff --git a/tests/Feature/Controllers/SearchFilteringOperationsTest.php b/tests/Feature/Controllers/SearchFilteringOperationsTest.php index 28dcab7..765e98b 100644 --- a/tests/Feature/Controllers/SearchFilteringOperationsTest.php +++ b/tests/Feature/Controllers/SearchFilteringOperationsTest.php @@ -11,6 +11,7 @@ use Lomkit\Rest\Tests\Support\Models\Model; use Lomkit\Rest\Tests\Support\Policies\GreenPolicy; use Lomkit\Rest\Tests\Support\Rest\Resources\ModelResource; +use Lomkit\Rest\Tests\Support\Rest\Resources\LimitedModelResource; class SearchFilteringOperationsTest extends TestCase { @@ -626,4 +627,53 @@ public function test_getting_a_list_of_resources_filtered_by_morphed_by_many_piv new ModelResource() ); } + + public function test_getting_a_list_of_resources_filtered_by_limited_operators(): void + { + $matchingModel = ModelFactory::new()->create(['name' => 'match'])->fresh(); + ModelFactory::new()->create(['name' => 'not match'])->fresh(); + + Gate::policy(Model::class, GreenPolicy::class); + + $response = $this->post( + '/api/limited-models/search', + [ + 'search' => [ + 'filters' => [ + ['field' => 'name', 'operator' => '=', 'value' => 'match'], + ], + ], + ], + ['Accept' => 'application/json'] + ); + + $this->assertResourcePaginated( + $response, + [$matchingModel], + new LimitedModelResource() + ); + } + + public function test_getting_a_list_of_resources_filtered_by_limited_operators_with_invalid_operator(): void + { + ModelFactory::new()->create(['name' => 'match'])->fresh(); + ModelFactory::new()->create(['name' => 'not match'])->fresh(); + + Gate::policy(Model::class, GreenPolicy::class); + + $response = $this->post( + '/api/limited-models/search', + [ + 'search' => [ + 'filters' => [ + ['field' => 'name', 'operator' => 'like', 'value' => 'match'], + ], + ], + ], + ['Accept' => 'application/json'] + ); + + $response->assertStatus(422); + $response->assertJsonStructure(['message', 'errors' => ['search.filters.0.operator']]); + } } diff --git a/tests/Support/Http/Controllers/LimitedModelController.php b/tests/Support/Http/Controllers/LimitedModelController.php new file mode 100644 index 0000000..59609d9 --- /dev/null +++ b/tests/Support/Http/Controllers/LimitedModelController.php @@ -0,0 +1,11 @@ + 'api.', 'prefix' => 'api'], function () { \Lomkit\Rest\Facades\Rest::resource('models', \Lomkit\Rest\Tests\Support\Http\Controllers\ModelController::class); + \Lomkit\Rest\Facades\Rest::resource('limited-models', \Lomkit\Rest\Tests\Support\Http\Controllers\LimitedModelController::class); \Lomkit\Rest\Facades\Rest::resource('searchable-models', \Lomkit\Rest\Tests\Support\Http\Controllers\SearchableModelController::class); \Lomkit\Rest\Facades\Rest::resource('model-hooks', \Lomkit\Rest\Tests\Support\Http\Controllers\ModelHooksController::class)->withSoftDeletes(); \Lomkit\Rest\Facades\Rest::resource('model-withs', \Lomkit\Rest\Tests\Support\Http\Controllers\ModelWithController::class); From e7d7ce22bc421a057e94670224f37f40e38078db Mon Sep 17 00:00:00 2001 From: Benjamin RS Date: Wed, 19 Mar 2025 10:06:38 +0100 Subject: [PATCH 3/3] fix styleCi --- src/Concerns/Resource/Operatable.php | 2 +- tests/Feature/Controllers/SearchFilteringOperationsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Concerns/Resource/Operatable.php b/src/Concerns/Resource/Operatable.php index 4fa03a8..fbb1abd 100644 --- a/src/Concerns/Resource/Operatable.php +++ b/src/Concerns/Resource/Operatable.php @@ -32,7 +32,7 @@ public function operators(RestRequest $request): array 'like', 'not like', 'in', - 'not in' + 'not in', ]; } diff --git a/tests/Feature/Controllers/SearchFilteringOperationsTest.php b/tests/Feature/Controllers/SearchFilteringOperationsTest.php index 765e98b..e459073 100644 --- a/tests/Feature/Controllers/SearchFilteringOperationsTest.php +++ b/tests/Feature/Controllers/SearchFilteringOperationsTest.php @@ -10,8 +10,8 @@ use Lomkit\Rest\Tests\Support\Database\Factories\MorphToManyRelationFactory; use Lomkit\Rest\Tests\Support\Models\Model; use Lomkit\Rest\Tests\Support\Policies\GreenPolicy; -use Lomkit\Rest\Tests\Support\Rest\Resources\ModelResource; use Lomkit\Rest\Tests\Support\Rest\Resources\LimitedModelResource; +use Lomkit\Rest\Tests\Support\Rest\Resources\ModelResource; class SearchFilteringOperationsTest extends TestCase {