mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-04-20 19:30:05 +00:00
Added active toggle to webhooks
To allow easy temporary de-activation without deletion or other workarounds. Updated tests to cover.
This commit is contained in:
parent
917598f7c8
commit
dbd4281ae8
10 changed files with 41 additions and 8 deletions
app
database
resources
tests/Actions
|
@ -84,10 +84,13 @@ class ActivityLogger
|
||||||
*/
|
*/
|
||||||
protected function dispatchWebhooks(string $type, $detail): void
|
protected function dispatchWebhooks(string $type, $detail): void
|
||||||
{
|
{
|
||||||
$webhooks = Webhook::query()->whereHas('trackedEvents', function(Builder $query) use ($type) {
|
$webhooks = Webhook::query()
|
||||||
|
->whereHas('trackedEvents', function(Builder $query) use ($type) {
|
||||||
$query->where('event', '=', $type)
|
$query->where('event', '=', $type)
|
||||||
->orWhere('event', '=', 'all');
|
->orWhere('event', '=', 'all');
|
||||||
})->get();
|
})
|
||||||
|
->where('active', '=', true)
|
||||||
|
->get();
|
||||||
|
|
||||||
foreach ($webhooks as $webhook) {
|
foreach ($webhooks as $webhook) {
|
||||||
dispatch(new DispatchWebhookJob($webhook, $type, $detail));
|
dispatch(new DispatchWebhookJob($webhook, $type, $detail));
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $endpoint
|
* @property string $endpoint
|
||||||
* @property Collection $trackedEvents
|
* @property Collection $trackedEvents
|
||||||
|
* @property bool $active
|
||||||
*/
|
*/
|
||||||
class Webhook extends Model implements Loggable
|
class Webhook extends Model implements Loggable
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,10 +43,12 @@ class WebhookController extends Controller
|
||||||
$validated = $this->validate($request, [
|
$validated = $this->validate($request, [
|
||||||
'name' => ['required', 'max:150'],
|
'name' => ['required', 'max:150'],
|
||||||
'endpoint' => ['required', 'url', 'max:500'],
|
'endpoint' => ['required', 'url', 'max:500'],
|
||||||
'events' => ['required', 'array']
|
'events' => ['required', 'array'],
|
||||||
|
'active' => ['required'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$webhook = new Webhook($validated);
|
$webhook = new Webhook($validated);
|
||||||
|
$webhook->active = $validated['active'] === 'true';
|
||||||
$webhook->save();
|
$webhook->save();
|
||||||
$webhook->updateTrackedEvents(array_values($validated['events']));
|
$webhook->updateTrackedEvents(array_values($validated['events']));
|
||||||
|
|
||||||
|
@ -75,12 +77,14 @@ class WebhookController extends Controller
|
||||||
$validated = $this->validate($request, [
|
$validated = $this->validate($request, [
|
||||||
'name' => ['required', 'max:150'],
|
'name' => ['required', 'max:150'],
|
||||||
'endpoint' => ['required', 'url', 'max:500'],
|
'endpoint' => ['required', 'url', 'max:500'],
|
||||||
'events' => ['required', 'array']
|
'events' => ['required', 'array'],
|
||||||
|
'active' => ['required'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** @var Webhook $webhook */
|
/** @var Webhook $webhook */
|
||||||
$webhook = Webhook::query()->findOrFail($id);
|
$webhook = Webhook::query()->findOrFail($id);
|
||||||
|
|
||||||
|
$webhook->active = $validated['active'] === 'true';
|
||||||
$webhook->fill($validated)->save();
|
$webhook->fill($validated)->save();
|
||||||
$webhook->updateTrackedEvents($validated['events']);
|
$webhook->updateTrackedEvents($validated['events']);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ class WebhookFactory extends Factory
|
||||||
return [
|
return [
|
||||||
'name' => 'My webhook for ' . $this->faker->country(),
|
'name' => 'My webhook for ' . $this->faker->country(),
|
||||||
'endpoint' => $this->faker->url,
|
'endpoint' => $this->faker->url,
|
||||||
|
'active' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,12 @@ class CreateWebhooksTable extends Migration
|
||||||
Schema::create('webhooks', function (Blueprint $table) {
|
Schema::create('webhooks', function (Blueprint $table) {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->string('name', 150);
|
$table->string('name', 150);
|
||||||
|
$table->boolean('active');
|
||||||
$table->string('endpoint', 500);
|
$table->string('endpoint', 500);
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
$table->index('name');
|
$table->index('name');
|
||||||
|
$table->index('active');
|
||||||
});
|
});
|
||||||
|
|
||||||
Schema::create('webhook_tracked_events', function (Blueprint $table) {
|
Schema::create('webhook_tracked_events', function (Blueprint $table) {
|
||||||
|
|
|
@ -71,6 +71,9 @@ return [
|
||||||
'list_view' => 'List View',
|
'list_view' => 'List View',
|
||||||
'default' => 'Default',
|
'default' => 'Default',
|
||||||
'breadcrumb' => 'Breadcrumb',
|
'breadcrumb' => 'Breadcrumb',
|
||||||
|
'status' => 'Status',
|
||||||
|
'status_active' => 'Active',
|
||||||
|
'status_inactive' => 'Inactive',
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
'header_menu_expand' => 'Expand Header Menu',
|
'header_menu_expand' => 'Expand Header Menu',
|
||||||
|
|
|
@ -236,6 +236,7 @@ return [
|
||||||
// Webhooks
|
// Webhooks
|
||||||
'webhooks' => 'Webhooks',
|
'webhooks' => 'Webhooks',
|
||||||
'webhooks_create' => 'Create New Webhook',
|
'webhooks_create' => 'Create New Webhook',
|
||||||
|
'webhooks_none_created' => 'No webhooks have yet been created.',
|
||||||
'webhooks_edit' => 'Edit Webhook',
|
'webhooks_edit' => 'Edit Webhook',
|
||||||
'webhooks_save' => 'Save Webhook',
|
'webhooks_save' => 'Save Webhook',
|
||||||
'webhooks_details' => 'Webhook Details',
|
'webhooks_details' => 'Webhook Details',
|
||||||
|
@ -246,6 +247,7 @@ return [
|
||||||
'webhooks_events_all' => 'All system events',
|
'webhooks_events_all' => 'All system events',
|
||||||
'webhooks_name' => 'Webhook Name',
|
'webhooks_name' => 'Webhook Name',
|
||||||
'webhooks_endpoint' => 'Webhook Endpoint',
|
'webhooks_endpoint' => 'Webhook Endpoint',
|
||||||
|
'webhooks_active' => 'Webhook Active',
|
||||||
'webhook_events_table_header' => 'Events',
|
'webhook_events_table_header' => 'Events',
|
||||||
'webhooks_delete' => 'Delete Webhook',
|
'webhooks_delete' => 'Delete Webhook',
|
||||||
'webhooks_delete_warning' => 'This will fully delete this webhook, with the name \':webhookName\', from the system.',
|
'webhooks_delete_warning' => 'This will fully delete this webhook, with the name \':webhookName\', from the system.',
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ trans('common.name') }}</th>
|
<th>{{ trans('common.name') }}</th>
|
||||||
<th>{{ trans('settings.webhook_events_table_header') }}</th>
|
<th>{{ trans('settings.webhook_events_table_header') }}</th>
|
||||||
|
<th>{{ trans('common.status') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
@foreach($webhooks as $webhook)
|
@foreach($webhooks as $webhook)
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -39,12 +40,15 @@
|
||||||
{{ $webhook->trackedEvents->count() }}
|
{{ $webhook->trackedEvents->count() }}
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ trans('common.status_' . ($webhook->active ? 'active' : 'inactive')) }}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</table>
|
</table>
|
||||||
@else
|
@else
|
||||||
<p class="text-muted empty-text">
|
<p class="text-muted empty-text px-none">
|
||||||
{{ trans('common.no_items') }}
|
{{ trans('settings.webhooks_none_created') }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,14 @@
|
||||||
<div>
|
<div>
|
||||||
<label class="setting-list-label">{{ trans('settings.webhooks_details') }}</label>
|
<label class="setting-list-label">{{ trans('settings.webhooks_details') }}</label>
|
||||||
<p class="small">{{ trans('settings.webhooks_details_desc') }}</p>
|
<p class="small">{{ trans('settings.webhooks_details_desc') }}</p>
|
||||||
|
<div>
|
||||||
|
@include('form.toggle-switch', [
|
||||||
|
'name' => 'active',
|
||||||
|
'value' => old('active') ?? $model->active ?? true,
|
||||||
|
'label' => trans('settings.webhooks_active'),
|
||||||
|
])
|
||||||
|
@include('form.errors', ['name' => 'active'])
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -22,6 +22,7 @@ class WebhookManagementTest extends TestCase
|
||||||
$resp->assertElementExists('a[href="' . $webhook->getUrl() . '"]', $webhook->name);
|
$resp->assertElementExists('a[href="' . $webhook->getUrl() . '"]', $webhook->name);
|
||||||
$resp->assertSee($webhook->endpoint);
|
$resp->assertSee($webhook->endpoint);
|
||||||
$resp->assertSee('All system events');
|
$resp->assertSee('All system events');
|
||||||
|
$resp->assertSee('Active');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_create_view()
|
public function test_create_view()
|
||||||
|
@ -38,6 +39,7 @@ class WebhookManagementTest extends TestCase
|
||||||
'name' => 'My first webhook',
|
'name' => 'My first webhook',
|
||||||
'endpoint' => 'https://example.com/webhook',
|
'endpoint' => 'https://example.com/webhook',
|
||||||
'events' => ['all'],
|
'events' => ['all'],
|
||||||
|
'active' => 'true'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$resp->assertRedirect('/settings/webhooks');
|
$resp->assertRedirect('/settings/webhooks');
|
||||||
|
@ -49,6 +51,7 @@ class WebhookManagementTest extends TestCase
|
||||||
$this->assertDatabaseHas('webhooks', [
|
$this->assertDatabaseHas('webhooks', [
|
||||||
'name' => 'My first webhook',
|
'name' => 'My first webhook',
|
||||||
'endpoint' => 'https://example.com/webhook',
|
'endpoint' => 'https://example.com/webhook',
|
||||||
|
'active' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** @var Webhook $webhook */
|
/** @var Webhook $webhook */
|
||||||
|
@ -79,6 +82,7 @@ class WebhookManagementTest extends TestCase
|
||||||
'name' => 'My updated webhook',
|
'name' => 'My updated webhook',
|
||||||
'endpoint' => 'https://example.com/updated-webhook',
|
'endpoint' => 'https://example.com/updated-webhook',
|
||||||
'events' => [ActivityType::PAGE_CREATE, ActivityType::PAGE_UPDATE],
|
'events' => [ActivityType::PAGE_CREATE, ActivityType::PAGE_UPDATE],
|
||||||
|
'active' => 'true'
|
||||||
]);
|
]);
|
||||||
$resp->assertRedirect('/settings/webhooks');
|
$resp->assertRedirect('/settings/webhooks');
|
||||||
|
|
||||||
|
@ -89,6 +93,7 @@ class WebhookManagementTest extends TestCase
|
||||||
'id' => $webhook->id,
|
'id' => $webhook->id,
|
||||||
'name' => 'My updated webhook',
|
'name' => 'My updated webhook',
|
||||||
'endpoint' => 'https://example.com/updated-webhook',
|
'endpoint' => 'https://example.com/updated-webhook',
|
||||||
|
'active' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$trackedEvents = $webhook->trackedEvents()->get();
|
$trackedEvents = $webhook->trackedEvents()->get();
|
||||||
|
|
Loading…
Add table
Reference in a new issue