From dbd4281ae80a5be2d631a0c8bd9e8dc29546c92e Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Sun, 12 Dec 2021 17:39:06 +0000
Subject: [PATCH] Added active toggle to webhooks

To allow easy temporary de-activation without deletion or other
workarounds. Updated tests to cover.
---
 app/Actions/ActivityLogger.php                        | 11 +++++++----
 app/Actions/Webhook.php                               |  1 +
 app/Http/Controllers/WebhookController.php            |  8 ++++++--
 database/factories/Actions/WebhookFactory.php         |  1 +
 .../2021_12_07_111343_create_webhooks_table.php       |  2 ++
 resources/lang/en/common.php                          |  3 +++
 resources/lang/en/settings.php                        |  2 ++
 resources/views/settings/webhooks/index.blade.php     |  8 ++++++--
 .../views/settings/webhooks/parts/form.blade.php      |  8 ++++++++
 tests/Actions/WebhookManagementTest.php               |  5 +++++
 10 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/app/Actions/ActivityLogger.php b/app/Actions/ActivityLogger.php
index ad4ee7375..870e7f96d 100644
--- a/app/Actions/ActivityLogger.php
+++ b/app/Actions/ActivityLogger.php
@@ -84,10 +84,13 @@ class ActivityLogger
      */
     protected function dispatchWebhooks(string $type, $detail): void
     {
-        $webhooks = Webhook::query()->whereHas('trackedEvents', function(Builder $query) use ($type) {
-            $query->where('event', '=', $type)
-                ->orWhere('event', '=', 'all');
-        })->get();
+        $webhooks = Webhook::query()
+            ->whereHas('trackedEvents', function(Builder $query) use ($type) {
+                $query->where('event', '=', $type)
+                    ->orWhere('event', '=', 'all');
+            })
+            ->where('active', '=', true)
+            ->get();
 
         foreach ($webhooks as $webhook) {
             dispatch(new DispatchWebhookJob($webhook, $type, $detail));
diff --git a/app/Actions/Webhook.php b/app/Actions/Webhook.php
index 55bc855ce..ed13856f3 100644
--- a/app/Actions/Webhook.php
+++ b/app/Actions/Webhook.php
@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
  * @property string $name
  * @property string $endpoint
  * @property Collection $trackedEvents
+ * @property bool $active
  */
 class Webhook extends Model implements Loggable
 {
diff --git a/app/Http/Controllers/WebhookController.php b/app/Http/Controllers/WebhookController.php
index 497d623b2..588b256a3 100644
--- a/app/Http/Controllers/WebhookController.php
+++ b/app/Http/Controllers/WebhookController.php
@@ -43,10 +43,12 @@ class WebhookController extends Controller
         $validated = $this->validate($request, [
             'name' => ['required', 'max:150'],
             'endpoint' => ['required', 'url', 'max:500'],
-            'events' => ['required', 'array']
+            'events' => ['required', 'array'],
+            'active' => ['required'],
         ]);
 
         $webhook = new Webhook($validated);
+        $webhook->active = $validated['active'] === 'true';
         $webhook->save();
         $webhook->updateTrackedEvents(array_values($validated['events']));
 
@@ -75,12 +77,14 @@ class WebhookController extends Controller
         $validated = $this->validate($request, [
             'name' => ['required', 'max:150'],
             'endpoint' => ['required', 'url', 'max:500'],
-            'events' => ['required', 'array']
+            'events' => ['required', 'array'],
+            'active' => ['required'],
         ]);
 
         /** @var Webhook $webhook */
         $webhook = Webhook::query()->findOrFail($id);
 
+        $webhook->active = $validated['active'] === 'true';
         $webhook->fill($validated)->save();
         $webhook->updateTrackedEvents($validated['events']);
 
diff --git a/database/factories/Actions/WebhookFactory.php b/database/factories/Actions/WebhookFactory.php
index a18ffbbc8..1230d49d1 100644
--- a/database/factories/Actions/WebhookFactory.php
+++ b/database/factories/Actions/WebhookFactory.php
@@ -20,6 +20,7 @@ class WebhookFactory extends Factory
         return [
             'name' => 'My webhook for ' . $this->faker->country(),
             'endpoint' => $this->faker->url,
+            'active' => true,
         ];
     }
 }
diff --git a/database/migrations/2021_12_07_111343_create_webhooks_table.php b/database/migrations/2021_12_07_111343_create_webhooks_table.php
index 22b8549f4..be4fc539d 100644
--- a/database/migrations/2021_12_07_111343_create_webhooks_table.php
+++ b/database/migrations/2021_12_07_111343_create_webhooks_table.php
@@ -16,10 +16,12 @@ class CreateWebhooksTable extends Migration
         Schema::create('webhooks', function (Blueprint $table) {
             $table->increments('id');
             $table->string('name', 150);
+            $table->boolean('active');
             $table->string('endpoint', 500);
             $table->timestamps();
 
             $table->index('name');
+            $table->index('active');
         });
 
         Schema::create('webhook_tracked_events', function (Blueprint $table) {
diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php
index 722bf00db..53db3cf40 100644
--- a/resources/lang/en/common.php
+++ b/resources/lang/en/common.php
@@ -71,6 +71,9 @@ return [
     'list_view' => 'List View',
     'default' => 'Default',
     'breadcrumb' => 'Breadcrumb',
+    'status' => 'Status',
+    'status_active' => 'Active',
+    'status_inactive' => 'Inactive',
 
     // Header
     'header_menu_expand' => 'Expand Header Menu',
diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php
index 209702d0e..3556fcf64 100755
--- a/resources/lang/en/settings.php
+++ b/resources/lang/en/settings.php
@@ -236,6 +236,7 @@ return [
     // Webhooks
     'webhooks' => 'Webhooks',
     'webhooks_create' => 'Create New Webhook',
+    'webhooks_none_created' => 'No webhooks have yet been created.',
     'webhooks_edit' => 'Edit Webhook',
     'webhooks_save' => 'Save Webhook',
     'webhooks_details' => 'Webhook Details',
@@ -246,6 +247,7 @@ return [
     'webhooks_events_all' => 'All system events',
     'webhooks_name' => 'Webhook Name',
     'webhooks_endpoint' => 'Webhook Endpoint',
+    'webhooks_active' => 'Webhook Active',
     'webhook_events_table_header' => 'Events',
     'webhooks_delete' => 'Delete Webhook',
     'webhooks_delete_warning' => 'This will fully delete this webhook, with the name \':webhookName\', from the system.',
diff --git a/resources/views/settings/webhooks/index.blade.php b/resources/views/settings/webhooks/index.blade.php
index 999a458ec..d6423b6fb 100644
--- a/resources/views/settings/webhooks/index.blade.php
+++ b/resources/views/settings/webhooks/index.blade.php
@@ -25,6 +25,7 @@
                     <tr>
                         <th>{{ trans('common.name') }}</th>
                         <th>{{ trans('settings.webhook_events_table_header') }}</th>
+                        <th>{{ trans('common.status') }}</th>
                     </tr>
                     @foreach($webhooks as $webhook)
                         <tr>
@@ -39,12 +40,15 @@
                                     {{ $webhook->trackedEvents->count() }}
                                 @endif
                             </td>
+                            <td>
+                                {{ trans('common.status_' . ($webhook->active ? 'active' : 'inactive')) }}
+                            </td>
                         </tr>
                     @endforeach
                 </table>
             @else
-                <p class="text-muted empty-text">
-                    {{ trans('common.no_items') }}
+                <p class="text-muted empty-text px-none">
+                    {{ trans('settings.webhooks_none_created') }}
                 </p>
             @endif
 
diff --git a/resources/views/settings/webhooks/parts/form.blade.php b/resources/views/settings/webhooks/parts/form.blade.php
index e2b3fc34d..458b6767b 100644
--- a/resources/views/settings/webhooks/parts/form.blade.php
+++ b/resources/views/settings/webhooks/parts/form.blade.php
@@ -9,6 +9,14 @@
             <div>
                 <label class="setting-list-label">{{ trans('settings.webhooks_details') }}</label>
                 <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 class="form-group">
diff --git a/tests/Actions/WebhookManagementTest.php b/tests/Actions/WebhookManagementTest.php
index 1423fe6ef..8abf06fc5 100644
--- a/tests/Actions/WebhookManagementTest.php
+++ b/tests/Actions/WebhookManagementTest.php
@@ -22,6 +22,7 @@ class WebhookManagementTest extends TestCase
         $resp->assertElementExists('a[href="' . $webhook->getUrl() . '"]', $webhook->name);
         $resp->assertSee($webhook->endpoint);
         $resp->assertSee('All system events');
+        $resp->assertSee('Active');
     }
 
     public function test_create_view()
@@ -38,6 +39,7 @@ class WebhookManagementTest extends TestCase
             'name' => 'My first webhook',
             'endpoint' => 'https://example.com/webhook',
             'events' => ['all'],
+            'active' => 'true'
         ]);
 
         $resp->assertRedirect('/settings/webhooks');
@@ -49,6 +51,7 @@ class WebhookManagementTest extends TestCase
         $this->assertDatabaseHas('webhooks', [
             'name' => 'My first webhook',
             'endpoint' => 'https://example.com/webhook',
+            'active' => true,
         ]);
 
         /** @var Webhook $webhook */
@@ -79,6 +82,7 @@ class WebhookManagementTest extends TestCase
             'name' => 'My updated webhook',
             'endpoint' => 'https://example.com/updated-webhook',
             'events' => [ActivityType::PAGE_CREATE, ActivityType::PAGE_UPDATE],
+            'active' => 'true'
         ]);
         $resp->assertRedirect('/settings/webhooks');
 
@@ -89,6 +93,7 @@ class WebhookManagementTest extends TestCase
             'id' => $webhook->id,
             'name' => 'My updated webhook',
             'endpoint' => 'https://example.com/updated-webhook',
+            'active' => true,
         ]);
 
         $trackedEvents = $webhook->trackedEvents()->get();