Manage webhooks from the panel
Some checks failed
Tests / lint (push) Has been cancelled
Tests / test (push) Has been cancelled
Tests / test-postgres (push) Has been cancelled
Tests / mcp (push) Has been cancelled

Create one and see its secret once, send a test, change the secret, and read
each delivery with what the other end answered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 11:44:11 +02:00
parent d80ed1a3e8
commit d4cf4a66b7
14 changed files with 797 additions and 26 deletions

View File

@@ -8,9 +8,9 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\Api\V1\WebhookRequest;
use App\Http\Resources\WebhookDeliveryResource;
use App\Http\Resources\WebhookResource;
use App\Jobs\DeliverWebhook;
use App\Models\Webhook;
use App\Models\WebhookDelivery;
use App\Support\Webhooks\Webhooks;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
@@ -115,15 +115,9 @@ class WebhookController extends Controller
{
$this->authorize('update', $webhook);
$delivery = $webhook->deliveries()->create([
'uuid' => (string) Str::uuid(),
'event' => 'ping',
'payload' => ['webhook' => $webhook->id, 'events' => $webhook->events],
]);
$delivery = Webhooks::ping($webhook);
DeliverWebhook::dispatch($delivery);
return WebhookDeliveryResource::make($delivery->refresh())->response()->setStatusCode(202);
return WebhookDeliveryResource::make($delivery)->response()->setStatusCode(202);
}
/**
@@ -133,14 +127,8 @@ class WebhookController extends Controller
{
$this->authorize('update', $delivery->webhook);
$again = $delivery->webhook->deliveries()->create([
'uuid' => (string) Str::uuid(),
'event' => $delivery->event,
'payload' => $delivery->payload,
]);
$again = Webhooks::redeliver($delivery);
DeliverWebhook::dispatch($again);
return WebhookDeliveryResource::make($again->refresh())->response()->setStatusCode(202);
return WebhookDeliveryResource::make($again)->response()->setStatusCode(202);
}
}

View File

@@ -5,8 +5,7 @@ declare(strict_types=1);
namespace App\Http\Requests\Api\V1;
use App\Models\Webhook;
use App\Support\Webhooks\PublicEndpoint;
use Closure;
use App\Rules\PublicHttpsUrl;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@@ -34,13 +33,7 @@ class WebhookRequest extends FormRequest
'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}"));
}
},
new PublicHttpsUrl,
],
'events' => [$sometimes, 'array', 'min:1'],
'events.*' => ['string', 'distinct', Rule::in(['*', ...Webhook::EVENTS])],