feat: add custom webhook notification support
Add basic infrastructure for custom webhook notifications: - Create webhook_notification_settings table with event toggles - Add WebhookNotificationSettings model with encrypted URL - Integrate webhook settings into Team model and HasNotificationSettings trait - Create Livewire component and Blade view for webhook configuration - Add webhook navigation route and UI This provides the foundation for sending webhook notifications to custom HTTP/HTTPS endpoints when events occur in Coolify. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
503da6da21
commit
27879377a0
8 changed files with 385 additions and 0 deletions
180
app/Livewire/Notifications/Webhook.php
Normal file
180
app/Livewire/Notifications/Webhook.php
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Notifications;
|
||||||
|
|
||||||
|
use App\Models\Team;
|
||||||
|
use App\Models\WebhookNotificationSettings;
|
||||||
|
use App\Notifications\Test;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
use Livewire\Attributes\Validate;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class Webhook extends Component
|
||||||
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
|
public Team $team;
|
||||||
|
|
||||||
|
public WebhookNotificationSettings $settings;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $webhookEnabled = false;
|
||||||
|
|
||||||
|
#[Validate(['url', 'nullable'])]
|
||||||
|
public ?string $webhookUrl = null;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $deploymentSuccessWebhookNotifications = false;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $deploymentFailureWebhookNotifications = true;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $statusChangeWebhookNotifications = false;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $backupSuccessWebhookNotifications = false;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $backupFailureWebhookNotifications = true;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $scheduledTaskSuccessWebhookNotifications = false;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $scheduledTaskFailureWebhookNotifications = true;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $dockerCleanupSuccessWebhookNotifications = false;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $dockerCleanupFailureWebhookNotifications = true;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $serverDiskUsageWebhookNotifications = true;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $serverReachableWebhookNotifications = false;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $serverUnreachableWebhookNotifications = true;
|
||||||
|
|
||||||
|
#[Validate(['boolean'])]
|
||||||
|
public bool $serverPatchWebhookNotifications = false;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->team = auth()->user()->currentTeam();
|
||||||
|
$this->settings = $this->team->webhookNotificationSettings;
|
||||||
|
$this->authorize('view', $this->settings);
|
||||||
|
$this->syncData();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function syncData(bool $toModel = false)
|
||||||
|
{
|
||||||
|
if ($toModel) {
|
||||||
|
$this->validate();
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
|
$this->settings->webhook_enabled = $this->webhookEnabled;
|
||||||
|
$this->settings->webhook_url = $this->webhookUrl;
|
||||||
|
|
||||||
|
$this->settings->deployment_success_webhook_notifications = $this->deploymentSuccessWebhookNotifications;
|
||||||
|
$this->settings->deployment_failure_webhook_notifications = $this->deploymentFailureWebhookNotifications;
|
||||||
|
$this->settings->status_change_webhook_notifications = $this->statusChangeWebhookNotifications;
|
||||||
|
$this->settings->backup_success_webhook_notifications = $this->backupSuccessWebhookNotifications;
|
||||||
|
$this->settings->backup_failure_webhook_notifications = $this->backupFailureWebhookNotifications;
|
||||||
|
$this->settings->scheduled_task_success_webhook_notifications = $this->scheduledTaskSuccessWebhookNotifications;
|
||||||
|
$this->settings->scheduled_task_failure_webhook_notifications = $this->scheduledTaskFailureWebhookNotifications;
|
||||||
|
$this->settings->docker_cleanup_success_webhook_notifications = $this->dockerCleanupSuccessWebhookNotifications;
|
||||||
|
$this->settings->docker_cleanup_failure_webhook_notifications = $this->dockerCleanupFailureWebhookNotifications;
|
||||||
|
$this->settings->server_disk_usage_webhook_notifications = $this->serverDiskUsageWebhookNotifications;
|
||||||
|
$this->settings->server_reachable_webhook_notifications = $this->serverReachableWebhookNotifications;
|
||||||
|
$this->settings->server_unreachable_webhook_notifications = $this->serverUnreachableWebhookNotifications;
|
||||||
|
$this->settings->server_patch_webhook_notifications = $this->serverPatchWebhookNotifications;
|
||||||
|
|
||||||
|
$this->settings->save();
|
||||||
|
refreshSession();
|
||||||
|
} else {
|
||||||
|
$this->webhookEnabled = $this->settings->webhook_enabled;
|
||||||
|
$this->webhookUrl = $this->settings->webhook_url;
|
||||||
|
|
||||||
|
$this->deploymentSuccessWebhookNotifications = $this->settings->deployment_success_webhook_notifications;
|
||||||
|
$this->deploymentFailureWebhookNotifications = $this->settings->deployment_failure_webhook_notifications;
|
||||||
|
$this->statusChangeWebhookNotifications = $this->settings->status_change_webhook_notifications;
|
||||||
|
$this->backupSuccessWebhookNotifications = $this->settings->backup_success_webhook_notifications;
|
||||||
|
$this->backupFailureWebhookNotifications = $this->settings->backup_failure_webhook_notifications;
|
||||||
|
$this->scheduledTaskSuccessWebhookNotifications = $this->settings->scheduled_task_success_webhook_notifications;
|
||||||
|
$this->scheduledTaskFailureWebhookNotifications = $this->settings->scheduled_task_failure_webhook_notifications;
|
||||||
|
$this->dockerCleanupSuccessWebhookNotifications = $this->settings->docker_cleanup_success_webhook_notifications;
|
||||||
|
$this->dockerCleanupFailureWebhookNotifications = $this->settings->docker_cleanup_failure_webhook_notifications;
|
||||||
|
$this->serverDiskUsageWebhookNotifications = $this->settings->server_disk_usage_webhook_notifications;
|
||||||
|
$this->serverReachableWebhookNotifications = $this->settings->server_reachable_webhook_notifications;
|
||||||
|
$this->serverUnreachableWebhookNotifications = $this->settings->server_unreachable_webhook_notifications;
|
||||||
|
$this->serverPatchWebhookNotifications = $this->settings->server_patch_webhook_notifications;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function instantSaveWebhookEnabled()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$original = $this->webhookEnabled;
|
||||||
|
$this->validate([
|
||||||
|
'webhookUrl' => 'required',
|
||||||
|
], [
|
||||||
|
'webhookUrl.required' => 'Webhook URL is required.',
|
||||||
|
]);
|
||||||
|
$this->saveModel();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->webhookEnabled = $original;
|
||||||
|
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function instantSave()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->syncData(true);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function submit()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->resetErrorBag();
|
||||||
|
$this->syncData(true);
|
||||||
|
$this->saveModel();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveModel()
|
||||||
|
{
|
||||||
|
$this->syncData(true);
|
||||||
|
refreshSession();
|
||||||
|
$this->dispatch('success', 'Settings saved.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendTestNotification()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('sendTest', $this->settings);
|
||||||
|
$this->team->notify(new Test(channel: 'webhook'));
|
||||||
|
$this->dispatch('success', 'Test notification sent.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.notifications.webhook');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -54,6 +54,7 @@ protected static function booted()
|
||||||
$team->slackNotificationSettings()->create();
|
$team->slackNotificationSettings()->create();
|
||||||
$team->telegramNotificationSettings()->create();
|
$team->telegramNotificationSettings()->create();
|
||||||
$team->pushoverNotificationSettings()->create();
|
$team->pushoverNotificationSettings()->create();
|
||||||
|
$team->webhookNotificationSettings()->create();
|
||||||
});
|
});
|
||||||
|
|
||||||
static::saving(function ($team) {
|
static::saving(function ($team) {
|
||||||
|
|
@ -307,4 +308,9 @@ public function pushoverNotificationSettings()
|
||||||
{
|
{
|
||||||
return $this->hasOne(PushoverNotificationSettings::class);
|
return $this->hasOne(PushoverNotificationSettings::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function webhookNotificationSettings()
|
||||||
|
{
|
||||||
|
return $this->hasOne(WebhookNotificationSettings::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
app/Models/WebhookNotificationSettings.php
Normal file
64
app/Models/WebhookNotificationSettings.php
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
|
class WebhookNotificationSettings extends Model
|
||||||
|
{
|
||||||
|
use Notifiable;
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'team_id',
|
||||||
|
|
||||||
|
'webhook_enabled',
|
||||||
|
'webhook_url',
|
||||||
|
|
||||||
|
'deployment_success_webhook_notifications',
|
||||||
|
'deployment_failure_webhook_notifications',
|
||||||
|
'status_change_webhook_notifications',
|
||||||
|
'backup_success_webhook_notifications',
|
||||||
|
'backup_failure_webhook_notifications',
|
||||||
|
'scheduled_task_success_webhook_notifications',
|
||||||
|
'scheduled_task_failure_webhook_notifications',
|
||||||
|
'docker_cleanup_webhook_notifications',
|
||||||
|
'server_disk_usage_webhook_notifications',
|
||||||
|
'server_reachable_webhook_notifications',
|
||||||
|
'server_unreachable_webhook_notifications',
|
||||||
|
'server_patch_webhook_notifications',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'webhook_enabled' => 'boolean',
|
||||||
|
'webhook_url' => 'encrypted',
|
||||||
|
|
||||||
|
'deployment_success_webhook_notifications' => 'boolean',
|
||||||
|
'deployment_failure_webhook_notifications' => 'boolean',
|
||||||
|
'status_change_webhook_notifications' => 'boolean',
|
||||||
|
'backup_success_webhook_notifications' => 'boolean',
|
||||||
|
'backup_failure_webhook_notifications' => 'boolean',
|
||||||
|
'scheduled_task_success_webhook_notifications' => 'boolean',
|
||||||
|
'scheduled_task_failure_webhook_notifications' => 'boolean',
|
||||||
|
'docker_cleanup_webhook_notifications' => 'boolean',
|
||||||
|
'server_disk_usage_webhook_notifications' => 'boolean',
|
||||||
|
'server_reachable_webhook_notifications' => 'boolean',
|
||||||
|
'server_unreachable_webhook_notifications' => 'boolean',
|
||||||
|
'server_patch_webhook_notifications' => 'boolean',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function team()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Team::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEnabled()
|
||||||
|
{
|
||||||
|
return $this->webhook_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,7 @@ public function getNotificationSettings(string $channel): ?Model
|
||||||
'telegram' => $this->telegramNotificationSettings,
|
'telegram' => $this->telegramNotificationSettings,
|
||||||
'slack' => $this->slackNotificationSettings,
|
'slack' => $this->slackNotificationSettings,
|
||||||
'pushover' => $this->pushoverNotificationSettings,
|
'pushover' => $this->pushoverNotificationSettings,
|
||||||
|
'webhook' => $this->webhookNotificationSettings,
|
||||||
default => null,
|
default => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('webhook_notification_settings', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('team_id')->constrained()->cascadeOnDelete();
|
||||||
|
|
||||||
|
$table->boolean('webhook_enabled')->default(false);
|
||||||
|
$table->text('webhook_url')->nullable();
|
||||||
|
|
||||||
|
$table->boolean('deployment_success_webhook_notifications')->default(false);
|
||||||
|
$table->boolean('deployment_failure_webhook_notifications')->default(true);
|
||||||
|
$table->boolean('status_change_webhook_notifications')->default(false);
|
||||||
|
$table->boolean('backup_success_webhook_notifications')->default(false);
|
||||||
|
$table->boolean('backup_failure_webhook_notifications')->default(true);
|
||||||
|
$table->boolean('scheduled_task_success_webhook_notifications')->default(false);
|
||||||
|
$table->boolean('scheduled_task_failure_webhook_notifications')->default(true);
|
||||||
|
$table->boolean('docker_cleanup_success_webhook_notifications')->default(false);
|
||||||
|
$table->boolean('docker_cleanup_failure_webhook_notifications')->default(true);
|
||||||
|
$table->boolean('server_disk_usage_webhook_notifications')->default(true);
|
||||||
|
$table->boolean('server_reachable_webhook_notifications')->default(false);
|
||||||
|
$table->boolean('server_unreachable_webhook_notifications')->default(true);
|
||||||
|
|
||||||
|
$table->unique(['team_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('webhook_notification_settings');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -23,6 +23,10 @@
|
||||||
href="{{ route('notifications.pushover') }}">
|
href="{{ route('notifications.pushover') }}">
|
||||||
<button>Pushover</button>
|
<button>Pushover</button>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="{{ request()->routeIs('notifications.webhook') ? 'dark:text-white' : '' }}"
|
||||||
|
href="{{ route('notifications.webhook') }}">
|
||||||
|
<button>Webhook</button>
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
83
resources/views/livewire/notifications/webhook.blade.php
Normal file
83
resources/views/livewire/notifications/webhook.blade.php
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
<div>
|
||||||
|
<x-slot:title>
|
||||||
|
Notifications | Coolify
|
||||||
|
</x-slot>
|
||||||
|
<x-notification.navbar />
|
||||||
|
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h2>Webhook</h2>
|
||||||
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
|
Save
|
||||||
|
</x-forms.button>
|
||||||
|
@if ($webhookEnabled)
|
||||||
|
<x-forms.button canGate="sendTest" :canResource="$settings" class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||||
|
wire:click="sendTestNotification">
|
||||||
|
Send Test Notification
|
||||||
|
</x-forms.button>
|
||||||
|
@else
|
||||||
|
<x-forms.button canGate="sendTest" :canResource="$settings" disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
||||||
|
Send Test Notification
|
||||||
|
</x-forms.button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="w-48">
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSaveWebhookEnabled" id="webhookEnabled" label="Enabled" />
|
||||||
|
</div>
|
||||||
|
<x-forms.input canGate="update" :canResource="$settings" type="url"
|
||||||
|
helper="Enter a valid HTTP or HTTPS URL. Coolify will send POST requests to this endpoint when events occur."
|
||||||
|
required id="webhookUrl" label="Webhook URL" />
|
||||||
|
</form>
|
||||||
|
<h2 class="mt-4">Notification Settings</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Select events for which you would like to receive webhook notifications.
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-col gap-4 max-w-2xl">
|
||||||
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
|
<h3 class="font-medium mb-3">Deployments</h3>
|
||||||
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentSuccessWebhookNotifications"
|
||||||
|
label="Deployment Success" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentFailureWebhookNotifications"
|
||||||
|
label="Deployment Failure" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel"
|
||||||
|
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
||||||
|
id="statusChangeWebhookNotifications" label="Container Status Changes" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
|
<h3 class="font-medium mb-3">Backups</h3>
|
||||||
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupSuccessWebhookNotifications"
|
||||||
|
label="Backup Success" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupFailureWebhookNotifications"
|
||||||
|
label="Backup Failure" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
|
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
||||||
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskSuccessWebhookNotifications"
|
||||||
|
label="Scheduled Task Success" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskFailureWebhookNotifications"
|
||||||
|
label="Scheduled Task Failure" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
|
<h3 class="font-medium mb-3">Server</h3>
|
||||||
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupSuccessWebhookNotifications"
|
||||||
|
label="Docker Cleanup Success" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupFailureWebhookNotifications"
|
||||||
|
label="Docker Cleanup Failure" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverDiskUsageWebhookNotifications"
|
||||||
|
label="Server Disk Usage" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverReachableWebhookNotifications"
|
||||||
|
label="Server Reachable" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverUnreachableWebhookNotifications"
|
||||||
|
label="Server Unreachable" />
|
||||||
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverPatchWebhookNotifications"
|
||||||
|
label="Server Patching" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
use App\Livewire\Notifications\Pushover as NotificationPushover;
|
use App\Livewire\Notifications\Pushover as NotificationPushover;
|
||||||
use App\Livewire\Notifications\Slack as NotificationSlack;
|
use App\Livewire\Notifications\Slack as NotificationSlack;
|
||||||
use App\Livewire\Notifications\Telegram as NotificationTelegram;
|
use App\Livewire\Notifications\Telegram as NotificationTelegram;
|
||||||
|
use App\Livewire\Notifications\Webhook as NotificationWebhook;
|
||||||
use App\Livewire\Profile\Index as ProfileIndex;
|
use App\Livewire\Profile\Index as ProfileIndex;
|
||||||
use App\Livewire\Project\Application\Configuration as ApplicationConfiguration;
|
use App\Livewire\Project\Application\Configuration as ApplicationConfiguration;
|
||||||
use App\Livewire\Project\Application\Deployment\Index as DeploymentIndex;
|
use App\Livewire\Project\Application\Deployment\Index as DeploymentIndex;
|
||||||
|
|
@ -125,6 +126,7 @@
|
||||||
Route::get('/discord', NotificationDiscord::class)->name('notifications.discord');
|
Route::get('/discord', NotificationDiscord::class)->name('notifications.discord');
|
||||||
Route::get('/slack', NotificationSlack::class)->name('notifications.slack');
|
Route::get('/slack', NotificationSlack::class)->name('notifications.slack');
|
||||||
Route::get('/pushover', NotificationPushover::class)->name('notifications.pushover');
|
Route::get('/pushover', NotificationPushover::class)->name('notifications.pushover');
|
||||||
|
Route::get('/webhook', NotificationWebhook::class)->name('notifications.webhook');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('storages')->group(function () {
|
Route::prefix('storages')->group(function () {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue