Send signed outgoing webhooks
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>
This commit is contained in:
80
app/Models/Webhook.php
Normal file
80
app/Models/Webhook.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* Somewhere to tell when something happens here.
|
||||
*/
|
||||
#[Fillable(['name', 'url', 'secret', 'events', 'include_personal_data', 'is_active'])]
|
||||
#[Hidden(['secret'])]
|
||||
class Webhook extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* What can be subscribed to. `*` is all of them.
|
||||
*/
|
||||
public const EVENTS = [
|
||||
'application.received',
|
||||
'content.published',
|
||||
'content.unpublished',
|
||||
'review.requested',
|
||||
'review.returned',
|
||||
];
|
||||
|
||||
/**
|
||||
* Switched off after this many failed deliveries in a row, so a dead
|
||||
* endpoint does not keep a queue busy forever. Switching it back on is a
|
||||
* person's decision.
|
||||
*/
|
||||
public const MAX_FAILURES = 20;
|
||||
|
||||
protected $attributes = [
|
||||
'include_personal_data' => false,
|
||||
'is_active' => true,
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'secret' => 'encrypted',
|
||||
'events' => 'array',
|
||||
'include_personal_data' => 'boolean',
|
||||
'is_active' => 'boolean',
|
||||
'last_delivered_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<WebhookDelivery, $this>
|
||||
*/
|
||||
public function deliveries(): HasMany
|
||||
{
|
||||
return $this->hasMany(WebhookDelivery::class)->latest('id');
|
||||
}
|
||||
|
||||
public function listensTo(string $event): bool
|
||||
{
|
||||
$events = $this->events ?? [];
|
||||
|
||||
return in_array('*', $events, true) || in_array($event, $events, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Builder<$this> $query
|
||||
* @return Builder<$this>
|
||||
*/
|
||||
public function scopeActive(Builder $query): Builder
|
||||
{
|
||||
return $query->where('is_active', true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user