refactor(form-builder): strict validator on save; strip rules.unique fallback

This commit is contained in:
2026-04-24 22:26:44 +02:00
parent 800b1b6c01
commit 64ec4bcc5c
12 changed files with 469 additions and 29 deletions

View File

@@ -5,6 +5,9 @@ declare(strict_types=1);
namespace App\Http\Requests\Api\V1\FormBuilder;
use App\Enums\FormBuilder\FormFieldType;
use App\Exceptions\FormBuilder\UnknownValidationRuleTypeException;
use App\Services\FormBuilder\FormFieldValidationRuleService;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@@ -33,6 +36,10 @@ final class StoreFormFieldLibraryRequest extends FormRequest
'help_text' => ['nullable', 'string'],
'options' => ['nullable', 'array'],
'validation_rules' => ['nullable', 'array'],
'validation_rules.*' => ['array'],
'validation_rules.*.rule_type' => ['required', 'string', 'max:40'],
'validation_rules.*.parameters' => ['nullable', 'array'],
'validation_rules.*.error_message_key' => ['nullable', 'string', 'max:100'],
'default_is_required' => ['boolean'],
'default_is_filterable' => ['boolean'],
'default_binding' => ['nullable', 'array'],
@@ -43,4 +50,24 @@ final class StoreFormFieldLibraryRequest extends FormRequest
'is_system' => ['prohibited'],
];
}
/**
* @return array<int, \Closure>
*/
public function after(): array
{
return [
function (Validator $validator): void {
$specs = $this->input('validation_rules');
if (! is_array($specs) || $specs === []) {
return;
}
try {
app(FormFieldValidationRuleService::class)->assertSpecsValid($specs);
} catch (UnknownValidationRuleTypeException $e) {
$validator->errors()->add('validation_rules', $e->getMessage());
}
},
];
}
}

View File

@@ -7,7 +7,10 @@ namespace App\Http\Requests\Api\V1\FormBuilder;
use App\Enums\FormBuilder\FormFieldDisplayWidth;
use App\Enums\FormBuilder\FormFieldType;
use App\Enums\FormBuilder\FormValueStorageHint;
use App\Exceptions\FormBuilder\UnknownValidationRuleTypeException;
use App\Models\FormBuilder\FormSchema;
use App\Services\FormBuilder\FormFieldValidationRuleService;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@@ -47,6 +50,10 @@ final class StoreFormFieldRequest extends FormRequest
],
'options' => ['nullable', 'array'],
'validation_rules' => ['nullable', 'array'],
'validation_rules.*' => ['array'],
'validation_rules.*.rule_type' => ['required', 'string', 'max:40'],
'validation_rules.*.parameters' => ['nullable', 'array'],
'validation_rules.*.error_message_key' => ['nullable', 'string', 'max:100'],
'is_required' => ['boolean'],
'is_filterable' => ['boolean'],
'is_portal_visible' => ['boolean'],
@@ -64,4 +71,24 @@ final class StoreFormFieldRequest extends FormRequest
'form_schema_id' => ['prohibited'],
];
}
/**
* @return array<int, \Closure>
*/
public function after(): array
{
return [
function (Validator $validator): void {
$specs = $this->input('validation_rules');
if (! is_array($specs) || $specs === []) {
return;
}
try {
app(FormFieldValidationRuleService::class)->assertSpecsValid($specs);
} catch (UnknownValidationRuleTypeException $e) {
$validator->errors()->add('validation_rules', $e->getMessage());
}
},
];
}
}

View File

@@ -5,6 +5,9 @@ declare(strict_types=1);
namespace App\Http\Requests\Api\V1\FormBuilder;
use App\Enums\FormBuilder\FormFieldType;
use App\Exceptions\FormBuilder\UnknownValidationRuleTypeException;
use App\Services\FormBuilder\FormFieldValidationRuleService;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@@ -33,6 +36,10 @@ final class UpdateFormFieldLibraryRequest extends FormRequest
'help_text' => ['sometimes', 'nullable', 'string'],
'options' => ['sometimes', 'nullable', 'array'],
'validation_rules' => ['sometimes', 'nullable', 'array'],
'validation_rules.*' => ['array'],
'validation_rules.*.rule_type' => ['required', 'string', 'max:40'],
'validation_rules.*.parameters' => ['nullable', 'array'],
'validation_rules.*.error_message_key' => ['nullable', 'string', 'max:100'],
'default_is_required' => ['sometimes', 'boolean'],
'default_is_filterable' => ['sometimes', 'boolean'],
'default_binding' => ['sometimes', 'nullable', 'array'],
@@ -43,4 +50,27 @@ final class UpdateFormFieldLibraryRequest extends FormRequest
'is_system' => ['prohibited'],
];
}
/**
* @return array<int, \Closure>
*/
public function after(): array
{
return [
function (Validator $validator): void {
if (! $this->has('validation_rules')) {
return;
}
$specs = $this->input('validation_rules');
if (! is_array($specs) || $specs === []) {
return;
}
try {
app(FormFieldValidationRuleService::class)->assertSpecsValid($specs);
} catch (UnknownValidationRuleTypeException $e) {
$validator->errors()->add('validation_rules', $e->getMessage());
}
},
];
}
}

View File

@@ -7,7 +7,10 @@ namespace App\Http\Requests\Api\V1\FormBuilder;
use App\Enums\FormBuilder\FormFieldDisplayWidth;
use App\Enums\FormBuilder\FormFieldType;
use App\Enums\FormBuilder\FormValueStorageHint;
use App\Exceptions\FormBuilder\UnknownValidationRuleTypeException;
use App\Models\FormBuilder\FormSchema;
use App\Services\FormBuilder\FormFieldValidationRuleService;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@@ -43,6 +46,10 @@ final class UpdateFormFieldRequest extends FormRequest
],
'options' => ['sometimes', 'nullable', 'array'],
'validation_rules' => ['sometimes', 'nullable', 'array'],
'validation_rules.*' => ['array'],
'validation_rules.*.rule_type' => ['required', 'string', 'max:40'],
'validation_rules.*.parameters' => ['nullable', 'array'],
'validation_rules.*.error_message_key' => ['nullable', 'string', 'max:100'],
'is_required' => ['sometimes', 'boolean'],
'is_filterable' => ['sometimes', 'boolean'],
'is_portal_visible' => ['sometimes', 'boolean'],
@@ -61,4 +68,27 @@ final class UpdateFormFieldRequest extends FormRequest
'form_schema_id' => ['prohibited'],
];
}
/**
* @return array<int, \Closure>
*/
public function after(): array
{
return [
function (Validator $validator): void {
if (! $this->has('validation_rules')) {
return;
}
$specs = $this->input('validation_rules');
if (! is_array($specs) || $specs === []) {
return;
}
try {
app(FormFieldValidationRuleService::class)->assertSpecsValid($specs);
} catch (UnknownValidationRuleTypeException $e) {
$validator->errors()->add('validation_rules', $e->getMessage());
}
},
];
}
}