diff --git a/README.md b/README.md
index dac48d127..56edffd31 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,8 @@ # Donations
### Special Sponsors
-
+
+
* [CCCareers](https://cccareers.org/) - A career development platform connecting coding bootcamp graduates with job opportunities in the tech industry.
* [Hetzner](http://htznr.li/CoolifyXHetzner) - A German web hosting company offering affordable dedicated servers, cloud services, and web hosting solutions.
@@ -52,7 +53,9 @@ ### Special Sponsors
* [SupaGuide](https://supa.guide/?ref=coolify.io) - A comprehensive resource hub offering guides and tutorials for web development using Supabase.
* [GoldenVM](https://billing.goldenvm.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
* [Tigris](https://tigrisdata.com/?ref=coolify.io) - A fully managed serverless object storage service compatible with Amazon S3 API. Offers high performance, scalability, and built-in search capabilities for efficient data management.
-* [Advin](https://coolify.ad.vin/?ref=coolify.io) - A digital advertising agency specializing in programmatic advertising and data-driven marketing strategies.
+* [Cloudify.ro](https://cloudify.ro/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
+* [Syntaxfm](https://syntax.fm/?ref=coolify.io) - Podcast for web developers.
+* [PFGlabs](https://pfglabs.com/?ref=coolify.io) - Build real project with Golang.
* [Treive](https://trieve.ai/?ref=coolify.io) - An AI-powered search and discovery platform for enhancing information retrieval in large datasets.
* [Blacksmith](https://blacksmith.sh/?ref=coolify.io) - A cloud-native platform for automating infrastructure provisioning and management across multiple cloud providers.
* [Brand Dev](https://brand.dev/?ref=coolify.io) - A web development agency specializing in creating custom digital experiences and brand identities.
@@ -92,6 +95,9 @@ ## Github Sponsors ($40+)
+
+
+
diff --git a/app/Console/Commands/NotifyDemo.php b/app/Console/Commands/NotifyDemo.php
index f0131b7b2..990a03869 100644
--- a/app/Console/Commands/NotifyDemo.php
+++ b/app/Console/Commands/NotifyDemo.php
@@ -59,9 +59,10 @@ private function showHelp()
Channels:
email
-
slack
discord
telegram
+
slack
+
pushover
@@ -72,6 +73,6 @@ private function showHelp()
In which manner you wish a coolified notification?
- HTML, ['email', 'slack', 'discord', 'telegram']);
+ HTML, ['email', 'discord', 'telegram', 'slack', 'pushover']);
}
}
diff --git a/app/Console/Commands/Seeder.php b/app/Console/Commands/Seeder.php
new file mode 100644
index 000000000..e37b6a9d2
--- /dev/null
+++ b/app/Console/Commands/Seeder.php
@@ -0,0 +1,24 @@
+info('Seeder is enabled on this server.');
+ $this->call('db:seed', ['--class' => 'ProductionSeeder', '--force' => true]);
+ exit(0);
+ } else {
+ $this->info('Seeder is disabled on this server.');
+ exit(0);
+ }
+ }
+}
diff --git a/app/Jobs/SendMessageToPushoverJob.php b/app/Jobs/SendMessageToPushoverJob.php
new file mode 100644
index 000000000..834a32b07
--- /dev/null
+++ b/app/Jobs/SendMessageToPushoverJob.php
@@ -0,0 +1,50 @@
+onQueue('high');
+ }
+
+ /**
+ * Execute the job.
+ */
+ public function handle(): void
+ {
+ $response = Http::post('https://api.pushover.net/1/messages.json', $this->message->toPayload($this->token, $this->user));
+ if ($response->failed()) {
+ throw new \RuntimeException('Pushover notification failed with ' . $response->status() . ' status code.' . $response->body());
+ }
+ }
+}
diff --git a/app/Jobs/SendMessageToTelegramJob.php b/app/Jobs/SendMessageToTelegramJob.php
index 85f4fc934..6b0a64ae3 100644
--- a/app/Jobs/SendMessageToTelegramJob.php
+++ b/app/Jobs/SendMessageToTelegramJob.php
@@ -32,7 +32,7 @@ public function __construct(
public array $buttons,
public string $token,
public string $chatId,
- public ?string $topicId = null,
+ public ?string $threadId = null,
) {
$this->onQueue('high');
}
@@ -67,8 +67,8 @@ public function handle(): void
'chat_id' => $this->chatId,
'text' => $this->text,
];
- if ($this->topicId) {
- $payload['message_thread_id'] = $this->topicId;
+ if ($this->threadId) {
+ $payload['message_thread_id'] = $this->threadId;
}
$response = Http::post($url, $payload);
if ($response->failed()) {
diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php
index dc2a95e84..eac48cf77 100644
--- a/app/Livewire/Notifications/Email.php
+++ b/app/Livewire/Notifications/Email.php
@@ -14,8 +14,10 @@ class Email extends Component
{
protected $listeners = ['refresh' => '$refresh'];
+ #[Locked]
public Team $team;
+ #[Locked]
public EmailNotificationSettings $settings;
#[Locked]
diff --git a/app/Livewire/Notifications/Pushover.php b/app/Livewire/Notifications/Pushover.php
new file mode 100644
index 000000000..f1e4c464d
--- /dev/null
+++ b/app/Livewire/Notifications/Pushover.php
@@ -0,0 +1,184 @@
+ '$refresh'];
+
+ #[Locked]
+ public Team $team;
+
+ #[Locked]
+ public PushoverNotificationSettings $settings;
+
+ #[Validate(['boolean'])]
+ public bool $pushoverEnabled = false;
+
+ #[Validate(['nullable', 'string'])]
+ public ?string $pushoverUserKey = null;
+
+ #[Validate(['nullable', 'string'])]
+ public ?string $pushoverApiToken = null;
+
+ #[Validate(['boolean'])]
+ public bool $deploymentSuccessPushoverNotifications = false;
+
+ #[Validate(['boolean'])]
+ public bool $deploymentFailurePushoverNotifications = true;
+
+ #[Validate(['boolean'])]
+ public bool $statusChangePushoverNotifications = false;
+
+ #[Validate(['boolean'])]
+ public bool $backupSuccessPushoverNotifications = false;
+
+ #[Validate(['boolean'])]
+ public bool $backupFailurePushoverNotifications = true;
+
+ #[Validate(['boolean'])]
+ public bool $scheduledTaskSuccessPushoverNotifications = false;
+
+ #[Validate(['boolean'])]
+ public bool $scheduledTaskFailurePushoverNotifications = true;
+
+ #[Validate(['boolean'])]
+ public bool $dockerCleanupSuccessPushoverNotifications = false;
+
+ #[Validate(['boolean'])]
+ public bool $dockerCleanupFailurePushoverNotifications = true;
+
+ #[Validate(['boolean'])]
+ public bool $serverDiskUsagePushoverNotifications = true;
+
+ #[Validate(['boolean'])]
+ public bool $serverReachablePushoverNotifications = false;
+
+ #[Validate(['boolean'])]
+ public bool $serverUnreachablePushoverNotifications = true;
+
+ public function mount()
+ {
+ try {
+ $this->team = auth()->user()->currentTeam();
+ $this->settings = $this->team->pushoverNotificationSettings;
+ $this->syncData();
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
+ public function syncData(bool $toModel = false)
+ {
+ if ($toModel) {
+ $this->validate();
+ $this->settings->pushover_enabled = $this->pushoverEnabled;
+ $this->settings->pushover_user_key = $this->pushoverUserKey;
+ $this->settings->pushover_api_token = $this->pushoverApiToken;
+
+ $this->settings->deployment_success_pushover_notifications = $this->deploymentSuccessPushoverNotifications;
+ $this->settings->deployment_failure_pushover_notifications = $this->deploymentFailurePushoverNotifications;
+ $this->settings->status_change_pushover_notifications = $this->statusChangePushoverNotifications;
+ $this->settings->backup_success_pushover_notifications = $this->backupSuccessPushoverNotifications;
+ $this->settings->backup_failure_pushover_notifications = $this->backupFailurePushoverNotifications;
+ $this->settings->scheduled_task_success_pushover_notifications = $this->scheduledTaskSuccessPushoverNotifications;
+ $this->settings->scheduled_task_failure_pushover_notifications = $this->scheduledTaskFailurePushoverNotifications;
+ $this->settings->docker_cleanup_success_pushover_notifications = $this->dockerCleanupSuccessPushoverNotifications;
+ $this->settings->docker_cleanup_failure_pushover_notifications = $this->dockerCleanupFailurePushoverNotifications;
+ $this->settings->server_disk_usage_pushover_notifications = $this->serverDiskUsagePushoverNotifications;
+ $this->settings->server_reachable_pushover_notifications = $this->serverReachablePushoverNotifications;
+ $this->settings->server_unreachable_pushover_notifications = $this->serverUnreachablePushoverNotifications;
+
+ $this->settings->save();
+ refreshSession();
+ } else {
+ $this->pushoverEnabled = $this->settings->pushover_enabled;
+ $this->pushoverUserKey = $this->settings->pushover_user_key;
+ $this->pushoverApiToken = $this->settings->pushover_api_token;
+
+ $this->deploymentSuccessPushoverNotifications = $this->settings->deployment_success_pushover_notifications;
+ $this->deploymentFailurePushoverNotifications = $this->settings->deployment_failure_pushover_notifications;
+ $this->statusChangePushoverNotifications = $this->settings->status_change_pushover_notifications;
+ $this->backupSuccessPushoverNotifications = $this->settings->backup_success_pushover_notifications;
+ $this->backupFailurePushoverNotifications = $this->settings->backup_failure_pushover_notifications;
+ $this->scheduledTaskSuccessPushoverNotifications = $this->settings->scheduled_task_success_pushover_notifications;
+ $this->scheduledTaskFailurePushoverNotifications = $this->settings->scheduled_task_failure_pushover_notifications;
+ $this->dockerCleanupSuccessPushoverNotifications = $this->settings->docker_cleanup_success_pushover_notifications;
+ $this->dockerCleanupFailurePushoverNotifications = $this->settings->docker_cleanup_failure_pushover_notifications;
+ $this->serverDiskUsagePushoverNotifications = $this->settings->server_disk_usage_pushover_notifications;
+ $this->serverReachablePushoverNotifications = $this->settings->server_reachable_pushover_notifications;
+ $this->serverUnreachablePushoverNotifications = $this->settings->server_unreachable_pushover_notifications;
+ }
+ }
+
+ public function instantSavePushoverEnabled()
+ {
+ try {
+ $this->validate([
+ 'pushoverUserKey' => 'required',
+ 'pushoverApiToken' => 'required',
+ ], [
+ 'pushoverUserKey.required' => 'Pushover User Key is required.',
+ 'pushoverApiToken.required' => 'Pushover API Token is required.',
+ ]);
+ $this->saveModel();
+ } catch (\Throwable $e) {
+ $this->pushoverEnabled = false;
+
+ return handleError($e, $this);
+ } finally {
+ $this->dispatch('refresh');
+ }
+ }
+
+ public function instantSave()
+ {
+ try {
+ $this->syncData(true);
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ } finally {
+ $this->dispatch('refresh');
+ }
+ }
+
+ 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->team->notify(new Test(channel: 'pushover'));
+ $this->dispatch('success', 'Test notification sent.');
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
+ public function render()
+ {
+ return view('livewire.notifications.pushover');
+ }
+}
diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php
index 97464fa1c..f47ad8a97 100644
--- a/app/Livewire/Notifications/Slack.php
+++ b/app/Livewire/Notifications/Slack.php
@@ -5,13 +5,18 @@
use App\Models\SlackNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
+use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Slack extends Component
{
+ protected $listeners = ['refresh' => '$refresh'];
+
+ #[Locked]
public Team $team;
+ #[Locked]
public SlackNotificationSettings $settings;
#[Validate(['boolean'])]
@@ -121,6 +126,8 @@ public function instantSaveSlackEnabled()
$this->slackEnabled = false;
return handleError($e, $this);
+ } finally {
+ $this->dispatch('refresh');
}
}
@@ -130,6 +137,8 @@ public function instantSave()
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
+ } finally {
+ $this->dispatch('refresh');
}
}
diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php
index de2fa9cdc..01afb4ac6 100644
--- a/app/Livewire/Notifications/Telegram.php
+++ b/app/Livewire/Notifications/Telegram.php
@@ -5,13 +5,18 @@
use App\Models\Team;
use App\Models\TelegramNotificationSettings;
use App\Notifications\Test;
+use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Telegram extends Component
{
+ protected $listeners = ['refresh' => '$refresh'];
+
+ #[Locked]
public Team $team;
+ #[Locked]
public TelegramNotificationSettings $settings;
#[Validate(['boolean'])]
@@ -60,40 +65,40 @@ class Telegram extends Component
public bool $serverUnreachableTelegramNotifications = true;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsDeploymentSuccessTopicId = null;
+ public ?string $telegramNotificationsDeploymentSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsDeploymentFailureTopicId = null;
+ public ?string $telegramNotificationsDeploymentFailureThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsStatusChangeTopicId = null;
+ public ?string $telegramNotificationsStatusChangeThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsBackupSuccessTopicId = null;
+ public ?string $telegramNotificationsBackupSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsBackupFailureTopicId = null;
+ public ?string $telegramNotificationsBackupFailureThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsScheduledTaskSuccessTopicId = null;
+ public ?string $telegramNotificationsScheduledTaskSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsScheduledTaskFailureTopicId = null;
+ public ?string $telegramNotificationsScheduledTaskFailureThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsDockerCleanupSuccessTopicId = null;
+ public ?string $telegramNotificationsDockerCleanupSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsDockerCleanupFailureTopicId = null;
+ public ?string $telegramNotificationsDockerCleanupFailureThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsServerDiskUsageTopicId = null;
+ public ?string $telegramNotificationsServerDiskUsageThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsServerReachableTopicId = null;
+ public ?string $telegramNotificationsServerReachableThreadId = null;
#[Validate(['nullable', 'string'])]
- public ?string $telegramNotificationsServerUnreachableTopicId = null;
+ public ?string $telegramNotificationsServerUnreachableThreadId = null;
public function mount()
{
@@ -127,21 +132,20 @@ public function syncData(bool $toModel = false)
$this->settings->server_reachable_telegram_notifications = $this->serverReachableTelegramNotifications;
$this->settings->server_unreachable_telegram_notifications = $this->serverUnreachableTelegramNotifications;
- $this->settings->telegram_notifications_deployment_success_topic_id = $this->telegramNotificationsDeploymentSuccessTopicId;
- $this->settings->telegram_notifications_deployment_failure_topic_id = $this->telegramNotificationsDeploymentFailureTopicId;
- $this->settings->telegram_notifications_status_change_topic_id = $this->telegramNotificationsStatusChangeTopicId;
- $this->settings->telegram_notifications_backup_success_topic_id = $this->telegramNotificationsBackupSuccessTopicId;
- $this->settings->telegram_notifications_backup_failure_topic_id = $this->telegramNotificationsBackupFailureTopicId;
- $this->settings->telegram_notifications_scheduled_task_success_topic_id = $this->telegramNotificationsScheduledTaskSuccessTopicId;
- $this->settings->telegram_notifications_scheduled_task_failure_topic_id = $this->telegramNotificationsScheduledTaskFailureTopicId;
- $this->settings->telegram_notifications_docker_cleanup_success_topic_id = $this->telegramNotificationsDockerCleanupSuccessTopicId;
- $this->settings->telegram_notifications_docker_cleanup_failure_topic_id = $this->telegramNotificationsDockerCleanupFailureTopicId;
- $this->settings->telegram_notifications_server_disk_usage_topic_id = $this->telegramNotificationsServerDiskUsageTopicId;
- $this->settings->telegram_notifications_server_reachable_topic_id = $this->telegramNotificationsServerReachableTopicId;
- $this->settings->telegram_notifications_server_unreachable_topic_id = $this->telegramNotificationsServerUnreachableTopicId;
+ $this->settings->telegram_notifications_deployment_success_thread_id = $this->telegramNotificationsDeploymentSuccessThreadId;
+ $this->settings->telegram_notifications_deployment_failure_thread_id = $this->telegramNotificationsDeploymentFailureThreadId;
+ $this->settings->telegram_notifications_status_change_thread_id = $this->telegramNotificationsStatusChangeThreadId;
+ $this->settings->telegram_notifications_backup_success_thread_id = $this->telegramNotificationsBackupSuccessThreadId;
+ $this->settings->telegram_notifications_backup_failure_thread_id = $this->telegramNotificationsBackupFailureThreadId;
+ $this->settings->telegram_notifications_scheduled_task_success_thread_id = $this->telegramNotificationsScheduledTaskSuccessThreadId;
+ $this->settings->telegram_notifications_scheduled_task_failure_thread_id = $this->telegramNotificationsScheduledTaskFailureThreadId;
+ $this->settings->telegram_notifications_docker_cleanup_success_thread_id = $this->telegramNotificationsDockerCleanupSuccessThreadId;
+ $this->settings->telegram_notifications_docker_cleanup_failure_thread_id = $this->telegramNotificationsDockerCleanupFailureThreadId;
+ $this->settings->telegram_notifications_server_disk_usage_thread_id = $this->telegramNotificationsServerDiskUsageThreadId;
+ $this->settings->telegram_notifications_server_reachable_thread_id = $this->telegramNotificationsServerReachableThreadId;
+ $this->settings->telegram_notifications_server_unreachable_thread_id = $this->telegramNotificationsServerUnreachableThreadId;
$this->settings->save();
- refreshSession();
} else {
$this->telegramEnabled = $this->settings->telegram_enabled;
$this->telegramToken = $this->settings->telegram_token;
@@ -160,18 +164,18 @@ public function syncData(bool $toModel = false)
$this->serverReachableTelegramNotifications = $this->settings->server_reachable_telegram_notifications;
$this->serverUnreachableTelegramNotifications = $this->settings->server_unreachable_telegram_notifications;
- $this->telegramNotificationsDeploymentSuccessTopicId = $this->settings->telegram_notifications_deployment_success_topic_id;
- $this->telegramNotificationsDeploymentFailureTopicId = $this->settings->telegram_notifications_deployment_failure_topic_id;
- $this->telegramNotificationsStatusChangeTopicId = $this->settings->telegram_notifications_status_change_topic_id;
- $this->telegramNotificationsBackupSuccessTopicId = $this->settings->telegram_notifications_backup_success_topic_id;
- $this->telegramNotificationsBackupFailureTopicId = $this->settings->telegram_notifications_backup_failure_topic_id;
- $this->telegramNotificationsScheduledTaskSuccessTopicId = $this->settings->telegram_notifications_scheduled_task_success_topic_id;
- $this->telegramNotificationsScheduledTaskFailureTopicId = $this->settings->telegram_notifications_scheduled_task_failure_topic_id;
- $this->telegramNotificationsDockerCleanupSuccessTopicId = $this->settings->telegram_notifications_docker_cleanup_success_topic_id;
- $this->telegramNotificationsDockerCleanupFailureTopicId = $this->settings->telegram_notifications_docker_cleanup_failure_topic_id;
- $this->telegramNotificationsServerDiskUsageTopicId = $this->settings->telegram_notifications_server_disk_usage_topic_id;
- $this->telegramNotificationsServerReachableTopicId = $this->settings->telegram_notifications_server_reachable_topic_id;
- $this->telegramNotificationsServerUnreachableTopicId = $this->settings->telegram_notifications_server_unreachable_topic_id;
+ $this->telegramNotificationsDeploymentSuccessThreadId = $this->settings->telegram_notifications_deployment_success_thread_id;
+ $this->telegramNotificationsDeploymentFailureThreadId = $this->settings->telegram_notifications_deployment_failure_thread_id;
+ $this->telegramNotificationsStatusChangeThreadId = $this->settings->telegram_notifications_status_change_thread_id;
+ $this->telegramNotificationsBackupSuccessThreadId = $this->settings->telegram_notifications_backup_success_thread_id;
+ $this->telegramNotificationsBackupFailureThreadId = $this->settings->telegram_notifications_backup_failure_thread_id;
+ $this->telegramNotificationsScheduledTaskSuccessThreadId = $this->settings->telegram_notifications_scheduled_task_success_thread_id;
+ $this->telegramNotificationsScheduledTaskFailureThreadId = $this->settings->telegram_notifications_scheduled_task_failure_thread_id;
+ $this->telegramNotificationsDockerCleanupSuccessThreadId = $this->settings->telegram_notifications_docker_cleanup_success_thread_id;
+ $this->telegramNotificationsDockerCleanupFailureThreadId = $this->settings->telegram_notifications_docker_cleanup_failure_thread_id;
+ $this->telegramNotificationsServerDiskUsageThreadId = $this->settings->telegram_notifications_server_disk_usage_thread_id;
+ $this->telegramNotificationsServerReachableThreadId = $this->settings->telegram_notifications_server_reachable_thread_id;
+ $this->telegramNotificationsServerUnreachableThreadId = $this->settings->telegram_notifications_server_unreachable_thread_id;
}
}
@@ -181,6 +185,8 @@ public function instantSave()
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
+ } finally {
+ $this->dispatch('refresh');
}
}
@@ -210,6 +216,8 @@ public function instantSaveTelegramEnabled()
$this->telegramEnabled = false;
return handleError($e, $this);
+ } finally {
+ $this->dispatch('refresh');
}
}
diff --git a/app/Models/PushoverNotificationSettings.php b/app/Models/PushoverNotificationSettings.php
new file mode 100644
index 000000000..e3191dcc3
--- /dev/null
+++ b/app/Models/PushoverNotificationSettings.php
@@ -0,0 +1,61 @@
+ 'boolean',
+ 'pushover_user_key' => 'encrypted',
+ 'pushover_api_token' => 'encrypted',
+
+ 'deployment_success_pushover_notifications' => 'boolean',
+ 'deployment_failure_pushover_notifications' => 'boolean',
+ 'status_change_pushover_notifications' => 'boolean',
+ 'backup_success_pushover_notifications' => 'boolean',
+ 'backup_failure_pushover_notifications' => 'boolean',
+ 'scheduled_task_success_pushover_notifications' => 'boolean',
+ 'scheduled_task_failure_pushover_notifications' => 'boolean',
+ 'docker_cleanup_pushover_notifications' => 'boolean',
+ 'server_disk_usage_pushover_notifications' => 'boolean',
+ 'server_reachable_pushover_notifications' => 'boolean',
+ 'server_unreachable_pushover_notifications' => 'boolean',
+ ];
+
+ public function team()
+ {
+ return $this->belongsTo(Team::class);
+ }
+
+ public function isEnabled()
+ {
+ return $this->pushover_enabled;
+ }
+}
diff --git a/app/Models/Team.php b/app/Models/Team.php
index 07424a55f..e55cb0d19 100644
--- a/app/Models/Team.php
+++ b/app/Models/Team.php
@@ -4,6 +4,7 @@
use App\Notifications\Channels\SendsDiscord;
use App\Notifications\Channels\SendsEmail;
+use App\Notifications\Channels\SendsPushover;
use App\Notifications\Channels\SendsSlack;
use App\Traits\HasNotificationSettings;
use Illuminate\Database\Eloquent\Casts\Attribute;
@@ -32,7 +33,7 @@
]
)]
-class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack
+class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, SendsSlack
{
use HasNotificationSettings, Notifiable;
@@ -49,6 +50,7 @@ protected static function booted()
$team->discordNotificationSettings()->create();
$team->slackNotificationSettings()->create();
$team->telegramNotificationSettings()->create();
+ $team->pushoverNotificationSettings()->create();
});
static::saving(function ($team) {
@@ -155,6 +157,14 @@ public function routeNotificationForSlack()
return data_get($this, 'slack_webhook_url', null);
}
+ public function routeNotificationForPushover()
+ {
+ return [
+ 'user' => data_get($this, 'pushover_user_key', null),
+ 'token' => data_get($this, 'pushover_api_token', null),
+ ];
+ }
+
public function getRecipients($notification)
{
$recipients = data_get($notification, 'emails', null);
@@ -174,7 +184,8 @@ public function isAnyNotificationEnabled()
return $this->getNotificationSettings('email')?->isEnabled() ||
$this->getNotificationSettings('discord')?->isEnabled() ||
$this->getNotificationSettings('slack')?->isEnabled() ||
- $this->getNotificationSettings('telegram')?->isEnabled();
+ $this->getNotificationSettings('telegram')?->isEnabled() ||
+ $this->getNotificationSettings('pushover')?->isEnabled();
}
public function subscriptionEnded()
@@ -276,4 +287,9 @@ public function slackNotificationSettings()
{
return $this->hasOne(SlackNotificationSettings::class);
}
+
+ public function pushoverNotificationSettings()
+ {
+ return $this->hasOne(PushoverNotificationSettings::class);
+ }
}
diff --git a/app/Models/TelegramNotificationSettings.php b/app/Models/TelegramNotificationSettings.php
index 2edca14ff..78bd841bd 100644
--- a/app/Models/TelegramNotificationSettings.php
+++ b/app/Models/TelegramNotificationSettings.php
@@ -30,17 +30,17 @@ class TelegramNotificationSettings extends Model
'server_reachable_telegram_notifications',
'server_unreachable_telegram_notifications',
- 'telegram_notifications_deployment_success_topic_id',
- 'telegram_notifications_deployment_failure_topic_id',
- 'telegram_notifications_status_change_topic_id',
- 'telegram_notifications_backup_success_topic_id',
- 'telegram_notifications_backup_failure_topic_id',
- 'telegram_notifications_scheduled_task_success_topic_id',
- 'telegram_notifications_scheduled_task_failure_topic_id',
- 'telegram_notifications_docker_cleanup_topic_id',
- 'telegram_notifications_server_disk_usage_topic_id',
- 'telegram_notifications_server_reachable_topic_id',
- 'telegram_notifications_server_unreachable_topic_id',
+ 'telegram_notifications_deployment_success_thread_id',
+ 'telegram_notifications_deployment_failure_thread_id',
+ 'telegram_notifications_status_change_thread_id',
+ 'telegram_notifications_backup_success_thread_id',
+ 'telegram_notifications_backup_failure_thread_id',
+ 'telegram_notifications_scheduled_task_success_thread_id',
+ 'telegram_notifications_scheduled_task_failure_thread_id',
+ 'telegram_notifications_docker_cleanup_thread_id',
+ 'telegram_notifications_server_disk_usage_thread_id',
+ 'telegram_notifications_server_reachable_thread_id',
+ 'telegram_notifications_server_unreachable_thread_id',
];
protected $casts = [
@@ -60,17 +60,17 @@ class TelegramNotificationSettings extends Model
'server_reachable_telegram_notifications' => 'boolean',
'server_unreachable_telegram_notifications' => 'boolean',
- 'telegram_notifications_deployment_success_topic_id' => 'encrypted',
- 'telegram_notifications_deployment_failure_topic_id' => 'encrypted',
- 'telegram_notifications_status_change_topic_id' => 'encrypted',
- 'telegram_notifications_backup_success_topic_id' => 'encrypted',
- 'telegram_notifications_backup_failure_topic_id' => 'encrypted',
- 'telegram_notifications_scheduled_task_success_topic_id' => 'encrypted',
- 'telegram_notifications_scheduled_task_failure_topic_id' => 'encrypted',
- 'telegram_notifications_docker_cleanup_topic_id' => 'encrypted',
- 'telegram_notifications_server_disk_usage_topic_id' => 'encrypted',
- 'telegram_notifications_server_reachable_topic_id' => 'encrypted',
- 'telegram_notifications_server_unreachable_topic_id' => 'encrypted',
+ 'telegram_notifications_deployment_success_thread_id' => 'encrypted',
+ 'telegram_notifications_deployment_failure_thread_id' => 'encrypted',
+ 'telegram_notifications_status_change_thread_id' => 'encrypted',
+ 'telegram_notifications_backup_success_thread_id' => 'encrypted',
+ 'telegram_notifications_backup_failure_thread_id' => 'encrypted',
+ 'telegram_notifications_scheduled_task_success_thread_id' => 'encrypted',
+ 'telegram_notifications_scheduled_task_failure_thread_id' => 'encrypted',
+ 'telegram_notifications_docker_cleanup_thread_id' => 'encrypted',
+ 'telegram_notifications_server_disk_usage_thread_id' => 'encrypted',
+ 'telegram_notifications_server_reachable_thread_id' => 'encrypted',
+ 'telegram_notifications_server_unreachable_thread_id' => 'encrypted',
];
public function team()
diff --git a/app/Notifications/Application/DeploymentFailed.php b/app/Notifications/Application/DeploymentFailed.php
index 06a2b48e3..80c1c421c 100644
--- a/app/Notifications/Application/DeploymentFailed.php
+++ b/app/Notifications/Application/DeploymentFailed.php
@@ -6,6 +6,7 @@
use App\Models\ApplicationPreview;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -130,6 +131,31 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ if ($this->preview) {
+ $title = "Pull request #{$this->preview->pull_request_id} deployment failed";
+ $message = "Pull request deployment failed for {$this->application_name}";
+ } else {
+ $title = 'Deployment failed';
+ $message = "Deployment failed for {$this->application_name}";
+ }
+
+ $buttons[] = [
+ 'text' => 'Deployment logs',
+ 'url' => $this->deployment_url,
+ ];
+
+ return new PushoverMessage(
+ title: $title,
+ level: 'error',
+ message: $message,
+ buttons: [
+ ...$buttons,
+ ],
+ );
+ }
+
public function toSlack(): SlackMessage
{
if ($this->preview) {
diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php
index 548f5c6e5..b1a3d5225 100644
--- a/app/Notifications/Application/DeploymentSuccess.php
+++ b/app/Notifications/Application/DeploymentSuccess.php
@@ -6,6 +6,7 @@
use App\Models\ApplicationPreview;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -139,6 +140,42 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ if ($this->preview) {
+ $title = "Pull request #{$this->preview->pull_request_id} successfully deployed";
+ $message = 'New PR' . $this->preview->pull_request_id . ' version successfully deployed of ' . $this->application_name . '';
+ if ($this->preview->fqdn) {
+ $buttons[] = [
+ 'text' => 'Open Application',
+ 'url' => $this->preview->fqdn,
+ ];
+ }
+ } else {
+ $title = 'New version successfully deployed';
+ $message = 'New version successfully deployed of ' . $this->application_name . '';
+ if ($this->fqdn) {
+ $buttons[] = [
+ 'text' => 'Open Application',
+ 'url' => $this->fqdn,
+ ];
+ }
+ }
+ $buttons[] = [
+ 'text' => 'Deployment logs',
+ 'url' => $this->deployment_url,
+ ];
+
+ return new PushoverMessage(
+ title: $title,
+ level: 'success',
+ message: $message,
+ buttons: [
+ ...$buttons,
+ ],
+ );
+ }
+
public function toSlack(): SlackMessage
{
if ($this->preview) {
diff --git a/app/Notifications/Application/StatusChanged.php b/app/Notifications/Application/StatusChanged.php
index 32a6a659a..c9c7344c4 100644
--- a/app/Notifications/Application/StatusChanged.php
+++ b/app/Notifications/Application/StatusChanged.php
@@ -5,6 +5,7 @@
use App\Models\Application;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -77,6 +78,23 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ $message = $this->resource_name . ' has been stopped.';
+
+ return new PushoverMessage(
+ title: 'Application stopped',
+ level: 'error',
+ message: $message,
+ buttons: [
+ [
+ 'text' => 'Open Application in Coolify',
+ 'url' => $this->resource_url,
+ ],
+ ],
+ );
+ }
+
public function toSlack(): SlackMessage
{
$title = 'Application stopped';
diff --git a/app/Notifications/Channels/PushoverChannel.php b/app/Notifications/Channels/PushoverChannel.php
new file mode 100644
index 000000000..3d3728d01
--- /dev/null
+++ b/app/Notifications/Channels/PushoverChannel.php
@@ -0,0 +1,21 @@
+toPushover();
+ $pushoverSettings = $notifiable->pushoverNotificationSettings;
+
+ if (! $pushoverSettings || ! $pushoverSettings->isEnabled() || ! $pushoverSettings->pushover_user_key || ! $pushoverSettings->pushover_api_token) {
+ return;
+ }
+
+ SendMessageToPushoverJob::dispatch($message, $pushoverSettings->pushover_api_token, $pushoverSettings->pushover_user_key);
+ }
+}
diff --git a/app/Notifications/Channels/SendsPushover.php b/app/Notifications/Channels/SendsPushover.php
new file mode 100644
index 000000000..7922eefb4
--- /dev/null
+++ b/app/Notifications/Channels/SendsPushover.php
@@ -0,0 +1,8 @@
+telegram_token;
$chatId = $settings->telegram_chat_id;
- $topicId = match (get_class($notification)) {
- \App\Notifications\Test::class => $settings->telegram_notifications_test_topic_id,
+ $threadId = match (get_class($notification)) {
+ \App\Notifications\Application\DeploymentSuccess::class => $settings->telegram_notifications_deployment_success_thread_id,
+ \App\Notifications\Application\DeploymentFailed::class => $settings->telegram_notifications_deployment_failure_thread_id,
\App\Notifications\Application\StatusChanged::class,
\App\Notifications\Container\ContainerRestarted::class,
- \App\Notifications\Container\ContainerStopped::class => $settings->telegram_notifications_status_change_topic_id,
- \App\Notifications\Application\DeploymentSuccess::class => $settings->telegram_notifications_deployment_success_topic_id,
- \App\Notifications\Application\DeploymentFailed::class => $settings->telegram_notifications_deployment_failure_topic_id,
- \App\Notifications\Database\BackupSuccess::class => $settings->telegram_notifications_backup_success_topic_id,
- \App\Notifications\Database\BackupFailed::class => $settings->telegram_notifications_backup_failure_topic_id,
- \App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_topic_id,
- \App\Notifications\Server\Unreachable::class => $settings->telegram_notifications_server_unreachable_topic_id,
- \App\Notifications\Server\Reachable::class => $settings->telegram_notifications_server_reachable_topic_id,
+ \App\Notifications\Container\ContainerStopped::class => $settings->telegram_notifications_status_change_thread_id,
+
+ \App\Notifications\Database\BackupSuccess::class => $settings->telegram_notifications_backup_success_thread_id,
+ \App\Notifications\Database\BackupFailed::class => $settings->telegram_notifications_backup_failure_thread_id,
+
+ \App\Notifications\ScheduledTask\TaskSuccess::class => $settings->telegram_notifications_scheduled_task_success_thread_id,
+ \App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_thread_id,
+
+ \App\Notifications\Server\DockerCleanupSuccess::class => $settings->telegram_notifications_docker_cleanup_success_thread_id,
+ \App\Notifications\Server\DockerCleanupFailed::class => $settings->telegram_notifications_docker_cleanup_failure_thread_id,
+ \App\Notifications\Server\HighDiskUsage::class => $settings->telegram_notifications_server_disk_usage_thread_id,
+ \App\Notifications\Server\Unreachable::class => $settings->telegram_notifications_server_unreachable_thread_id,
+ \App\Notifications\Server\Reachable::class => $settings->telegram_notifications_server_reachable_thread_id,
+
default => null,
};
@@ -35,6 +42,6 @@ public function send($notifiable, $notification): void
return;
}
- SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $topicId);
+ SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $threadId);
}
}
diff --git a/app/Notifications/Container/ContainerRestarted.php b/app/Notifications/Container/ContainerRestarted.php
index c25072ecf..68fc6b019 100644
--- a/app/Notifications/Container/ContainerRestarted.php
+++ b/app/Notifications/Container/ContainerRestarted.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -68,6 +69,24 @@ public function toTelegram(): array
return $payload;
}
+ public function toPushover(): PushoverMessage
+ {
+ $buttons = [];
+ if ($this->url) {
+ $buttons[] = [
+ 'text' => 'Check Proxy in Coolify',
+ 'url' => $this->url,
+ ];
+ }
+
+ return new PushoverMessage(
+ title: 'Resource restarted',
+ level: 'warning',
+ message: "A resource ({$this->name}) has been restarted automatically on {$this->server->name}",
+ buttons: $buttons,
+ );
+ }
+
public function toSlack(): SlackMessage
{
$title = 'Resource restarted';
diff --git a/app/Notifications/Container/ContainerStopped.php b/app/Notifications/Container/ContainerStopped.php
index bc6e52b6d..49aea196d 100644
--- a/app/Notifications/Container/ContainerStopped.php
+++ b/app/Notifications/Container/ContainerStopped.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -68,6 +69,25 @@ public function toTelegram(): array
return $payload;
}
+ public function toPushover(): PushoverMessage
+ {
+ $buttons = [];
+ if ($this->url) {
+ $buttons[] = [
+ 'text' => 'Open Application in Coolify',
+ 'url' => $this->url,
+ ];
+ }
+
+ return new PushoverMessage(
+ title: 'Resource stopped',
+ level: 'error',
+ message: "A resource ({$this->name}) has been stopped unexpectedly on {$this->server->name}",
+ buttons: $buttons,
+ );
+ }
+
+
public function toSlack(): SlackMessage
{
$title = 'Resource stopped';
diff --git a/app/Notifications/Database/BackupFailed.php b/app/Notifications/Database/BackupFailed.php
index 2208f7b1d..6dcb70583 100644
--- a/app/Notifications/Database/BackupFailed.php
+++ b/app/Notifications/Database/BackupFailed.php
@@ -5,6 +5,7 @@
use App\Models\ScheduledDatabaseBackup;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -64,6 +65,15 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Database backup failed',
+ level: 'error',
+ message: "Database backup for {$this->name} (db:{$this->database_name}) was FAILED
Frequency: {$this->frequency} . Reason: {$this->output}",
+ );
+ }
+
public function toSlack(): SlackMessage
{
$title = 'Database backup failed';
diff --git a/app/Notifications/Database/BackupSuccess.php b/app/Notifications/Database/BackupSuccess.php
index 10b4ff3df..4c3e8e060 100644
--- a/app/Notifications/Database/BackupSuccess.php
+++ b/app/Notifications/Database/BackupSuccess.php
@@ -5,6 +5,7 @@
use App\Models\ScheduledDatabaseBackup;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -62,6 +63,17 @@ public function toTelegram(): array
];
}
+
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Database backup successful',
+ level: 'success',
+ message: "Database backup for {$this->name} (db:{$this->database_name}) was successful.
Frequency: {$this->frequency}.",
+ );
+ }
+
+
public function toSlack(): SlackMessage
{
$title = 'Database backup successful';
diff --git a/app/Notifications/Dto/PushoverMessage.php b/app/Notifications/Dto/PushoverMessage.php
new file mode 100644
index 000000000..0efd1d526
--- /dev/null
+++ b/app/Notifications/Dto/PushoverMessage.php
@@ -0,0 +1,50 @@
+level) {
+ 'info' => 'ℹ️',
+ 'error' => '❌',
+ 'success' => '✅ ',
+ 'warning' => '⚠️',
+ };
+ }
+
+ public function toPayload(string $token, string $user): array
+ {
+ $levelIcon = $this->getLevelIcon();
+ $payload = [
+ 'token' => $token,
+ 'user' => $user,
+ 'title' => "{$levelIcon} {$this->title}",
+ 'message' => $this->message,
+ 'html' => 1,
+ ];
+
+ foreach ($this->buttons as $button) {
+ $buttonUrl = data_get($button, 'url');
+ $text = data_get($button, 'text', 'Click here');
+ if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) {
+ $buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl);
+ }
+ $payload['message'] .= " " . $text . '';
+ }
+
+ Log::info('Pushover message', $payload);
+
+ return $payload;
+ }
+}
diff --git a/app/Notifications/Internal/GeneralNotification.php b/app/Notifications/Internal/GeneralNotification.php
index 7049e3055..1d2367210 100644
--- a/app/Notifications/Internal/GeneralNotification.php
+++ b/app/Notifications/Internal/GeneralNotification.php
@@ -3,6 +3,7 @@
namespace App\Notifications\Internal;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -40,6 +41,15 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'General Notification',
+ level: 'info',
+ message: $this->message,
+ );
+ }
+
public function toSlack(): SlackMessage
{
return new SlackMessage(
diff --git a/app/Notifications/ScheduledTask/TaskFailed.php b/app/Notifications/ScheduledTask/TaskFailed.php
index 56c410ecb..c4d92f213 100644
--- a/app/Notifications/ScheduledTask/TaskFailed.php
+++ b/app/Notifications/ScheduledTask/TaskFailed.php
@@ -5,6 +5,7 @@
use App\Models\ScheduledTask;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -70,6 +71,30 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ $message = "Scheduled task ({$this->task->name}) failed ";
+
+ if ($this->output) {
+ $message .= " Error Output:{$this->output}";
+ }
+
+ $buttons = [];
+ if ($this->url) {
+ $buttons[] = [
+ 'text' => 'Open task in Coolify',
+ 'url' => (string) $this->url,
+ ];
+ }
+
+ return new PushoverMessage(
+ title: 'Scheduled task failed',
+ level: 'error',
+ message: $message,
+ buttons: $buttons,
+ );
+ }
+
public function toSlack(): SlackMessage
{
$title = 'Scheduled task failed';
diff --git a/app/Notifications/ScheduledTask/TaskSuccess.php b/app/Notifications/ScheduledTask/TaskSuccess.php
index fc79aea37..5d4154e7a 100644
--- a/app/Notifications/ScheduledTask/TaskSuccess.php
+++ b/app/Notifications/ScheduledTask/TaskSuccess.php
@@ -5,6 +5,7 @@
use App\Models\ScheduledTask;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -70,6 +71,25 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ $message = "Coolify: Scheduled task ({$this->task->name}) succeeded.";
+ $buttons = [];
+ if ($this->url) {
+ $buttons[] = [
+ 'text' => 'Open task in Coolify',
+ 'url' => (string) $this->url,
+ ];
+ }
+
+ return new PushoverMessage(
+ title: 'Scheduled task succeeded',
+ level: 'success',
+ message: $message,
+ buttons: $buttons,
+ );
+ }
+
public function toSlack(): SlackMessage
{
$title = 'Scheduled task succeeded';
diff --git a/app/Notifications/Server/DockerCleanupFailed.php b/app/Notifications/Server/DockerCleanupFailed.php
index 53714925c..0291eed19 100644
--- a/app/Notifications/Server/DockerCleanupFailed.php
+++ b/app/Notifications/Server/DockerCleanupFailed.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -48,6 +49,15 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Docker cleanup job failed',
+ level: 'error',
+ message: "[ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}!\n\n{$this->message}",
+ );
+ }
+
public function toSlack(): SlackMessage
{
return new SlackMessage(
diff --git a/app/Notifications/Server/DockerCleanupSuccess.php b/app/Notifications/Server/DockerCleanupSuccess.php
index 85a819da2..1a652d189 100644
--- a/app/Notifications/Server/DockerCleanupSuccess.php
+++ b/app/Notifications/Server/DockerCleanupSuccess.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -48,6 +49,15 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Docker cleanup job succeeded',
+ level: 'success',
+ message: "Docker cleanup job succeeded on {$this->server->name}!\n\n{$this->message}",
+ );
+ }
+
public function toSlack(): SlackMessage
{
return new SlackMessage(
diff --git a/app/Notifications/Server/ForceDisabled.php b/app/Notifications/Server/ForceDisabled.php
index e122849da..7a1f7bcbf 100644
--- a/app/Notifications/Server/ForceDisabled.php
+++ b/app/Notifications/Server/ForceDisabled.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -51,6 +52,15 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Server disabled',
+ level: 'error',
+ message: "Server ({$this->server->name}) disabled because it is not paid!\n All automations and integrations are stopped. Please update your subscription to enable the server again [here](https://app.coolify.io/subscriptions).",
+ );
+ }
+
public function toSlack(): SlackMessage
{
$title = 'Server disabled';
diff --git a/app/Notifications/Server/ForceEnabled.php b/app/Notifications/Server/ForceEnabled.php
index a0e0a8b59..36dad3c60 100644
--- a/app/Notifications/Server/ForceEnabled.php
+++ b/app/Notifications/Server/ForceEnabled.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -47,6 +48,15 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Server enabled',
+ level: 'success',
+ message: "Server ({$this->server->name}) enabled again!",
+ );
+ }
+
public function toSlack(): SlackMessage
{
return new SlackMessage(
diff --git a/app/Notifications/Server/HighDiskUsage.php b/app/Notifications/Server/HighDiskUsage.php
index 9f4826689..aea9abd03 100644
--- a/app/Notifications/Server/HighDiskUsage.php
+++ b/app/Notifications/Server/HighDiskUsage.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -57,6 +58,19 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'High disk usage detected',
+ level: 'warning',
+ message: "Server '{$this->server->name}' high disk usage detected!
Disk usage: {$this->disk_usage}%. Threshold: {$this->server_disk_usage_notification_threshold}%. Please cleanup your disk to prevent data-loss.",
+ buttons: [
+ 'Change settings' => base_url().'/server/'.$this->server->uuid."#advanced",
+ 'Tips for cleanup' => "https://coolify.io/docs/knowledge-base/server/automated-cleanup",
+ ],
+ );
+ }
+
public function toSlack(): SlackMessage
{
$description = "Server '{$this->server->name}' high disk usage detected!\n";
diff --git a/app/Notifications/Server/Reachable.php b/app/Notifications/Server/Reachable.php
index 4917e04f8..e03aef6b7 100644
--- a/app/Notifications/Server/Reachable.php
+++ b/app/Notifications/Server/Reachable.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -49,6 +50,15 @@ public function toDiscord(): DiscordMessage
);
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Server revived',
+ message: "Server '{$this->server->name}' revived. All automations & integrations are turned on again!",
+ level: 'success',
+ );
+ }
+
public function toTelegram(): array
{
return [
diff --git a/app/Notifications/Server/Unreachable.php b/app/Notifications/Server/Unreachable.php
index 43f176d49..fe90cc610 100644
--- a/app/Notifications/Server/Unreachable.php
+++ b/app/Notifications/Server/Unreachable.php
@@ -5,6 +5,7 @@
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -60,6 +61,15 @@ public function toTelegram(): ?array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Server unreachable',
+ level: 'error',
+ message: "Your server '{$this->server->name}' is unreachable. All automations & integrations are turned off!
IMPORTANT: We automatically try to revive your server and turn on all automations & integrations.",
+ );
+ }
+
public function toSlack(): SlackMessage
{
$description = "Your server '{$this->server->name}' is unreachable.\n";
diff --git a/app/Notifications/Test.php b/app/Notifications/Test.php
index da9098500..65971a0ee 100644
--- a/app/Notifications/Test.php
+++ b/app/Notifications/Test.php
@@ -6,7 +6,9 @@
use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\SlackChannel;
use App\Notifications\Channels\TelegramChannel;
+use App\Notifications\Channels\PushoverChannel;
use App\Notifications\Dto\DiscordMessage;
+use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -33,6 +35,7 @@ public function via(object $notifiable): array
'discord' => [DiscordChannel::class],
'telegram' => [TelegramChannel::class],
'slack' => [SlackChannel::class],
+ 'pushover' => [PushoverChannel::class],
default => [],
};
} else {
@@ -85,6 +88,20 @@ public function toTelegram(): array
];
}
+ public function toPushover(): PushoverMessage
+ {
+ return new PushoverMessage(
+ title: 'Test Pushover Notification',
+ message: 'This is a test Pushover notification from Coolify.',
+ buttons: [
+ [
+ 'text' => 'Go to your dashboard',
+ 'url' => base_url(),
+ ],
+ ],
+ );
+ }
+
public function toSlack(): SlackMessage
{
return new SlackMessage(
diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php
index 82cbda6ad..ef858d0b6 100644
--- a/app/Traits/HasNotificationSettings.php
+++ b/app/Traits/HasNotificationSettings.php
@@ -6,6 +6,7 @@
use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\SlackChannel;
use App\Notifications\Channels\TelegramChannel;
+use App\Notifications\Channels\PushoverChannel;
use Illuminate\Database\Eloquent\Model;
trait HasNotificationSettings
@@ -27,6 +28,7 @@ public function getNotificationSettings(string $channel): ?Model
'discord' => $this->discordNotificationSettings,
'telegram' => $this->telegramNotificationSettings,
'slack' => $this->slackNotificationSettings,
+ 'pushover' => $this->pushoverNotificationSettings,
default => null,
};
}
@@ -73,6 +75,7 @@ public function getEnabledChannels(string $event): array
'discord' => DiscordChannel::class,
'telegram' => TelegramChannel::class,
'slack' => SlackChannel::class,
+ 'pushover' => PushoverChannel::class,
];
if ($event === 'general') {
diff --git a/config/constants.php b/config/constants.php
index 3054df1f0..a02d6616a 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -37,6 +37,10 @@
'is_migration_enabled' => env('MIGRATION_ENABLED', true),
],
+ 'seeder' => [
+ 'is_seeder_enabled' => env('SEEDER_ENABLED', true),
+ ],
+
'horizon' => [
'is_horizon_enabled' => env('HORIZON_ENABLED', true),
'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true),
diff --git a/database/migrations/2024_10_30_074601_rename_token_permissions.php b/database/migrations/2024_10_30_074601_rename_token_permissions.php
index 2ca98d090..69d774d7f 100644
--- a/database/migrations/2024_10_30_074601_rename_token_permissions.php
+++ b/database/migrations/2024_10_30_074601_rename_token_permissions.php
@@ -40,7 +40,7 @@ public function down(): void
$tokens = PersonalAccessToken::all();
foreach ($tokens as $token) {
$abilities = collect();
- if (in_array('write', $token->abilities)) {
+ if (in_array('root', $token->abilities)) {
$abilities->push('*');
} else {
if (in_array('read', $token->abilities)) {
diff --git a/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php b/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php
index 190d148fc..db4d998e3 100644
--- a/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php
+++ b/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php
@@ -32,18 +32,18 @@ public function up(): void
$table->boolean('server_reachable_telegram_notifications')->default(false);
$table->boolean('server_unreachable_telegram_notifications')->default(true);
- $table->text('telegram_notifications_deployment_success_topic_id')->nullable();
- $table->text('telegram_notifications_deployment_failure_topic_id')->nullable();
- $table->text('telegram_notifications_status_change_topic_id')->nullable();
- $table->text('telegram_notifications_backup_success_topic_id')->nullable();
- $table->text('telegram_notifications_backup_failure_topic_id')->nullable();
- $table->text('telegram_notifications_scheduled_task_success_topic_id')->nullable();
- $table->text('telegram_notifications_scheduled_task_failure_topic_id')->nullable();
- $table->text('telegram_notifications_docker_cleanup_success_topic_id')->nullable();
- $table->text('telegram_notifications_docker_cleanup_failure_topic_id')->nullable();
- $table->text('telegram_notifications_server_disk_usage_topic_id')->nullable();
- $table->text('telegram_notifications_server_reachable_topic_id')->nullable();
- $table->text('telegram_notifications_server_unreachable_topic_id')->nullable();
+ $table->text('telegram_notifications_deployment_success_thread_id')->nullable();
+ $table->text('telegram_notifications_deployment_failure_thread_id')->nullable();
+ $table->text('telegram_notifications_status_change_thread_id')->nullable();
+ $table->text('telegram_notifications_backup_success_thread_id')->nullable();
+ $table->text('telegram_notifications_backup_failure_thread_id')->nullable();
+ $table->text('telegram_notifications_scheduled_task_success_thread_id')->nullable();
+ $table->text('telegram_notifications_scheduled_task_failure_thread_id')->nullable();
+ $table->text('telegram_notifications_docker_cleanup_success_thread_id')->nullable();
+ $table->text('telegram_notifications_docker_cleanup_failure_thread_id')->nullable();
+ $table->text('telegram_notifications_server_disk_usage_thread_id')->nullable();
+ $table->text('telegram_notifications_server_reachable_thread_id')->nullable();
+ $table->text('telegram_notifications_server_unreachable_thread_id')->nullable();
$table->unique(['team_id']);
});
diff --git a/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php
index 0c10646b9..df120e273 100644
--- a/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php
+++ b/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php
@@ -4,6 +4,7 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
@@ -30,17 +31,17 @@ public function up(): void
'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false,
'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true,
- 'telegram_notifications_deployment_success_topic_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null,
- 'telegram_notifications_deployment_failure_topic_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null,
- 'telegram_notifications_backup_success_topic_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null,
- 'telegram_notifications_backup_failure_topic_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null,
- 'telegram_notifications_scheduled_task_success_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null,
- 'telegram_notifications_scheduled_task_failure_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null,
- 'telegram_notifications_status_change_topic_id' => $team->telegram_notifications_status_changes_message_thread_id ? Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id) : null,
+ 'telegram_notifications_deployment_success_thread_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null,
+ 'telegram_notifications_deployment_failure_thread_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null,
+ 'telegram_notifications_backup_success_thread_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null,
+ 'telegram_notifications_backup_failure_thread_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null,
+ 'telegram_notifications_scheduled_task_success_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null,
+ 'telegram_notifications_scheduled_task_failure_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null,
+ 'telegram_notifications_status_change_thread_id' => $team->telegram_notifications_status_changes_message_thread_id ? Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id) : null,
]
);
} catch (Exception $e) {
- \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage());
+ Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage());
}
}
@@ -101,13 +102,13 @@ public function down(): void
'telegram_notifications_scheduled_tasks' => $setting->scheduled_task_success_telegram_notifications || $setting->scheduled_task_failure_telegram_notifications,
'telegram_notifications_server_disk_usage' => $setting->server_disk_usage_telegram_notifications,
- 'telegram_notifications_deployments_message_thread_id' => $setting->telegram_notifications_deployment_success_topic_id ? Crypt::decryptString($setting->telegram_notifications_deployment_success_topic_id) : null,
- 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_topic_id ? Crypt::decryptString($setting->telegram_notifications_status_change_topic_id) : null,
- 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_topic_id ? Crypt::decryptString($setting->telegram_notifications_backup_success_topic_id) : null,
- 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_topic_id ? Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_topic_id) : null,
+ 'telegram_notifications_deployments_message_thread_id' => $setting->telegram_notifications_deployment_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_deployment_success_thread_id) : null,
+ 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_thread_id ? Crypt::decryptString($setting->telegram_notifications_status_change_thread_id) : null,
+ 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_backup_success_thread_id) : null,
+ 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_thread_id) : null,
]);
} catch (Exception $e) {
- \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage());
+ Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage());
}
}
}
diff --git a/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php b/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php
index 790e0f667..8aee40d87 100644
--- a/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php
+++ b/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php
@@ -3,6 +3,7 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
@@ -42,7 +43,7 @@ public function up(): void
'team_id' => $team->id,
]);
} catch (\Throwable $e) {
- \Log::error('Error migrating slack notification settings from teams table: '.$e->getMessage());
+ Log::error('Error creating slack notification settings for existing teams: '.$e->getMessage());
}
}
}
diff --git a/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php
new file mode 100644
index 000000000..ad4215a07
--- /dev/null
+++ b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php
@@ -0,0 +1,59 @@
+id();
+ $table->foreignId('team_id')->constrained()->cascadeOnDelete();
+
+ $table->boolean('pushover_enabled')->default(false);
+ $table->text('pushover_user_key')->nullable();
+ $table->text('pushover_api_token')->nullable();
+
+ $table->boolean('deployment_success_pushover_notifications')->default(false);
+ $table->boolean('deployment_failure_pushover_notifications')->default(true);
+ $table->boolean('status_change_pushover_notifications')->default(false);
+ $table->boolean('backup_success_pushover_notifications')->default(false);
+ $table->boolean('backup_failure_pushover_notifications')->default(true);
+ $table->boolean('scheduled_task_success_pushover_notifications')->default(false);
+ $table->boolean('scheduled_task_failure_pushover_notifications')->default(true);
+ $table->boolean('docker_cleanup_success_pushover_notifications')->default(false);
+ $table->boolean('docker_cleanup_failure_pushover_notifications')->default(true);
+ $table->boolean('server_disk_usage_pushover_notifications')->default(true);
+ $table->boolean('server_reachable_pushover_notifications')->default(false);
+ $table->boolean('server_unreachable_pushover_notifications')->default(true);
+
+ $table->unique(['team_id']);
+ });
+ $teams = DB::table('teams')->get();
+
+ foreach ($teams as $team) {
+ try {
+ DB::table('pushover_notification_settings')->insert([
+ 'team_id' => $team->id,
+ ]);
+ } catch (\Throwable $e) {
+ Log::error('Error creating pushover notification settings for existing teams: '.$e->getMessage());
+ }
+ }
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('pushover_notification_settings');
+ }
+};
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up b/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up
index 20d17c58b..007f4233e 100644
--- a/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up
+++ b/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up
@@ -6,10 +6,7 @@ cd /var/www/html
foreground {
php
artisan
- db:seed
- --class
- ProductionSeeder
- --force
+ start:seeder
}
diff --git a/other/logos/internetgarden.ico b/other/logos/internetgarden.ico
new file mode 100644
index 000000000..e555984be
Binary files /dev/null and b/other/logos/internetgarden.ico differ
diff --git a/resources/views/components/notification/navbar.blade.php b/resources/views/components/notification/navbar.blade.php
index c4dbd25af..447a385c5 100644
--- a/resources/views/components/notification/navbar.blade.php
+++ b/resources/views/components/notification/navbar.blade.php
@@ -7,18 +7,22 @@
href="{{ route('notifications.email') }}">
-
-
-
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php
index 1f83ed061..6caf31176 100644
--- a/resources/views/livewire/notifications/discord.blade.php
+++ b/resources/views/livewire/notifications/discord.blade.php
@@ -24,7 +24,7 @@
Notification Settings
diff --git a/resources/views/livewire/notifications/pushover.blade.php b/resources/views/livewire/notifications/pushover.blade.php
new file mode 100644
index 000000000..c8dd777d8
--- /dev/null
+++ b/resources/views/livewire/notifications/pushover.blade.php
@@ -0,0 +1,86 @@
+
+
+ Notifications | Coolify
+
+
+
+
Notification Settings
+
+ Select events for which you would like to receive Pushover notifications.
+
@@ -61,8 +61,8 @@
label="Container Status Changes"
helper="Send a notification when a container status changes. It will send a notification for Stopped and Restarted events of a container." />
-
+
@@ -74,8 +74,8 @@
-
+
@@ -83,8 +83,8 @@
-
+
@@ -97,8 +97,8 @@
-
+
@@ -106,8 +106,8 @@
-
+
@@ -120,8 +120,8 @@
-
+
@@ -129,8 +129,8 @@
-
+
@@ -138,8 +138,8 @@
-
+
@@ -147,8 +147,8 @@
-
+
@@ -157,8 +157,8 @@
-
+
diff --git a/routes/web.php b/routes/web.php
index 3570fe0ed..3d12b9b46 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -12,6 +12,7 @@
use App\Livewire\ForcePasswordReset;
use App\Livewire\Notifications\Discord as NotificationDiscord;
use App\Livewire\Notifications\Email as NotificationEmail;
+use App\Livewire\Notifications\Pushover as NotificationPushover;
use App\Livewire\Notifications\Slack as NotificationSlack;
use App\Livewire\Notifications\Telegram as NotificationTelegram;
use App\Livewire\Profile\Index as ProfileIndex;
@@ -133,6 +134,7 @@
Route::get('/telegram', NotificationTelegram::class)->name('notifications.telegram');
Route::get('/discord', NotificationDiscord::class)->name('notifications.discord');
Route::get('/slack', NotificationSlack::class)->name('notifications.slack');
+ Route::get('/pushover', NotificationPushover::class)->name('notifications.pushover');
});
Route::prefix('storages')->group(function () {