feat(graphql): add strict validation to filters (#1041)

This commit is contained in:
Kyrch
2026-01-03 03:52:16 -03:00
committed by GitHub
parent ece37dcc73
commit d88376a289
7 changed files with 115 additions and 6 deletions
+12
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Filter;
use App\Rules\Api\IsValidBoolean;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Arr;
@@ -24,4 +25,15 @@ class BooleanFilter extends Filter
fn (string $filterValue): ?bool => filter_var($filterValue, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
);
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [
'required',
new IsValidBoolean(),
];
}
}
+14
View File
@@ -35,4 +35,18 @@ class DateTimeTzFilter extends Filter
}
);
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
$allowedDateFormats = array_column(AllowedDateFormat::cases(), 'value');
$dateFormats = implode(',', $allowedDateFormats);
return [
'required',
"date_format:$dateFormats",
];
}
}
+20 -5
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\GraphQL\Filter;
use App\Exceptions\GraphQL\ClientValidationException;
use BackedEnum;
use Closure;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Arr;
use Rebing\GraphQL\Support\Facades\GraphQL;
@@ -42,10 +42,6 @@ class EnumFilter extends Filter
$this->enumClass::cases(),
fn (UnitEnum $enum): bool => $enum->name === $filterValue
);
if (! $enum instanceof BackedEnum) {
throw new ClientValidationException("'{$filterValue}' does not exist in the ".class_basename($this->enumClass).' enum.');
}
}
$values[] = $enum ?? $filterValue;
@@ -53,4 +49,23 @@ class EnumFilter extends Filter
return $values;
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [
'required',
function ($attribute, mixed $value, Closure $fail): void {
if (
! is_string($value)
|| ! enum_exists($this->enumClass)
|| Arr::first($this->enumClass::cases(), fn (UnitEnum $enum): bool => $enum->name === $value) === null
) {
$fail("'{$value}' does not exist in the ".class_basename($this->enumClass).' enum.');
}
},
];
}
}
+36 -1
View File
@@ -5,9 +5,12 @@ declare(strict_types=1);
namespace App\GraphQL\Filter;
use App\Enums\Http\Api\Filter\ComparisonOperator;
use App\Exceptions\GraphQL\ClientValidationException;
use App\GraphQL\Argument\Argument;
use App\GraphQL\Argument\FilterArgument;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
abstract class Filter
{
@@ -21,9 +24,14 @@ abstract class Filter
protected readonly ?string $column = null,
) {}
public function getFieldName(): string
{
return $this->fieldName;
}
public function getColumn(): string
{
return $this->column ?? $this->fieldName;
return $this->column ?? $this->getFieldName();
}
/**
@@ -39,6 +47,8 @@ abstract class Filter
*/
public function getFilterValues(array $attemptedFilterValues): array
{
$this->validateFilterValues($attemptedFilterValues);
return $this->convertFilterValues($attemptedFilterValues);
}
@@ -47,6 +57,31 @@ abstract class Filter
*/
abstract protected function convertFilterValues(array $filterValues): array;
/**
* Validate the filter values against its rules based on types.
*/
protected function validateFilterValues(array $filterValues): void
{
foreach ($filterValues as $filterValue) {
try {
Validator::make(
[$this->fieldName => $filterValue],
[$this->fieldName => $this->getRules()],
)->validate();
} catch (ValidationException $e) {
throw new ClientValidationException($e->getMessage());
}
}
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [];
}
/**
* Allow the Equal operator to the filter.
*/
+11
View File
@@ -24,4 +24,15 @@ class FloatFilter extends Filter
fn (string $filterValue): ?float => filter_var($filterValue, FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE)
);
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [
'required',
'numeric',
];
}
}
+11
View File
@@ -24,4 +24,15 @@ class IntFilter extends Filter
fn (string $filterValue): ?int => filter_var($filterValue, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE)
);
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [
'required',
'integer',
];
}
}
+11
View File
@@ -20,4 +20,15 @@ class StringFilter extends Filter
{
return $filterValues;
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [
'required',
'string',
];
}
}