From 2b783b74704515dcfac2ad8b1016a4ae5d9e17a4 Mon Sep 17 00:00:00 2001 From: Hosteroid Date: Fri, 17 Oct 2025 11:13:25 +0300 Subject: [PATCH] Add generic webhook notification channel Introduces a new 'Webhook (Custom)' notification channel allowing users to send JSON payloads to any HTTP endpoint (e.g., n8n, Zapier, custom APIs). Updates the UI to support webhook configuration, adds backend validation, and implements the WebhookChannel for sending notifications. Documentation is updated with usage instructions and payload examples. --- README.md | 28 ++++ .../NotificationGroupController.php | 12 ++ app/Services/Channels/WebhookChannel.php | 48 ++++++ app/Services/NotificationService.php | 2 + app/Views/groups/edit.php | 55 +++++- app/Views/settings/index.php | 156 +++++++++--------- 6 files changed, 219 insertions(+), 82 deletions(-) create mode 100644 app/Services/Channels/WebhookChannel.php diff --git a/README.md b/README.md index 41b9ee9..e69ca77 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,34 @@ All application and email settings are now managed through the **Settings** page 4. Copy the webhook URL 5. Add it in the notification group settings +#### 🌐 Webhook (Custom) + +Send JSON payloads to any HTTP endpoint (e.g., n8n, Zapier, Make, your own API): + +1. Go to Notification Groups → Edit → Add Channel +2. Choose "Webhook (Custom)" +3. Paste your endpoint URL (HTTPS recommended) +4. Click "Test Channel" to verify + +Payload example sent on domain alerts: + +```json +{ + "event": "domain_expiration_alert", + "message": "⚠️ WARNING: Domain 'example.com' expires in 7 days (January 30, 2026)!\n\nRegistrar: Example Registrar\nPlease renew soon.", + "data": { + "domain": "example.com", + "domain_id": 123, + "days_left": 7, + "expiration_date": "2026-01-30", + "registrar": "Example Registrar" + }, + "sent_at": "2025-10-17T12:34:56Z" +} +``` + +Use this with n8n's "Webhook" trigger to start flows. + ## 📅 Setting Up Cron Jobs The application requires a cron job to check domains periodically. diff --git a/app/Controllers/NotificationGroupController.php b/app/Controllers/NotificationGroupController.php index db5eefd..d4fd843 100644 --- a/app/Controllers/NotificationGroupController.php +++ b/app/Controllers/NotificationGroupController.php @@ -214,6 +214,7 @@ class NotificationGroupController extends Controller break; case 'discord': case 'slack': + case 'webhook': $missingField = 'webhook URL'; break; } @@ -427,6 +428,17 @@ class NotificationGroupController extends Controller } return ['webhook_url' => $webhookUrl]; + case 'webhook': + $webhookUrl = trim($data['webhook_url'] ?? ''); + if (empty($webhookUrl) || !filter_var($webhookUrl, FILTER_VALIDATE_URL)) { + return null; + } + // Optional: Allow any HTTPS URL; prefer HTTPS for security + if (!str_starts_with($webhookUrl, 'https://') && !str_starts_with($webhookUrl, 'http://')) { + return null; + } + return ['webhook_url' => $webhookUrl]; + default: return null; } diff --git a/app/Services/Channels/WebhookChannel.php b/app/Services/Channels/WebhookChannel.php new file mode 100644 index 0000000..7900f7a --- /dev/null +++ b/app/Services/Channels/WebhookChannel.php @@ -0,0 +1,48 @@ +httpClient = new Client(['timeout' => 10]); + } + + public function send(array $config, string $message, array $data = []): bool + { + $url = trim($config['webhook_url'] ?? ''); + if (empty($url)) { + return false; + } + + // Build a sane, generic JSON payload for automation tools (n8n, Zapier, etc.) + $payload = [ + 'event' => 'domain_expiration_alert', + 'message' => $message, + 'data' => $data, + 'sent_at' => date('c') + ]; + + try { + $response = $this->httpClient->post($url, [ + 'headers' => [ + 'Content-Type' => 'application/json' + ], + 'json' => $payload + ]); + + $status = $response->getStatusCode(); + return $status >= 200 && $status < 300; + } catch (\Exception $e) { + error_log('Webhook send failed: ' . $e->getMessage()); + return false; + } + } +} + + diff --git a/app/Services/NotificationService.php b/app/Services/NotificationService.php index 7badf6a..cef98db 100644 --- a/app/Services/NotificationService.php +++ b/app/Services/NotificationService.php @@ -6,6 +6,7 @@ use App\Services\Channels\EmailChannel; use App\Services\Channels\TelegramChannel; use App\Services\Channels\DiscordChannel; use App\Services\Channels\SlackChannel; +use App\Services\Channels\WebhookChannel; class NotificationService { @@ -18,6 +19,7 @@ class NotificationService 'telegram' => new TelegramChannel(), 'discord' => new DiscordChannel(), 'slack' => new SlackChannel(), + 'webhook' => new WebhookChannel(), ]; } diff --git a/app/Views/groups/edit.php b/app/Views/groups/edit.php index fbec48b..424e2d3 100644 --- a/app/Views/groups/edit.php +++ b/app/Views/groups/edit.php @@ -78,9 +78,9 @@ ob_start();
'fa-envelope', 'telegram' => 'fa-telegram', 'discord' => 'fa-discord', 'slack' => 'fa-slack']; - $iconClasses = ['email' => 'fas', 'telegram' => 'fab', 'discord' => 'fab', 'slack' => 'fab']; - $colors = ['email' => 'blue', 'telegram' => 'blue', 'discord' => 'indigo', 'slack' => 'teal']; + $icons = ['email' => 'fa-envelope', 'telegram' => 'fa-telegram', 'discord' => 'fa-discord', 'slack' => 'fa-slack', 'webhook' => 'fa-link']; + $iconClasses = ['email' => 'fas', 'telegram' => 'fab', 'discord' => 'fab', 'slack' => 'fab', 'webhook' => 'fas']; + $colors = ['email' => 'blue', 'telegram' => 'blue', 'discord' => 'indigo', 'slack' => 'teal', 'webhook' => 'purple']; $icon = $icons[$channel['channel_type']] ?? 'fa-bell'; $iconClass = $iconClasses[$channel['channel_type']] ?? 'fas'; $color = $colors[$channel['channel_type']] ?? 'gray'; @@ -152,6 +152,7 @@ ob_start(); +
@@ -236,6 +237,24 @@ ob_start(); + + +
- + +
+
+

Two-Factor Authentication

+

Configure 2FA policy and security settings

+
- -
-
-

Two-Factor Authentication

-

Configure 2FA policy and security settings

+
+ +
+
+ + +

+ + Users must have verified email addresses to enable 2FA +

+
+ +
+
+ + +

Maximum failed attempts per IP address

+
+ +
+ + +

How long email backup codes remain valid

+
+
+ + +
+

+ + Two-Factor Authentication Features +

+
    +
  • TOTP Authenticator Apps: Google Authenticator, Authy, Microsoft Authenticator
  • +
  • Email Backup Codes: One-time codes sent to verified email addresses
  • +
  • Backup Recovery Codes: 8 single-use codes generated during setup
  • +
  • Rate Limiting: Prevents brute force attacks on verification codes
  • +
+
+
+ +
+ +
+
- -
- -
-
- - -

- - Users must have verified email addresses to enable 2FA -

-
- -
-
- - -

Maximum failed attempts per IP address

-
- -
- - -

How long email backup codes remain valid

-
-
- - -
-

- - Two-Factor Authentication Features -

-
    -
  • TOTP Authenticator Apps: Google Authenticator, Authy, Microsoft Authenticator
  • -
  • Email Backup Codes: One-time codes sent to verified email addresses
  • -
  • Backup Recovery Codes: 8 single-use codes generated during setup
  • -
  • Rate Limiting: Prevents brute force attacks on verification codes
  • -
-
-
- -
- -
-
-