Fed by the records themselves, delivered only to public HTTPS addresses checked at every attempt, retried, and switched off after repeated failures. A submitter's details travel only to webhooks that opted into them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.7 KiB
PHP
54 lines
1.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Requests\Api\V1;
|
|
|
|
use App\Models\Webhook;
|
|
use App\Support\Webhooks\PublicEndpoint;
|
|
use Closure;
|
|
use Illuminate\Foundation\Http\FormRequest;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class WebhookRequest extends FormRequest
|
|
{
|
|
public function authorize(): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function rules(): array
|
|
{
|
|
$creating = ! $this->route('webhook') instanceof Webhook;
|
|
$sometimes = $creating ? 'required' : 'sometimes';
|
|
|
|
return [
|
|
'name' => [$sometimes, 'string', 'max:120'],
|
|
'url' => [
|
|
$sometimes,
|
|
'string',
|
|
'url',
|
|
'max:2048',
|
|
// Refused now rather than at the first delivery; checked
|
|
// again at every delivery all the same.
|
|
function (string $attribute, mixed $value, Closure $fail): void {
|
|
[, $reason] = app(PublicEndpoint::class)->check((string) $value);
|
|
|
|
if ($reason !== null) {
|
|
$fail(__("rules.media.remote.{$reason}"));
|
|
}
|
|
},
|
|
],
|
|
'events' => [$sometimes, 'array', 'min:1'],
|
|
'events.*' => ['string', 'distinct', Rule::in(['*', ...Webhook::EVENTS])],
|
|
'secret' => [$creating ? 'sometimes' : 'prohibited', 'nullable', 'string', 'min:16', 'max:255'],
|
|
'rotate_secret' => [$creating ? 'prohibited' : 'sometimes', 'boolean'],
|
|
'include_personal_data' => ['sometimes', 'boolean'],
|
|
'is_active' => ['sometimes', 'boolean'],
|
|
];
|
|
}
|
|
}
|