From 9c5a75859ee204a75309e2c711cc87362ced95e5 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:33:10 +0100 Subject: [PATCH 01/80] Create 2024_12_05_212355_create_email_notification_settings_table.php --- ...eate_email_notification_settings_table.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 database/migrations/2024_12_05_212355_create_email_notification_settings_table.php diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php new file mode 100644 index 000000000..45b106827 --- /dev/null +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -0,0 +1,57 @@ +id(); + $table->foreignId('team_id')->constrained()->cascadeOnDelete(); + + // SMTP Configuration + $table->boolean('smtp_enabled')->default(false); + $table->string('smtp_from_address')->nullable(); + $table->string('smtp_from_name')->nullable(); + $table->string('smtp_recipients')->nullable(); + $table->string('smtp_host')->nullable(); + $table->integer('smtp_port')->nullable(); + $table->string('smtp_encryption')->nullable(); + $table->text('smtp_username')->nullable(); + $table->text('smtp_password')->nullable(); + $table->integer('smtp_timeout')->nullable(); + + $table->boolean('use_instance_email_settings')->default(false); + + // Resend Configuration + $table->boolean('resend_enabled')->default(false); + $table->encryptedText('resend_api_key')->nullable(); + + // Notification Settings + $table->boolean('deployment_success_email_notification')->default(false); + $table->boolean('deployment_failure_email_notification')->default(true); + $table->boolean('backup_success_email_notification')->default(false); + $table->boolean('backup_failure_email_notification')->default(true); + $table->boolean('scheduled_task_success_email_notification')->default(false); + $table->boolean('scheduled_task_failure_email_notification')->default(true); + $table->boolean('status_change_email_notification')->default(false); + $table->boolean('server_disk_usage_email_notification')->default(true); + + $table->unique(['team_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('email_notification_settings'); + } +}; From 67b9bebd044c2e43eba28ac73508eee91ab7a6e1 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:33:16 +0100 Subject: [PATCH 02/80] Create 2024_12_05_212416_create_discord_notification_settings_table.php --- ...te_discord_notification_settings_table.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php diff --git a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php new file mode 100644 index 000000000..5c6ebbd2c --- /dev/null +++ b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php @@ -0,0 +1,42 @@ +id(); + $table->foreignId('team_id')->constrained()->cascadeOnDelete(); + + $table->boolean('discord_enabled')->default(false); + $table->string('discord_webhook_url')->nullable(); + + // Notification Settings + $table->boolean('deployment_success_discord_notification')->default(false); + $table->boolean('deployment_failure_discord_notification')->default(true); + $table->boolean('backup_success_discord_notification')->default(false); + $table->boolean('backup_failure_discord_notification')->default(true); + $table->boolean('scheduled_task_success_discord_notification')->default(false); + $table->boolean('scheduled_task_failure_discord_notification')->default(true); + $table->boolean('status_change_discord_notification')->default(false); + $table->boolean('server_disk_usage_discord_notification')->default(true); + + $table->unique(['team_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('discord_notification_settings'); + } +}; From 832239bbc76fd93feb64da29cf56369471958102 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:33:19 +0100 Subject: [PATCH 03/80] Create 2024_12_05_212440_create_telegram_notification_settings_table.php --- ...e_telegram_notification_settings_table.php | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php 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 new file mode 100644 index 000000000..3a2e8d8a6 --- /dev/null +++ b/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php @@ -0,0 +1,54 @@ +id(); + $table->foreignId('team_id')->constrained()->cascadeOnDelete(); + + // Telegram Configuration + $table->boolean('telegram_enabled')->default(false); + $table->text('telegram_token')->nullable(); + $table->text('telegram_chat_id')->nullable(); + + // Notification Settings + $table->boolean('deployment_success_telegram_notification')->default(false); + $table->boolean('deployment_failure_telegram_notification')->default(true); + $table->boolean('backup_success_telegram_notification')->default(false); + $table->boolean('backup_failure_telegram_notification')->default(true); + $table->boolean('scheduled_task_success_telegram_notification')->default(false); + $table->boolean('scheduled_task_failure_telegram_notification')->default(true); + $table->boolean('status_change_telegram_notification')->default(false); + $table->boolean('server_disk_usage_telegram_notification')->default(true); + + // Thread IDs for Different Notifications + $table->text('telegram_notifications_deployment_success_thread_id')->nullable(); + $table->text('telegram_notifications_deployment_failure_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_status_change_thread_id')->nullable(); + $table->text('telegram_notifications_server_disk_usage_thread_id')->nullable(); + + $table->unique(['team_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('telegram_notification_settings'); + } +}; From 33b91e09e52020a3102d3f4ab19a1651b6369a0e Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:33:45 +0100 Subject: [PATCH 04/80] feat: migrate old email notification settings from the teams table --- ...notification_settings_from_teams_table.php | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php new file mode 100644 index 000000000..243a72b21 --- /dev/null +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -0,0 +1,115 @@ +emailNotificationSettings()->updateOrCreate( + ['team_id' => $team->id], + [ + 'smtp_enabled' => $team->smtp_enabled ?? false, + 'smtp_from_address' => $team->smtp_from_address, + 'smtp_from_name' => $team->smtp_from_name, + 'smtp_recipients' => $team->smtp_recipients, + 'smtp_host' => $team->smtp_host, + 'smtp_port' => $team->smtp_port, + 'smtp_encryption' => $team->smtp_encryption, + 'smtp_username' => $team->smtp_username, + 'smtp_password' => $team->smtp_password, + 'smtp_timeout' => $team->smtp_timeout, + + 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, + + 'resend_enabled' => $team->resend_enabled ?? false, + 'resend_api_key' => $team->resend_api_key, + + 'deployment_success_email_notification' => $team->smtp_notifications_deployments ?? false, + 'deployment_failure_email_notification' => $team->smtp_notifications_deployments ?? true, + 'backup_success_email_notification' => $team->smtp_notifications_database_backups ?? false, + 'backup_failure_email_notification' => $team->smtp_notifications_database_backups ?? true, + 'scheduled_task_success_email_notification' => $team->smtp_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_email_notification' => $team->smtp_notifications_scheduled_tasks ?? true, + 'status_change_email_notification' => $team->smtp_notifications_status_changes ?? false, + 'server_disk_usage_email_notification' => true, + ] + ); + } + + Schema::table('teams', function (Blueprint $table) { + $table->dropColumn([ + 'smtp_enabled', + 'smtp_from_address', + 'smtp_from_name', + 'smtp_recipients', + 'smtp_host', + 'smtp_port', + 'smtp_encryption', + 'smtp_username', + 'smtp_password', + 'smtp_timeout', + 'use_instance_email_settings', + 'resend_enabled', + 'resend_api_key', + 'smtp_notifications_deployments', + 'smtp_notifications_database_backups', + 'smtp_notifications_scheduled_tasks', + 'smtp_notifications_status_changes', + ]); + }); + } + + public function down(): void + { + Schema::table('teams', function (Blueprint $table) { + $table->boolean('smtp_enabled')->default(false); + $table->string('smtp_from_address')->nullable(); + $table->string('smtp_from_name')->nullable(); + $table->string('smtp_recipients')->nullable(); + $table->string('smtp_host')->nullable(); + $table->integer('smtp_port')->nullable(); + $table->string('smtp_encryption')->nullable(); + $table->text('smtp_username')->nullable(); + $table->text('smtp_password')->nullable(); + $table->integer('smtp_timeout')->nullable(); + $table->boolean('use_instance_email_settings')->default(false); + $table->boolean('resend_enabled')->default(false); + $table->text('resend_api_key')->nullable(); + $table->boolean('smtp_notifications_deployments')->default(false); + $table->boolean('smtp_notifications_database_backups')->default(true); + $table->boolean('smtp_notifications_scheduled_tasks')->default(false); + $table->boolean('smtp_notifications_status_changes')->default(false); + }); + + $teams = Team::with('emailNotificationSettings')->get(); + foreach ($teams as $team) { + if ($settings = $team->emailNotificationSettings) { + $team->update([ + 'smtp_enabled' => $settings->smtp_enabled, + 'smtp_from_address' => $settings->smtp_from_address, + 'smtp_from_name' => $settings->smtp_from_name, + 'smtp_recipients' => $settings->smtp_recipients, + 'smtp_host' => $settings->smtp_host, + 'smtp_port' => $settings->smtp_port, + 'smtp_encryption' => $settings->smtp_encryption, + 'smtp_username' => $settings->smtp_username, + 'smtp_password' => $settings->smtp_password, + 'smtp_timeout' => $settings->smtp_timeout, + 'use_instance_email_settings' => $settings->use_instance_email_settings, + 'resend_enabled' => $settings->resend_enabled, + 'resend_api_key' => $settings->resend_api_key, + 'smtp_notifications_deployments' => $settings->deployment_success_email_notification, + 'smtp_notifications_database_backups' => $settings->backup_success_email_notification, + 'smtp_notifications_scheduled_tasks' => $settings->scheduled_task_success_email_notification, + 'smtp_notifications_status_changes' => $settings->status_change_email_notification, + ]); + } + } + } +}; From fd2d9479335390873bd7c7441f82d7891d5b2c51 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:33:57 +0100 Subject: [PATCH 05/80] feat: migrate old discord notification settings from the teams table --- ...notification_settings_from_teams_table.php | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php diff --git a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php new file mode 100644 index 000000000..8a2b79c54 --- /dev/null +++ b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php @@ -0,0 +1,81 @@ +discordNotificationSettings()->updateOrCreate( + ['team_id' => $team->id], + [ + 'discord_enabled' => $team->discord_enabled ?? false, + 'discord_webhook_url' => $team->discord_webhook_url, + + 'deployment_success_discord_notification' => $team->discord_notifications_deployments ?? false, + 'deployment_failure_discord_notification' => $team->discord_notifications_deployments ?? true, + 'backup_success_discord_notification' => $team->discord_notifications_database_backups ?? false, + 'backup_failure_discord_notification' => $team->discord_notifications_database_backups ?? true, + 'scheduled_task_success_discord_notification' => $team->discord_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_discord_notification' => $team->discord_notifications_scheduled_tasks ?? true, + 'status_change_discord_notification' => $team->discord_notifications_status_changes ?? false, + 'server_disk_usage_discord_notification' => $team->discord_notifications_server_disk_usage ?? true, + ] + ); + } + + Schema::table('teams', function (Blueprint $table) { + $table->dropColumn([ + 'discord_enabled', + 'discord_webhook_url', + 'discord_notifications_test', + 'discord_notifications_deployments', + 'discord_notifications_status_changes', + 'discord_notifications_database_backups', + 'discord_notifications_scheduled_tasks', + 'discord_notifications_server_disk_usage', + ]); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('teams', function (Blueprint $table) { + $table->boolean('discord_enabled')->default(false); + $table->string('discord_webhook_url')->nullable(); + $table->boolean('discord_notifications_test')->default(true); + $table->boolean('discord_notifications_deployments')->default(true); + $table->boolean('discord_notifications_status_changes')->default(true); + $table->boolean('discord_notifications_database_backups')->default(true); + $table->boolean('discord_notifications_scheduled_tasks')->default(true); + $table->boolean('discord_notifications_server_disk_usage')->default(true); + }); + + $teams = Team::with('discordNotificationSettings')->get(); + foreach ($teams as $team) { + if ($settings = $team->discordNotificationSettings) { + $team->update([ + 'discord_enabled' => $settings->discord_enabled, + 'discord_webhook_url' => $settings->discord_webhook_url, + 'discord_notifications_test' => true, + 'discord_notifications_deployments' => $settings->deployment_success_discord_notification, + 'discord_notifications_status_changes' => $settings->status_change_discord_notification, + 'discord_notifications_database_backups' => $settings->backup_success_discord_notification, + 'discord_notifications_scheduled_tasks' => $settings->scheduled_task_success_discord_notification, + 'discord_notifications_server_disk_usage' => $settings->server_disk_usage_discord_notification, + ]); + } + } + } +}; From fb49c4daf451a60016140120a3a1aad4a5a6e7aa Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:34:08 +0100 Subject: [PATCH 06/80] feat: migrate old telegram notification settings from the teams table --- ...notification_settings_from_teams_table.php | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php 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 new file mode 100644 index 000000000..416c14439 --- /dev/null +++ b/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php @@ -0,0 +1,106 @@ +telegramNotificationSettings()->updateOrCreate( + ['team_id' => $team->id], + [ + 'telegram_enabled' => $team->telegram_enabled ?? false, + 'telegram_token' => $team->telegram_token, + 'telegram_chat_id' => $team->telegram_chat_id, + + 'deployment_success_telegram_notification' => $team->telegram_notifications_deployments ?? false, + 'deployment_failure_telegram_notification' => $team->telegram_notifications_deployments ?? true, + 'backup_success_telegram_notification' => $team->telegram_notifications_database_backups ?? false, + 'backup_failure_telegram_notification' => $team->telegram_notifications_database_backups ?? true, + 'scheduled_task_success_telegram_notification' => $team->telegram_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_telegram_notification' => $team->telegram_notifications_scheduled_tasks ?? true, + 'status_change_telegram_notification' => $team->telegram_notifications_status_changes ?? false, + 'server_disk_usage_telegram_notification' => $team->telegram_notifications_server_disk_usage ?? true, + + 'telegram_notifications_deployment_success_thread_id' => $team->telegram_notifications_deployments_message_thread_id, + 'telegram_notifications_deployment_failure_thread_id' => $team->telegram_notifications_deployments_message_thread_id, + 'telegram_notifications_backup_success_thread_id' => $team->telegram_notifications_database_backups_message_thread_id, + 'telegram_notifications_backup_failure_thread_id' => $team->telegram_notifications_database_backups_message_thread_id, + 'telegram_notifications_scheduled_task_success_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id, + 'telegram_notifications_scheduled_task_failure_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id, + 'telegram_notifications_status_change_thread_id' => $team->telegram_notifications_status_changes_message_thread_id, + ] + ); + } + + // Drop the old columns + Schema::table('teams', function (Blueprint $table) { + $table->dropColumn([ + 'telegram_enabled', + 'telegram_token', + 'telegram_chat_id', + 'telegram_notifications_test', + 'telegram_notifications_deployments', + 'telegram_notifications_status_changes', + 'telegram_notifications_database_backups', + 'telegram_notifications_scheduled_tasks', + 'telegram_notifications_server_disk_usage', + 'telegram_notifications_test_message_thread_id', + 'telegram_notifications_deployments_message_thread_id', + 'telegram_notifications_status_changes_message_thread_id', + 'telegram_notifications_database_backups_message_thread_id', + 'telegram_notifications_scheduled_tasks_thread_id', + ]); + }); + } + + public function down(): void + { + // Add back the old columns + Schema::table('teams', function (Blueprint $table) { + $table->boolean('telegram_enabled')->default(false); + $table->text('telegram_token')->nullable(); + $table->text('telegram_chat_id')->nullable(); + $table->boolean('telegram_notifications_test')->default(true); + $table->boolean('telegram_notifications_deployments')->default(true); + $table->boolean('telegram_notifications_status_changes')->default(true); + $table->boolean('telegram_notifications_database_backups')->default(true); + $table->boolean('telegram_notifications_scheduled_tasks')->default(true); + $table->boolean('telegram_notifications_server_disk_usage')->default(true); + $table->text('telegram_notifications_test_message_thread_id')->nullable(); + $table->text('telegram_notifications_deployments_message_thread_id')->nullable(); + $table->text('telegram_notifications_status_changes_message_thread_id')->nullable(); + $table->text('telegram_notifications_database_backups_message_thread_id')->nullable(); + $table->text('telegram_notifications_scheduled_tasks_thread_id')->nullable(); + }); + + // Migrate data back from the new table to the old columns + $teams = Team::with('telegramNotificationSettings')->get(); + foreach ($teams as $team) { + if ($settings = $team->telegramNotificationSettings) { + $team->update([ + 'telegram_enabled' => $settings->telegram_enabled, + 'telegram_token' => $settings->telegram_token, + 'telegram_chat_id' => $settings->telegram_chat_id, + 'telegram_notifications_test' => true, + 'telegram_notifications_deployments' => $settings->deployment_success_telegram_notification, + 'telegram_notifications_status_changes' => $settings->status_change_telegram_notification, + 'telegram_notifications_database_backups' => $settings->backup_success_telegram_notification, + 'telegram_notifications_scheduled_tasks' => $settings->scheduled_task_success_telegram_notification, + 'telegram_notifications_server_disk_usage' => $settings->server_disk_usage_telegram_notification, + 'telegram_notifications_deployments_message_thread_id' => $settings->telegram_notifications_deployment_success_thread_id, + 'telegram_notifications_status_changes_message_thread_id' => $settings->telegram_notifications_status_change_thread_id, + 'telegram_notifications_database_backups_message_thread_id' => $settings->telegram_notifications_backup_success_thread_id, + 'telegram_notifications_scheduled_tasks_thread_id' => $settings->telegram_notifications_scheduled_task_success_thread_id, + ]); + } + } + } +}; From 251d4cfb53921b6bb2a3906db139301cf90b3769 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 23:01:10 +0100 Subject: [PATCH 07/80] chore: remove comments and improve DB column naming --- ...eate_email_notification_settings_table.php | 19 +++---- ...te_discord_notification_settings_table.php | 17 +++---- ...e_telegram_notification_settings_table.php | 35 ++++++------- ...notification_settings_from_teams_table.php | 25 +++++----- ...notification_settings_from_teams_table.php | 27 +++++----- ...notification_settings_from_teams_table.php | 49 +++++++++---------- 6 files changed, 82 insertions(+), 90 deletions(-) diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php index 45b106827..783e1f9e1 100644 --- a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -15,7 +15,6 @@ return new class extends Migration $table->id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); - // SMTP Configuration $table->boolean('smtp_enabled')->default(false); $table->string('smtp_from_address')->nullable(); $table->string('smtp_from_name')->nullable(); @@ -29,19 +28,17 @@ return new class extends Migration $table->boolean('use_instance_email_settings')->default(false); - // Resend Configuration $table->boolean('resend_enabled')->default(false); $table->encryptedText('resend_api_key')->nullable(); - // Notification Settings - $table->boolean('deployment_success_email_notification')->default(false); - $table->boolean('deployment_failure_email_notification')->default(true); - $table->boolean('backup_success_email_notification')->default(false); - $table->boolean('backup_failure_email_notification')->default(true); - $table->boolean('scheduled_task_success_email_notification')->default(false); - $table->boolean('scheduled_task_failure_email_notification')->default(true); - $table->boolean('status_change_email_notification')->default(false); - $table->boolean('server_disk_usage_email_notification')->default(true); + $table->boolean('deployment_success_email_notifications')->default(false); + $table->boolean('deployment_failure_email_notifications')->default(true); + $table->boolean('backup_success_email_notifications')->default(false); + $table->boolean('backup_failure_email_notifications')->default(true); + $table->boolean('scheduled_task_success_email_notifications')->default(false); + $table->boolean('scheduled_task_failure_email_notifications')->default(true); + $table->boolean('status_change_email_notifications')->default(false); + $table->boolean('server_disk_usage_email_notifications')->default(true); $table->unique(['team_id']); }); diff --git a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php index 5c6ebbd2c..6989444bb 100644 --- a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php +++ b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php @@ -18,15 +18,14 @@ return new class extends Migration $table->boolean('discord_enabled')->default(false); $table->string('discord_webhook_url')->nullable(); - // Notification Settings - $table->boolean('deployment_success_discord_notification')->default(false); - $table->boolean('deployment_failure_discord_notification')->default(true); - $table->boolean('backup_success_discord_notification')->default(false); - $table->boolean('backup_failure_discord_notification')->default(true); - $table->boolean('scheduled_task_success_discord_notification')->default(false); - $table->boolean('scheduled_task_failure_discord_notification')->default(true); - $table->boolean('status_change_discord_notification')->default(false); - $table->boolean('server_disk_usage_discord_notification')->default(true); + $table->boolean('deployment_success_discord_notifications')->default(false); + $table->boolean('deployment_failure_discord_notifications')->default(true); + $table->boolean('backup_success_discord_notifications')->default(false); + $table->boolean('backup_failure_discord_notifications')->default(true); + $table->boolean('scheduled_task_success_discord_notifications')->default(false); + $table->boolean('scheduled_task_failure_discord_notifications')->default(true); + $table->boolean('status_change_discord_notifications')->default(false); + $table->boolean('server_disk_usage_discord_notifications')->default(true); $table->unique(['team_id']); }); 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 3a2e8d8a6..a85794636 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 @@ -15,30 +15,27 @@ return new class extends Migration $table->id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); - // Telegram Configuration $table->boolean('telegram_enabled')->default(false); $table->text('telegram_token')->nullable(); $table->text('telegram_chat_id')->nullable(); - // Notification Settings - $table->boolean('deployment_success_telegram_notification')->default(false); - $table->boolean('deployment_failure_telegram_notification')->default(true); - $table->boolean('backup_success_telegram_notification')->default(false); - $table->boolean('backup_failure_telegram_notification')->default(true); - $table->boolean('scheduled_task_success_telegram_notification')->default(false); - $table->boolean('scheduled_task_failure_telegram_notification')->default(true); - $table->boolean('status_change_telegram_notification')->default(false); - $table->boolean('server_disk_usage_telegram_notification')->default(true); + $table->boolean('deployment_success_telegram_notifications')->default(false); + $table->boolean('deployment_failure_telegram_notifications')->default(true); + $table->boolean('backup_success_telegram_notifications')->default(false); + $table->boolean('backup_failure_telegram_notifications')->default(true); + $table->boolean('scheduled_task_success_telegram_notifications')->default(false); + $table->boolean('scheduled_task_failure_telegram_notifications')->default(true); + $table->boolean('status_change_telegram_notifications')->default(false); + $table->boolean('server_disk_usage_telegram_notifications')->default(true); - // Thread IDs for Different Notifications - $table->text('telegram_notifications_deployment_success_thread_id')->nullable(); - $table->text('telegram_notifications_deployment_failure_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_status_change_thread_id')->nullable(); - $table->text('telegram_notifications_server_disk_usage_thread_id')->nullable(); + $table->text('telegram_notifications_deployment_success_topic_id')->nullable(); + $table->text('telegram_notifications_deployment_failure_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_status_change_topic_id')->nullable(); + $table->text('telegram_notifications_server_disk_usage_topic_id')->nullable(); $table->unique(['team_id']); }); diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index 243a72b21..b8ba245b9 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -30,14 +30,14 @@ return new class extends Migration 'resend_enabled' => $team->resend_enabled ?? false, 'resend_api_key' => $team->resend_api_key, - 'deployment_success_email_notification' => $team->smtp_notifications_deployments ?? false, - 'deployment_failure_email_notification' => $team->smtp_notifications_deployments ?? true, - 'backup_success_email_notification' => $team->smtp_notifications_database_backups ?? false, - 'backup_failure_email_notification' => $team->smtp_notifications_database_backups ?? true, - 'scheduled_task_success_email_notification' => $team->smtp_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_email_notification' => $team->smtp_notifications_scheduled_tasks ?? true, - 'status_change_email_notification' => $team->smtp_notifications_status_changes ?? false, - 'server_disk_usage_email_notification' => true, + 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, + 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, + 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, + 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, + 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, + 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, + 'server_disk_usage_email_notifications' => true, ] ); } @@ -104,10 +104,11 @@ return new class extends Migration 'use_instance_email_settings' => $settings->use_instance_email_settings, 'resend_enabled' => $settings->resend_enabled, 'resend_api_key' => $settings->resend_api_key, - 'smtp_notifications_deployments' => $settings->deployment_success_email_notification, - 'smtp_notifications_database_backups' => $settings->backup_success_email_notification, - 'smtp_notifications_scheduled_tasks' => $settings->scheduled_task_success_email_notification, - 'smtp_notifications_status_changes' => $settings->status_change_email_notification, + 'smtp_notifications_deployments' => $settings->deployment_success_email_notifications || $settings->deployment_failure_email_notifications, + 'smtp_notifications_database_backups' => $settings->backup_success_email_notifications || $settings->backup_failure_email_notifications, + 'smtp_notifications_scheduled_tasks' => $settings->scheduled_task_success_email_notifications || $settings->scheduled_task_failure_email_notifications, + 'smtp_notifications_status_changes' => $settings->status_change_email_notifications, + 'smtp_notifications_server_disk_usage' => $settings->server_disk_usage_email_notifications, ]); } } diff --git a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php index 8a2b79c54..efb89b09a 100644 --- a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php @@ -20,14 +20,14 @@ return new class extends Migration 'discord_enabled' => $team->discord_enabled ?? false, 'discord_webhook_url' => $team->discord_webhook_url, - 'deployment_success_discord_notification' => $team->discord_notifications_deployments ?? false, - 'deployment_failure_discord_notification' => $team->discord_notifications_deployments ?? true, - 'backup_success_discord_notification' => $team->discord_notifications_database_backups ?? false, - 'backup_failure_discord_notification' => $team->discord_notifications_database_backups ?? true, - 'scheduled_task_success_discord_notification' => $team->discord_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_discord_notification' => $team->discord_notifications_scheduled_tasks ?? true, - 'status_change_discord_notification' => $team->discord_notifications_status_changes ?? false, - 'server_disk_usage_discord_notification' => $team->discord_notifications_server_disk_usage ?? true, + 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, + 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, + 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, + 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, + 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, + 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, + 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, ] ); } @@ -68,12 +68,11 @@ return new class extends Migration $team->update([ 'discord_enabled' => $settings->discord_enabled, 'discord_webhook_url' => $settings->discord_webhook_url, - 'discord_notifications_test' => true, - 'discord_notifications_deployments' => $settings->deployment_success_discord_notification, - 'discord_notifications_status_changes' => $settings->status_change_discord_notification, - 'discord_notifications_database_backups' => $settings->backup_success_discord_notification, - 'discord_notifications_scheduled_tasks' => $settings->scheduled_task_success_discord_notification, - 'discord_notifications_server_disk_usage' => $settings->server_disk_usage_discord_notification, + 'discord_notifications_deployments' => $settings->deployment_success_discord_notifications || $settings->deployment_failure_discord_notifications, + 'discord_notifications_status_changes' => $settings->status_change_discord_notifications, + 'discord_notifications_database_backups' => $settings->backup_success_discord_notifications || $settings->backup_failure_discord_notifications, + 'discord_notifications_scheduled_tasks' => $settings->scheduled_task_success_discord_notifications || $settings->scheduled_task_failure_discord_notifications, + 'discord_notifications_server_disk_usage' => $settings->server_disk_usage_discord_notifications, ]); } } 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 416c14439..6796a18cb 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 @@ -20,22 +20,22 @@ return new class extends Migration 'telegram_token' => $team->telegram_token, 'telegram_chat_id' => $team->telegram_chat_id, - 'deployment_success_telegram_notification' => $team->telegram_notifications_deployments ?? false, - 'deployment_failure_telegram_notification' => $team->telegram_notifications_deployments ?? true, - 'backup_success_telegram_notification' => $team->telegram_notifications_database_backups ?? false, - 'backup_failure_telegram_notification' => $team->telegram_notifications_database_backups ?? true, - 'scheduled_task_success_telegram_notification' => $team->telegram_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_telegram_notification' => $team->telegram_notifications_scheduled_tasks ?? true, - 'status_change_telegram_notification' => $team->telegram_notifications_status_changes ?? false, - 'server_disk_usage_telegram_notification' => $team->telegram_notifications_server_disk_usage ?? true, + 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, + 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, + 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, + 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, + 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, + '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_thread_id' => $team->telegram_notifications_deployments_message_thread_id, - 'telegram_notifications_deployment_failure_thread_id' => $team->telegram_notifications_deployments_message_thread_id, - 'telegram_notifications_backup_success_thread_id' => $team->telegram_notifications_database_backups_message_thread_id, - 'telegram_notifications_backup_failure_thread_id' => $team->telegram_notifications_database_backups_message_thread_id, - 'telegram_notifications_scheduled_task_success_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id, - 'telegram_notifications_scheduled_task_failure_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id, - 'telegram_notifications_status_change_thread_id' => $team->telegram_notifications_status_changes_message_thread_id, + 'telegram_notifications_deployment_success_topic_id' => $team->telegram_notifications_deployments_message_thread_id, + 'telegram_notifications_deployment_failure_topic_id' => $team->telegram_notifications_deployments_message_thread_id, + 'telegram_notifications_backup_success_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, + 'telegram_notifications_backup_failure_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, + 'telegram_notifications_scheduled_task_success_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, + 'telegram_notifications_scheduled_task_failure_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, + 'telegram_notifications_status_change_topic_id' => $team->telegram_notifications_status_changes_message_thread_id, ] ); } @@ -89,16 +89,15 @@ return new class extends Migration 'telegram_enabled' => $settings->telegram_enabled, 'telegram_token' => $settings->telegram_token, 'telegram_chat_id' => $settings->telegram_chat_id, - 'telegram_notifications_test' => true, - 'telegram_notifications_deployments' => $settings->deployment_success_telegram_notification, - 'telegram_notifications_status_changes' => $settings->status_change_telegram_notification, - 'telegram_notifications_database_backups' => $settings->backup_success_telegram_notification, - 'telegram_notifications_scheduled_tasks' => $settings->scheduled_task_success_telegram_notification, - 'telegram_notifications_server_disk_usage' => $settings->server_disk_usage_telegram_notification, - 'telegram_notifications_deployments_message_thread_id' => $settings->telegram_notifications_deployment_success_thread_id, - 'telegram_notifications_status_changes_message_thread_id' => $settings->telegram_notifications_status_change_thread_id, - 'telegram_notifications_database_backups_message_thread_id' => $settings->telegram_notifications_backup_success_thread_id, - 'telegram_notifications_scheduled_tasks_thread_id' => $settings->telegram_notifications_scheduled_task_success_thread_id, + 'telegram_notifications_deployments' => $settings->deployment_success_telegram_notifications || $settings->deployment_failure_telegram_notifications, + 'telegram_notifications_status_changes' => $settings->status_change_telegram_notifications, + 'telegram_notifications_database_backups' => $settings->backup_success_telegram_notifications || $settings->backup_failure_telegram_notifications, + 'telegram_notifications_scheduled_tasks' => $settings->scheduled_task_success_telegram_notifications || $settings->scheduled_task_failure_telegram_notifications, + 'telegram_notifications_server_disk_usage' => $settings->server_disk_usage_telegram_notifications, + 'telegram_notifications_deployments_message_thread_id' => $settings->telegram_notifications_deployment_success_topic_id, + 'telegram_notifications_status_changes_message_thread_id' => $settings->telegram_notifications_status_change_topic_id, + 'telegram_notifications_database_backups_message_thread_id' => $settings->telegram_notifications_backup_success_topic_id, + 'telegram_notifications_scheduled_tasks_thread_id' => $settings->telegram_notifications_scheduled_task_success_topic_id, ]); } } From 92992a884477af7fddd323c03e14b0203362ed00 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 23:03:39 +0100 Subject: [PATCH 08/80] fix: DB migration error --- ...24_12_05_212355_create_email_notification_settings_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php index 783e1f9e1..525168ec0 100644 --- a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -29,7 +29,7 @@ return new class extends Migration $table->boolean('use_instance_email_settings')->default(false); $table->boolean('resend_enabled')->default(false); - $table->encryptedText('resend_api_key')->nullable(); + $table->text('resend_api_key')->nullable(); $table->boolean('deployment_success_email_notifications')->default(false); $table->boolean('deployment_failure_email_notifications')->default(true); From fbd8b96b66275df167dbac328fc2d734fa523207 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 5 Dec 2024 23:06:42 +0100 Subject: [PATCH 09/80] fix: drop all unused smtp columns --- ...546_migrate_email_notification_settings_from_teams_table.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index b8ba245b9..737c0bab6 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -57,10 +57,12 @@ return new class extends Migration 'use_instance_email_settings', 'resend_enabled', 'resend_api_key', + 'smtp_notifications_test', 'smtp_notifications_deployments', 'smtp_notifications_database_backups', 'smtp_notifications_scheduled_tasks', 'smtp_notifications_status_changes', + 'smtp_notifications_server_disk_usage', ]); }); } From 4ff317001dad6944eb02e60abaa8893be36995de Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Fri, 6 Dec 2024 15:19:31 +0100 Subject: [PATCH 10/80] fix: backward compatibility - Add migrations that move email, discord and telegram notifications to the new settings tables for each notification - drop now unused columns form the teams table --- ...notification_settings_from_teams_table.php | 103 +++++++++--------- ...notification_settings_from_teams_table.php | 58 +++++----- ...notification_settings_from_teams_table.php | 86 +++++++-------- 3 files changed, 117 insertions(+), 130 deletions(-) diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index 737c0bab6..d835ec2ed 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -1,45 +1,41 @@ get(); + foreach ($teams as $team) { - $team->emailNotificationSettings()->updateOrCreate( - ['team_id' => $team->id], - [ - 'smtp_enabled' => $team->smtp_enabled ?? false, - 'smtp_from_address' => $team->smtp_from_address, - 'smtp_from_name' => $team->smtp_from_name, - 'smtp_recipients' => $team->smtp_recipients, - 'smtp_host' => $team->smtp_host, - 'smtp_port' => $team->smtp_port, - 'smtp_encryption' => $team->smtp_encryption, - 'smtp_username' => $team->smtp_username, - 'smtp_password' => $team->smtp_password, - 'smtp_timeout' => $team->smtp_timeout, - - 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, - - 'resend_enabled' => $team->resend_enabled ?? false, - 'resend_api_key' => $team->resend_api_key, - - 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, - 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, - 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, - 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, - 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, - 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, - 'server_disk_usage_email_notifications' => true, - ] - ); + DB::table('email_notification_settings')->insert([ + 'team_id' => $team->id, + 'smtp_enabled' => $team->smtp_enabled ?? false, + 'smtp_from_address' => $team->smtp_from_address, + 'smtp_from_name' => $team->smtp_from_name, + 'smtp_recipients' => $team->smtp_recipients, + 'smtp_host' => $team->smtp_host, + 'smtp_port' => $team->smtp_port, + 'smtp_encryption' => $team->smtp_encryption, + 'smtp_username' => $team->smtp_username, + 'smtp_password' => $team->smtp_password, + 'smtp_timeout' => $team->smtp_timeout, + 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, + 'resend_enabled' => $team->resend_enabled ?? false, + 'resend_api_key' => $team->resend_api_key, + 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, + 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? false, + 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, + 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? false, + 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, + 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, + 'server_disk_usage_email_notifications' => true, + ]); } Schema::table('teams', function (Blueprint $table) { @@ -89,30 +85,29 @@ return new class extends Migration $table->boolean('smtp_notifications_status_changes')->default(false); }); - $teams = Team::with('emailNotificationSettings')->get(); - foreach ($teams as $team) { - if ($settings = $team->emailNotificationSettings) { - $team->update([ - 'smtp_enabled' => $settings->smtp_enabled, - 'smtp_from_address' => $settings->smtp_from_address, - 'smtp_from_name' => $settings->smtp_from_name, - 'smtp_recipients' => $settings->smtp_recipients, - 'smtp_host' => $settings->smtp_host, - 'smtp_port' => $settings->smtp_port, - 'smtp_encryption' => $settings->smtp_encryption, - 'smtp_username' => $settings->smtp_username, - 'smtp_password' => $settings->smtp_password, - 'smtp_timeout' => $settings->smtp_timeout, - 'use_instance_email_settings' => $settings->use_instance_email_settings, - 'resend_enabled' => $settings->resend_enabled, - 'resend_api_key' => $settings->resend_api_key, - 'smtp_notifications_deployments' => $settings->deployment_success_email_notifications || $settings->deployment_failure_email_notifications, - 'smtp_notifications_database_backups' => $settings->backup_success_email_notifications || $settings->backup_failure_email_notifications, - 'smtp_notifications_scheduled_tasks' => $settings->scheduled_task_success_email_notifications || $settings->scheduled_task_failure_email_notifications, - 'smtp_notifications_status_changes' => $settings->status_change_email_notifications, - 'smtp_notifications_server_disk_usage' => $settings->server_disk_usage_email_notifications, + $settings = DB::table('email_notification_settings')->get(); + foreach ($settings as $setting) { + DB::table('teams') + ->where('id', $setting->team_id) + ->update([ + 'smtp_enabled' => $setting->smtp_enabled, + 'smtp_from_address' => $setting->smtp_from_address, + 'smtp_from_name' => $setting->smtp_from_name, + 'smtp_recipients' => $setting->smtp_recipients, + 'smtp_host' => $setting->smtp_host, + 'smtp_port' => $setting->smtp_port, + 'smtp_encryption' => $setting->smtp_encryption, + 'smtp_username' => $setting->smtp_username, + 'smtp_password' => $setting->smtp_password, + 'smtp_timeout' => $setting->smtp_timeout, + 'use_instance_email_settings' => $setting->use_instance_email_settings, + 'resend_enabled' => $setting->resend_enabled, + 'resend_api_key' => $setting->resend_api_key, + 'smtp_notifications_deployments' => $setting->deployment_success_email_notifications || $setting->deployment_failure_email_notifications, + 'smtp_notifications_database_backups' => $setting->backup_success_email_notifications || $setting->backup_failure_email_notifications, + 'smtp_notifications_scheduled_tasks' => $setting->scheduled_task_success_email_notifications || $setting->scheduled_task_failure_email_notifications, + 'smtp_notifications_status_changes' => $setting->status_change_email_notifications, ]); - } } } }; diff --git a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php index efb89b09a..72d56ac08 100644 --- a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php @@ -1,8 +1,8 @@ discordNotificationSettings()->updateOrCreate( - ['team_id' => $team->id], - [ - 'discord_enabled' => $team->discord_enabled ?? false, - 'discord_webhook_url' => $team->discord_webhook_url, + $teams = DB::table('teams')->get(); - 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, - 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, - 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, - 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, - 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, - 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, - 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, - ] - ); + foreach ($teams as $team) { + DB::table('discord_notification_settings')->insert([ + 'team_id' => $team->id, + 'discord_enabled' => $team->discord_enabled ?? false, + 'discord_webhook_url' => $team->discord_webhook_url, + 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, + 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? false, + 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, + 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? false, + 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, + 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, + 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, + ]); } Schema::table('teams', function (Blueprint $table) { @@ -62,19 +60,19 @@ return new class extends Migration $table->boolean('discord_notifications_server_disk_usage')->default(true); }); - $teams = Team::with('discordNotificationSettings')->get(); - foreach ($teams as $team) { - if ($settings = $team->discordNotificationSettings) { - $team->update([ - 'discord_enabled' => $settings->discord_enabled, - 'discord_webhook_url' => $settings->discord_webhook_url, - 'discord_notifications_deployments' => $settings->deployment_success_discord_notifications || $settings->deployment_failure_discord_notifications, - 'discord_notifications_status_changes' => $settings->status_change_discord_notifications, - 'discord_notifications_database_backups' => $settings->backup_success_discord_notifications || $settings->backup_failure_discord_notifications, - 'discord_notifications_scheduled_tasks' => $settings->scheduled_task_success_discord_notifications || $settings->scheduled_task_failure_discord_notifications, - 'discord_notifications_server_disk_usage' => $settings->server_disk_usage_discord_notifications, + $settings = DB::table('discord_notification_settings')->get(); + foreach ($settings as $setting) { + DB::table('teams') + ->where('id', $setting->team_id) + ->update([ + 'discord_enabled' => $setting->discord_enabled, + 'discord_webhook_url' => $setting->discord_webhook_url, + 'discord_notifications_deployments' => $setting->deployment_success_discord_notifications || $setting->deployment_failure_discord_notifications, + 'discord_notifications_status_changes' => $setting->status_change_discord_notifications, + 'discord_notifications_database_backups' => $setting->backup_success_discord_notifications || $setting->backup_failure_discord_notifications, + 'discord_notifications_scheduled_tasks' => $setting->scheduled_task_success_discord_notifications || $setting->scheduled_task_failure_discord_notifications, + 'discord_notifications_server_disk_usage' => $setting->server_disk_usage_discord_notifications, ]); - } } } }; 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 6796a18cb..82e928649 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 @@ -1,46 +1,42 @@ get(); foreach ($teams as $team) { + DB::table('telegram_notification_settings')->insert([ + 'team_id' => $team->id, + 'telegram_enabled' => $team->telegram_enabled ?? false, + 'telegram_token' => $team->telegram_token, + 'telegram_chat_id' => $team->telegram_chat_id, - $team->telegramNotificationSettings()->updateOrCreate( - ['team_id' => $team->id], - [ - 'telegram_enabled' => $team->telegram_enabled ?? false, - 'telegram_token' => $team->telegram_token, - 'telegram_chat_id' => $team->telegram_chat_id, + 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, + 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? false, + 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, + 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, + 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, + 'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false, + 'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true, - 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, - 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, - 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, - 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, - 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, - '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, - 'telegram_notifications_deployment_failure_topic_id' => $team->telegram_notifications_deployments_message_thread_id, - 'telegram_notifications_backup_success_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, - 'telegram_notifications_backup_failure_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, - 'telegram_notifications_scheduled_task_success_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, - 'telegram_notifications_scheduled_task_failure_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, - 'telegram_notifications_status_change_topic_id' => $team->telegram_notifications_status_changes_message_thread_id, - ] - ); + 'telegram_notifications_deployment_success_topic_id' => $team->telegram_notifications_deployments_message_thread_id, + 'telegram_notifications_deployment_failure_topic_id' => $team->telegram_notifications_deployments_message_thread_id, + 'telegram_notifications_backup_success_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, + 'telegram_notifications_backup_failure_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, + 'telegram_notifications_scheduled_task_success_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, + 'telegram_notifications_scheduled_task_failure_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, + 'telegram_notifications_status_change_topic_id' => $team->telegram_notifications_status_changes_message_thread_id, + ]); } - // Drop the old columns Schema::table('teams', function (Blueprint $table) { $table->dropColumn([ 'telegram_enabled', @@ -63,7 +59,6 @@ return new class extends Migration public function down(): void { - // Add back the old columns Schema::table('teams', function (Blueprint $table) { $table->boolean('telegram_enabled')->default(false); $table->text('telegram_token')->nullable(); @@ -81,25 +76,24 @@ return new class extends Migration $table->text('telegram_notifications_scheduled_tasks_thread_id')->nullable(); }); - // Migrate data back from the new table to the old columns - $teams = Team::with('telegramNotificationSettings')->get(); - foreach ($teams as $team) { - if ($settings = $team->telegramNotificationSettings) { - $team->update([ - 'telegram_enabled' => $settings->telegram_enabled, - 'telegram_token' => $settings->telegram_token, - 'telegram_chat_id' => $settings->telegram_chat_id, - 'telegram_notifications_deployments' => $settings->deployment_success_telegram_notifications || $settings->deployment_failure_telegram_notifications, - 'telegram_notifications_status_changes' => $settings->status_change_telegram_notifications, - 'telegram_notifications_database_backups' => $settings->backup_success_telegram_notifications || $settings->backup_failure_telegram_notifications, - 'telegram_notifications_scheduled_tasks' => $settings->scheduled_task_success_telegram_notifications || $settings->scheduled_task_failure_telegram_notifications, - 'telegram_notifications_server_disk_usage' => $settings->server_disk_usage_telegram_notifications, - 'telegram_notifications_deployments_message_thread_id' => $settings->telegram_notifications_deployment_success_topic_id, - 'telegram_notifications_status_changes_message_thread_id' => $settings->telegram_notifications_status_change_topic_id, - 'telegram_notifications_database_backups_message_thread_id' => $settings->telegram_notifications_backup_success_topic_id, - 'telegram_notifications_scheduled_tasks_thread_id' => $settings->telegram_notifications_scheduled_task_success_topic_id, + $settings = DB::table('telegram_notification_settings')->get(); + foreach ($settings as $setting) { + DB::table('teams') + ->where('id', $setting->team_id) + ->update([ + 'telegram_enabled' => $setting->telegram_enabled, + 'telegram_token' => $setting->telegram_token, + 'telegram_chat_id' => $setting->telegram_chat_id, + 'telegram_notifications_deployments' => $setting->deployment_success_telegram_notifications || $setting->deployment_failure_telegram_notifications, + 'telegram_notifications_status_changes' => $setting->status_change_telegram_notifications, + 'telegram_notifications_database_backups' => $setting->backup_success_telegram_notifications || $setting->backup_failure_telegram_notifications, + '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, + 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_topic_id, + 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_topic_id, + 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_topic_id, ]); - } } } }; From cc894defc5939915cc7c6dec47d5f68284b1acd4 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Fri, 6 Dec 2024 15:25:37 +0100 Subject: [PATCH 11/80] feat: add slack notifications to a new table --- ...add_slack_notifications_to_teams_table.php | 38 ----------------- ...eate_slack_notification_settings_table.php | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 38 deletions(-) delete mode 100644 database/migrations/2024_11_12_213200_add_slack_notifications_to_teams_table.php create mode 100644 database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php diff --git a/database/migrations/2024_11_12_213200_add_slack_notifications_to_teams_table.php b/database/migrations/2024_11_12_213200_add_slack_notifications_to_teams_table.php deleted file mode 100644 index a6457269a..000000000 --- a/database/migrations/2024_11_12_213200_add_slack_notifications_to_teams_table.php +++ /dev/null @@ -1,38 +0,0 @@ -boolean('slack_enabled')->default(false); - $table->string('slack_webhook_url')->nullable(); - $table->boolean('slack_notifications_test')->default(true); - $table->boolean('slack_notifications_deployments')->default(true); - $table->boolean('slack_notifications_status_changes')->default(true); - $table->boolean('slack_notifications_database_backups')->default(true); - $table->boolean('slack_notifications_scheduled_tasks')->default(true); - $table->boolean('slack_notifications_server_disk_usage')->default(true); - }); - } - - public function down(): void - { - Schema::table('teams', function (Blueprint $table) { - $table->dropColumn([ - 'slack_enabled', - 'slack_webhook_url', - 'slack_notifications_test', - 'slack_notifications_deployments', - 'slack_notifications_status_changes', - 'slack_notifications_database_backups', - 'slack_notifications_scheduled_tasks', - 'slack_notifications_server_disk_usage', - ]); - }); - } -}; 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 new file mode 100644 index 000000000..6eb988619 --- /dev/null +++ b/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php @@ -0,0 +1,41 @@ +id(); + $table->foreignId('team_id')->constrained()->cascadeOnDelete(); + + $table->boolean('slack_enabled')->default(false); + $table->string('slack_webhook_url')->nullable(); + + $table->boolean('deployment_success_slack_notifications')->default(false); + $table->boolean('deployment_failure_slack_notifications')->default(true); + $table->boolean('backup_success_slack_notifications')->default(false); + $table->boolean('backup_failure_slack_notifications')->default(true); + $table->boolean('scheduled_task_success_slack_notifications')->default(false); + $table->boolean('scheduled_task_failure_slack_notifications')->default(true); + $table->boolean('status_change_slack_notifications')->default(false); + $table->boolean('server_disk_usage_slack_notifications')->default(true); + + $table->unique(['team_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('slack_notification_settings'); + } +}; From 19064beb2a30513d9c0be67f4935f6cb18e85e62 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Fri, 6 Dec 2024 15:50:20 +0100 Subject: [PATCH 12/80] chore: remove unused seeder --- database/seeders/TestTeamSeeder.php | 42 ----------------------------- 1 file changed, 42 deletions(-) delete mode 100644 database/seeders/TestTeamSeeder.php diff --git a/database/seeders/TestTeamSeeder.php b/database/seeders/TestTeamSeeder.php deleted file mode 100644 index 940c45cc5..000000000 --- a/database/seeders/TestTeamSeeder.php +++ /dev/null @@ -1,42 +0,0 @@ -create([ - 'name' => '1 personal, 1 other team, owner, no other members', - 'email' => '1@example.com', - ]); - $team = Team::create([ - 'name' => '1@example.com', - 'personal_team' => false, - 'show_boarding' => true, - ]); - $user->teams()->attach($team, ['role' => 'owner']); - - // User has 2 teams, 1 personal, 1 other where it is the owner and 1 other member is in the team - $user = User::factory()->create([ - 'name' => 'owner: 1 personal, 1 other team, owner, 1 other member', - 'email' => '2@example.com', - ]); - $team = Team::create([ - 'name' => '2@example.com', - 'personal_team' => false, - 'show_boarding' => true, - ]); - $user->teams()->attach($team, ['role' => 'owner']); - $user = User::factory()->create([ - 'name' => 'member: 1 personal, 1 other team, owner, 1 other member', - 'email' => '3@example.com', - ]); - $team->members()->attach($user, ['role' => 'member']); - } -} From d9248508b48cc0966f9b7714ee0aac351b36c3ba Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:00:54 +0100 Subject: [PATCH 13/80] chore: remove unused waitlist stuff --- app/Console/Commands/WaitlistInvite.php | 114 ------------------ app/Http/Controllers/Webhook/Waitlist.php | 63 ---------- app/Jobs/SendConfirmationForWaitlistJob.php | 37 ------ app/Livewire/Waitlist/Index.php | 70 ----------- app/Models/Waitlist.php | 12 -- bootstrap/helpers/subscriptions.php | 1 - config/constants.php | 5 - ...2024_12_09_105711_drop_waitlists_table.php | 31 +++++ .../emails/waitlist-confirmation.blade.php | 7 -- .../views/livewire/waitlist/index.blade.php | 37 ------ routes/webhooks.php | 4 - 11 files changed, 31 insertions(+), 350 deletions(-) delete mode 100644 app/Console/Commands/WaitlistInvite.php delete mode 100644 app/Http/Controllers/Webhook/Waitlist.php delete mode 100755 app/Jobs/SendConfirmationForWaitlistJob.php delete mode 100644 app/Livewire/Waitlist/Index.php delete mode 100644 app/Models/Waitlist.php create mode 100644 database/migrations/2024_12_09_105711_drop_waitlists_table.php delete mode 100644 resources/views/emails/waitlist-confirmation.blade.php delete mode 100644 resources/views/livewire/waitlist/index.blade.php diff --git a/app/Console/Commands/WaitlistInvite.php b/app/Console/Commands/WaitlistInvite.php deleted file mode 100644 index 2e330068c..000000000 --- a/app/Console/Commands/WaitlistInvite.php +++ /dev/null @@ -1,114 +0,0 @@ -option('people'); - for ($i = 0; $i < $people; $i++) { - $this->main(); - } - } - - private function main() - { - if ($this->argument('email')) { - if ($this->option('only-email')) { - $this->next_patient = User::whereEmail($this->argument('email'))->first(); - $this->password = Str::password(); - $this->next_patient->update([ - 'password' => Hash::make($this->password), - 'force_password_reset' => true, - ]); - } else { - $this->next_patient = Waitlist::where('email', $this->argument('email'))->first(); - } - if (! $this->next_patient) { - $this->error("{$this->argument('email')} not found in the waitlist."); - - return; - } - } else { - $this->next_patient = Waitlist::orderBy('created_at', 'asc')->where('verified', true)->first(); - } - if ($this->next_patient) { - if ($this->option('only-email')) { - $this->send_email(); - - return; - } - $this->register_user(); - $this->remove_from_waitlist(); - $this->send_email(); - } else { - $this->info('No verified user found in the waitlist. 👀'); - } - } - - private function register_user() - { - $already_registered = User::whereEmail($this->next_patient->email)->first(); - if (! $already_registered) { - $this->password = Str::password(); - User::create([ - 'name' => str($this->next_patient->email)->before('@'), - 'email' => $this->next_patient->email, - 'password' => Hash::make($this->password), - 'force_password_reset' => true, - ]); - $this->info("User registered ({$this->next_patient->email}) successfully. 🎉"); - } else { - throw new \Exception('User already registered'); - } - } - - private function remove_from_waitlist() - { - $this->next_patient->delete(); - $this->info('User removed from waitlist successfully.'); - } - - private function send_email() - { - $token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password"); - $loginLink = route('auth.link', ['token' => $token]); - $mail = new MailMessage; - $mail->view('emails.waitlist-invitation', [ - 'loginLink' => $loginLink, - ]); - $mail->subject('Congratulations! You are invited to join Coolify Cloud.'); - send_user_an_email($mail, $this->next_patient->email); - $this->info('Email sent successfully. 📧'); - } -} diff --git a/app/Http/Controllers/Webhook/Waitlist.php b/app/Http/Controllers/Webhook/Waitlist.php deleted file mode 100644 index dec8ca72d..000000000 --- a/app/Http/Controllers/Webhook/Waitlist.php +++ /dev/null @@ -1,63 +0,0 @@ -get('email'); - $confirmation_code = request()->get('confirmation_code'); - try { - $found = ModelsWaitlist::where('uuid', $confirmation_code)->where('email', $email)->first(); - if ($found) { - if (! $found->verified) { - if ($found->created_at > now()->subMinutes(config('constants.waitlist.expiration'))) { - $found->verified = true; - $found->save(); - send_internal_notification('Waitlist confirmed: '.$email); - - return 'Thank you for confirming your email address. We will notify you when you are next in line.'; - } else { - $found->delete(); - send_internal_notification('Waitlist expired: '.$email); - - return 'Your confirmation code has expired. Please sign up again.'; - } - } - } - - return redirect()->route('dashboard'); - } catch (Exception $e) { - send_internal_notification('Waitlist confirmation failed: '.$e->getMessage()); - - return redirect()->route('dashboard'); - } - } - - public function cancel(Request $request) - { - $email = request()->get('email'); - $confirmation_code = request()->get('confirmation_code'); - try { - $found = ModelsWaitlist::where('uuid', $confirmation_code)->where('email', $email)->first(); - if ($found && ! $found->verified) { - $found->delete(); - send_internal_notification('Waitlist cancelled: '.$email); - - return 'Your email address has been removed from the waitlist.'; - } - - return redirect()->route('dashboard'); - } catch (Exception $e) { - send_internal_notification('Waitlist cancellation failed: '.$e->getMessage()); - - return redirect()->route('dashboard'); - } - } -} diff --git a/app/Jobs/SendConfirmationForWaitlistJob.php b/app/Jobs/SendConfirmationForWaitlistJob.php deleted file mode 100755 index 7af8205fc..000000000 --- a/app/Jobs/SendConfirmationForWaitlistJob.php +++ /dev/null @@ -1,37 +0,0 @@ -email.'&confirmation_code='.$this->uuid; - $cancel_url = base_url().'/webhooks/waitlist/cancel?email='.$this->email.'&confirmation_code='.$this->uuid; - $mail->view('emails.waitlist-confirmation', - [ - 'confirmation_url' => $confirmation_url, - 'cancel_url' => $cancel_url, - ]); - $mail->subject('You are on the waitlist!'); - send_user_an_email($mail, $this->email); - } catch (\Throwable $e) { - send_internal_notification("SendConfirmationForWaitlistJob failed for {$this->email} with error: ".$e->getMessage()); - throw $e; - } - } -} diff --git a/app/Livewire/Waitlist/Index.php b/app/Livewire/Waitlist/Index.php deleted file mode 100644 index 0524b495c..000000000 --- a/app/Livewire/Waitlist/Index.php +++ /dev/null @@ -1,70 +0,0 @@ - 'required|email', - ]; - - public function render() - { - return view('livewire.waitlist.index')->layout('layouts.simple'); - } - - public function mount() - { - if (config('constants.waitlist.enabled') == false) { - return redirect()->route('register'); - } - $this->waitingInLine = Waitlist::whereVerified(true)->count(); - $this->users = User::count(); - if (isDev()) { - $this->email = 'waitlist@example.com'; - } - } - - public function submit() - { - $this->validate(); - try { - $already_registered = User::whereEmail($this->email)->first(); - if ($already_registered) { - throw new \Exception('You are already on the waitlist or registered.
Please check your email to verify your email address or contact support.'); - } - $found = Waitlist::where('email', $this->email)->first(); - if ($found) { - if (! $found->verified) { - $this->dispatch('error', 'You are already on the waitlist.
Please check your email to verify your email address.'); - - return; - } - $this->dispatch('error', 'You are already on the waitlist.
You will be notified when your turn comes.
Thank you.'); - - return; - } - $waitlist = Waitlist::create([ - 'email' => Str::lower($this->email), - 'type' => 'registration', - ]); - - $this->dispatch('success', 'Check your email to verify your email address.'); - dispatch(new SendConfirmationForWaitlistJob($this->email, $waitlist->uuid)); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } -} diff --git a/app/Models/Waitlist.php b/app/Models/Waitlist.php deleted file mode 100644 index 28e5f01fd..000000000 --- a/app/Models/Waitlist.php +++ /dev/null @@ -1,12 +0,0 @@ - [ - 'enabled' => env('WAITLIST', false), - 'expiration' => 10, - ], - 'sentry' => [ 'sentry_dsn' => env('SENTRY_DSN'), ], diff --git a/database/migrations/2024_12_09_105711_drop_waitlists_table.php b/database/migrations/2024_12_09_105711_drop_waitlists_table.php new file mode 100644 index 000000000..0e319369d --- /dev/null +++ b/database/migrations/2024_12_09_105711_drop_waitlists_table.php @@ -0,0 +1,31 @@ +id(); + $table->string('uuid'); + $table->string('type'); + $table->string('email')->unique(); + $table->boolean('verified')->default(false); + $table->timestamps(); + }); + } +}; diff --git a/resources/views/emails/waitlist-confirmation.blade.php b/resources/views/emails/waitlist-confirmation.blade.php deleted file mode 100644 index afd22916a..000000000 --- a/resources/views/emails/waitlist-confirmation.blade.php +++ /dev/null @@ -1,7 +0,0 @@ - -Someone added this email to the Coolify Cloud's waitlist. [Click here]({{ $confirmation_url }}) to confirm! - -The link will expire in {{ config('constants.waitlist.expiration') }} minutes. - -You have no idea what [Coolify Cloud](https://coolify.io) is or this waitlist? [Click here]({{ $cancel_url }}) to remove you from the waitlist. - diff --git a/resources/views/livewire/waitlist/index.blade.php b/resources/views/livewire/waitlist/index.blade.php deleted file mode 100644 index 548e722fc..000000000 --- a/resources/views/livewire/waitlist/index.blade.php +++ /dev/null @@ -1,37 +0,0 @@ -
-
- -
-

Self-hosting in the cloud - - - - - - -

-
-
- - Join Waitlist - -
People waiting in the line: {{ $waitingInLine }}
-
Already using Coolify Cloud: {{ $users }}
-
- This is a paid & hosted version of Coolify.
See the pricing here. -
-
- If you are looking for the self-hosted version go here. -
-
-
diff --git a/routes/webhooks.php b/routes/webhooks.php index ed5c2e233..d8d8e094a 100644 --- a/routes/webhooks.php +++ b/routes/webhooks.php @@ -5,7 +5,6 @@ use App\Http\Controllers\Webhook\Gitea; use App\Http\Controllers\Webhook\Github; use App\Http\Controllers\Webhook\Gitlab; use App\Http\Controllers\Webhook\Stripe; -use App\Http\Controllers\Webhook\Waitlist; use Illuminate\Support\Facades\Route; Route::get('/source/github/redirect', [Github::class, 'redirect']); @@ -20,6 +19,3 @@ Route::post('/source/bitbucket/events/manual', [Bitbucket::class, 'manual']); Route::post('/source/gitea/events/manual', [Gitea::class, 'manual']); Route::post('/payments/stripe/events', [Stripe::class, 'events']); - -Route::get('/waitlist/confirm', [Waitlist::class, 'confirm'])->name('webhooks.waitlist.confirm'); -Route::get('/waitlist/cancel', [Waitlist::class, 'cancel'])->name('webhooks.waitlist.cancel'); From 27b880e177ecd36b8443cfb42ebbe47b4f70795b Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:01:23 +0100 Subject: [PATCH 14/80] chore: remove wired.php (not used anymore) --- app/Console/Commands/Weird.php | 58 ---------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 app/Console/Commands/Weird.php diff --git a/app/Console/Commands/Weird.php b/app/Console/Commands/Weird.php deleted file mode 100644 index e471a5f96..000000000 --- a/app/Console/Commands/Weird.php +++ /dev/null @@ -1,58 +0,0 @@ -error('This command can only be run in development mode'); - - return; - } - $run = $this->option('run'); - if ($run) { - $servers = Server::all(); - foreach ($servers as $server) { - ServerCheck::dispatch($server); - } - - return; - } - $number = $this->option('number'); - for ($i = 0; $i < $number; $i++) { - $uuid = Str::uuid(); - $server = Server::create([ - 'name' => 'localhost-'.$uuid, - 'description' => 'This is a test docker container in development mode', - 'ip' => 'coolify-testing-host', - 'team_id' => 0, - 'private_key_id' => 1, - 'proxy' => [ - 'type' => ProxyTypes::NONE->value, - 'status' => ProxyStatus::EXITED->value, - ], - ]); - $server->settings->update([ - 'is_usable' => true, - 'is_reachable' => true, - ]); - } - } catch (\Exception $e) { - $this->error($e->getMessage()); - } - } -} From 6438c080963acc77e93c6c4cd8369df87313a008 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:02:08 +0100 Subject: [PATCH 15/80] chore: remove unused resale license job --- app/Jobs/CheckResaleLicenseJob.php | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 app/Jobs/CheckResaleLicenseJob.php diff --git a/app/Jobs/CheckResaleLicenseJob.php b/app/Jobs/CheckResaleLicenseJob.php deleted file mode 100644 index 7479867b6..000000000 --- a/app/Jobs/CheckResaleLicenseJob.php +++ /dev/null @@ -1,28 +0,0 @@ -getMessage()); - throw $e; - } - } -} From 9ed2e37236f9ffc769746d0cb52c9ca2b124ef6d Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:03:04 +0100 Subject: [PATCH 16/80] chore: remove commented out internal notification --- app/Console/Commands/CleanupUnreachableServers.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Console/Commands/CleanupUnreachableServers.php b/app/Console/Commands/CleanupUnreachableServers.php index df0c6b81b..def01b265 100644 --- a/app/Console/Commands/CleanupUnreachableServers.php +++ b/app/Console/Commands/CleanupUnreachableServers.php @@ -18,7 +18,6 @@ class CleanupUnreachableServers extends Command if ($servers->count() > 0) { foreach ($servers as $server) { echo "Cleanup unreachable server ($server->id) with name $server->name"; - // send_internal_notification("Server $server->name is unreachable for 7 days. Cleaning up..."); $server->update([ 'ip' => '1.2.3.4', ]); From fd21a4a2a8a072932ebb82610bc5e7ae26c09ae6 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:03:23 +0100 Subject: [PATCH 17/80] chore: remove more waitlist stuff --- app/Console/Commands/Emails.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/Console/Commands/Emails.php b/app/Console/Commands/Emails.php index f0e0e7fa0..79eca1d84 100644 --- a/app/Console/Commands/Emails.php +++ b/app/Console/Commands/Emails.php @@ -2,14 +2,12 @@ namespace App\Console\Commands; -use App\Jobs\SendConfirmationForWaitlistJob; use App\Models\Application; use App\Models\ApplicationPreview; use App\Models\ScheduledDatabaseBackup; use App\Models\Server; use App\Models\StandalonePostgresql; use App\Models\Team; -use App\Models\Waitlist; use App\Notifications\Application\DeploymentFailed; use App\Notifications\Application\DeploymentSuccess; use App\Notifications\Application\StatusChanged; @@ -64,8 +62,6 @@ class Emails extends Command 'backup-success' => 'Database - Backup Success', 'backup-failed' => 'Database - Backup Failed', // 'invitation-link' => 'Invitation Link', - 'waitlist-invitation-link' => 'Waitlist Invitation Link', - 'waitlist-confirmation' => 'Waitlist Confirmation', 'realusers-before-trial' => 'REAL - Registered Users Before Trial without Subscription', 'realusers-server-lost-connection' => 'REAL - Server Lost Connection', ], @@ -187,7 +183,7 @@ class Emails extends Command 'team_id' => 0, ]); } - // $this->mail = (new BackupSuccess($backup->frequency, $db->name))->toMail(); + //$this->mail = (new BackupSuccess($backup->frequency, $db->name))->toMail(); $this->sendEmail(); break; // case 'invitation-link': From 5515f07f14915b8cadab824cee748aa32504e57e Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:05:18 +0100 Subject: [PATCH 18/80] chore: remove commented out notification --- app/Http/Controllers/Controller.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 9f1e4eeb8..f70f29dc2 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -44,7 +44,6 @@ class Controller extends BaseController $request->fulfill(); $name = request()->user()?->name; - // send_internal_notification("User {$name} verified their email address."); return redirect(RouteServiceProvider::HOME); } From 2da4e9a274d7d19c0de24049eb3af9fbb3bc16b7 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:08:27 +0100 Subject: [PATCH 19/80] feat: enable success messages again --- app/Jobs/ApplicationDeploymentJob.php | 2 +- app/Jobs/DatabaseBackupJob.php | 4 +++- app/Models/Server.php | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 04e71c4e3..6b677fa0e 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -2409,7 +2409,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); if (! $this->only_this_server) { $this->deploy_to_additional_destinations(); } - //$this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview)); + $this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview)); } } diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index ee702202f..06aec5e49 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -306,7 +306,9 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue if ($this->backup->save_s3) { $this->upload_to_s3(); } - //$this->team?->notify(new BackupSuccess($this->backup, $this->database, $database)); + + $this->team->notify(new BackupSuccess($this->backup, $this->database, $database)); + $this->backup_log->update([ 'status' => 'success', 'message' => $this->backup_output, diff --git a/app/Models/Server.php b/app/Models/Server.php index 6dfb0a4a1..cc8211789 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -1042,7 +1042,7 @@ $schema://$host { $this->unreachable_notification_sent = false; $this->save(); $this->refresh(); - // $this->team->notify(new Reachable($this)); + $this->team->notify(new Reachable($this)); } public function sendUnreachableNotification() @@ -1050,7 +1050,7 @@ $schema://$host { $this->unreachable_notification_sent = true; $this->save(); $this->refresh(); - // $this->team->notify(new Unreachable($this)); + $this->team->notify(new Unreachable($this)); } public function validateConnection(bool $justCheckingNewKey = false) From bd36149f09b7bc916e0dc27afb623b8f697013d6 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:33:27 +0100 Subject: [PATCH 20/80] feat: use new notification stuff inside team model - Use new notification relationships - Use trait - Make sure that when a new team is created, notification settings are also created - reorder team model for better readability --- app/Models/Team.php | 177 ++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 96 deletions(-) diff --git a/app/Models/Team.php b/app/Models/Team.php index 29c469b3b..07424a55f 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -5,6 +5,7 @@ namespace App\Models; use App\Notifications\Channels\SendsDiscord; use App\Notifications\Channels\SendsEmail; use App\Notifications\Channels\SendsSlack; +use App\Traits\HasNotificationSettings; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; use Illuminate\Notifications\Notifiable; @@ -20,49 +21,8 @@ use OpenApi\Attributes as OA; 'personal_team' => ['type' => 'boolean', 'description' => 'Whether the team is personal or not.'], 'created_at' => ['type' => 'string', 'description' => 'The date and time the team was created.'], 'updated_at' => ['type' => 'string', 'description' => 'The date and time the team was last updated.'], - 'smtp_enabled' => ['type' => 'boolean', 'description' => 'Whether SMTP is enabled or not.'], - 'smtp_from_address' => ['type' => 'string', 'description' => 'The email address to send emails from.'], - 'smtp_from_name' => ['type' => 'string', 'description' => 'The name to send emails from.'], - 'smtp_recipients' => ['type' => 'string', 'description' => 'The email addresses to send emails to.'], - 'smtp_host' => ['type' => 'string', 'description' => 'The SMTP host.'], - 'smtp_port' => ['type' => 'string', 'description' => 'The SMTP port.'], - 'smtp_encryption' => ['type' => 'string', 'description' => 'The SMTP encryption.'], - 'smtp_username' => ['type' => 'string', 'description' => 'The SMTP username.'], - 'smtp_password' => ['type' => 'string', 'description' => 'The SMTP password.'], - 'smtp_timeout' => ['type' => 'string', 'description' => 'The SMTP timeout.'], - 'smtp_notifications_test' => ['type' => 'boolean', 'description' => 'Whether to send test notifications via SMTP.'], - 'smtp_notifications_deployments' => ['type' => 'boolean', 'description' => 'Whether to send deployment notifications via SMTP.'], - 'smtp_notifications_status_changes' => ['type' => 'boolean', 'description' => 'Whether to send status change notifications via SMTP.'], - 'smtp_notifications_scheduled_tasks' => ['type' => 'boolean', 'description' => 'Whether to send scheduled task notifications via SMTP.'], - 'smtp_notifications_database_backups' => ['type' => 'boolean', 'description' => 'Whether to send database backup notifications via SMTP.'], - 'smtp_notifications_server_disk_usage' => ['type' => 'boolean', 'description' => 'Whether to send server disk usage notifications via SMTP.'], - 'discord_enabled' => ['type' => 'boolean', 'description' => 'Whether Discord is enabled or not.'], - 'discord_webhook_url' => ['type' => 'string', 'description' => 'The Discord webhook URL.'], - 'discord_notifications_test' => ['type' => 'boolean', 'description' => 'Whether to send test notifications via Discord.'], - 'discord_notifications_deployments' => ['type' => 'boolean', 'description' => 'Whether to send deployment notifications via Discord.'], - 'discord_notifications_status_changes' => ['type' => 'boolean', 'description' => 'Whether to send status change notifications via Discord.'], - 'discord_notifications_database_backups' => ['type' => 'boolean', 'description' => 'Whether to send database backup notifications via Discord.'], - 'discord_notifications_scheduled_tasks' => ['type' => 'boolean', 'description' => 'Whether to send scheduled task notifications via Discord.'], - 'discord_notifications_server_disk_usage' => ['type' => 'boolean', 'description' => 'Whether to send server disk usage notifications via Discord.'], 'show_boarding' => ['type' => 'boolean', 'description' => 'Whether to show the boarding screen or not.'], - 'resend_enabled' => ['type' => 'boolean', 'description' => 'Whether to enable resending or not.'], - 'resend_api_key' => ['type' => 'string', 'description' => 'The resending API key.'], - 'use_instance_email_settings' => ['type' => 'boolean', 'description' => 'Whether to use instance email settings or not.'], - 'telegram_enabled' => ['type' => 'boolean', 'description' => 'Whether Telegram is enabled or not.'], - 'telegram_token' => ['type' => 'string', 'description' => 'The Telegram token.'], - 'telegram_chat_id' => ['type' => 'string', 'description' => 'The Telegram chat ID.'], - 'telegram_notifications_test' => ['type' => 'boolean', 'description' => 'Whether to send test notifications via Telegram.'], - 'telegram_notifications_deployments' => ['type' => 'boolean', 'description' => 'Whether to send deployment notifications via Telegram.'], - 'telegram_notifications_status_changes' => ['type' => 'boolean', 'description' => 'Whether to send status change notifications via Telegram.'], - 'telegram_notifications_database_backups' => ['type' => 'boolean', 'description' => 'Whether to send database backup notifications via Telegram.'], - 'telegram_notifications_test_message_thread_id' => ['type' => 'string', 'description' => 'The Telegram test message thread ID.'], - 'telegram_notifications_deployments_message_thread_id' => ['type' => 'string', 'description' => 'The Telegram deployment message thread ID.'], - 'telegram_notifications_status_changes_message_thread_id' => ['type' => 'string', 'description' => 'The Telegram status change message thread ID.'], - 'telegram_notifications_database_backups_message_thread_id' => ['type' => 'string', 'description' => 'The Telegram database backup message thread ID.'], - 'custom_server_limit' => ['type' => 'string', 'description' => 'The custom server limit.'], - 'telegram_notifications_scheduled_tasks' => ['type' => 'boolean', 'description' => 'Whether to send scheduled task notifications via Telegram.'], - 'telegram_notifications_scheduled_tasks_thread_id' => ['type' => 'string', 'description' => 'The Telegram scheduled task message thread ID.'], 'members' => new OA\Property( property: 'members', type: 'array', @@ -71,20 +31,26 @@ use OpenApi\Attributes as OA; ), ] )] + class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack { - use Notifiable; + use HasNotificationSettings, Notifiable; protected $guarded = []; protected $casts = [ 'personal_team' => 'boolean', - 'smtp_password' => 'encrypted', - 'resend_api_key' => 'encrypted', ]; protected static function booted() { + static::created(function ($team) { + $team->emailNotificationSettings()->create(); + $team->discordNotificationSettings()->create(); + $team->slackNotificationSettings()->create(); + $team->telegramNotificationSettings()->create(); + }); + static::saving(function ($team) { if (auth()->user()?->isMember()) { throw new \Exception('You are not allowed to update this team.'); @@ -115,34 +81,6 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack }); } - public function routeNotificationForDiscord() - { - return data_get($this, 'discord_webhook_url', null); - } - - public function routeNotificationForTelegram() - { - return [ - 'token' => data_get($this, 'telegram_token', null), - 'chat_id' => data_get($this, 'telegram_chat_id', null), - ]; - } - - public function routeNotificationForSlack() - { - return data_get($this, 'slack_webhook_url', null); - } - - public function getRecepients($notification) - { - $recipients = data_get($notification, 'emails', null); - if (is_null($recipients)) { - return $this->members()->pluck('email')->toArray(); - } - - return explode(',', $recipients); - } - public static function serverLimitReached() { $serverLimit = Team::serverLimit(); @@ -167,7 +105,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack return 9999999; } $team = Team::find(currentTeam()->id); - if (!$team) { + if (! $team) { return 0; } @@ -196,10 +134,66 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack return $serverLimit ?? 2; } - ); } + public function routeNotificationForDiscord() + { + return data_get($this, 'discord_webhook_url', null); + } + + public function routeNotificationForTelegram() + { + return [ + 'token' => data_get($this, 'telegram_token', null), + 'chat_id' => data_get($this, 'telegram_chat_id', null), + ]; + } + + public function routeNotificationForSlack() + { + return data_get($this, 'slack_webhook_url', null); + } + + public function getRecipients($notification) + { + $recipients = data_get($notification, 'emails', null); + if (is_null($recipients)) { + return $this->members()->pluck('email')->toArray(); + } + + return explode(',', $recipients); + } + + public function isAnyNotificationEnabled() + { + if (isCloud()) { + return true; + } + + return $this->getNotificationSettings('email')?->isEnabled() || + $this->getNotificationSettings('discord')?->isEnabled() || + $this->getNotificationSettings('slack')?->isEnabled() || + $this->getNotificationSettings('telegram')?->isEnabled(); + } + + public function subscriptionEnded() + { + $this->subscription->update([ + 'stripe_subscription_id' => null, + 'stripe_plan_id' => null, + 'stripe_cancel_at_period_end' => false, + 'stripe_invoice_paid' => false, + 'stripe_trial_already_ended' => false, + ]); + foreach ($this->servers as $server) { + $server->settings()->update([ + 'is_usable' => false, + 'is_reachable' => false, + ]); + } + } + public function environment_variables() { return $this->hasMany(SharedEnvironmentVariable::class)->whereNull('project_id')->whereNull('environment_id'); @@ -263,32 +257,23 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack return $this->hasMany(S3Storage::class)->where('is_usable', true); } - public function subscriptionEnded() + public function emailNotificationSettings() { - $this->subscription->update([ - 'stripe_subscription_id' => null, - 'stripe_plan_id' => null, - 'stripe_cancel_at_period_end' => false, - 'stripe_invoice_paid' => false, - 'stripe_trial_already_ended' => false, - ]); - foreach ($this->servers as $server) { - $server->settings()->update([ - 'is_usable' => false, - 'is_reachable' => false, - ]); - } + return $this->hasOne(EmailNotificationSettings::class); } - public function isAnyNotificationEnabled() + public function discordNotificationSettings() { - if (isCloud()) { - return true; - } - if ($this->smtp_enabled || $this->resend_enabled || $this->discord_enabled || $this->telegram_enabled || $this->use_instance_email_settings) { - return true; - } + return $this->hasOne(DiscordNotificationSettings::class); + } - return false; + public function telegramNotificationSettings() + { + return $this->hasOne(TelegramNotificationSettings::class); + } + + public function slackNotificationSettings() + { + return $this->hasOne(SlackNotificationSettings::class); } } From e40f3778793c9fa74deca70705ba2b7f9081503a Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:34:16 +0100 Subject: [PATCH 21/80] chore: remove more waitlist stuff --- app/Console/Commands/Emails.php | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/app/Console/Commands/Emails.php b/app/Console/Commands/Emails.php index 79eca1d84..33ddf3019 100644 --- a/app/Console/Commands/Emails.php +++ b/app/Console/Commands/Emails.php @@ -200,23 +200,6 @@ class Emails extends Command // $this->mail = (new InvitationLink($user))->toMail(); // $this->sendEmail(); // break; - case 'waitlist-invitation-link': - $this->mail = new MailMessage; - $this->mail->view('emails.waitlist-invitation', [ - 'loginLink' => 'https://coolify.io', - ]); - $this->mail->subject('Congratulations! You are invited to join Coolify Cloud.'); - $this->sendEmail(); - break; - case 'waitlist-confirmation': - $found = Waitlist::where('email', $this->email)->first(); - if ($found) { - SendConfirmationForWaitlistJob::dispatch($this->email, $found->uuid); - } else { - throw new Exception('Waitlist not found'); - } - - break; case 'realusers-before-trial': $this->mail = new MailMessage; $this->mail->view('emails.before-trial-conversion'); From c995819ed3268ea8c8415e31c8a3cca754b3dd3f Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:34:45 +0100 Subject: [PATCH 22/80] chore: remove unused code --- app/Http/Controllers/Controller.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index f70f29dc2..2de2c79f6 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -42,7 +42,6 @@ class Controller extends BaseController public function email_verify(EmailVerificationRequest $request) { $request->fulfill(); - $name = request()->user()?->name; return redirect(RouteServiceProvider::HOME); } From 4428b95a65c8dc65d42cbfce11e440d5bac271f6 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:36:33 +0100 Subject: [PATCH 23/80] chore: fix typo --- app/Models/InstanceSettings.php | 2 +- app/Models/User.php | 2 +- app/Notifications/Channels/SendsEmail.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Models/InstanceSettings.php b/app/Models/InstanceSettings.php index eeb803925..45ccece1f 100644 --- a/app/Models/InstanceSettings.php +++ b/app/Models/InstanceSettings.php @@ -81,7 +81,7 @@ class InstanceSettings extends Model implements SendsEmail return InstanceSettings::findOrFail(0); } - public function getRecepients($notification) + public function getRecipients($notification) { $recipients = data_get($notification, 'emails', null); if (is_null($recipients) || $recipients === '') { diff --git a/app/Models/User.php b/app/Models/User.php index 25fb33d66..7c23631c3 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -114,7 +114,7 @@ class User extends Authenticatable implements SendsEmail return $this->belongsToMany(Team::class)->withPivot('role'); } - public function getRecepients($notification) + public function getRecipients($notification) { return $this->email; } diff --git a/app/Notifications/Channels/SendsEmail.php b/app/Notifications/Channels/SendsEmail.php index fc7528834..3adc6d0a2 100644 --- a/app/Notifications/Channels/SendsEmail.php +++ b/app/Notifications/Channels/SendsEmail.php @@ -4,5 +4,5 @@ namespace App\Notifications\Channels; interface SendsEmail { - public function getRecepients($notification); + public function getRecipients($notification); } From 060c8262bc477dc9d1cdbcb8638f70695f6cf02a Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:48:54 +0100 Subject: [PATCH 24/80] chore: remove comment out code --- app/Jobs/ScheduledTaskJob.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php index 00575e187..4c20a4382 100644 --- a/app/Jobs/ScheduledTaskJob.php +++ b/app/Jobs/ScheduledTaskJob.php @@ -125,7 +125,6 @@ class ScheduledTaskJob implements ShouldQueue ]); } $this->team?->notify(new TaskFailed($this->task, $e->getMessage())); - // send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage()); throw $e; } finally { ScheduledTaskDone::dispatch($this->team->id); From 0c08e11b53d2e4d8a230a3619ad160b7df4364a7 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:11:12 +0100 Subject: [PATCH 25/80] feat: some more notification settings and better defaults - add reachable and unreachable notifications - add docker cleanup notifications - better defaults --- ...212355_create_email_notification_settings_table.php | 5 ++++- ...2416_create_discord_notification_settings_table.php | 5 ++++- ...440_create_telegram_notification_settings_table.php | 10 ++++++++-- ...te_email_notification_settings_from_teams_table.php | 8 ++++---- ..._discord_notification_settings_from_teams_table.php | 6 +++--- ...telegram_notification_settings_from_teams_table.php | 6 +++--- ...142014_create_slack_notification_settings_table.php | 5 ++++- 7 files changed, 30 insertions(+), 15 deletions(-) diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php index 525168ec0..50413f3b6 100644 --- a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -33,12 +33,15 @@ return new class extends Migration $table->boolean('deployment_success_email_notifications')->default(false); $table->boolean('deployment_failure_email_notifications')->default(true); + $table->boolean('status_change_email_notifications')->default(false); $table->boolean('backup_success_email_notifications')->default(false); $table->boolean('backup_failure_email_notifications')->default(true); $table->boolean('scheduled_task_success_email_notifications')->default(false); $table->boolean('scheduled_task_failure_email_notifications')->default(true); - $table->boolean('status_change_email_notifications')->default(false); + $table->boolean('docker_cleanup_email_notifications')->default(false); $table->boolean('server_disk_usage_email_notifications')->default(true); + $table->boolean('server_reachable_email_notifications')->default(false); + $table->boolean('server_unreachable_email_notifications')->default(true); $table->unique(['team_id']); }); diff --git a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php index 6989444bb..271f33ac6 100644 --- a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php +++ b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php @@ -20,12 +20,15 @@ return new class extends Migration $table->boolean('deployment_success_discord_notifications')->default(false); $table->boolean('deployment_failure_discord_notifications')->default(true); + $table->boolean('status_change_discord_notifications')->default(false); $table->boolean('backup_success_discord_notifications')->default(false); $table->boolean('backup_failure_discord_notifications')->default(true); $table->boolean('scheduled_task_success_discord_notifications')->default(false); $table->boolean('scheduled_task_failure_discord_notifications')->default(true); - $table->boolean('status_change_discord_notifications')->default(false); + $table->boolean('docker_cleanup_discord_notifications')->default(false); $table->boolean('server_disk_usage_discord_notifications')->default(true); + $table->boolean('server_reachable_discord_notifications')->default(false); + $table->boolean('server_unreachable_discord_notifications')->default(true); $table->unique(['team_id']); }); 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 a85794636..be0764a71 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 @@ -21,21 +21,27 @@ return new class extends Migration $table->boolean('deployment_success_telegram_notifications')->default(false); $table->boolean('deployment_failure_telegram_notifications')->default(true); + $table->boolean('status_change_telegram_notifications')->default(false); $table->boolean('backup_success_telegram_notifications')->default(false); $table->boolean('backup_failure_telegram_notifications')->default(true); $table->boolean('scheduled_task_success_telegram_notifications')->default(false); $table->boolean('scheduled_task_failure_telegram_notifications')->default(true); - $table->boolean('status_change_telegram_notifications')->default(false); + $table->boolean('docker_cleanup_telegram_notifications')->default(false); $table->boolean('server_disk_usage_telegram_notifications')->default(true); + $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_status_change_topic_id')->nullable(); + $table->text('telegram_notifications_docker_cleanup_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->unique(['team_id']); }); diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index d835ec2ed..dce7f13a8 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -28,13 +28,13 @@ return new class extends Migration 'resend_enabled' => $team->resend_enabled ?? false, 'resend_api_key' => $team->resend_api_key, 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, - 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? false, + 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, - 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? false, + 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, - 'server_disk_usage_email_notifications' => true, + 'server_disk_usage_email_notifications' => $team->smtp_notifications_server_disk_usage ?? true, ]); } diff --git a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php index 72d56ac08..6a738dd22 100644 --- a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php @@ -20,11 +20,11 @@ return new class extends Migration 'discord_enabled' => $team->discord_enabled ?? false, 'discord_webhook_url' => $team->discord_webhook_url, 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, - 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? false, + 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, - 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? false, + 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, ]); 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 82e928649..b706ac544 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 @@ -19,11 +19,11 @@ return new class extends Migration 'telegram_chat_id' => $team->telegram_chat_id, 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, - 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? false, + 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, - 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, + 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, 'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false, 'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true, 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 6eb988619..fcc4dc8ce 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 @@ -20,12 +20,15 @@ return new class extends Migration $table->boolean('deployment_success_slack_notifications')->default(false); $table->boolean('deployment_failure_slack_notifications')->default(true); + $table->boolean('status_change_slack_notifications')->default(false); $table->boolean('backup_success_slack_notifications')->default(false); $table->boolean('backup_failure_slack_notifications')->default(true); $table->boolean('scheduled_task_success_slack_notifications')->default(false); $table->boolean('scheduled_task_failure_slack_notifications')->default(true); - $table->boolean('status_change_slack_notifications')->default(false); + $table->boolean('docker_cleanup_slack_notifications')->default(false); $table->boolean('server_disk_usage_slack_notifications')->default(true); + $table->boolean('server_reachable_slack_notifications')->default(false); + $table->boolean('server_unreachable_slack_notifications')->default(true); $table->unique(['team_id']); }); From 586a1a86f038aa665faedbc51f5ef0d97e85ca4b Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:27:58 +0100 Subject: [PATCH 26/80] chore: some reordering --- ..._12_05_212355_create_email_notification_settings_table.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php index 50413f3b6..6d564e331 100644 --- a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -26,11 +26,11 @@ return new class extends Migration $table->text('smtp_password')->nullable(); $table->integer('smtp_timeout')->nullable(); - $table->boolean('use_instance_email_settings')->default(false); - $table->boolean('resend_enabled')->default(false); $table->text('resend_api_key')->nullable(); + $table->boolean('use_instance_email_settings')->default(false); + $table->boolean('deployment_success_email_notifications')->default(false); $table->boolean('deployment_failure_email_notifications')->default(true); $table->boolean('status_change_email_notifications')->default(false); From a6086ee38ba8a86b08e95dd7dbf44521e3ad8ac9 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:56:52 +0100 Subject: [PATCH 27/80] feat: New email notification settings --- app/Livewire/Notifications/Email.php | 256 +++++++++++++----- .../livewire/notifications/email.blade.php | 121 +++++---- 2 files changed, 262 insertions(+), 115 deletions(-) diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index ab3768643..d81535a80 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -19,9 +19,6 @@ class Email extends Component #[Validate(['boolean'])] public bool $smtpEnabled = false; - #[Validate(['boolean'])] - public bool $useInstanceEmailSettings = false; - #[Validate(['nullable', 'email'])] public ?string $smtpFromAddress = null; @@ -50,29 +47,47 @@ class Email extends Component public ?int $smtpTimeout = null; #[Validate(['boolean'])] - public bool $smtpNotificationsTest = false; - - #[Validate(['boolean'])] - public bool $smtpNotificationsDeployments = false; - - #[Validate(['boolean'])] - public bool $smtpNotificationsStatusChanges = false; - - #[Validate(['boolean'])] - public bool $smtpNotificationsDatabaseBackups = false; - - #[Validate(['boolean'])] - public bool $smtpNotificationsScheduledTasks = false; - - #[Validate(['boolean'])] - public bool $smtpNotificationsServerDiskUsage = false; - - #[Validate(['boolean'])] - public bool $resendEnabled; + public bool $resendEnabled = false; #[Validate(['nullable', 'string'])] public ?string $resendApiKey = null; + #[Validate(['boolean'])] + public bool $useInstanceEmailSettings = false; + + #[Validate(['boolean'])] + public bool $deploymentSuccessEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $deploymentFailureEmailNotifications = true; + + #[Validate(['boolean'])] + public bool $statusChangeEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $backupSuccessEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $backupFailureEmailNotifications = true; + + #[Validate(['boolean'])] + public bool $scheduledTaskSuccessEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $scheduledTaskFailureEmailNotifications = true; + + #[Validate(['boolean'])] + public bool $dockerCleanupEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $serverDiskUsageEmailNotifications = true; + + #[Validate(['boolean'])] + public bool $serverReachableEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $serverUnreachableEmailNotifications = true; + #[Validate(['nullable', 'email'])] public ?string $testEmailAddress = null; @@ -91,47 +106,67 @@ class Email extends Component { if ($toModel) { $this->validate(); - $this->team->smtp_enabled = $this->smtpEnabled; - $this->team->smtp_from_address = $this->smtpFromAddress; - $this->team->smtp_from_name = $this->smtpFromName; - $this->team->smtp_host = $this->smtpHost; - $this->team->smtp_port = $this->smtpPort; - $this->team->smtp_encryption = $this->smtpEncryption; - $this->team->smtp_username = $this->smtpUsername; - $this->team->smtp_password = $this->smtpPassword; - $this->team->smtp_timeout = $this->smtpTimeout; - $this->team->smtp_recipients = $this->smtpRecipients; - $this->team->smtp_notifications_test = $this->smtpNotificationsTest; - $this->team->smtp_notifications_deployments = $this->smtpNotificationsDeployments; - $this->team->smtp_notifications_status_changes = $this->smtpNotificationsStatusChanges; - $this->team->smtp_notifications_database_backups = $this->smtpNotificationsDatabaseBackups; - $this->team->smtp_notifications_scheduled_tasks = $this->smtpNotificationsScheduledTasks; - $this->team->smtp_notifications_server_disk_usage = $this->smtpNotificationsServerDiskUsage; - $this->team->use_instance_email_settings = $this->useInstanceEmailSettings; - $this->team->resend_enabled = $this->resendEnabled; - $this->team->resend_api_key = $this->resendApiKey; - $this->team->save(); + $settings = $this->team->emailNotificationSettings; + $settings->smtp_enabled = $this->smtpEnabled; + $settings->smtp_from_address = $this->smtpFromAddress; + $settings->smtp_from_name = $this->smtpFromName; + $settings->smtp_recipients = $this->smtpRecipients; + $settings->smtp_host = $this->smtpHost; + $settings->smtp_port = $this->smtpPort; + $settings->smtp_encryption = $this->smtpEncryption; + $settings->smtp_username = $this->smtpUsername; + $settings->smtp_password = $this->smtpPassword; + $settings->smtp_timeout = $this->smtpTimeout; + + $settings->resend_enabled = $this->resendEnabled; + $settings->resend_api_key = $this->resendApiKey; + + $settings->use_instance_email_settings = $this->useInstanceEmailSettings; + + $settings->deployment_success_email_notifications = $this->deploymentSuccessEmailNotifications; + $settings->deployment_failure_email_notifications = $this->deploymentFailureEmailNotifications; + $settings->status_change_email_notifications = $this->statusChangeEmailNotifications; + $settings->backup_success_email_notifications = $this->backupSuccessEmailNotifications; + $settings->backup_failure_email_notifications = $this->backupFailureEmailNotifications; + $settings->scheduled_task_success_email_notifications = $this->scheduledTaskSuccessEmailNotifications; + $settings->scheduled_task_failure_email_notifications = $this->scheduledTaskFailureEmailNotifications; + $settings->docker_cleanup_email_notifications = $this->dockerCleanupEmailNotifications; + $settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; + $settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; + $settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; + + $settings->save(); refreshSession(); } else { - $this->smtpEnabled = $this->team->smtp_enabled; - $this->smtpFromAddress = $this->team->smtp_from_address; - $this->smtpFromName = $this->team->smtp_from_name; - $this->smtpHost = $this->team->smtp_host; - $this->smtpPort = $this->team->smtp_port; - $this->smtpEncryption = $this->team->smtp_encryption; - $this->smtpUsername = $this->team->smtp_username; - $this->smtpPassword = $this->team->smtp_password; - $this->smtpTimeout = $this->team->smtp_timeout; - $this->smtpRecipients = $this->team->smtp_recipients; - $this->smtpNotificationsTest = $this->team->smtp_notifications_test; - $this->smtpNotificationsDeployments = $this->team->smtp_notifications_deployments; - $this->smtpNotificationsStatusChanges = $this->team->smtp_notifications_status_changes; - $this->smtpNotificationsDatabaseBackups = $this->team->smtp_notifications_database_backups; - $this->smtpNotificationsScheduledTasks = $this->team->smtp_notifications_scheduled_tasks; - $this->smtpNotificationsServerDiskUsage = $this->team->smtp_notifications_server_disk_usage; - $this->useInstanceEmailSettings = $this->team->use_instance_email_settings; - $this->resendEnabled = $this->team->resend_enabled; - $this->resendApiKey = $this->team->resend_api_key; + $settings = $this->team->emailNotificationSettings; + + $this->smtpEnabled = $settings->smtp_enabled; + $this->smtpFromAddress = $settings->smtp_from_address; + $this->smtpFromName = $settings->smtp_from_name; + $this->smtpRecipients = $settings->smtp_recipients; + $this->smtpHost = $settings->smtp_host; + $this->smtpPort = $settings->smtp_port; + $this->smtpEncryption = $settings->smtp_encryption; + $this->smtpUsername = $settings->smtp_username; + $this->smtpPassword = $settings->smtp_password; + $this->smtpTimeout = $settings->smtp_timeout; + + $this->resendEnabled = $settings->resend_enabled; + $this->resendApiKey = $settings->resend_api_key; + + $this->useInstanceEmailSettings = $settings->use_instance_email_settings; + + $this->deploymentSuccessEmailNotifications = $settings->deployment_success_email_notifications; + $this->deploymentFailureEmailNotifications = $settings->deployment_failure_email_notifications; + $this->statusChangeEmailNotifications = $settings->status_change_email_notifications; + $this->backupSuccessEmailNotifications = $settings->backup_success_email_notifications; + $this->backupFailureEmailNotifications = $settings->backup_failure_email_notifications; + $this->scheduledTaskSuccessEmailNotifications = $settings->scheduled_task_success_email_notifications; + $this->scheduledTaskFailureEmailNotifications = $settings->scheduled_task_failure_email_notifications; + $this->dockerCleanupEmailNotifications = $settings->docker_cleanup_email_notifications; + $this->serverDiskUsageEmailNotifications = $settings->server_disk_usage_email_notifications; + $this->serverReachableEmailNotifications = $settings->server_reachable_email_notifications; + $this->serverUnreachableEmailNotifications = $settings->server_unreachable_email_notifications; } } @@ -178,13 +213,26 @@ class Email extends Component { try { $this->validate([ - 'smtpHost' => 'required', + 'smtpEnabled' => 'boolean', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + 'smtpHost' => 'required|string', 'smtpPort' => 'required|numeric', + 'smtpEncryption' => 'required|string|in:tls,ssl,none', + 'smtpUsername' => 'nullable|string', + 'smtpPassword' => 'nullable|string', + 'smtpTimeout' => 'nullable|numeric', ], [ + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', 'smtpHost.required' => 'SMTP Host is required.', 'smtpPort.required' => 'SMTP Port is required.', + 'smtpPort.numeric' => 'SMTP Port must be a number.', + 'smtpEncryption.required' => 'Encryption type is required.', ]); $this->resendEnabled = false; + $this->useInstanceEmailSettings = false; $this->saveModel(); } catch (\Throwable $e) { $this->smtpEnabled = false; @@ -197,11 +245,18 @@ class Email extends Component { try { $this->validate([ - 'resendApiKey' => 'required', + 'resendEnabled' => 'boolean', + 'resendApiKey' => 'required|string', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', ], [ 'resendApiKey.required' => 'Resend API Key is required.', + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', ]); $this->smtpEnabled = false; + $this->useInstanceEmailSettings = false; $this->saveModel(); } catch (\Throwable $e) { $this->resendEnabled = false; @@ -258,6 +313,81 @@ class Email extends Component $this->dispatch('error', 'Instance SMTP/Resend settings are not enabled.'); } + public function submitSmtp() + { + try { + $this->resetErrorBag(); + $this->validate([ + 'smtpEnabled' => 'boolean', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + 'smtpHost' => 'required|string', + 'smtpPort' => 'required|numeric', + 'smtpEncryption' => 'required|string|in:tls,ssl,none', + 'smtpUsername' => 'nullable|string', + 'smtpPassword' => 'nullable|string', + 'smtpTimeout' => 'nullable|numeric', + ], [ + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + 'smtpHost.required' => 'SMTP Host is required.', + 'smtpPort.required' => 'SMTP Port is required.', + 'smtpPort.numeric' => 'SMTP Port must be a number.', + 'smtpEncryption.required' => 'Encryption type is required.', + ]); + + $settings = $this->team->emailNotificationSettings; + + $settings->smtp_enabled = $this->smtpEnabled; + $settings->smtp_from_address = $this->smtpFromAddress; + $settings->smtp_from_name = $this->smtpFromName; + $settings->smtp_host = $this->smtpHost; + $settings->smtp_port = $this->smtpPort; + $settings->smtp_encryption = $this->smtpEncryption; + $settings->smtp_username = $this->smtpUsername; + $settings->smtp_password = $this->smtpPassword; + $settings->smtp_timeout = $this->smtpTimeout; + + $settings->save(); + refreshSession(); + $this->dispatch('success', 'SMTP settings saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function submitResend() + { + try { + $this->resetErrorBag(); + $this->validate([ + 'resendEnabled' => 'boolean', + 'resendApiKey' => 'required|string', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + ], [ + 'resendApiKey.required' => 'Resend API Key is required.', + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + ]); + + $settings = $this->team->emailNotificationSettings; + + $settings->resend_enabled = $this->resendEnabled; + $settings->resend_api_key = $this->resendApiKey; + $settings->smtp_from_address = $this->smtpFromAddress; + $settings->smtp_from_name = $this->smtpFromName; + + $settings->save(); + refreshSession(); + $this->dispatch('success', 'Resend settings saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() { return view('livewire.notifications.email'); diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index fba21d0b2..4e5d3a647 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -1,54 +1,50 @@
Notifications | Coolify - - -
-
-

Email

- - Save - - @if (isInstanceAdmin() && !$useInstanceEmailSettings) + + + +
+

Email

+ + Save + + @if (isInstanceAdmin() && !$useInstanceEmailSettings) Copy from Instance Settings - @endif - @if (isEmailEnabled($team) && auth()->user()->isAdminFromSession() && isTestEmailEnabled($team)) + @endif + @if (isEmailEnabled($team) && auth()->user()->isAdminFromSession()) - + Send Email - @endif -
- @if (!isCloud()) -
- + @endif
- @endif - @if (!$useInstanceEmailSettings) + @if (!isCloud()) +
+ +
+ @endif + @if (!$useInstanceEmailSettings)
- +
- @endif - - @if (isCloud()) + @endif + + @if (isCloud())
- +
- @endif - @if (!$useInstanceEmailSettings) + @endif + @if (!$useInstanceEmailSettings)
-
+

SMTP Server

@@ -72,13 +68,12 @@
- +
-
+

Resend

@@ -91,28 +86,50 @@
- +
- @endif - @if (isEmailEnabled($team) || $useInstanceEmailSettings) -

Subscribe to events

-
- @if (isDev()) - - @endif - - - - - + @endif + @if (isEmailEnabled($team) || $useInstanceEmailSettings) +

Notification Settings

+

+ Select events for which you would like to receive email notifications. +

+
+
+

Deployments

+
+ + + +
+
+
+

Backups

+
+ + +
+
+
+

Scheduled Tasks

+
+ + +
+
+
+

Server

+
+ + + + +
+
- @endif + @endif
From e36ccd3d78d03300e2d01bb65ac49cd7ee654014 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:29:41 +0100 Subject: [PATCH 28/80] chore: remove resale license reference --- app/Models/InstanceSettings.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Models/InstanceSettings.php b/app/Models/InstanceSettings.php index 45ccece1f..7110b8cff 100644 --- a/app/Models/InstanceSettings.php +++ b/app/Models/InstanceSettings.php @@ -16,7 +16,6 @@ class InstanceSettings extends Model implements SendsEmail protected $guarded = []; protected $casts = [ - 'resale_license' => 'encrypted', 'smtp_password' => 'encrypted', 'allowed_ip_ranges' => 'array', 'is_auto_update_enabled' => 'boolean', From 208766455ddd6fd87e8a67ecd2f13d0d861ca78a Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:30:56 +0100 Subject: [PATCH 29/80] fix: email notification channel enabled function --- resources/views/livewire/notifications/email.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 4e5d3a647..64530c1d4 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -14,7 +14,7 @@ Copy from Instance Settings @endif - @if (isEmailEnabled($team) && auth()->user()->isAdminFromSession()) + @if ($team->isNotificationEnabled('email') && auth()->user()->isAdminFromSession())
@@ -93,7 +93,7 @@
@endif - @if (isEmailEnabled($team) || $useInstanceEmailSettings) + @if ($team->isNotificationEnabled('email') || $useInstanceEmailSettings)

Notification Settings

Select events for which you would like to receive email notifications. From 2aacb1dc28233043403f28902a3b63c133b596b5 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:39:50 +0100 Subject: [PATCH 30/80] fix: Instance email settins - fix: resend, smtp save button should only save respective settings - feat: ability to send test email --- app/Livewire/SettingsEmail.php | 143 +++++++++++++++--- .../views/livewire/settings-email.blade.php | 133 ++++++++-------- 2 files changed, 196 insertions(+), 80 deletions(-) diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index abf3a12f9..daf8e8cab 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -3,6 +3,8 @@ namespace App\Livewire; use App\Models\InstanceSettings; +use App\Notifications\Test; +use Illuminate\Support\Facades\RateLimiter; use Livewire\Attributes\Validate; use Livewire\Component; @@ -13,6 +15,15 @@ class SettingsEmail extends Component #[Validate(['boolean'])] public bool $smtpEnabled = false; + #[Validate(['nullable', 'email'])] + public ?string $smtpFromAddress = null; + + #[Validate(['nullable', 'string'])] + public ?string $smtpFromName = null; + + #[Validate(['nullable', 'string'])] + public ?string $smtpRecipients = null; + #[Validate(['nullable', 'string'])] public ?string $smtpHost = null; @@ -20,29 +31,26 @@ class SettingsEmail extends Component public ?int $smtpPort = null; #[Validate(['nullable', 'string', 'in:tls,ssl,none'])] - public ?string $smtpEncryption = null; + public ?string $smtpEncryption = 'tls'; #[Validate(['nullable', 'string'])] public ?string $smtpUsername = null; - #[Validate(['nullable'])] + #[Validate(['nullable', 'string'])] public ?string $smtpPassword = null; #[Validate(['nullable', 'numeric'])] public ?int $smtpTimeout = null; - #[Validate(['nullable', 'email'])] - public ?string $smtpFromAddress = null; - - #[Validate(['nullable', 'string'])] - public ?string $smtpFromName = null; - #[Validate(['boolean'])] public bool $resendEnabled = false; #[Validate(['nullable', 'string'])] public ?string $resendApiKey = null; + #[Validate(['nullable', 'email'])] + public ?string $testEmailAddress = null; + public function mount() { if (isInstanceAdmin() === false) { @@ -90,7 +98,7 @@ class SettingsEmail extends Component try { $this->resetErrorBag(); $this->syncData(true); - $this->dispatch('success', 'Settings saved.'); + $this->dispatch('success', 'Transactional email settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -99,19 +107,120 @@ class SettingsEmail extends Component public function instantSave(string $type) { try { + $this->resetErrorBag(); + if ($type === 'SMTP') { - $this->resendEnabled = false; - } else { - $this->smtpEnabled = false; + $this->submitSmtp(); + } elseif ($type === 'Resend') { + $this->submitResend(); } - $this->syncData(true); - if ($this->smtpEnabled || $this->resendEnabled) { - $this->dispatch('success', "{$type} enabled."); - } else { - $this->dispatch('success', "{$type} disabled."); + + } catch (\Throwable $e) { + if ($type === 'SMTP') { + $this->smtpEnabled = false; + } elseif ($type === 'Resend') { + $this->resendEnabled = false; + } + + return handleError($e, $this); + } + } + + public function submitSmtp(): void + { + $this->validate([ + 'smtpEnabled' => 'boolean', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + 'smtpHost' => 'required|string', + 'smtpPort' => 'required|numeric', + 'smtpEncryption' => 'required|string|in:tls,ssl,none', + 'smtpUsername' => 'nullable|string', + 'smtpPassword' => 'nullable|string', + 'smtpTimeout' => 'nullable|numeric', + ], [ + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + 'smtpHost.required' => 'SMTP Host is required.', + 'smtpPort.required' => 'SMTP Port is required.', + 'smtpPort.numeric' => 'SMTP Port must be a number.', + 'smtpEncryption.required' => 'Encryption type is required.', + ]); + + $this->resendEnabled = false; + + $this->settings->smtp_enabled = $this->smtpEnabled; + $this->settings->smtp_host = $this->smtpHost; + $this->settings->smtp_port = $this->smtpPort; + $this->settings->smtp_encryption = $this->smtpEncryption; + $this->settings->smtp_username = $this->smtpUsername; + $this->settings->smtp_password = $this->smtpPassword; + $this->settings->smtp_timeout = $this->smtpTimeout; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; + $this->settings->resend_enabled = false; + $this->settings->save(); + + $this->dispatch('success', 'SMTP settings updated.'); + } + + public function submitResend(): void + { + $this->validate([ + 'resendEnabled' => 'boolean', + 'resendApiKey' => 'required|string', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + ], [ + 'resendApiKey.required' => 'Resend API Key is required.', + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + ]); + + $this->smtpEnabled = false; + + $this->settings->resend_enabled = $this->resendEnabled; + $this->settings->resend_api_key = $this->resendApiKey; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; + $this->settings->smtp_enabled = false; + $this->settings->save(); + + $this->dispatch('success', 'Resend settings updated.'); + } + + public function sendTestEmail() + { + try { + $this->validate([ + 'testEmailAddress' => 'required|email', + ], [ + 'testEmailAddress.required' => 'Test email address is required.', + 'testEmailAddress.email' => 'Please enter a valid email address.', + ]); + + $executed = RateLimiter::attempt( + 'test-email:'.$this->team->id, + $perMinute = 0, + function () { + $this->team?->notify(new Test($this->testEmailAddress)); + $this->dispatch('success', 'Test Email sent.'); + }, + $decaySeconds = 10, + ); + + if (! $executed) { + throw new \Exception('Too many messages sent!'); } } catch (\Throwable $e) { return handleError($e, $this); } } + + public function isEmailEnabled(): bool + { + return $this->settings->smtp_enabled || $this->settings->resend_enabled; + } } diff --git a/resources/views/livewire/settings-email.blade.php b/resources/views/livewire/settings-email.blade.php index 141922584..bbe9512a0 100644 --- a/resources/views/livewire/settings-email.blade.php +++ b/resources/views/livewire/settings-email.blade.php @@ -1,71 +1,78 @@

Transactional Email | Coolify - - -
-
-

Transactional Email

- - Save - -
-
Email settings for password resets, invitations, etc.
-
- - -
- -
-
-
-
-
-

SMTP Server

- - Save - -
-
- -
-
-
- - - - - - - + + + +
+

Transactional Email

+ + Save + + @if ($this->isEmailEnabled() && auth()->user()->isAdminFromSession()) + + + + + Send Email + + + + @endif +
+
Instance wide email settings for password resets, invitations, etc.
+
+ + +
+ +
+
+
+
+

SMTP Server

+ + Save +
-
- - - +
+
-
-
-
-
-
-
-

Resend

- - Save - -
-
- -
-
-
- +
+
+ + + + + + + +
+
+ + + +
-
- + +
+
+
+
+

Resend

+ + Save + +
+
+ +
+
+
+ +
+
+
+
-
From 67438e28ca7e1dd2ba9f7c62ae0f5fedd32a9f7d Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:19:59 +0100 Subject: [PATCH 31/80] fix: make sure resend is false if SMTP is true and vice versa --- app/Livewire/SettingsEmail.php | 120 ++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index daf8e8cab..9a139f984 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -126,69 +126,83 @@ class SettingsEmail extends Component } } - public function submitSmtp(): void + public function submitSmtp() { - $this->validate([ - 'smtpEnabled' => 'boolean', - 'smtpFromAddress' => 'required|email', - 'smtpFromName' => 'required|string', - 'smtpHost' => 'required|string', - 'smtpPort' => 'required|numeric', - 'smtpEncryption' => 'required|string|in:tls,ssl,none', - 'smtpUsername' => 'nullable|string', - 'smtpPassword' => 'nullable|string', - 'smtpTimeout' => 'nullable|numeric', - ], [ - 'smtpFromAddress.required' => 'From Address is required.', - 'smtpFromAddress.email' => 'Please enter a valid email address.', - 'smtpFromName.required' => 'From Name is required.', - 'smtpHost.required' => 'SMTP Host is required.', - 'smtpPort.required' => 'SMTP Port is required.', - 'smtpPort.numeric' => 'SMTP Port must be a number.', - 'smtpEncryption.required' => 'Encryption type is required.', - ]); + try { + $this->validate([ + 'smtpEnabled' => 'boolean', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + 'smtpHost' => 'required|string', + 'smtpPort' => 'required|numeric', + 'smtpEncryption' => 'required|string|in:tls,ssl,none', + 'smtpUsername' => 'nullable|string', + 'smtpPassword' => 'nullable|string', + 'smtpTimeout' => 'nullable|numeric', + ], [ + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + 'smtpHost.required' => 'SMTP Host is required.', + 'smtpPort.required' => 'SMTP Port is required.', + 'smtpPort.numeric' => 'SMTP Port must be a number.', + 'smtpEncryption.required' => 'Encryption type is required.', + ]); - $this->resendEnabled = false; + $this->resendEnabled = false; + $this->settings->resend_enabled = false; - $this->settings->smtp_enabled = $this->smtpEnabled; - $this->settings->smtp_host = $this->smtpHost; - $this->settings->smtp_port = $this->smtpPort; - $this->settings->smtp_encryption = $this->smtpEncryption; - $this->settings->smtp_username = $this->smtpUsername; - $this->settings->smtp_password = $this->smtpPassword; - $this->settings->smtp_timeout = $this->smtpTimeout; - $this->settings->smtp_from_address = $this->smtpFromAddress; - $this->settings->smtp_from_name = $this->smtpFromName; - $this->settings->resend_enabled = false; - $this->settings->save(); + $this->settings->smtp_enabled = $this->smtpEnabled; + $this->settings->smtp_host = $this->smtpHost; + $this->settings->smtp_port = $this->smtpPort; + $this->settings->smtp_encryption = $this->smtpEncryption; + $this->settings->smtp_username = $this->smtpUsername; + $this->settings->smtp_password = $this->smtpPassword; + $this->settings->smtp_timeout = $this->smtpTimeout; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; - $this->dispatch('success', 'SMTP settings updated.'); + $this->settings->save(); + + $this->dispatch('success', 'SMTP settings updated.'); + } catch (\Throwable $e) { + $this->smtpEnabled = false; + + return handleError($e); + } } - public function submitResend(): void + public function submitResend() { - $this->validate([ - 'resendEnabled' => 'boolean', - 'resendApiKey' => 'required|string', - 'smtpFromAddress' => 'required|email', - 'smtpFromName' => 'required|string', - ], [ - 'resendApiKey.required' => 'Resend API Key is required.', - 'smtpFromAddress.required' => 'From Address is required.', - 'smtpFromAddress.email' => 'Please enter a valid email address.', - 'smtpFromName.required' => 'From Name is required.', - ]); + try { + $this->validate([ + 'resendEnabled' => 'boolean', + 'resendApiKey' => 'required|string', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + ], [ + 'resendApiKey.required' => 'Resend API Key is required.', + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + ]); - $this->smtpEnabled = false; + $this->smtpEnabled = false; + $this->settings->smtp_enabled = false; - $this->settings->resend_enabled = $this->resendEnabled; - $this->settings->resend_api_key = $this->resendApiKey; - $this->settings->smtp_from_address = $this->smtpFromAddress; - $this->settings->smtp_from_name = $this->smtpFromName; - $this->settings->smtp_enabled = false; - $this->settings->save(); + $this->settings->resend_enabled = $this->resendEnabled; + $this->settings->resend_api_key = $this->resendApiKey; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; - $this->dispatch('success', 'Resend settings updated.'); + $this->settings->save(); + + $this->dispatch('success', 'Resend settings updated.'); + } catch (\Throwable $e) { + $this->resendEnabled = false; + + return handleError($e, $this); + } } public function sendTestEmail() From ee7a901a77dd9f36e083a17aa2b849d89a7ec967 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:23:32 +0100 Subject: [PATCH 32/80] fix: Email Notification saving - fix: SMTP and resend should only save their respective settings - chore: improve component validation and code to make it much smaller (less code - same functionality) --- app/Livewire/Notifications/Email.php | 293 ++++++++---------- .../livewire/notifications/email.blade.php | 18 +- 2 files changed, 141 insertions(+), 170 deletions(-) diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index d81535a80..a4a16e5e5 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -31,11 +31,11 @@ class Email extends Component #[Validate(['nullable', 'string'])] public ?string $smtpHost = null; - #[Validate(['nullable', 'numeric'])] + #[Validate(['nullable', 'numeric', 'min:1', 'max:65535'])] public ?int $smtpPort = null; #[Validate(['nullable', 'string', 'in:tls,ssl,none'])] - public ?string $smtpEncryption = null; + public ?string $smtpEncryption = 'tls'; #[Validate(['nullable', 'string'])] public ?string $smtpUsername = null; @@ -170,6 +170,136 @@ class Email extends Component } } + public function submit() + { + try { + $this->resetErrorBag(); + $this->saveModel(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function saveModel() + { + $this->syncData(true); + refreshSession(); + $this->dispatch('success', 'Email notifications settings updated.'); + } + + public function instantSave(?string $type = null) + { + try { + $this->resetErrorBag(); + + if ($type === 'SMTP') { + $this->submitSmtp(); + } elseif ($type === 'Resend') { + $this->submitResend(); + } else { + $this->smtpEnabled = false; + $this->resendEnabled = false; + $this->saveModel(); + + return; + } + } catch (\Throwable $e) { + if ($type === 'SMTP') { + $this->smtpEnabled = false; + } elseif ($type === 'Resend') { + $this->resendEnabled = false; + } + + return handleError($e, $this); + } + } + + public function submitSmtp() + { + try { + $this->resetErrorBag(); + $this->validate([ + 'smtpEnabled' => 'boolean', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + 'smtpHost' => 'required|string', + 'smtpPort' => 'required|numeric', + 'smtpEncryption' => 'required|string|in:tls,ssl,none', + 'smtpUsername' => 'nullable|string', + 'smtpPassword' => 'nullable|string', + 'smtpTimeout' => 'nullable|numeric', + ], [ + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + 'smtpHost.required' => 'SMTP Host is required.', + 'smtpPort.required' => 'SMTP Port is required.', + 'smtpPort.numeric' => 'SMTP Port must be a number.', + 'smtpEncryption.required' => 'Encryption type is required.', + ]); + + $settings = $this->team->emailNotificationSettings; + + $settings->resend_enabled = false; + $settings->use_instance_email_settings = false; + $this->resendEnabled = false; + $this->useInstanceEmailSettings = false; + + $settings->smtp_enabled = $this->smtpEnabled; + $settings->smtp_from_address = $this->smtpFromAddress; + $settings->smtp_from_name = $this->smtpFromName; + $settings->smtp_host = $this->smtpHost; + $settings->smtp_port = $this->smtpPort; + $settings->smtp_encryption = $this->smtpEncryption; + $settings->smtp_username = $this->smtpUsername; + $settings->smtp_password = $this->smtpPassword; + $settings->smtp_timeout = $this->smtpTimeout; + + $settings->save(); + refreshSession(); + $this->dispatch('success', 'SMTP settings updated.'); + } catch (\Throwable $e) { + $this->smtpEnabled = false; + + return handleError($e); + } + } + + public function submitResend() + { + try { + $this->resetErrorBag(); + $this->validate([ + 'resendEnabled' => 'boolean', + 'resendApiKey' => 'required|string', + 'smtpFromAddress' => 'required|email', + 'smtpFromName' => 'required|string', + ], [ + 'resendApiKey.required' => 'Resend API Key is required.', + 'smtpFromAddress.required' => 'From Address is required.', + 'smtpFromAddress.email' => 'Please enter a valid email address.', + 'smtpFromName.required' => 'From Name is required.', + ]); + $settings = $this->team->emailNotificationSettings; + + $settings->smtp_enabled = false; + $settings->use_instance_email_settings = false; + $this->smtpEnabled = false; + $this->useInstanceEmailSettings = false; + + $settings->resend_enabled = $this->resendEnabled; + $settings->resend_api_key = $this->resendApiKey; + $settings->smtp_from_address = $this->smtpFromAddress; + $settings->smtp_from_name = $this->smtpFromName; + + $settings->save(); + refreshSession(); + $this->dispatch('success', 'Resend settings updated.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function sendTestEmail() { try { @@ -198,90 +328,6 @@ class Email extends Component } } - public function instantSaveInstance() - { - try { - $this->smtpEnabled = false; - $this->resendEnabled = false; - $this->saveModel(); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function instantSaveSmtpEnabled() - { - try { - $this->validate([ - 'smtpEnabled' => 'boolean', - 'smtpFromAddress' => 'required|email', - 'smtpFromName' => 'required|string', - 'smtpHost' => 'required|string', - 'smtpPort' => 'required|numeric', - 'smtpEncryption' => 'required|string|in:tls,ssl,none', - 'smtpUsername' => 'nullable|string', - 'smtpPassword' => 'nullable|string', - 'smtpTimeout' => 'nullable|numeric', - ], [ - 'smtpFromAddress.required' => 'From Address is required.', - 'smtpFromAddress.email' => 'Please enter a valid email address.', - 'smtpFromName.required' => 'From Name is required.', - 'smtpHost.required' => 'SMTP Host is required.', - 'smtpPort.required' => 'SMTP Port is required.', - 'smtpPort.numeric' => 'SMTP Port must be a number.', - 'smtpEncryption.required' => 'Encryption type is required.', - ]); - $this->resendEnabled = false; - $this->useInstanceEmailSettings = false; - $this->saveModel(); - } catch (\Throwable $e) { - $this->smtpEnabled = false; - - return handleError($e, $this); - } - } - - public function instantSaveResend() - { - try { - $this->validate([ - 'resendEnabled' => 'boolean', - 'resendApiKey' => 'required|string', - 'smtpFromAddress' => 'required|email', - 'smtpFromName' => 'required|string', - ], [ - 'resendApiKey.required' => 'Resend API Key is required.', - 'smtpFromAddress.required' => 'From Address is required.', - 'smtpFromAddress.email' => 'Please enter a valid email address.', - 'smtpFromName.required' => 'From Name is required.', - ]); - $this->smtpEnabled = false; - $this->useInstanceEmailSettings = false; - $this->saveModel(); - } catch (\Throwable $e) { - $this->resendEnabled = false; - - return handleError($e, $this); - } - } - - public function saveModel() - { - $this->syncData(true); - refreshSession(); - $this->dispatch('success', 'Settings saved.'); - } - - public function submit() - { - try { - $this->resetErrorBag(); - $this->saveModel(); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - public function copyFromInstanceSettings() { $settings = instanceSettings(); @@ -313,81 +359,6 @@ class Email extends Component $this->dispatch('error', 'Instance SMTP/Resend settings are not enabled.'); } - public function submitSmtp() - { - try { - $this->resetErrorBag(); - $this->validate([ - 'smtpEnabled' => 'boolean', - 'smtpFromAddress' => 'required|email', - 'smtpFromName' => 'required|string', - 'smtpHost' => 'required|string', - 'smtpPort' => 'required|numeric', - 'smtpEncryption' => 'required|string|in:tls,ssl,none', - 'smtpUsername' => 'nullable|string', - 'smtpPassword' => 'nullable|string', - 'smtpTimeout' => 'nullable|numeric', - ], [ - 'smtpFromAddress.required' => 'From Address is required.', - 'smtpFromAddress.email' => 'Please enter a valid email address.', - 'smtpFromName.required' => 'From Name is required.', - 'smtpHost.required' => 'SMTP Host is required.', - 'smtpPort.required' => 'SMTP Port is required.', - 'smtpPort.numeric' => 'SMTP Port must be a number.', - 'smtpEncryption.required' => 'Encryption type is required.', - ]); - - $settings = $this->team->emailNotificationSettings; - - $settings->smtp_enabled = $this->smtpEnabled; - $settings->smtp_from_address = $this->smtpFromAddress; - $settings->smtp_from_name = $this->smtpFromName; - $settings->smtp_host = $this->smtpHost; - $settings->smtp_port = $this->smtpPort; - $settings->smtp_encryption = $this->smtpEncryption; - $settings->smtp_username = $this->smtpUsername; - $settings->smtp_password = $this->smtpPassword; - $settings->smtp_timeout = $this->smtpTimeout; - - $settings->save(); - refreshSession(); - $this->dispatch('success', 'SMTP settings saved.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function submitResend() - { - try { - $this->resetErrorBag(); - $this->validate([ - 'resendEnabled' => 'boolean', - 'resendApiKey' => 'required|string', - 'smtpFromAddress' => 'required|email', - 'smtpFromName' => 'required|string', - ], [ - 'resendApiKey.required' => 'Resend API Key is required.', - 'smtpFromAddress.required' => 'From Address is required.', - 'smtpFromAddress.email' => 'Please enter a valid email address.', - 'smtpFromName.required' => 'From Name is required.', - ]); - - $settings = $this->team->emailNotificationSettings; - - $settings->resend_enabled = $this->resendEnabled; - $settings->resend_api_key = $this->resendApiKey; - $settings->smtp_from_address = $this->smtpFromAddress; - $settings->smtp_from_name = $this->smtpFromName; - - $settings->save(); - refreshSession(); - $this->dispatch('success', 'Resend settings saved.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - public function render() { return view('livewire.notifications.email'); diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 64530c1d4..868e27ce8 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -9,11 +9,6 @@ Save - @if (isInstanceAdmin() && !$useInstanceEmailSettings) - - Copy from Instance Settings - - @endif @if ($team->isNotificationEnabled('email') && auth()->user()->isAdminFromSession())
@@ -24,10 +19,15 @@
@endif + @if (isInstanceAdmin() && !$useInstanceEmailSettings) + + Copy from Instance Settings + + @endif
@if (!isCloud())
- +
@endif @if (!$useInstanceEmailSettings) @@ -39,7 +39,7 @@ @if (isCloud())
- +
@endif @if (!$useInstanceEmailSettings) @@ -52,7 +52,7 @@
- +
@@ -81,7 +81,7 @@
- +
From b13d77377c49af025346f85ebc8aab1283aeb8a6 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:34:24 +0100 Subject: [PATCH 33/80] feat: new shared function name `is_transactional_emails_enabled()` --- app/Http/Controllers/Controller.php | 2 +- app/Livewire/SettingsEmail.php | 9 ++------- app/Models/S3Storage.php | 2 +- resources/views/auth/forgot-password.blade.php | 2 +- resources/views/livewire/settings-email.blade.php | 2 +- resources/views/livewire/team/invite-link.blade.php | 2 +- resources/views/livewire/team/member/index.blade.php | 2 +- 7 files changed, 8 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 2de2c79f6..522683efa 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -48,7 +48,7 @@ class Controller extends BaseController public function forgot_password(Request $request) { - if (is_transactional_emails_active()) { + if (is_transactional_emails_enabled()) { $arrayOfRequest = $request->only(Fortify::email()); $request->merge([ 'email' => Str::lower($arrayOfRequest['email']), diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index 9a139f984..4636a3b25 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -201,7 +201,7 @@ class SettingsEmail extends Component } catch (\Throwable $e) { $this->resendEnabled = false; - return handleError($e, $this); + return handleError($e); } } @@ -229,12 +229,7 @@ class SettingsEmail extends Component throw new \Exception('Too many messages sent!'); } } catch (\Throwable $e) { - return handleError($e, $this); + return handleError($e); } } - - public function isEmailEnabled(): bool - { - return $this->settings->smtp_enabled || $this->settings->resend_enabled; - } } diff --git a/app/Models/S3Storage.php b/app/Models/S3Storage.php index a432a6e9c..f1247e6f7 100644 --- a/app/Models/S3Storage.php +++ b/app/Models/S3Storage.php @@ -59,7 +59,7 @@ class S3Storage extends BaseModel $this->is_usable = true; } catch (\Throwable $e) { $this->is_usable = false; - if ($this->unusable_email_sent === false && is_transactional_emails_active()) { + if ($this->unusable_email_sent === false && is_transactional_emails_enabled()) { $mail = new MailMessage; $mail->subject('Coolify: S3 Storage Connection Error'); $mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('storage.show', ['storage_uuid' => $this->uuid])]); diff --git a/resources/views/auth/forgot-password.blade.php b/resources/views/auth/forgot-password.blade.php index 00cf95a44..a61a8fb32 100644 --- a/resources/views/auth/forgot-password.blade.php +++ b/resources/views/auth/forgot-password.blade.php @@ -9,7 +9,7 @@
- @if (is_transactional_emails_active()) + @if (is_transactional_emails_enabled())
@csrf diff --git a/resources/views/livewire/settings-email.blade.php b/resources/views/livewire/settings-email.blade.php index bbe9512a0..81ee4878e 100644 --- a/resources/views/livewire/settings-email.blade.php +++ b/resources/views/livewire/settings-email.blade.php @@ -9,7 +9,7 @@ Save - @if ($this->isEmailEnabled() && auth()->user()->isAdminFromSession()) + @if (is_transactional_emails_enabled() && auth()->user()->isAdminFromSession()) diff --git a/resources/views/livewire/team/invite-link.blade.php b/resources/views/livewire/team/invite-link.blade.php index 2e0f02078..1f8702b6f 100644 --- a/resources/views/livewire/team/invite-link.blade.php +++ b/resources/views/livewire/team/invite-link.blade.php @@ -11,7 +11,7 @@
Generate Invitation Link - @if (is_transactional_emails_active()) + @if (is_transactional_emails_enabled()) Send Invitation via Email @endif
diff --git a/resources/views/livewire/team/member/index.blade.php b/resources/views/livewire/team/member/index.blade.php index f756414b6..122c03402 100644 --- a/resources/views/livewire/team/member/index.blade.php +++ b/resources/views/livewire/team/member/index.blade.php @@ -33,7 +33,7 @@
@if (auth()->user()->isAdminFromSession())
- @if (is_transactional_emails_active()) + @if (is_transactional_emails_enabled())

Invite New Member

@else

Invite New Member

From df6c5c55e18d89112fe63f1f3b40650c8cba1dcb Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:37:11 +0100 Subject: [PATCH 34/80] feat: new shared notifications functions --- bootstrap/helpers/notifications.php | 87 +++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 bootstrap/helpers/notifications.php diff --git a/bootstrap/helpers/notifications.php b/bootstrap/helpers/notifications.php new file mode 100644 index 000000000..3b1eb758b --- /dev/null +++ b/bootstrap/helpers/notifications.php @@ -0,0 +1,87 @@ +smtp_enabled || $settings->resend_enabled; +} + +function send_internal_notification(string $message): void +{ + try { + $team = Team::find(0); + $team?->notify(new GeneralNotification($message)); + } catch (\Throwable $e) { + ray($e->getMessage()); + } +} + +function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null): void +{ + $settings = instanceSettings(); + $type = set_transanctional_email_settings($settings); + if (! $type) { + throw new Exception('No email settings found.'); + } + if ($cc) { + Mail::send( + [], + [], + fn (Message $message) => $message + ->to($email) + ->replyTo($email) + ->cc($cc) + ->subject($mail->subject) + ->html((string) $mail->render()) + ); + } else { + Mail::send( + [], + [], + fn (Message $message) => $message + ->to($email) + ->subject($mail->subject) + ->html((string) $mail->render()) + ); + } +} + +function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string // +{ + if (! $settings) { + $settings = instanceSettings(); + } + config()->set('mail.from.address', data_get($settings, 'smtp_from_address')); + config()->set('mail.from.name', data_get($settings, 'smtp_from_name')); + if (data_get($settings, 'resend_enabled')) { + config()->set('mail.default', 'resend'); + config()->set('resend.api_key', data_get($settings, 'resend_api_key')); + + return 'resend'; + } + if (data_get($settings, 'smtp_enabled')) { + config()->set('mail.default', 'smtp'); + config()->set('mail.mailers.smtp', [ + 'transport' => 'smtp', + 'host' => data_get($settings, 'smtp_host'), + 'port' => data_get($settings, 'smtp_port'), + 'encryption' => data_get($settings, 'smtp_encryption'), + 'username' => data_get($settings, 'smtp_username'), + 'password' => data_get($settings, 'smtp_password'), + 'timeout' => data_get($settings, 'smtp_timeout'), + 'local_domain' => null, + ]); + + return 'smtp'; + } + + return null; +} From d289f41ff6e76d45d305ca5664833016df34e636 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:38:21 +0100 Subject: [PATCH 35/80] chore: remove functions from shared.php - Removed all notification functions from shared.php to make it easier to maintain and test. --- bootstrap/helpers/shared.php | 377 ++++++++++++----------------------- 1 file changed, 127 insertions(+), 250 deletions(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 40c5acb21..ea051c84e 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -25,23 +25,15 @@ use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; use App\Models\Team; use App\Models\User; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; -use App\Notifications\Channels\SlackChannel; -use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Internal\GeneralNotification; use Carbon\CarbonImmutable; use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException; use Illuminate\Database\UniqueConstraintViolationException; -use Illuminate\Mail\Message; -use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Process\Pool; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Request; @@ -68,27 +60,27 @@ function base_configuration_dir(): string } function application_configuration_dir(): string { - return base_configuration_dir() . '/applications'; + return base_configuration_dir().'/applications'; } function service_configuration_dir(): string { - return base_configuration_dir() . '/services'; + return base_configuration_dir().'/services'; } function database_configuration_dir(): string { - return base_configuration_dir() . '/databases'; + return base_configuration_dir().'/databases'; } function database_proxy_dir($uuid): string { - return base_configuration_dir() . "/databases/$uuid/proxy"; + return base_configuration_dir()."/databases/$uuid/proxy"; } function backup_dir(): string { - return base_configuration_dir() . '/backups'; + return base_configuration_dir().'/backups'; } function metrics_dir(): string { - return base_configuration_dir() . '/metrics'; + return base_configuration_dir().'/metrics'; } function sanitize_string(?string $input = null): ?string @@ -139,15 +131,15 @@ function showBoarding(): bool } function refreshSession(?Team $team = null): void { - if (!$team) { + if (! $team) { if (Auth::user()->currentTeam()) { $team = Team::find(Auth::user()->currentTeam()->id); } else { $team = User::find(Auth::id())->teams->first(); } } - Cache::forget('team:' . Auth::id()); - Cache::remember('team:' . Auth::id(), 3600, function () use ($team) { + Cache::forget('team:'.Auth::id()); + Cache::remember('team:'.Auth::id(), 3600, function () use ($team) { return $team; }); session(['currentTeam' => $team]); @@ -179,7 +171,7 @@ function handleError(?Throwable $error = null, ?Livewire\Component $livewire = n $message = null; } if ($customErrorMessage) { - $message = $customErrorMessage . ' ' . $message; + $message = $customErrorMessage.' '.$message; } if (isset($livewire)) { @@ -252,7 +244,7 @@ function generateSSHKey(string $type = 'rsa') function formatPrivateKey(string $privateKey) { $privateKey = trim($privateKey); - if (!str_ends_with($privateKey, "\n")) { + if (! str_ends_with($privateKey, "\n")) { $privateKey .= "\n"; } @@ -267,43 +259,6 @@ function generate_application_name(string $git_repository, string $git_branch, ? return Str::kebab("$git_repository:$git_branch-$cuid"); } -function is_transactional_emails_active(): bool -{ - return isEmailEnabled(\App\Models\InstanceSettings::get()); -} - -function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string -{ - if (!$settings) { - $settings = instanceSettings(); - } - config()->set('mail.from.address', data_get($settings, 'smtp_from_address')); - config()->set('mail.from.name', data_get($settings, 'smtp_from_name')); - if (data_get($settings, 'resend_enabled')) { - config()->set('mail.default', 'resend'); - config()->set('resend.api_key', data_get($settings, 'resend_api_key')); - - return 'resend'; - } - if (data_get($settings, 'smtp_enabled')) { - config()->set('mail.default', 'smtp'); - config()->set('mail.mailers.smtp', [ - 'transport' => 'smtp', - 'host' => data_get($settings, 'smtp_host'), - 'port' => data_get($settings, 'smtp_port'), - 'encryption' => data_get($settings, 'smtp_encryption'), - 'username' => data_get($settings, 'smtp_username'), - 'password' => data_get($settings, 'smtp_password'), - 'timeout' => data_get($settings, 'smtp_timeout'), - 'local_domain' => null, - ]); - - return 'smtp'; - } - - return null; -} - function base_ip(): string { if (isDev()) { @@ -374,7 +329,7 @@ function isSubscribed() function isProduction(): bool { - return !isDev(); + return ! isDev(); } function isDev(): bool { @@ -414,85 +369,7 @@ function validate_timezone(string $timezone): bool { return in_array($timezone, timezone_identifiers_list()); } -function send_internal_notification(string $message): void -{ - try { - $team = Team::find(0); - $team?->notify(new GeneralNotification($message)); - } catch (\Throwable $e) { - ray($e->getMessage()); - } -} -function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null): void -{ - $settings = instanceSettings(); - $type = set_transanctional_email_settings($settings); - if (!$type) { - throw new Exception('No email settings found.'); - } - if ($cc) { - Mail::send( - [], - [], - fn(Message $message) => $message - ->to($email) - ->replyTo($email) - ->cc($cc) - ->subject($mail->subject) - ->html((string) $mail->render()) - ); - } else { - Mail::send( - [], - [], - fn(Message $message) => $message - ->to($email) - ->subject($mail->subject) - ->html((string) $mail->render()) - ); - } -} -function isTestEmailEnabled($notifiable) -{ - if (data_get($notifiable, 'use_instance_email_settings') && isInstanceAdmin()) { - return true; - } elseif (data_get($notifiable, 'smtp_enabled') || data_get($notifiable, 'resend_enabled') && auth()->user()->isAdminFromSession()) { - return true; - } - return false; -} -function isEmailEnabled($notifiable) -{ - return data_get($notifiable, 'smtp_enabled') || data_get($notifiable, 'resend_enabled') || data_get($notifiable, 'use_instance_email_settings'); -} -function setNotificationChannels($notifiable, $event) -{ - $channels = []; - $isEmailEnabled = isEmailEnabled($notifiable); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSubscribedToEmailEvent = data_get($notifiable, "smtp_notifications_$event"); - $isSubscribedToDiscordEvent = data_get($notifiable, "discord_notifications_$event"); - $isSubscribedToTelegramEvent = data_get($notifiable, "telegram_notifications_$event"); - $isSubscribedToSlackEvent = data_get($notifiable, "slack_notifications_$event"); - - if ($isDiscordEnabled && $isSubscribedToDiscordEvent) { - $channels[] = DiscordChannel::class; - } - if ($isEmailEnabled && $isSubscribedToEmailEvent) { - $channels[] = EmailChannel::class; - } - if ($isTelegramEnabled && $isSubscribedToTelegramEvent) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled && $isSubscribedToSlackEvent) { - $channels[] = SlackChannel::class; - } - - return $channels; -} function parseEnvFormatToArray($env_file_contents) { $env_array = []; @@ -594,7 +471,7 @@ function getResourceByUuid(string $uuid, ?int $teamId = null) return null; } $resource = queryResourcesByUuid($uuid); - if (!is_null($resource) && $resource->environment->project->team_id === $teamId) { + if (! is_null($resource) && $resource->environment->project->team_id === $teamId) { return $resource; } @@ -686,29 +563,29 @@ function queryResourcesByUuid(string $uuid) function generateTagDeployWebhook($tag_name) { $baseUrl = base_url(); - $api = Url::fromString($baseUrl) . '/api/v1'; + $api = Url::fromString($baseUrl).'/api/v1'; $endpoint = "/deploy?tag=$tag_name"; - return $api . $endpoint; + return $api.$endpoint; } function generateDeployWebhook($resource) { $baseUrl = base_url(); - $api = Url::fromString($baseUrl) . '/api/v1'; + $api = Url::fromString($baseUrl).'/api/v1'; $endpoint = '/deploy'; $uuid = data_get($resource, 'uuid'); - return $api . $endpoint . "?uuid=$uuid&force=false"; + return $api.$endpoint."?uuid=$uuid&force=false"; } function generateGitManualWebhook($resource, $type) { - if ($resource->source_id !== 0 && !is_null($resource->source_id)) { + if ($resource->source_id !== 0 && ! is_null($resource->source_id)) { return null; } if ($resource->getMorphClass() === \App\Models\Application::class) { $baseUrl = base_url(); - return Url::fromString($baseUrl) . "/webhooks/source/$type/events/manual"; + return Url::fromString($baseUrl)."/webhooks/source/$type/events/manual"; } return null; @@ -735,7 +612,7 @@ function getTopLevelNetworks(Service|Application $resource) $hasHostNetworkMode = data_get($service, 'network_mode') === 'host' ? true : false; // Only add 'networks' key if 'network_mode' is not 'host' - if (!$hasHostNetworkMode) { + if (! $hasHostNetworkMode) { // Collect/create/update networks if ($serviceNetworks->count() > 0) { foreach ($serviceNetworks as $networkName => $networkDetails) { @@ -749,7 +626,7 @@ function getTopLevelNetworks(Service|Application $resource) $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); - if (!$networkExists) { + if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } @@ -760,7 +637,7 @@ function getTopLevelNetworks(Service|Application $resource) $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); - if (!$definedNetworkExists) { + if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { $topLevelNetworks->put($network, [ 'name' => $network, @@ -801,7 +678,7 @@ function getTopLevelNetworks(Service|Application $resource) $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); - if (!$networkExists) { + if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } @@ -811,7 +688,7 @@ function getTopLevelNetworks(Service|Application $resource) $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); - if (!$definedNetworkExists) { + if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { $topLevelNetworks->put($network, [ 'name' => $network, @@ -947,7 +824,7 @@ function generateEnvValue(string $command, Service|Application|null $service = n case 'PASSWORD_64': $generatedValue = Str::password(length: 64, symbols: false); break; - // This is not base64, it's just a random string + // This is not base64, it's just a random string case 'BASE64_64': $generatedValue = Str::random(64); break; @@ -958,7 +835,7 @@ function generateEnvValue(string $command, Service|Application|null $service = n case 'BASE64_32': $generatedValue = Str::random(32); break; - // This is base64, + // This is base64, case 'REALBASE64_64': $generatedValue = base64_encode(Str::random(64)); break; @@ -1058,7 +935,7 @@ function validate_dns_entry(string $fqdn, Server $server) } $settings = instanceSettings(); $is_dns_validation_enabled = data_get($settings, 'is_dns_validation_enabled'); - if (!$is_dns_validation_enabled) { + if (! $is_dns_validation_enabled) { return true; } $dns_servers = data_get($settings, 'custom_dns_servers'); @@ -1076,7 +953,7 @@ function validate_dns_entry(string $fqdn, Server $server) $query = new DNSQuery($dns_server); $results = $query->query($host, $type); if ($results === false || $query->hasError()) { - ray('Error: ' . $query->getLasterror()); + ray('Error: '.$query->getLasterror()); } else { foreach ($results as $result) { if ($result->getType() == $type) { @@ -1086,7 +963,7 @@ function validate_dns_entry(string $fqdn, Server $server) break; } if ($result->getData() === $ip) { - ray($host . ' has IP address ' . $result->getData()); + ray($host.' has IP address '.$result->getData()); ray($result->getString()); $found_matching_ip = true; break; @@ -1134,15 +1011,15 @@ function checkIfDomainIsAlreadyUsed(Collection|array $domains, ?string $teamId = $applications = Application::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid']); $serviceApplications = ServiceApplication::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid']); if ($uuid) { - $applications = $applications->filter(fn($app) => $app->uuid !== $uuid); - $serviceApplications = $serviceApplications->filter(fn($app) => $app->uuid !== $uuid); + $applications = $applications->filter(fn ($app) => $app->uuid !== $uuid); + $serviceApplications = $serviceApplications->filter(fn ($app) => $app->uuid !== $uuid); } $domainFound = false; foreach ($applications as $app) { if (is_null($app->fqdn)) { continue; } - $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn($fqdn) => $fqdn !== ''); + $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== ''); foreach ($list_of_domains as $domain) { if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); @@ -1161,7 +1038,7 @@ function checkIfDomainIsAlreadyUsed(Collection|array $domains, ?string $teamId = if (str($app->fqdn)->isEmpty()) { continue; } - $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn($fqdn) => $fqdn !== ''); + $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== ''); foreach ($list_of_domains as $domain) { if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); @@ -1211,7 +1088,7 @@ function check_domain_usage(ServiceApplication|Application|null $resource = null }); $apps = Application::all(); foreach ($apps as $app) { - $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn($fqdn) => $fqdn !== ''); + $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== ''); foreach ($list_of_domains as $domain) { if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); @@ -1230,7 +1107,7 @@ function check_domain_usage(ServiceApplication|Application|null $resource = null } $apps = ServiceApplication::all(); foreach ($apps as $app) { - $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn($fqdn) => $fqdn !== ''); + $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== ''); foreach ($list_of_domains as $domain) { if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); @@ -1266,7 +1143,7 @@ function parseCommandsByLineForSudo(Collection $commands, Server $server): array { $commands = $commands->map(function ($line) { if ( - !str(trim($line))->startsWith([ + ! str(trim($line))->startsWith([ 'cd', 'command', 'echo', @@ -1287,7 +1164,7 @@ function parseCommandsByLineForSudo(Collection $commands, Server $server): array $commands = $commands->map(function ($line) use ($server) { if (Str::startsWith($line, 'sudo mkdir -p')) { - return "$line && sudo chown -R $server->user:$server->user " . Str::after($line, 'sudo mkdir -p') . ' && sudo chmod -R o-rwx ' . Str::after($line, 'sudo mkdir -p'); + return "$line && sudo chown -R $server->user:$server->user ".Str::after($line, 'sudo mkdir -p').' && sudo chmod -R o-rwx '.Str::after($line, 'sudo mkdir -p'); } return $line; @@ -1315,11 +1192,11 @@ function parseCommandsByLineForSudo(Collection $commands, Server $server): array } function parseLineForSudo(string $command, Server $server): string { - if (!str($command)->startSwith('cd') && !str($command)->startSwith('command')) { + if (! str($command)->startSwith('cd') && ! str($command)->startSwith('command')) { $command = "sudo $command"; } if (Str::startsWith($command, 'sudo mkdir -p')) { - $command = "$command && sudo chown -R $server->user:$server->user " . Str::after($command, 'sudo mkdir -p') . ' && sudo chmod -R o-rwx ' . Str::after($command, 'sudo mkdir -p'); + $command = "$command && sudo chown -R $server->user:$server->user ".Str::after($command, 'sudo mkdir -p').' && sudo chmod -R o-rwx '.Str::after($command, 'sudo mkdir -p'); } if (str($command)->contains('$(') || str($command)->contains('`')) { $command = str($command)->replace('$(', '$(sudo ')->replace('`', '`sudo ')->value(); @@ -1441,7 +1318,7 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull $isDirectory = data_get($foundConfig, 'is_directory'); } else { $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); - if ((is_null($isDirectory) || !$isDirectory) && is_null($content)) { + if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { // if isDirectory is not set (or false) & content is also not set, we assume it is a directory ray('setting isDirectory to true'); $isDirectory = true; @@ -1456,9 +1333,9 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull return $volume; } if (get_class($resource) === \App\Models\Application::class) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + $dir = base_configuration_dir().'/applications/'.$resource->uuid; } else { - $dir = base_configuration_dir() . '/services/' . $resource->service->uuid; + $dir = base_configuration_dir().'/services/'.$resource->service->uuid; } if ($source->startsWith('.')) { @@ -1468,9 +1345,9 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull $source = $source->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { - $source = $source . "-pr-$pull_request_id"; + $source = $source."-pr-$pull_request_id"; } - if (!$resource?->settings?->is_preserve_repository_enabled || $foundConfig?->is_based_on_git) { + if (! $resource?->settings?->is_preserve_repository_enabled || $foundConfig?->is_based_on_git) { LocalFileVolume::updateOrCreate( [ 'mount_path' => $target, @@ -1599,7 +1476,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($serviceLabels->count() > 0) { $removedLabels = collect([]); $serviceLabels = $serviceLabels->filter(function ($serviceLabel, $serviceLabelName) use ($removedLabels) { - if (!str($serviceLabel)->contains('=')) { + if (! str($serviceLabel)->contains('=')) { $removedLabels->put($serviceLabelName, $serviceLabel); return false; @@ -1681,7 +1558,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); - if (!$networkExists) { + if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } @@ -1707,12 +1584,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $savedService->ports = $collectedPorts->implode(','); $savedService->save(); - if (!$hasHostNetworkMode) { + if (! $hasHostNetworkMode) { // Add Coolify specific networks $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); - if (!$definedNetworkExists) { + if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { $topLevelNetworks->put($network, [ 'name' => $network, @@ -1924,9 +1801,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $fqdn = "$fqdn$path"; } - if (!$isDatabase) { + if (! $isDatabase) { if ($savedService->fqdn) { - data_set($savedService, 'fqdn', $savedService->fqdn . ',' . $fqdn); + data_set($savedService, 'fqdn', $savedService->fqdn.','.$fqdn); } else { data_set($savedService, 'fqdn', $fqdn); } @@ -1941,7 +1818,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal ]); } // Caddy needs exact port in some cases. - if ($predefinedPort && !$key->endsWith("_{$predefinedPort}")) { + if ($predefinedPort && ! $key->endsWith("_{$predefinedPort}")) { $fqdns_exploded = str($savedService->fqdn)->explode(','); if ($fqdns_exploded->count() > 1) { continue; @@ -1981,12 +1858,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal 'service_id' => $resource->id, ])->first(); ['command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port] = parseEnvVariable($value); - if (!is_null($command)) { + if (! is_null($command)) { if ($command?->value() === 'FQDN' || $command?->value() === 'URL') { if (Str::lower($forService) === $serviceName) { $fqdn = generateFqdn($resource->server, $containerName); } else { - $fqdn = generateFqdn($resource->server, Str::lower($forService) . '-' . $resource->uuid); + $fqdn = generateFqdn($resource->server, Str::lower($forService).'-'.$resource->uuid); } if ($port) { $fqdn = "$fqdn:$port"; @@ -2016,13 +1893,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal 'is_preview' => false, ]); } - if (!$isDatabase) { - if ($command->value() === 'FQDN' && is_null($savedService->fqdn) && !$foundEnv) { + if (! $isDatabase) { + if ($command->value() === 'FQDN' && is_null($savedService->fqdn) && ! $foundEnv) { $savedService->fqdn = $fqdn; $savedService->save(); } // Caddy needs exact port in some cases. - if ($predefinedPort && !$key->endsWith("_{$predefinedPort}") && $command?->value() === 'FQDN' && $resource->server->proxyType() === 'CADDY') { + if ($predefinedPort && ! $key->endsWith("_{$predefinedPort}") && $command?->value() === 'FQDN' && $resource->server->proxyType() === 'CADDY') { $fqdns_exploded = str($savedService->fqdn)->explode(','); if ($fqdns_exploded->count() > 1) { continue; @@ -2044,7 +1921,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } else { $generatedValue = generateEnvValue($command, $resource); - if (!$foundEnv) { + if (! $foundEnv) { EnvironmentVariable::create([ 'key' => $key, 'value' => $generatedValue, @@ -2099,7 +1976,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } $defaultLabels = defaultLabels($resource->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id); $serviceLabels = $serviceLabels->merge($defaultLabels); - if (!$isDatabase && $fqdns->count() > 0) { + if (! $isDatabase && $fqdns->count() > 0) { if ($fqdns) { $shouldGenerateLabelsExactly = $resource->server->settings->generate_exact_labels; if ($shouldGenerateLabelsExactly) { @@ -2167,7 +2044,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); - if (!data_get($service, 'restart')) { + if (! data_get($service, 'restart')) { data_set($service, 'restart', RESTART_MODE); } if (data_get($service, 'restart') === 'no' || data_get($service, 'exclude_from_hc')) { @@ -2206,21 +2083,21 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $parsedServiceVariables->put('COOLIFY_CONTAINER_NAME', "$serviceName-{$resource->uuid}"); // TODO: move this in a shared function - if (!$parsedServiceVariables->has('COOLIFY_APP_NAME')) { + if (! $parsedServiceVariables->has('COOLIFY_APP_NAME')) { $parsedServiceVariables->put('COOLIFY_APP_NAME', "\"{$resource->name}\""); } - if (!$parsedServiceVariables->has('COOLIFY_SERVER_IP')) { + if (! $parsedServiceVariables->has('COOLIFY_SERVER_IP')) { $parsedServiceVariables->put('COOLIFY_SERVER_IP', "\"{$resource->destination->server->ip}\""); } - if (!$parsedServiceVariables->has('COOLIFY_ENVIRONMENT_NAME')) { + if (! $parsedServiceVariables->has('COOLIFY_ENVIRONMENT_NAME')) { $parsedServiceVariables->put('COOLIFY_ENVIRONMENT_NAME', "\"{$resource->environment->name}\""); } - if (!$parsedServiceVariables->has('COOLIFY_PROJECT_NAME')) { + if (! $parsedServiceVariables->has('COOLIFY_PROJECT_NAME')) { $parsedServiceVariables->put('COOLIFY_PROJECT_NAME', "\"{$resource->project()->name}\""); } $parsedServiceVariables = $parsedServiceVariables->map(function ($value, $key) use ($envs_from_coolify) { - if (!str($value)->startsWith('$')) { + if (! str($value)->startsWith('$')) { $found_env = $envs_from_coolify->where('key', $key)->first(); if ($found_env) { return $found_env->value; @@ -2304,7 +2181,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($serviceLabels->count() > 0) { $removedLabels = collect([]); $serviceLabels = $serviceLabels->filter(function ($serviceLabel, $serviceLabelName) use ($removedLabels) { - if (!str($serviceLabel)->contains('=')) { + if (! str($serviceLabel)->contains('=')) { $removedLabels->put($serviceLabelName, $serviceLabel); return false; @@ -2324,11 +2201,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $topLevelVolumes, $pull_request_id) { if (is_string($volume)) { $volume = str($volume); - if ($volume->contains(':') && !$volume->startsWith('/')) { + if ($volume->contains(':') && ! $volume->startsWith('/')) { $name = $volume->before(':'); $mount = $volume->after(':'); if ($name->startsWith('.') || $name->startsWith('~')) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + $dir = base_configuration_dir().'/applications/'.$resource->uuid; if ($name->startsWith('.')) { $name = $name->replaceFirst('.', $dir); } @@ -2336,12 +2213,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $name = $name->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { - $name = $name . "-pr-$pull_request_id"; + $name = $name."-pr-$pull_request_id"; } $volume = str("$name:$mount"); } else { if ($pull_request_id !== 0) { - $name = $name . "-pr-$pull_request_id"; + $name = $name."-pr-$pull_request_id"; $volume = str("$name:$mount"); if ($topLevelVolumes->has($name)) { $v = $topLevelVolumes->get($name); @@ -2380,7 +2257,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $name = $volume->before(':'); $mount = $volume->after(':'); if ($pull_request_id !== 0) { - $name = $name . "-pr-$pull_request_id"; + $name = $name."-pr-$pull_request_id"; } $volume = str("$name:$mount"); } @@ -2391,7 +2268,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $read_only = data_get($volume, 'read_only'); if ($source && $target) { if ((str($source)->startsWith('.') || str($source)->startsWith('~'))) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + $dir = base_configuration_dir().'/applications/'.$resource->uuid; if (str($source, '.')) { $source = str($source)->replaceFirst('.', $dir); } @@ -2399,23 +2276,23 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $source = str($source)->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { - $source = $source . "-pr-$pull_request_id"; + $source = $source."-pr-$pull_request_id"; } if ($read_only) { - data_set($volume, 'source', $source . ':' . $target . ':ro'); + data_set($volume, 'source', $source.':'.$target.':ro'); } else { - data_set($volume, 'source', $source . ':' . $target); + data_set($volume, 'source', $source.':'.$target); } } else { if ($pull_request_id !== 0) { - $source = $source . "-pr-$pull_request_id"; + $source = $source."-pr-$pull_request_id"; } if ($read_only) { - data_set($volume, 'source', $source . ':' . $target . ':ro'); + data_set($volume, 'source', $source.':'.$target.':ro'); } else { - data_set($volume, 'source', $source . ':' . $target); + data_set($volume, 'source', $source.':'.$target); } - if (!str($source)->startsWith('/')) { + if (! str($source)->startsWith('/')) { if ($topLevelVolumes->has($source)) { $v = $topLevelVolumes->get($source); if (data_get($v, 'driver_opts.type') === 'cifs') { @@ -2448,11 +2325,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $topLevelVolumes, $pull_request_id) { if (is_string($volume)) { $volume = str($volume); - if ($volume->contains(':') && !$volume->startsWith('/')) { + if ($volume->contains(':') && ! $volume->startsWith('/')) { $name = $volume->before(':'); $mount = $volume->after(':'); if ($name->startsWith('.') || $name->startsWith('~')) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + $dir = base_configuration_dir().'/applications/'.$resource->uuid; if ($name->startsWith('.')) { $name = $name->replaceFirst('.', $dir); } @@ -2460,13 +2337,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $name = $name->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { - $name = $name . "-pr-$pull_request_id"; + $name = $name."-pr-$pull_request_id"; } $volume = str("$name:$mount"); } else { if ($pull_request_id !== 0) { $uuid = $resource->uuid; - $name = $uuid . "-$name-pr-$pull_request_id"; + $name = $uuid."-$name-pr-$pull_request_id"; $volume = str("$name:$mount"); if ($topLevelVolumes->has($name)) { $v = $topLevelVolumes->get($name); @@ -2485,7 +2362,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } else { $uuid = $resource->uuid; - $name = str($uuid . "-$name"); + $name = str($uuid."-$name"); $volume = str("$name:$mount"); if ($topLevelVolumes->has($name->value())) { $v = $topLevelVolumes->get($name->value()); @@ -2508,7 +2385,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $name = $volume->before(':'); $mount = $volume->after(':'); if ($pull_request_id !== 0) { - $name = $name . "-pr-$pull_request_id"; + $name = $name."-pr-$pull_request_id"; } $volume = str("$name:$mount"); } @@ -2520,7 +2397,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($source && $target) { $uuid = $resource->uuid; if ((str($source)->startsWith('.') || str($source)->startsWith('~') || str($source)->startsWith('/'))) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + $dir = base_configuration_dir().'/applications/'.$resource->uuid; if (str($source, '.')) { $source = str($source)->replaceFirst('.', $dir); } @@ -2528,22 +2405,22 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $source = str($source)->replaceFirst('~', $dir); } if ($read_only) { - data_set($volume, 'source', $source . ':' . $target . ':ro'); + data_set($volume, 'source', $source.':'.$target.':ro'); } else { - data_set($volume, 'source', $source . ':' . $target); + data_set($volume, 'source', $source.':'.$target); } } else { if ($pull_request_id === 0) { - $source = $uuid . "-$source"; + $source = $uuid."-$source"; } else { - $source = $uuid . "-$source-pr-$pull_request_id"; + $source = $uuid."-$source-pr-$pull_request_id"; } if ($read_only) { - data_set($volume, 'source', $source . ':' . $target . ':ro'); + data_set($volume, 'source', $source.':'.$target.':ro'); } else { - data_set($volume, 'source', $source . ':' . $target); + data_set($volume, 'source', $source.':'.$target); } - if (!str($source)->startsWith('/')) { + if (! str($source)->startsWith('/')) { if ($topLevelVolumes->has($source)) { $v = $topLevelVolumes->get($source); if (data_get($v, 'driver_opts.type') === 'cifs') { @@ -2576,7 +2453,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($pull_request_id !== 0 && count($serviceDependencies) > 0) { $serviceDependencies = $serviceDependencies->map(function ($dependency) use ($pull_request_id) { - return $dependency . "-pr-$pull_request_id"; + return $dependency."-pr-$pull_request_id"; }); data_set($service, 'depends_on', $serviceDependencies->toArray()); } @@ -2598,7 +2475,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); - if (!$networkExists) { + if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } @@ -2626,7 +2503,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); - if (!$definedNetworkExists) { + if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { if ($pull_request_id !== 0) { $topLevelNetworks->put($network, [ @@ -2744,12 +2621,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal 'application_id' => $resource->id, ])->first(); ['command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port] = parseEnvVariable($value); - if (!is_null($command)) { + if (! is_null($command)) { if ($command?->value() === 'FQDN' || $command?->value() === 'URL') { if (Str::lower($forService) === $serviceName) { $fqdn = generateFqdn($server, $containerName); } else { - $fqdn = generateFqdn($server, Str::lower($forService) . '-' . $resource->uuid); + $fqdn = generateFqdn($server, Str::lower($forService).'-'.$resource->uuid); } if ($port) { $fqdn = "$fqdn:$port"; @@ -2770,7 +2647,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } else { $generatedValue = generateEnvValue($command); - if (!$foundEnv) { + if (! $foundEnv) { EnvironmentVariable::create([ 'key' => $key, 'value' => $generatedValue, @@ -2942,7 +2819,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); - if (!data_get($service, 'restart')) { + if (! data_get($service, 'restart')) { data_set($service, 'restart', RESTART_MODE); } data_set($service, 'container_name', $containerName); @@ -2953,7 +2830,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal }); if ($pull_request_id !== 0) { $services->each(function ($service, $serviceName) use ($pull_request_id, $services) { - $services[$serviceName . "-pr-$pull_request_id"] = $service; + $services[$serviceName."-pr-$pull_request_id"] = $service; data_forget($services, $serviceName); }); } @@ -2981,7 +2858,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $uuid = data_get($resource, 'uuid'); $compose = data_get($resource, 'docker_compose_raw'); - if (!$compose) { + if (! $compose) { return collect([]); } @@ -3374,29 +3251,29 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $isDirectory = data_get($foundConfig, 'is_directory'); } else { // if isDirectory is not set (or false) & content is also not set, we assume it is a directory - if ((is_null($isDirectory) || !$isDirectory) && is_null($content)) { + if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { $isDirectory = true; } } } if ($type->value() === 'bind') { if ($source->value() === '/var/run/docker.sock') { - $volume = $source->value() . ':' . $target->value(); + $volume = $source->value().':'.$target->value(); } elseif ($source->value() === '/tmp' || $source->value() === '/tmp/') { - $volume = $source->value() . ':' . $target->value(); + $volume = $source->value().':'.$target->value(); } else { if ((int) $resource->compose_parsing_version >= 4) { if ($isApplication) { - $mainDirectory = str(base_configuration_dir() . '/applications/' . $uuid); + $mainDirectory = str(base_configuration_dir().'/applications/'.$uuid); } elseif ($isService) { - $mainDirectory = str(base_configuration_dir() . '/services/' . $uuid); + $mainDirectory = str(base_configuration_dir().'/services/'.$uuid); } } else { - $mainDirectory = str(base_configuration_dir() . '/applications/' . $uuid); + $mainDirectory = str(base_configuration_dir().'/applications/'.$uuid); } $source = replaceLocalSource($source, $mainDirectory); if ($isApplication && $isPullRequest) { - $source = $source . "-pr-$pullRequestId"; + $source = $source."-pr-$pullRequestId"; } LocalFileVolume::updateOrCreate( [ @@ -3416,12 +3293,12 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int if (isDev()) { if ((int) $resource->compose_parsing_version >= 4) { if ($isApplication) { - $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/' . $uuid); + $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/'.$uuid); } elseif ($isService) { - $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/services/' . $uuid); + $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/services/'.$uuid); } } else { - $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/' . $uuid); + $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/'.$uuid); } } $volume = "$source:$target"; @@ -3488,7 +3365,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $depends_on = $newDependsOn; } } - if (!$use_network_mode) { + if (! $use_network_mode) { if ($topLevel->get('networks')?->count() > 0) { foreach ($topLevel->get('networks') as $networkName => $network) { if ($networkName === 'default') { @@ -3501,7 +3378,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $networkExists = $networks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); - if (!$networkExists) { + if (! $networkExists) { $networks->put($networkName, null); } } @@ -3509,7 +3386,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $baseNetworkExists = $networks->contains(function ($value, $_) use ($baseNetwork) { return $value == $baseNetwork; }); - if (!$baseNetworkExists) { + if (! $baseNetworkExists) { foreach ($baseNetwork as $network) { $topLevel->get('networks')->put($network, [ 'name' => $network, @@ -3541,7 +3418,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $networks_temp = collect(); - if (!$use_network_mode) { + if (! $use_network_mode) { foreach ($networks as $key => $network) { if (gettype($network) === 'string') { // networks: @@ -3572,7 +3449,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $normalEnvironments = $environment->diffKeys($allMagicEnvironments); $normalEnvironments = $normalEnvironments->filter(function ($value, $key) { - return !str($value)->startsWith('SERVICE_'); + return ! str($value)->startsWith('SERVICE_'); }); foreach ($normalEnvironments as $key => $value) { @@ -3592,7 +3469,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int continue; } - if (!$value->startsWith('$')) { + if (! $value->startsWith('$')) { continue; } if ($key->value() === $parsedValue->value()) { @@ -3723,7 +3600,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $defaultLabels = defaultLabels($resource->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id); } // Add COOLIFY_FQDN & COOLIFY_URL to environment - if (!$isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { + if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { $coolifyEnvironments->put('COOLIFY_URL', $fqdns->implode(',')); $urls = $fqdns->map(function ($fqdn) { @@ -3735,7 +3612,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int if ($environment->count() > 0) { $environment = $environment->filter(function ($value, $key) { - return !str($key)->startsWith('SERVICE_FQDN_'); + return ! str($key)->startsWith('SERVICE_FQDN_'); })->map(function ($value, $key) use ($resource) { // if value is empty, set it to null so if you set the environment variable in the .env file (Coolify's UI), it will used if (str($value)->isEmpty()) { @@ -3762,7 +3639,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int }); } } - if (!$isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { + if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { if ($isApplication) { $shouldGenerateLabelsExactly = $resource->destination->server->settings->generate_exact_labels; $uuid = $resource->uuid; @@ -3855,7 +3732,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int 'restart' => $restart->value(), 'labels' => $serviceLabels, ]); - if (!$use_network_mode) { + if (! $use_network_mode) { $payload['networks'] = $networks_temp; } if ($ports->count() > 0) { @@ -3915,7 +3792,7 @@ function isAssociativeArray($array) $array = $array->toArray(); } - if (!is_array($array)) { + if (! is_array($array)) { throw new \InvalidArgumentException('Input must be an array or a Collection.'); } @@ -4028,7 +3905,7 @@ function instanceSettings() function loadConfigFromGit(string $repository, string $branch, string $base_directory, int $server_id, int $team_id) { $server = Server::find($server_id)->where('team_id', $team_id)->first(); - if (!$server) { + if (! $server) { return; } $uuid = new Cuid2; @@ -4055,7 +3932,7 @@ function loadConfigFromGit(string $repository, string $branch, string $base_dire function loggy($message = null, array $context = []) { - if (!isDev()) { + if (! isDev()) { return; } if (function_exists('ray') && config('app.debug')) { @@ -4090,7 +3967,7 @@ function isEmailRateLimited(string $limiterKey, int $decaySeconds = 3600, ?calla $limiterKey, $maxAttempts = 0, function () use (&$rateLimited, &$limiterKey, $callbackOnSuccess) { - isDev() && loggy('Rate limit not reached for ' . $limiterKey); + isDev() && loggy('Rate limit not reached for '.$limiterKey); $rateLimited = false; if ($callbackOnSuccess) { @@ -4099,8 +3976,8 @@ function isEmailRateLimited(string $limiterKey, int $decaySeconds = 3600, ?calla }, $decaySeconds, ); - if (!$executed) { - isDev() && loggy('Rate limit reached for ' . $limiterKey . '. Rate limiter will be disabled for ' . $decaySeconds . ' seconds.'); + if (! $executed) { + isDev() && loggy('Rate limit reached for '.$limiterKey.'. Rate limiter will be disabled for '.$decaySeconds.' seconds.'); $rateLimited = true; } From cf21ae13f1ba7f9ec5d92737f5fdf9b6b0def882 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:47:05 +0100 Subject: [PATCH 36/80] feat: Email Notification Settings Model --- app/Models/EmailNotificationSettings.php | 78 ++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 app/Models/EmailNotificationSettings.php diff --git a/app/Models/EmailNotificationSettings.php b/app/Models/EmailNotificationSettings.php new file mode 100644 index 000000000..640a44b7a --- /dev/null +++ b/app/Models/EmailNotificationSettings.php @@ -0,0 +1,78 @@ + 'boolean', + 'smtp_from_address' => 'encrypted', + 'smtp_recipients' => 'encrypted', + 'smtp_host' => 'encrypted', + 'smtp_port' => 'integer', + 'smtp_username' => 'encrypted', + 'smtp_password' => 'encrypted', + 'smtp_timeout' => 'integer', + + 'resend_enabled' => 'boolean', + 'resend_api_key' => 'encrypted', + + 'use_instance_email_settings' => 'boolean', + + 'deployment_success_email_notifications' => 'boolean', + 'deployment_failure_email_notifications' => 'boolean', + 'status_change_email_notifications' => 'boolean', + 'backup_success_email_notifications' => 'boolean', + 'backup_failure_email_notifications' => 'boolean', + 'scheduled_task_success_email_notifications' => 'boolean', + 'scheduled_task_failure_email_notifications' => 'boolean', + 'server_disk_usage_email_notifications' => 'boolean', + ]; + + public function team() + { + return $this->belongsTo(Team::class); + } + + public function isEnabled() + { + if (isCloud()) { + return true; + } + + return $this->smtp_enabled || $this->resend_enabled || $this->use_instance_email_settings; + } +} From b5351448ed9f5fb8873ca5766499bfa72b830df7 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:50:23 +0100 Subject: [PATCH 37/80] feat: Telegram notification settings Model --- app/Models/TelegramNotificationSettings.php | 85 +++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 app/Models/TelegramNotificationSettings.php diff --git a/app/Models/TelegramNotificationSettings.php b/app/Models/TelegramNotificationSettings.php new file mode 100644 index 000000000..2edca14ff --- /dev/null +++ b/app/Models/TelegramNotificationSettings.php @@ -0,0 +1,85 @@ + 'boolean', + 'telegram_token' => 'encrypted', + 'telegram_chat_id' => 'encrypted', + + 'deployment_success_telegram_notifications' => 'boolean', + 'deployment_failure_telegram_notifications' => 'boolean', + 'status_change_telegram_notifications' => 'boolean', + 'backup_success_telegram_notifications' => 'boolean', + 'backup_failure_telegram_notifications' => 'boolean', + 'scheduled_task_success_telegram_notifications' => 'boolean', + 'scheduled_task_failure_telegram_notifications' => 'boolean', + 'docker_cleanup_telegram_notifications' => 'boolean', + 'server_disk_usage_telegram_notifications' => 'boolean', + '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', + ]; + + public function team() + { + return $this->belongsTo(Team::class); + } + + public function isEnabled() + { + return $this->telegram_enabled; + } +} From 2166899721b89ac5449e3f60136c10c70b4ca567 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:52:50 +0100 Subject: [PATCH 38/80] feat: Discord notification settings Model --- app/Models/DiscordNotificationSettings.php | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 app/Models/DiscordNotificationSettings.php diff --git a/app/Models/DiscordNotificationSettings.php b/app/Models/DiscordNotificationSettings.php new file mode 100644 index 000000000..619393ddc --- /dev/null +++ b/app/Models/DiscordNotificationSettings.php @@ -0,0 +1,59 @@ + 'boolean', + 'discord_webhook_url' => 'encrypted', + + 'deployment_success_discord_notifications' => 'boolean', + 'deployment_failure_discord_notifications' => 'boolean', + 'status_change_discord_notifications' => 'boolean', + 'backup_success_discord_notifications' => 'boolean', + 'backup_failure_discord_notifications' => 'boolean', + 'scheduled_task_success_discord_notifications' => 'boolean', + 'scheduled_task_failure_discord_notifications' => 'boolean', + 'docker_cleanup_discord_notifications' => 'boolean', + 'server_disk_usage_discord_notifications' => 'boolean', + 'server_reachable_discord_notifications' => 'boolean', + 'server_unreachable_discord_notifications' => 'boolean', + ]; + + public function team() + { + return $this->belongsTo(Team::class); + } + + public function isEnabled() + { + return $this->discord_enabled; + } +} From 868d80bde62115a56a5195fa2f9842d8a6a87a5d Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:54:52 +0100 Subject: [PATCH 39/80] feat: Slack notification settings Model --- app/Models/SlackNotificationSettings.php | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 app/Models/SlackNotificationSettings.php diff --git a/app/Models/SlackNotificationSettings.php b/app/Models/SlackNotificationSettings.php new file mode 100644 index 000000000..48153f2ea --- /dev/null +++ b/app/Models/SlackNotificationSettings.php @@ -0,0 +1,59 @@ + 'boolean', + 'slack_webhook_url' => 'encrypted', + + 'deployment_success_slack_notifications' => 'boolean', + 'deployment_failure_slack_notifications' => 'boolean', + 'status_change_slack_notifications' => 'boolean', + 'backup_success_slack_notifications' => 'boolean', + 'backup_failure_slack_notifications' => 'boolean', + 'scheduled_task_success_slack_notifications' => 'boolean', + 'scheduled_task_failure_slack_notifications' => 'boolean', + 'docker_cleanup_slack_notifications' => 'boolean', + 'server_disk_usage_slack_notifications' => 'boolean', + 'server_reachable_slack_notifications' => 'boolean', + 'server_unreachable_slack_notifications' => 'boolean', + ]; + + public function team() + { + return $this->belongsTo(Team::class); + } + + public function isEnabled() + { + return $this->slack_enabled; + } +} From 119c18468a9b549f9006d429d2c69bcb9fd026d8 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:03:43 +0100 Subject: [PATCH 40/80] chore: public settings for email notification --- app/Livewire/Notifications/Email.php | 146 +++++++++++++-------------- 1 file changed, 72 insertions(+), 74 deletions(-) diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index a4a16e5e5..7af25694f 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -2,6 +2,7 @@ namespace App\Livewire\Notifications; +use App\Models\EmailNotificationSettings; use App\Models\Team; use App\Notifications\Test; use Illuminate\Support\Facades\RateLimiter; @@ -13,6 +14,8 @@ class Email extends Component { public Team $team; + public EmailNotificationSettings $settings; + #[Locked] public string $emails; @@ -96,6 +99,7 @@ class Email extends Component try { $this->team = auth()->user()->currentTeam(); $this->emails = auth()->user()->email; + $this->settings = $this->team->emailNotificationSettings; $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); @@ -106,67 +110,64 @@ class Email extends Component { if ($toModel) { $this->validate(); - $settings = $this->team->emailNotificationSettings; - $settings->smtp_enabled = $this->smtpEnabled; - $settings->smtp_from_address = $this->smtpFromAddress; - $settings->smtp_from_name = $this->smtpFromName; - $settings->smtp_recipients = $this->smtpRecipients; - $settings->smtp_host = $this->smtpHost; - $settings->smtp_port = $this->smtpPort; - $settings->smtp_encryption = $this->smtpEncryption; - $settings->smtp_username = $this->smtpUsername; - $settings->smtp_password = $this->smtpPassword; - $settings->smtp_timeout = $this->smtpTimeout; + $this->settings->smtp_enabled = $this->smtpEnabled; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; + $this->settings->smtp_recipients = $this->smtpRecipients; + $this->settings->smtp_host = $this->smtpHost; + $this->settings->smtp_port = $this->smtpPort; + $this->settings->smtp_encryption = $this->smtpEncryption; + $this->settings->smtp_username = $this->smtpUsername; + $this->settings->smtp_password = $this->smtpPassword; + $this->settings->smtp_timeout = $this->smtpTimeout; - $settings->resend_enabled = $this->resendEnabled; - $settings->resend_api_key = $this->resendApiKey; + $this->settings->resend_enabled = $this->resendEnabled; + $this->settings->resend_api_key = $this->resendApiKey; - $settings->use_instance_email_settings = $this->useInstanceEmailSettings; + $this->settings->use_instance_email_settings = $this->useInstanceEmailSettings; - $settings->deployment_success_email_notifications = $this->deploymentSuccessEmailNotifications; - $settings->deployment_failure_email_notifications = $this->deploymentFailureEmailNotifications; - $settings->status_change_email_notifications = $this->statusChangeEmailNotifications; - $settings->backup_success_email_notifications = $this->backupSuccessEmailNotifications; - $settings->backup_failure_email_notifications = $this->backupFailureEmailNotifications; - $settings->scheduled_task_success_email_notifications = $this->scheduledTaskSuccessEmailNotifications; - $settings->scheduled_task_failure_email_notifications = $this->scheduledTaskFailureEmailNotifications; - $settings->docker_cleanup_email_notifications = $this->dockerCleanupEmailNotifications; - $settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; - $settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; - $settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; + $this->settings->deployment_success_email_notifications = $this->deploymentSuccessEmailNotifications; + $this->settings->deployment_failure_email_notifications = $this->deploymentFailureEmailNotifications; + $this->settings->status_change_email_notifications = $this->statusChangeEmailNotifications; + $this->settings->backup_success_email_notifications = $this->backupSuccessEmailNotifications; + $this->settings->backup_failure_email_notifications = $this->backupFailureEmailNotifications; + $this->settings->scheduled_task_success_email_notifications = $this->scheduledTaskSuccessEmailNotifications; + $this->settings->scheduled_task_failure_email_notifications = $this->scheduledTaskFailureEmailNotifications; + $this->settings->docker_cleanup_email_notifications = $this->dockerCleanupEmailNotifications; + $this->settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; + $this->settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; + $this->settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; - $settings->save(); + $this->settings->save(); refreshSession(); } else { - $settings = $this->team->emailNotificationSettings; + $this->smtpEnabled = $this->settings->smtp_enabled; + $this->smtpFromAddress = $this->settings->smtp_from_address; + $this->smtpFromName = $this->settings->smtp_from_name; + $this->smtpRecipients = $this->settings->smtp_recipients; + $this->smtpHost = $this->settings->smtp_host; + $this->smtpPort = $this->settings->smtp_port; + $this->smtpEncryption = $this->settings->smtp_encryption; + $this->smtpUsername = $this->settings->smtp_username; + $this->smtpPassword = $this->settings->smtp_password; + $this->smtpTimeout = $this->settings->smtp_timeout; - $this->smtpEnabled = $settings->smtp_enabled; - $this->smtpFromAddress = $settings->smtp_from_address; - $this->smtpFromName = $settings->smtp_from_name; - $this->smtpRecipients = $settings->smtp_recipients; - $this->smtpHost = $settings->smtp_host; - $this->smtpPort = $settings->smtp_port; - $this->smtpEncryption = $settings->smtp_encryption; - $this->smtpUsername = $settings->smtp_username; - $this->smtpPassword = $settings->smtp_password; - $this->smtpTimeout = $settings->smtp_timeout; + $this->resendEnabled = $this->settings->resend_enabled; + $this->resendApiKey = $this->settings->resend_api_key; - $this->resendEnabled = $settings->resend_enabled; - $this->resendApiKey = $settings->resend_api_key; + $this->useInstanceEmailSettings = $this->settings->use_instance_email_settings; - $this->useInstanceEmailSettings = $settings->use_instance_email_settings; - - $this->deploymentSuccessEmailNotifications = $settings->deployment_success_email_notifications; - $this->deploymentFailureEmailNotifications = $settings->deployment_failure_email_notifications; - $this->statusChangeEmailNotifications = $settings->status_change_email_notifications; - $this->backupSuccessEmailNotifications = $settings->backup_success_email_notifications; - $this->backupFailureEmailNotifications = $settings->backup_failure_email_notifications; - $this->scheduledTaskSuccessEmailNotifications = $settings->scheduled_task_success_email_notifications; - $this->scheduledTaskFailureEmailNotifications = $settings->scheduled_task_failure_email_notifications; - $this->dockerCleanupEmailNotifications = $settings->docker_cleanup_email_notifications; - $this->serverDiskUsageEmailNotifications = $settings->server_disk_usage_email_notifications; - $this->serverReachableEmailNotifications = $settings->server_reachable_email_notifications; - $this->serverUnreachableEmailNotifications = $settings->server_unreachable_email_notifications; + $this->deploymentSuccessEmailNotifications = $this->settings->deployment_success_email_notifications; + $this->deploymentFailureEmailNotifications = $this->settings->deployment_failure_email_notifications; + $this->statusChangeEmailNotifications = $this->settings->status_change_email_notifications; + $this->backupSuccessEmailNotifications = $this->settings->backup_success_email_notifications; + $this->backupFailureEmailNotifications = $this->settings->backup_failure_email_notifications; + $this->scheduledTaskSuccessEmailNotifications = $this->settings->scheduled_task_success_email_notifications; + $this->scheduledTaskFailureEmailNotifications = $this->settings->scheduled_task_failure_email_notifications; + $this->dockerCleanupEmailNotifications = $this->settings->docker_cleanup_email_notifications; + $this->serverDiskUsageEmailNotifications = $this->settings->server_disk_usage_email_notifications; + $this->serverReachableEmailNotifications = $this->settings->server_reachable_email_notifications; + $this->serverUnreachableEmailNotifications = $this->settings->server_unreachable_email_notifications; } } @@ -238,24 +239,22 @@ class Email extends Component 'smtpEncryption.required' => 'Encryption type is required.', ]); - $settings = $this->team->emailNotificationSettings; - - $settings->resend_enabled = false; - $settings->use_instance_email_settings = false; + $this->settings->resend_enabled = false; + $this->settings->use_instance_email_settings = false; $this->resendEnabled = false; $this->useInstanceEmailSettings = false; - $settings->smtp_enabled = $this->smtpEnabled; - $settings->smtp_from_address = $this->smtpFromAddress; - $settings->smtp_from_name = $this->smtpFromName; - $settings->smtp_host = $this->smtpHost; - $settings->smtp_port = $this->smtpPort; - $settings->smtp_encryption = $this->smtpEncryption; - $settings->smtp_username = $this->smtpUsername; - $settings->smtp_password = $this->smtpPassword; - $settings->smtp_timeout = $this->smtpTimeout; + $this->settings->smtp_enabled = $this->smtpEnabled; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; + $this->settings->smtp_host = $this->smtpHost; + $this->settings->smtp_port = $this->smtpPort; + $this->settings->smtp_encryption = $this->smtpEncryption; + $this->settings->smtp_username = $this->smtpUsername; + $this->settings->smtp_password = $this->smtpPassword; + $this->settings->smtp_timeout = $this->smtpTimeout; - $settings->save(); + $this->settings->save(); refreshSession(); $this->dispatch('success', 'SMTP settings updated.'); } catch (\Throwable $e) { @@ -280,19 +279,18 @@ class Email extends Component 'smtpFromAddress.email' => 'Please enter a valid email address.', 'smtpFromName.required' => 'From Name is required.', ]); - $settings = $this->team->emailNotificationSettings; - $settings->smtp_enabled = false; - $settings->use_instance_email_settings = false; + $this->settings->smtp_enabled = false; + $this->settings->use_instance_email_settings = false; $this->smtpEnabled = false; $this->useInstanceEmailSettings = false; - $settings->resend_enabled = $this->resendEnabled; - $settings->resend_api_key = $this->resendApiKey; - $settings->smtp_from_address = $this->smtpFromAddress; - $settings->smtp_from_name = $this->smtpFromName; + $this->settings->resend_enabled = $this->resendEnabled; + $this->settings->resend_api_key = $this->resendApiKey; + $this->settings->smtp_from_address = $this->smtpFromAddress; + $this->settings->smtp_from_name = $this->smtpFromName; - $settings->save(); + $this->settings->save(); refreshSession(); $this->dispatch('success', 'Resend settings updated.'); } catch (\Throwable $e) { From c27e2e328f06b7f78267acf5da9899f30d9ce229 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:37:36 +0100 Subject: [PATCH 41/80] chore: remove waitlist redirect --- app/Providers/FortifyServiceProvider.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index bbbf48345..ed27a158a 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -50,13 +50,10 @@ class FortifyServiceProvider extends ServiceProvider if (! $settings->is_registration_enabled) { return redirect()->route('login'); } - if (config('constants.waitlist.enabled')) { - return redirect()->route('waitlist.index'); - } else { - return view('auth.register', [ - 'isFirstUser' => $isFirstUser, - ]); - } + + return view('auth.register', [ + 'isFirstUser' => $isFirstUser, + ]); }); Fortify::loginView(function () { From 5210218a45a24da5c830ca2482b769cd983559d9 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:38:25 +0100 Subject: [PATCH 42/80] feat: New Discord notification UI --- app/Livewire/Notifications/Discord.php | 78 +++++++++++++------ .../livewire/notifications/discord.blade.php | 56 +++++++++---- 2 files changed, 94 insertions(+), 40 deletions(-) diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php index 7a177a227..c5ec471d7 100644 --- a/app/Livewire/Notifications/Discord.php +++ b/app/Livewire/Notifications/Discord.php @@ -2,6 +2,7 @@ namespace App\Livewire\Notifications; +use App\Models\DiscordNotificationSettings; use App\Models\Team; use App\Notifications\Test; use Livewire\Attributes\Validate; @@ -11,6 +12,8 @@ class Discord extends Component { public Team $team; + public DiscordNotificationSettings $settings; + #[Validate(['boolean'])] public bool $discordEnabled = false; @@ -18,27 +21,43 @@ class Discord extends Component public ?string $discordWebhookUrl = null; #[Validate(['boolean'])] - public bool $discordNotificationsTest = false; + public bool $deploymentSuccessDiscordNotifications = false; #[Validate(['boolean'])] - public bool $discordNotificationsDeployments = false; + public bool $deploymentFailureDiscordNotifications = true; #[Validate(['boolean'])] - public bool $discordNotificationsStatusChanges = false; + public bool $statusChangeDiscordNotifications = false; #[Validate(['boolean'])] - public bool $discordNotificationsDatabaseBackups = false; + public bool $backupSuccessDiscordNotifications = false; #[Validate(['boolean'])] - public bool $discordNotificationsScheduledTasks = false; + public bool $backupFailureDiscordNotifications = true; #[Validate(['boolean'])] - public bool $discordNotificationsServerDiskUsage = false; + public bool $scheduledTaskSuccessDiscordNotifications = false; + + #[Validate(['boolean'])] + public bool $scheduledTaskFailureDiscordNotifications = true; + + #[Validate(['boolean'])] + public bool $dockerCleanupDiscordNotifications = false; + + #[Validate(['boolean'])] + public bool $serverDiskUsageDiscordNotifications = true; + + #[Validate(['boolean'])] + public bool $serverReachableDiscordNotifications = false; + + #[Validate(['boolean'])] + public bool $serverUnreachableDiscordNotifications = true; public function mount() { try { $this->team = auth()->user()->currentTeam(); + $this->settings = $this->team->discordNotificationSettings; $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); @@ -49,25 +68,38 @@ class Discord extends Component { if ($toModel) { $this->validate(); - $this->team->discord_enabled = $this->discordEnabled; - $this->team->discord_webhook_url = $this->discordWebhookUrl; - $this->team->discord_notifications_test = $this->discordNotificationsTest; - $this->team->discord_notifications_deployments = $this->discordNotificationsDeployments; - $this->team->discord_notifications_status_changes = $this->discordNotificationsStatusChanges; - $this->team->discord_notifications_database_backups = $this->discordNotificationsDatabaseBackups; - $this->team->discord_notifications_scheduled_tasks = $this->discordNotificationsScheduledTasks; - $this->team->discord_notifications_server_disk_usage = $this->discordNotificationsServerDiskUsage; - $this->team->save(); + $this->settings->discord_enabled = $this->discordEnabled; + $this->settings->discord_webhook_url = $this->discordWebhookUrl; + + $this->settings->deployment_success_discord_notifications = $this->deploymentSuccessDiscordNotifications; + $this->settings->deployment_failure_discord_notifications = $this->deploymentFailureDiscordNotifications; + $this->settings->status_change_discord_notifications = $this->statusChangeDiscordNotifications; + $this->settings->backup_success_discord_notifications = $this->backupSuccessDiscordNotifications; + $this->settings->backup_failure_discord_notifications = $this->backupFailureDiscordNotifications; + $this->settings->scheduled_task_success_discord_notifications = $this->scheduledTaskSuccessDiscordNotifications; + $this->settings->scheduled_task_failure_discord_notifications = $this->scheduledTaskFailureDiscordNotifications; + $this->settings->docker_cleanup_discord_notifications = $this->dockerCleanupDiscordNotifications; + $this->settings->server_disk_usage_discord_notifications = $this->serverDiskUsageDiscordNotifications; + $this->settings->server_reachable_discord_notifications = $this->serverReachableDiscordNotifications; + $this->settings->server_unreachable_discord_notifications = $this->serverUnreachableDiscordNotifications; + + $this->settings->save(); refreshSession(); } else { - $this->discordEnabled = $this->team->discord_enabled; - $this->discordWebhookUrl = $this->team->discord_webhook_url; - $this->discordNotificationsTest = $this->team->discord_notifications_test; - $this->discordNotificationsDeployments = $this->team->discord_notifications_deployments; - $this->discordNotificationsStatusChanges = $this->team->discord_notifications_status_changes; - $this->discordNotificationsDatabaseBackups = $this->team->discord_notifications_database_backups; - $this->discordNotificationsScheduledTasks = $this->team->discord_notifications_scheduled_tasks; - $this->discordNotificationsServerDiskUsage = $this->team->discord_notifications_server_disk_usage; + $this->discordEnabled = $this->settings->discord_enabled; + $this->discordWebhookUrl = $this->settings->discord_webhook_url; + + $this->deploymentSuccessDiscordNotifications = $this->settings->deployment_success_discord_notifications; + $this->deploymentFailureDiscordNotifications = $this->settings->deployment_failure_discord_notifications; + $this->statusChangeDiscordNotifications = $this->settings->status_change_discord_notifications; + $this->backupSuccessDiscordNotifications = $this->settings->backup_success_discord_notifications; + $this->backupFailureDiscordNotifications = $this->settings->backup_failure_discord_notifications; + $this->scheduledTaskSuccessDiscordNotifications = $this->settings->scheduled_task_success_discord_notifications; + $this->scheduledTaskFailureDiscordNotifications = $this->settings->scheduled_task_failure_discord_notifications; + $this->dockerCleanupDiscordNotifications = $this->settings->docker_cleanup_discord_notifications; + $this->serverDiskUsageDiscordNotifications = $this->settings->server_disk_usage_discord_notifications; + $this->serverReachableDiscordNotifications = $this->settings->server_reachable_discord_notifications; + $this->serverUnreachableDiscordNotifications = $this->settings->server_unreachable_discord_notifications; } } diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index af6f98b0a..0173e8d2e 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -3,7 +3,7 @@ Notifications | Coolify - +

Discord

@@ -12,7 +12,7 @@ @if ($discordEnabled) - Send Test Notifications + Send Test Notification @endif
@@ -24,20 +24,42 @@ id="discordWebhookUrl" label="Webhook" /> @if ($discordEnabled) -

Subscribe to events

-
- @if (isDev()) - - @endif - - - - - -
+

Notification Settings

+

+ Select events for which you would like to receive Discord notifications. +

+
+
+

Deployments

+
+ + + +
+
+
+

Backups

+
+ + +
+
+
+

Scheduled Tasks

+
+ + +
+
+
+

Server

+
+ + + + +
+
+
@endif
From b4b48692afb9cb3b32f7f770a7744408aea580f8 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:39:19 +0100 Subject: [PATCH 43/80] feat: New Slack notification UI --- app/Livewire/Notifications/Slack.php | 81 +++++++++++----- .../livewire/notifications/slack.blade.php | 92 ++++++++++++------- 2 files changed, 114 insertions(+), 59 deletions(-) diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php index edd32a071..7fa881641 100644 --- a/app/Livewire/Notifications/Slack.php +++ b/app/Livewire/Notifications/Slack.php @@ -2,6 +2,7 @@ namespace App\Livewire\Notifications; +use App\Models\SlackNotificationSettings; use App\Models\Team; use App\Notifications\Test; use Livewire\Attributes\Validate; @@ -11,6 +12,8 @@ class Slack extends Component { public Team $team; + public SlackNotificationSettings $settings; + #[Validate(['boolean'])] public bool $slackEnabled = false; @@ -18,27 +21,43 @@ class Slack extends Component public ?string $slackWebhookUrl = null; #[Validate(['boolean'])] - public bool $slackNotificationsTest = false; + public bool $deploymentSuccessSlackNotifications = false; #[Validate(['boolean'])] - public bool $slackNotificationsDeployments = false; + public bool $deploymentFailureSlackNotifications = true; #[Validate(['boolean'])] - public bool $slackNotificationsStatusChanges = false; + public bool $statusChangeSlackNotifications = false; #[Validate(['boolean'])] - public bool $slackNotificationsDatabaseBackups = false; + public bool $backupSuccessSlackNotifications = false; #[Validate(['boolean'])] - public bool $slackNotificationsScheduledTasks = false; + public bool $backupFailureSlackNotifications = true; #[Validate(['boolean'])] - public bool $slackNotificationsServerDiskUsage = false; + public bool $scheduledTaskSuccessSlackNotifications = false; + + #[Validate(['boolean'])] + public bool $scheduledTaskFailureSlackNotifications = true; + + #[Validate(['boolean'])] + public bool $dockerCleanupSlackNotifications = false; + + #[Validate(['boolean'])] + public bool $serverDiskUsageSlackNotifications = true; + + #[Validate(['boolean'])] + public bool $serverReachableSlackNotifications = false; + + #[Validate(['boolean'])] + public bool $serverUnreachableSlackNotifications = true; public function mount() { try { $this->team = auth()->user()->currentTeam(); + $this->settings = $this->team->slackNotificationSettings; $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); @@ -49,25 +68,38 @@ class Slack extends Component { if ($toModel) { $this->validate(); - $this->team->slack_enabled = $this->slackEnabled; - $this->team->slack_webhook_url = $this->slackWebhookUrl; - $this->team->slack_notifications_test = $this->slackNotificationsTest; - $this->team->slack_notifications_deployments = $this->slackNotificationsDeployments; - $this->team->slack_notifications_status_changes = $this->slackNotificationsStatusChanges; - $this->team->slack_notifications_database_backups = $this->slackNotificationsDatabaseBackups; - $this->team->slack_notifications_scheduled_tasks = $this->slackNotificationsScheduledTasks; - $this->team->slack_notifications_server_disk_usage = $this->slackNotificationsServerDiskUsage; - $this->team->save(); + $this->settings->slack_enabled = $this->slackEnabled; + $this->settings->slack_webhook_url = $this->slackWebhookUrl; + + $this->settings->deployment_success_slack_notifications = $this->deploymentSuccessSlackNotifications; + $this->settings->deployment_failure_slack_notifications = $this->deploymentFailureSlackNotifications; + $this->settings->status_change_slack_notifications = $this->statusChangeSlackNotifications; + $this->settings->backup_success_slack_notifications = $this->backupSuccessSlackNotifications; + $this->settings->backup_failure_slack_notifications = $this->backupFailureSlackNotifications; + $this->settings->scheduled_task_success_slack_notifications = $this->scheduledTaskSuccessSlackNotifications; + $this->settings->scheduled_task_failure_slack_notifications = $this->scheduledTaskFailureSlackNotifications; + $this->settings->docker_cleanup_slack_notifications = $this->dockerCleanupSlackNotifications; + $this->settings->server_disk_usage_slack_notifications = $this->serverDiskUsageSlackNotifications; + $this->settings->server_reachable_slack_notifications = $this->serverReachableSlackNotifications; + $this->settings->server_unreachable_slack_notifications = $this->serverUnreachableSlackNotifications; + + $this->settings->save(); refreshSession(); } else { - $this->slackEnabled = $this->team->slack_enabled; - $this->slackWebhookUrl = $this->team->slack_webhook_url; - $this->slackNotificationsTest = $this->team->slack_notifications_test; - $this->slackNotificationsDeployments = $this->team->slack_notifications_deployments; - $this->slackNotificationsStatusChanges = $this->team->slack_notifications_status_changes; - $this->slackNotificationsDatabaseBackups = $this->team->slack_notifications_database_backups; - $this->slackNotificationsScheduledTasks = $this->team->slack_notifications_scheduled_tasks; - $this->slackNotificationsServerDiskUsage = $this->team->slack_notifications_server_disk_usage; + $this->slackEnabled = $this->settings->slack_enabled; + $this->slackWebhookUrl = $this->settings->slack_webhook_url; + + $this->deploymentSuccessSlackNotifications = $this->settings->deployment_success_slack_notifications; + $this->deploymentFailureSlackNotifications = $this->settings->deployment_failure_slack_notifications; + $this->statusChangeSlackNotifications = $this->settings->status_change_slack_notifications; + $this->backupSuccessSlackNotifications = $this->settings->backup_success_slack_notifications; + $this->backupFailureSlackNotifications = $this->settings->backup_failure_slack_notifications; + $this->scheduledTaskSuccessSlackNotifications = $this->settings->scheduled_task_success_slack_notifications; + $this->scheduledTaskFailureSlackNotifications = $this->settings->scheduled_task_failure_slack_notifications; + $this->dockerCleanupSlackNotifications = $this->settings->docker_cleanup_slack_notifications; + $this->serverDiskUsageSlackNotifications = $this->settings->server_disk_usage_slack_notifications; + $this->serverReachableSlackNotifications = $this->settings->server_reachable_slack_notifications; + $this->serverUnreachableSlackNotifications = $this->settings->server_unreachable_slack_notifications; } } @@ -82,6 +114,7 @@ class Slack extends Component $this->saveModel(); } catch (\Throwable $e) { $this->slackEnabled = false; + return handleError($e, $this); } } @@ -127,4 +160,4 @@ class Slack extends Component { return view('livewire.notifications.slack'); } -} \ No newline at end of file +} diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index b3685173c..052581837 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -1,43 +1,65 @@
Notifications | Coolify - - -
-
-

Slack

- - Save + + + +
+

Slack

+ + Save + + @if ($slackEnabled) + + Send Test Notification - @if ($slackEnabled) - - Send Test Notifications - - @endif + @endif +
+
+ +
+ + + @if ($slackEnabled) +

Notification Settings

+

+ Select events for which you would like to receive Slack notifications. +

+
+
+

Deployments

+
+ + + +
-
- +
+

Backups

+
+ + +
- - - @if ($slackEnabled) -

Subscribe to events

-
- @if (isDev()) - - @endif - - - - - +
+

Scheduled Tasks

+
+ + +
- @endif +
+

Server

+
+ + + + +
+
+
+ @endif
\ No newline at end of file From bc726ddd6ee7b8224dfbfa354a7438723d5cef33 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:49:09 +0100 Subject: [PATCH 44/80] feat: new telegram UI --- app/Livewire/Notifications/Telegram.php | 165 ++++++++++++------ .../livewire/notifications/telegram.blade.php | 116 +++++++----- 2 files changed, 186 insertions(+), 95 deletions(-) diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index 15ec20577..c83020830 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -3,6 +3,7 @@ namespace App\Livewire\Notifications; use App\Models\Team; +use App\Models\TelegramNotificationSettings; use App\Notifications\Test; use Livewire\Attributes\Validate; use Livewire\Component; @@ -11,6 +12,8 @@ class Telegram extends Component { public Team $team; + public TelegramNotificationSettings $settings; + #[Validate(['boolean'])] public bool $telegramEnabled = false; @@ -21,42 +24,76 @@ class Telegram extends Component public ?string $telegramChatId = null; #[Validate(['boolean'])] - public bool $telegramNotificationsTest = false; + public bool $deploymentSuccessTelegramNotifications = false; #[Validate(['boolean'])] - public bool $telegramNotificationsDeployments = false; + public bool $deploymentFailureTelegramNotifications = true; #[Validate(['boolean'])] - public bool $telegramNotificationsStatusChanges = false; + public bool $statusChangeTelegramNotifications = false; #[Validate(['boolean'])] - public bool $telegramNotificationsDatabaseBackups = false; + public bool $backupSuccessTelegramNotifications = false; #[Validate(['boolean'])] - public bool $telegramNotificationsScheduledTasks = false; - - #[Validate(['nullable', 'string'])] - public ?string $telegramNotificationsTestMessageThreadId = null; - - #[Validate(['nullable', 'string'])] - public ?string $telegramNotificationsDeploymentsMessageThreadId = null; - - #[Validate(['nullable', 'string'])] - public ?string $telegramNotificationsStatusChangesMessageThreadId = null; - - #[Validate(['nullable', 'string'])] - public ?string $telegramNotificationsDatabaseBackupsMessageThreadId = null; - - #[Validate(['nullable', 'string'])] - public ?string $telegramNotificationsScheduledTasksThreadId = null; + public bool $backupFailureTelegramNotifications = true; #[Validate(['boolean'])] - public bool $telegramNotificationsServerDiskUsage = false; + public bool $scheduledTaskSuccessTelegramNotifications = false; + + #[Validate(['boolean'])] + public bool $scheduledTaskFailureTelegramNotifications = true; + + #[Validate(['boolean'])] + public bool $dockerCleanupTelegramNotifications = false; + + #[Validate(['boolean'])] + public bool $serverDiskUsageTelegramNotifications = true; + + #[Validate(['boolean'])] + public bool $serverReachableTelegramNotifications = false; + + #[Validate(['boolean'])] + public bool $serverUnreachableTelegramNotifications = true; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsDeploymentSuccessTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsDeploymentFailureTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsStatusChangeTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsBackupSuccessTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsBackupFailureTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsScheduledTaskSuccessTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsScheduledTaskFailureTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsDockerCleanupTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsServerDiskUsageTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsServerReachableTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsServerUnreachableTopicId = null; public function mount() { try { $this->team = auth()->user()->currentTeam(); + $this->settings = $this->team->telegramNotificationSettings; $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); @@ -67,39 +104,65 @@ class Telegram extends Component { if ($toModel) { $this->validate(); - $this->team->telegram_enabled = $this->telegramEnabled; - $this->team->telegram_token = $this->telegramToken; - $this->team->telegram_chat_id = $this->telegramChatId; - $this->team->telegram_notifications_test = $this->telegramNotificationsTest; - $this->team->telegram_notifications_deployments = $this->telegramNotificationsDeployments; - $this->team->telegram_notifications_status_changes = $this->telegramNotificationsStatusChanges; - $this->team->telegram_notifications_database_backups = $this->telegramNotificationsDatabaseBackups; - $this->team->telegram_notifications_scheduled_tasks = $this->telegramNotificationsScheduledTasks; - $this->team->telegram_notifications_test_message_thread_id = $this->telegramNotificationsTestMessageThreadId; - $this->team->telegram_notifications_deployments_message_thread_id = $this->telegramNotificationsDeploymentsMessageThreadId; - $this->team->telegram_notifications_status_changes_message_thread_id = $this->telegramNotificationsStatusChangesMessageThreadId; - $this->team->telegram_notifications_database_backups_message_thread_id = $this->telegramNotificationsDatabaseBackupsMessageThreadId; - $this->team->telegram_notifications_scheduled_tasks_thread_id = $this->telegramNotificationsScheduledTasksThreadId; - $this->team->telegram_notifications_server_disk_usage = $this->telegramNotificationsServerDiskUsage; - $this->team->save(); + $this->settings->telegram_enabled = $this->telegramEnabled; + $this->settings->telegram_token = $this->telegramToken; + $this->settings->telegram_chat_id = $this->telegramChatId; + + $this->settings->deployment_success_telegram_notifications = $this->deploymentSuccessTelegramNotifications; + $this->settings->deployment_failure_telegram_notifications = $this->deploymentFailureTelegramNotifications; + $this->settings->status_change_telegram_notifications = $this->statusChangeTelegramNotifications; + $this->settings->backup_success_telegram_notifications = $this->backupSuccessTelegramNotifications; + $this->settings->backup_failure_telegram_notifications = $this->backupFailureTelegramNotifications; + $this->settings->scheduled_task_success_telegram_notifications = $this->scheduledTaskSuccessTelegramNotifications; + $this->settings->scheduled_task_failure_telegram_notifications = $this->scheduledTaskFailureTelegramNotifications; + $this->settings->docker_cleanup_telegram_notifications = $this->dockerCleanupTelegramNotifications; + $this->settings->server_disk_usage_telegram_notifications = $this->serverDiskUsageTelegramNotifications; + $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_topic_id = $this->telegramNotificationsDockerCleanupTopicId; + $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->save(); refreshSession(); } else { - $this->telegramEnabled = $this->team->telegram_enabled; - $this->telegramToken = $this->team->telegram_token; - $this->telegramChatId = $this->team->telegram_chat_id; - $this->telegramNotificationsTest = $this->team->telegram_notifications_test; - $this->telegramNotificationsDeployments = $this->team->telegram_notifications_deployments; - $this->telegramNotificationsStatusChanges = $this->team->telegram_notifications_status_changes; - $this->telegramNotificationsDatabaseBackups = $this->team->telegram_notifications_database_backups; - $this->telegramNotificationsScheduledTasks = $this->team->telegram_notifications_scheduled_tasks; - $this->telegramNotificationsTestMessageThreadId = $this->team->telegram_notifications_test_message_thread_id; - $this->telegramNotificationsDeploymentsMessageThreadId = $this->team->telegram_notifications_deployments_message_thread_id; - $this->telegramNotificationsStatusChangesMessageThreadId = $this->team->telegram_notifications_status_changes_message_thread_id; - $this->telegramNotificationsDatabaseBackupsMessageThreadId = $this->team->telegram_notifications_database_backups_message_thread_id; - $this->telegramNotificationsScheduledTasksThreadId = $this->team->telegram_notifications_scheduled_tasks_thread_id; - $this->telegramNotificationsServerDiskUsage = $this->team->telegram_notifications_server_disk_usage; - } + $this->telegramEnabled = $this->settings->telegram_enabled; + $this->telegramToken = $this->settings->telegram_token; + $this->telegramChatId = $this->settings->telegram_chat_id; + $this->deploymentSuccessTelegramNotifications = $this->settings->deployment_success_telegram_notifications; + $this->deploymentFailureTelegramNotifications = $this->settings->deployment_failure_telegram_notifications; + $this->statusChangeTelegramNotifications = $this->settings->status_change_telegram_notifications; + $this->backupSuccessTelegramNotifications = $this->settings->backup_success_telegram_notifications; + $this->backupFailureTelegramNotifications = $this->settings->backup_failure_telegram_notifications; + $this->scheduledTaskSuccessTelegramNotifications = $this->settings->scheduled_task_success_telegram_notifications; + $this->scheduledTaskFailureTelegramNotifications = $this->settings->scheduled_task_failure_telegram_notifications; + $this->dockerCleanupTelegramNotifications = $this->settings->docker_cleanup_telegram_notifications; + $this->serverDiskUsageTelegramNotifications = $this->settings->server_disk_usage_telegram_notifications; + $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->telegramNotificationsDockerCleanupTopicId = $this->settings->telegram_notifications_docker_cleanup_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; + } } public function instantSave() diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index 76378ada1..790bf3143 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -12,7 +12,7 @@ @if ($telegramEnabled) - Send Test Notifications + Send Test Notification @endif
@@ -20,7 +20,6 @@
- @@ -28,51 +27,80 @@ id="telegramChatId" label="Chat ID" />
@if ($telegramEnabled) -

Subscribe to events

-
- @if (isDev()) -
-

Test Notification

- - +

Notification Settings

+

+ Select events for which you would like to receive Telegram notifications. +

+
+
+

Backups

+
+

Backup Success

+
+ + +
+ +

Backup Failure

+
+ + +
- @endif -
-

Container Status Changes

- -
-
-

Application Deployments

- - + +
+

Scheduled Tasks

+
+

Scheduled Task Success

+
+ + +
+ +

Scheduled Task Failure

+
+ + +
+
-
-

Database Backup Status

- - -
-
-

Scheduled Tasks Status

- - -
-
-

Server Disk Usage

- + +
+

Server

+
+

Docker Cleanup

+
+ + +
+ +

Server Disk Usage

+
+ + +
+ +

Server Reachable

+
+ + +
+ +

Server Unreachable

+
+ + +
+
@endif From b6500142c4048928fa309e4a04b33c973483546f Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:57:15 +0100 Subject: [PATCH 45/80] feat: use new notification event names --- .../Application/DeploymentFailed.php | 24 +++++----- .../Application/DeploymentSuccess.php | 31 +++++-------- .../Application/StatusChanged.php | 14 +++--- .../Container/ContainerRestarted.php | 8 ++-- .../Container/ContainerStopped.php | 8 ++-- app/Notifications/Database/BackupFailed.php | 8 ++-- app/Notifications/Database/BackupSuccess.php | 6 +-- .../ScheduledTask/TaskFailed.php | 8 ++-- app/Notifications/Server/DockerCleanup.php | 45 ++++++------------- app/Notifications/Server/HighDiskUsage.php | 8 ++-- app/Notifications/Server/Reachable.php | 33 ++------------ app/Notifications/Server/Unreachable.php | 32 ++----------- 12 files changed, 75 insertions(+), 150 deletions(-) diff --git a/app/Notifications/Application/DeploymentFailed.php b/app/Notifications/Application/DeploymentFailed.php index cdcec3261..06a2b48e3 100644 --- a/app/Notifications/Application/DeploymentFailed.php +++ b/app/Notifications/Application/DeploymentFailed.php @@ -40,12 +40,12 @@ class DeploymentFailed extends CustomEmailNotification if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } - $this->deployment_url = base_url() . "/project/{$this->project_uuid}/" . urlencode($this->environment_name) . "/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; + $this->deployment_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; } public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'deployments'); + return $notifiable->getEnabledChannels('deployment_failure'); } public function toMail(): MailMessage @@ -54,10 +54,10 @@ class DeploymentFailed extends CustomEmailNotification $pull_request_id = data_get($this->preview, 'pull_request_id', 0); $fqdn = $this->fqdn; if ($pull_request_id === 0) { - $mail->subject('Coolify: Deployment failed of ' . $this->application_name . '.'); + $mail->subject('Coolify: Deployment failed of '.$this->application_name.'.'); } else { $fqdn = $this->preview->fqdn; - $mail->subject('Coolify: Deployment failed of pull request #' . $this->preview->pull_request_id . ' of ' . $this->application_name . '.'); + $mail->subject('Coolify: Deployment failed of pull request #'.$this->preview->pull_request_id.' of '.$this->application_name.'.'); } $mail->view('emails.application-deployment-failed', [ 'name' => $this->application_name, @@ -74,7 +74,7 @@ class DeploymentFailed extends CustomEmailNotification if ($this->preview) { $message = new DiscordMessage( title: ':cross_mark: Deployment failed', - description: 'Pull request: ' . $this->preview->pull_request_id, + description: 'Pull request: '.$this->preview->pull_request_id, color: DiscordMessage::errorColor(), isCritical: true, ); @@ -83,13 +83,13 @@ class DeploymentFailed extends CustomEmailNotification $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); - $message->addField('Deployment Logs', '[Link](' . $this->deployment_url . ')'); + $message->addField('Deployment Logs', '[Link]('.$this->deployment_url.')'); if ($this->fqdn) { $message->addField('Domain', $this->fqdn, true); } } else { if ($this->fqdn) { - $description = '[Open application](' . $this->fqdn . ')'; + $description = '[Open application]('.$this->fqdn.')'; } else { $description = ''; } @@ -104,7 +104,7 @@ class DeploymentFailed extends CustomEmailNotification $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); - $message->addField('Deployment Logs', '[Link](' . $this->deployment_url . ')'); + $message->addField('Deployment Logs', '[Link]('.$this->deployment_url.')'); } return $message; @@ -113,9 +113,9 @@ class DeploymentFailed extends CustomEmailNotification public function toTelegram(): array { if ($this->preview) { - $message = 'Coolify: Pull request #' . $this->preview->pull_request_id . ' of ' . $this->application_name . ' (' . $this->preview->fqdn . ') deployment failed: '; + $message = 'Coolify: Pull request #'.$this->preview->pull_request_id.' of '.$this->application_name.' ('.$this->preview->fqdn.') deployment failed: '; } else { - $message = 'Coolify: Deployment failed of ' . $this->application_name . ' (' . $this->fqdn . '): '; + $message = 'Coolify: Deployment failed of '.$this->application_name.' ('.$this->fqdn.'): '; } $buttons[] = [ 'text' => 'Deployment logs', @@ -139,14 +139,14 @@ class DeploymentFailed extends CustomEmailNotification $description .= "\nPreview URL: {$this->preview->fqdn}"; } } else { - $title = "Deployment failed"; + $title = 'Deployment failed'; $description = "Deployment failed for {$this->application_name}"; if ($this->fqdn) { $description .= "\nApplication URL: {$this->fqdn}"; } } - $description .= "\n\n**Project:** " . data_get($this->application, 'environment.project.name'); + $description .= "\n\n**Project:** ".data_get($this->application, 'environment.project.name'); $description .= "\n**Environment:** {$this->environment_name}"; $description .= "\n**Deployment Logs:** {$this->deployment_url}"; diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php index 565bce0a5..548f5c6e5 100644 --- a/app/Notifications/Application/DeploymentSuccess.php +++ b/app/Notifications/Application/DeploymentSuccess.php @@ -6,8 +6,8 @@ use App\Models\Application; use App\Models\ApplicationPreview; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class DeploymentSuccess extends CustomEmailNotification { @@ -40,18 +40,12 @@ class DeploymentSuccess extends CustomEmailNotification if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } - $this->deployment_url = base_url() . "/project/{$this->project_uuid}/" . urlencode($this->environment_name) . "/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; + $this->deployment_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; } public function via(object $notifiable): array { - $channels = setNotificationChannels($notifiable, 'deployments'); - if (isCloud()) { - // TODO: Make batch notifications work with email - $channels = array_diff($channels, [\App\Notifications\Channels\EmailChannel::class]); - } - - return $channels; + return $notifiable->getEnabledChannels('deployment_success'); } public function toMail(): MailMessage @@ -80,21 +74,21 @@ class DeploymentSuccess extends CustomEmailNotification if ($this->preview) { $message = new DiscordMessage( title: ':white_check_mark: Preview deployment successful', - description: 'Pull request: ' . $this->preview->pull_request_id, + description: 'Pull request: '.$this->preview->pull_request_id, color: DiscordMessage::successColor(), ); if ($this->preview->fqdn) { - $message->addField('Application', '[Link](' . $this->preview->fqdn . ')'); + $message->addField('Application', '[Link]('.$this->preview->fqdn.')'); } $message->addField('Project', data_get($this->application, 'environment.project.name'), true); $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); - $message->addField('Deployment logs', '[Link](' . $this->deployment_url . ')'); + $message->addField('Deployment logs', '[Link]('.$this->deployment_url.')'); } else { if ($this->fqdn) { - $description = '[Open application](' . $this->fqdn . ')'; + $description = '[Open application]('.$this->fqdn.')'; } else { $description = ''; } @@ -107,7 +101,7 @@ class DeploymentSuccess extends CustomEmailNotification $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); - $message->addField('Deployment logs', '[Link](' . $this->deployment_url . ')'); + $message->addField('Deployment logs', '[Link]('.$this->deployment_url.')'); } return $message; @@ -116,7 +110,7 @@ class DeploymentSuccess extends CustomEmailNotification public function toTelegram(): array { if ($this->preview) { - $message = 'Coolify: New PR' . $this->preview->pull_request_id . ' version successfully deployed of ' . $this->application_name . ''; + $message = 'Coolify: New PR'.$this->preview->pull_request_id.' version successfully deployed of '.$this->application_name.''; if ($this->preview->fqdn) { $buttons[] = [ 'text' => 'Open Application', @@ -124,7 +118,7 @@ class DeploymentSuccess extends CustomEmailNotification ]; } } else { - $message = '✅ New version successfully deployed of ' . $this->application_name . ''; + $message = '✅ New version successfully deployed of '.$this->application_name.''; if ($this->fqdn) { $buttons[] = [ 'text' => 'Open Application', @@ -145,7 +139,6 @@ class DeploymentSuccess extends CustomEmailNotification ]; } - public function toSlack(): SlackMessage { if ($this->preview) { @@ -155,14 +148,14 @@ class DeploymentSuccess extends CustomEmailNotification $description .= "\nPreview URL: {$this->preview->fqdn}"; } } else { - $title = "New version successfully deployed"; + $title = 'New version successfully deployed'; $description = "New version successfully deployed for {$this->application_name}"; if ($this->fqdn) { $description .= "\nApplication URL: {$this->fqdn}"; } } - $description .= "\n\n**Project:** " . data_get($this->application, 'environment.project.name'); + $description .= "\n\n**Project:** ".data_get($this->application, 'environment.project.name'); $description .= "\n**Environment:** {$this->environment_name}"; $description .= "\n**Deployment Logs:** {$this->deployment_url}"; diff --git a/app/Notifications/Application/StatusChanged.php b/app/Notifications/Application/StatusChanged.php index 18c042ca6..32a6a659a 100644 --- a/app/Notifications/Application/StatusChanged.php +++ b/app/Notifications/Application/StatusChanged.php @@ -5,8 +5,8 @@ namespace App\Notifications\Application; use App\Models\Application; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class StatusChanged extends CustomEmailNotification { @@ -30,12 +30,12 @@ class StatusChanged extends CustomEmailNotification if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } - $this->resource_url = base_url() . "/project/{$this->project_uuid}/" . urlencode($this->environment_name) . "/application/{$this->resource->uuid}"; + $this->resource_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->resource->uuid}"; } public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'status_changes'); + return $notifiable->getEnabledChannels('status_change'); } public function toMail(): MailMessage @@ -56,7 +56,7 @@ class StatusChanged extends CustomEmailNotification { return new DiscordMessage( title: ':cross_mark: Application stopped', - description: '[Open Application in Coolify](' . $this->resource_url . ')', + description: '[Open Application in Coolify]('.$this->resource_url.')', color: DiscordMessage::errorColor(), isCritical: true, ); @@ -64,7 +64,7 @@ class StatusChanged extends CustomEmailNotification public function toTelegram(): array { - $message = 'Coolify: ' . $this->resource_name . ' has been stopped.'; + $message = 'Coolify: '.$this->resource_name.' has been stopped.'; return [ 'message' => $message, @@ -79,10 +79,10 @@ class StatusChanged extends CustomEmailNotification public function toSlack(): SlackMessage { - $title = "Application stopped"; + $title = 'Application stopped'; $description = "{$this->resource_name} has been stopped"; - $description .= "\n\n**Project:** " . data_get($this->resource, 'environment.project.name'); + $description .= "\n\n**Project:** ".data_get($this->resource, 'environment.project.name'); $description .= "\n**Environment:** {$this->environment_name}"; $description .= "\n**Application URL:** {$this->resource_url}"; diff --git a/app/Notifications/Container/ContainerRestarted.php b/app/Notifications/Container/ContainerRestarted.php index e1cf836ff..c25072ecf 100644 --- a/app/Notifications/Container/ContainerRestarted.php +++ b/app/Notifications/Container/ContainerRestarted.php @@ -5,8 +5,8 @@ namespace App\Notifications\Container; use App\Models\Server; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class ContainerRestarted extends CustomEmailNotification { @@ -17,7 +17,7 @@ class ContainerRestarted extends CustomEmailNotification public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'status_changes'); + return $notifiable->getEnabledChannels('status_change'); } public function toMail(): MailMessage @@ -42,7 +42,7 @@ class ContainerRestarted extends CustomEmailNotification ); if ($this->url) { - $message->addField('Resource', '[Link](' . $this->url . ')'); + $message->addField('Resource', '[Link]('.$this->url.')'); } return $message; @@ -70,7 +70,7 @@ class ContainerRestarted extends CustomEmailNotification public function toSlack(): SlackMessage { - $title = "Resource restarted"; + $title = 'Resource restarted'; $description = "A resource ({$this->name}) has been restarted automatically on {$this->server->name}"; if ($this->url) { diff --git a/app/Notifications/Container/ContainerStopped.php b/app/Notifications/Container/ContainerStopped.php index 76c2dae80..bc6e52b6d 100644 --- a/app/Notifications/Container/ContainerStopped.php +++ b/app/Notifications/Container/ContainerStopped.php @@ -5,8 +5,8 @@ namespace App\Notifications\Container; use App\Models\Server; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class ContainerStopped extends CustomEmailNotification { @@ -17,7 +17,7 @@ class ContainerStopped extends CustomEmailNotification public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'status_changes'); + return $notifiable->getEnabledChannels('status_change'); } public function toMail(): MailMessage @@ -42,7 +42,7 @@ class ContainerStopped extends CustomEmailNotification ); if ($this->url) { - $message->addField('Resource', '[Link](' . $this->url . ')'); + $message->addField('Resource', '[Link]('.$this->url.')'); } return $message; @@ -70,7 +70,7 @@ class ContainerStopped extends CustomEmailNotification public function toSlack(): SlackMessage { - $title = "Resource stopped"; + $title = 'Resource stopped'; $description = "A resource ({$this->name}) has been stopped unexpectedly on {$this->server->name}"; if ($this->url) { diff --git a/app/Notifications/Database/BackupFailed.php b/app/Notifications/Database/BackupFailed.php index a1b5c42e5..2208f7b1d 100644 --- a/app/Notifications/Database/BackupFailed.php +++ b/app/Notifications/Database/BackupFailed.php @@ -5,8 +5,8 @@ namespace App\Notifications\Database; use App\Models\ScheduledDatabaseBackup; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class BackupFailed extends CustomEmailNotification { @@ -23,13 +23,13 @@ class BackupFailed extends CustomEmailNotification public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'database_backups'); + return $notifiable->getEnabledChannels('backup_failure'); } public function toMail(): MailMessage { $mail = new MailMessage; - $mail->subject("Coolify: [ACTION REQUIRED] Backup FAILED for {$this->database->name}"); + $mail->subject("Coolify: [ACTION REQUIRED] Database Backup FAILED for {$this->database->name}"); $mail->view('emails.backup-failed', [ 'name' => $this->name, 'database_name' => $this->database_name, @@ -66,7 +66,7 @@ class BackupFailed extends CustomEmailNotification public function toSlack(): SlackMessage { - $title = "Database backup failed"; + $title = 'Database backup failed'; $description = "Database backup for {$this->name} (db:{$this->database_name}) has FAILED."; $description .= "\n\n**Frequency:** {$this->frequency}"; diff --git a/app/Notifications/Database/BackupSuccess.php b/app/Notifications/Database/BackupSuccess.php index f2aa247a6..10b4ff3df 100644 --- a/app/Notifications/Database/BackupSuccess.php +++ b/app/Notifications/Database/BackupSuccess.php @@ -5,8 +5,8 @@ namespace App\Notifications\Database; use App\Models\ScheduledDatabaseBackup; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class BackupSuccess extends CustomEmailNotification { @@ -24,7 +24,7 @@ class BackupSuccess extends CustomEmailNotification public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'database_backups'); + return $notifiable->getEnabledChannels('backup_success'); } public function toMail(): MailMessage @@ -64,7 +64,7 @@ class BackupSuccess extends CustomEmailNotification public function toSlack(): SlackMessage { - $title = "Database backup successful"; + $title = 'Database backup successful'; $description = "Database backup for {$this->name} (db:{$this->database_name}) was successful."; $description .= "\n\n**Frequency:** {$this->frequency}"; diff --git a/app/Notifications/ScheduledTask/TaskFailed.php b/app/Notifications/ScheduledTask/TaskFailed.php index 53b7f46a3..878eae5bc 100644 --- a/app/Notifications/ScheduledTask/TaskFailed.php +++ b/app/Notifications/ScheduledTask/TaskFailed.php @@ -5,8 +5,8 @@ namespace App\Notifications\ScheduledTask; use App\Models\ScheduledTask; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; -use Illuminate\Notifications\Messages\MailMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class TaskFailed extends CustomEmailNotification { @@ -24,7 +24,7 @@ class TaskFailed extends CustomEmailNotification public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'scheduled_tasks'); + return $notifiable->getEnabledChannels('scheduled_task_failure'); } public function toMail(): MailMessage @@ -49,7 +49,7 @@ class TaskFailed extends CustomEmailNotification ); if ($this->url) { - $message->addField('Scheduled task', '[Link](' . $this->url . ')'); + $message->addField('Scheduled task', '[Link]('.$this->url.')'); } return $message; @@ -72,7 +72,7 @@ class TaskFailed extends CustomEmailNotification public function toSlack(): SlackMessage { - $title = "Scheduled task failed"; + $title = 'Scheduled task failed'; $description = "Scheduled task ({$this->task->name}) failed."; if ($this->output) { diff --git a/app/Notifications/Server/DockerCleanup.php b/app/Notifications/Server/DockerCleanup.php index 46b730c7b..f4f8ffd09 100644 --- a/app/Notifications/Server/DockerCleanup.php +++ b/app/Notifications/Server/DockerCleanup.php @@ -3,11 +3,10 @@ namespace App\Notifications\Server; use App\Models\Server; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\TelegramChannel; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; use App\Notifications\Dto\SlackMessage; +use Illuminate\Notifications\Messages\MailMessage; class DockerCleanup extends CustomEmailNotification { @@ -18,38 +17,20 @@ class DockerCleanup extends CustomEmailNotification public function via(object $notifiable): array { - $channels = []; - // $isEmailEnabled = isEmailEnabled($notifiable); - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - if ($isDiscordEnabled) { - $channels[] = DiscordChannel::class; - } - // if ($isEmailEnabled) { - // $channels[] = EmailChannel::class; - // } - if ($isTelegramEnabled) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled) { - $channels[] = SlackChannel::class; - } - - return $channels; + return $notifiable->getEnabledChannels('docker_cleanup'); } - // public function toMail(): MailMessage - // { - // $mail = new MailMessage(); - // $mail->subject("Coolify: Server ({$this->server->name}) high disk usage detected!"); - // $mail->view('emails.high-disk-usage', [ - // 'name' => $this->server->name, - // 'disk_usage' => $this->disk_usage, - // 'threshold' => $this->docker_cleanup_threshold, - // ]); - // return $mail; - // } + public function toMail(): MailMessage + { + $mail = new MailMessage; + $mail->subject("Coolify: Server ({$this->server->name}) docker cleanup job done!"); + $mail->view('emails.docker-cleanup', [ + 'name' => $this->server->name, + 'message' => $this->message, + ]); + + return $mail; + } public function toDiscord(): DiscordMessage { diff --git a/app/Notifications/Server/HighDiskUsage.php b/app/Notifications/Server/HighDiskUsage.php index 40c0e2cb6..9f4826689 100644 --- a/app/Notifications/Server/HighDiskUsage.php +++ b/app/Notifications/Server/HighDiskUsage.php @@ -17,7 +17,7 @@ class HighDiskUsage extends CustomEmailNotification public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'server_disk_usage'); + return $notifiable->getEnabledChannels('server_disk_usage'); } public function toMail(): MailMessage @@ -45,7 +45,7 @@ class HighDiskUsage extends CustomEmailNotification $message->addField('Disk usage', "{$this->disk_usage}%", true); $message->addField('Threshold', "{$this->server_disk_usage_notification_threshold}%", true); $message->addField('What to do?', '[Link](https://coolify.io/docs/knowledge-base/server/automated-cleanup)', true); - $message->addField('Change Settings', '[Threshold](' . base_url() . '/server/' . $this->server->uuid . '#advanced) | [Notification](' . base_url() . '/notifications/discord)'); + $message->addField('Change Settings', '[Threshold]('.base_url().'/server/'.$this->server->uuid.'#advanced) | [Notification]('.base_url().'/notifications/discord)'); return $message; } @@ -65,8 +65,8 @@ class HighDiskUsage extends CustomEmailNotification $description .= "Please cleanup your disk to prevent data-loss.\n"; $description .= "Tips for cleanup: https://coolify.io/docs/knowledge-base/server/automated-cleanup\n"; $description .= "Change settings:\n"; - $description .= "- Threshold: " . base_url() . "/server/" . $this->server->uuid . "#advanced\n"; - $description .= "- Notifications: " . base_url() . "/notifications/discord"; + $description .= '- Threshold: '.base_url().'/server/'.$this->server->uuid."#advanced\n"; + $description .= '- Notifications: '.base_url().'/notifications/discord'; return new SlackMessage( title: 'High disk usage detected', diff --git a/app/Notifications/Server/Reachable.php b/app/Notifications/Server/Reachable.php index a0dfd1cc5..4917e04f8 100644 --- a/app/Notifications/Server/Reachable.php +++ b/app/Notifications/Server/Reachable.php @@ -3,13 +3,9 @@ namespace App\Notifications\Server; use App\Models\Server; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; -use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\SlackChannel; -use App\Notifications\Dto\SlackMessage; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; +use App\Notifications\Dto\SlackMessage; use Illuminate\Notifications\Messages\MailMessage; class Reachable extends CustomEmailNotification @@ -20,7 +16,7 @@ class Reachable extends CustomEmailNotification { $this->onQueue('high'); $this->isRateLimited = isEmailRateLimited( - limiterKey: 'server-reachable:' . $this->server->id, + limiterKey: 'server-reachable:'.$this->server->id, ); } @@ -30,25 +26,7 @@ class Reachable extends CustomEmailNotification return []; } - $channels = []; - $isEmailEnabled = isEmailEnabled($notifiable); - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - if ($isDiscordEnabled) { - $channels[] = DiscordChannel::class; - } - if ($isEmailEnabled) { - $channels[] = EmailChannel::class; - } - if ($isTelegramEnabled) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled) { - $channels[] = SlackChannel::class; - } - - return $channels; + return $notifiable->getEnabledChannels('server_reachable'); } public function toMail(): MailMessage @@ -78,13 +56,10 @@ class Reachable extends CustomEmailNotification ]; } - - - public function toSlack(): SlackMessage { return new SlackMessage( - title: "Server revived", + title: 'Server revived', description: "Server '{$this->server->name}' revived.\nAll automations & integrations are turned on again!", color: SlackMessage::successColor() ); diff --git a/app/Notifications/Server/Unreachable.php b/app/Notifications/Server/Unreachable.php index 0bd44ef3d..43f176d49 100644 --- a/app/Notifications/Server/Unreachable.php +++ b/app/Notifications/Server/Unreachable.php @@ -3,13 +3,9 @@ namespace App\Notifications\Server; use App\Models\Server; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; -use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\SlackChannel; -use App\Notifications\Dto\SlackMessage; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; +use App\Notifications\Dto\SlackMessage; use Illuminate\Notifications\Messages\MailMessage; class Unreachable extends CustomEmailNotification @@ -20,7 +16,7 @@ class Unreachable extends CustomEmailNotification { $this->onQueue('high'); $this->isRateLimited = isEmailRateLimited( - limiterKey: 'server-unreachable:' . $this->server->id, + limiterKey: 'server-unreachable:'.$this->server->id, ); } @@ -30,26 +26,7 @@ class Unreachable extends CustomEmailNotification return []; } - $channels = []; - $isEmailEnabled = isEmailEnabled($notifiable); - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - - if ($isDiscordEnabled) { - $channels[] = DiscordChannel::class; - } - if ($isEmailEnabled) { - $channels[] = EmailChannel::class; - } - if ($isTelegramEnabled) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled) { - $channels[] = SlackChannel::class; - } - - return $channels; + return $notifiable->getEnabledChannels('server_unreachable'); } public function toMail(): ?MailMessage @@ -83,12 +60,11 @@ class Unreachable extends CustomEmailNotification ]; } - public function toSlack(): SlackMessage { $description = "Your server '{$this->server->name}' is unreachable.\n"; $description .= "All automations & integrations are turned off!\n\n"; - $description .= "*IMPORTANT:* We automatically try to revive your server and turn on all automations & integrations."; + $description .= '*IMPORTANT:* We automatically try to revive your server and turn on all automations & integrations.'; return new SlackMessage( title: 'Server unreachable', From a849bfdc3eb2221277957fc61c531b842b29ed7d Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:00:07 +0100 Subject: [PATCH 46/80] feat: always sent notifications --- .../Internal/GeneralNotification.php | 20 +----------- app/Notifications/Server/ForceDisabled.php | 31 +++---------------- app/Notifications/Server/ForceEnabled.php | 28 ++--------------- 3 files changed, 7 insertions(+), 72 deletions(-) diff --git a/app/Notifications/Internal/GeneralNotification.php b/app/Notifications/Internal/GeneralNotification.php index 699291d16..7049e3055 100644 --- a/app/Notifications/Internal/GeneralNotification.php +++ b/app/Notifications/Internal/GeneralNotification.php @@ -2,9 +2,6 @@ namespace App\Notifications\Internal; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\SlackChannel; use App\Notifications\Dto\DiscordMessage; use App\Notifications\Dto\SlackMessage; use Illuminate\Bus\Queueable; @@ -24,22 +21,7 @@ class GeneralNotification extends Notification implements ShouldQueue public function via(object $notifiable): array { - $channels = []; - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - - if ($isDiscordEnabled) { - $channels[] = DiscordChannel::class; - } - if ($isTelegramEnabled) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled) { - $channels[] = SlackChannel::class; - } - - return $channels; + return $notifiable->getEnabledChannels('general'); } public function toDiscord(): DiscordMessage diff --git a/app/Notifications/Server/ForceDisabled.php b/app/Notifications/Server/ForceDisabled.php index 1939170f6..e122849da 100644 --- a/app/Notifications/Server/ForceDisabled.php +++ b/app/Notifications/Server/ForceDisabled.php @@ -3,13 +3,9 @@ namespace App\Notifications\Server; use App\Models\Server; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; -use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\SlackChannel; -use App\Notifications\Dto\SlackMessage; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; +use App\Notifications\Dto\SlackMessage; use Illuminate\Notifications\Messages\MailMessage; class ForceDisabled extends CustomEmailNotification @@ -21,25 +17,7 @@ class ForceDisabled extends CustomEmailNotification public function via(object $notifiable): array { - $channels = []; - $isEmailEnabled = isEmailEnabled($notifiable); - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - if ($isDiscordEnabled) { - $channels[] = DiscordChannel::class; - } - if ($isEmailEnabled) { - $channels[] = EmailChannel::class; - } - if ($isTelegramEnabled) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled) { - $channels[] = SlackChannel::class; - } - - return $channels; + return $notifiable->getEnabledChannels('server_force_disabled'); } public function toMail(): MailMessage @@ -73,13 +51,12 @@ class ForceDisabled extends CustomEmailNotification ]; } - public function toSlack(): SlackMessage { - $title = "Server disabled"; + $title = 'Server disabled'; $description = "Server ({$this->server->name}) disabled because it is not paid!\n"; $description .= "All automations and integrations are stopped.\n\n"; - $description .= "Please update your subscription to enable the server again: https://app.coolify.io/subscriptions"; + $description .= 'Please update your subscription to enable the server again: https://app.coolify.io/subscriptions'; return new SlackMessage( title: $title, diff --git a/app/Notifications/Server/ForceEnabled.php b/app/Notifications/Server/ForceEnabled.php index 4b6181e19..a0e0a8b59 100644 --- a/app/Notifications/Server/ForceEnabled.php +++ b/app/Notifications/Server/ForceEnabled.php @@ -3,13 +3,9 @@ namespace App\Notifications\Server; use App\Models\Server; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; -use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\SlackChannel; -use App\Notifications\Dto\SlackMessage; use App\Notifications\CustomEmailNotification; use App\Notifications\Dto\DiscordMessage; +use App\Notifications\Dto\SlackMessage; use Illuminate\Notifications\Messages\MailMessage; class ForceEnabled extends CustomEmailNotification @@ -21,25 +17,7 @@ class ForceEnabled extends CustomEmailNotification public function via(object $notifiable): array { - $channels = []; - $isEmailEnabled = isEmailEnabled($notifiable); - $isDiscordEnabled = data_get($notifiable, 'discord_enabled'); - $isTelegramEnabled = data_get($notifiable, 'telegram_enabled'); - $isSlackEnabled = data_get($notifiable, 'slack_enabled'); - if ($isDiscordEnabled) { - $channels[] = DiscordChannel::class; - } - if ($isEmailEnabled) { - $channels[] = EmailChannel::class; - } - if ($isTelegramEnabled) { - $channels[] = TelegramChannel::class; - } - if ($isSlackEnabled) { - $channels[] = SlackChannel::class; - } - - return $channels; + return $notifiable->getEnabledChannels('server_force_enabled'); } public function toMail(): MailMessage @@ -69,7 +47,6 @@ class ForceEnabled extends CustomEmailNotification ]; } - public function toSlack(): SlackMessage { return new SlackMessage( @@ -78,5 +55,4 @@ class ForceEnabled extends CustomEmailNotification color: SlackMessage::successColor() ); } - } From bf585470828dacff2742fce3d88a3cadada54498 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:00:33 +0100 Subject: [PATCH 47/80] feat: scheduled task success notification --- .../ScheduledTask/TaskSuccess.php | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 app/Notifications/ScheduledTask/TaskSuccess.php diff --git a/app/Notifications/ScheduledTask/TaskSuccess.php b/app/Notifications/ScheduledTask/TaskSuccess.php new file mode 100644 index 000000000..aaf9cf14b --- /dev/null +++ b/app/Notifications/ScheduledTask/TaskSuccess.php @@ -0,0 +1,88 @@ +onQueue('high'); + if ($task->application) { + $this->url = $task->application->failedTaskLink($task->uuid); + } elseif ($task->service) { + $this->url = $task->service->failedTaskLink($task->uuid); + } + } + + public function via(object $notifiable): array + { + return $notifiable->getEnabledChannels('scheduled_task_success'); + } + + public function toMail(): MailMessage + { + $mail = new MailMessage; + $mail->subject("Coolify: Scheduled task ({$this->task->name}) succeeded."); + $mail->view('emails.scheduled-task-failed', [ + 'task' => $this->task, + 'url' => $this->url, + 'output' => $this->output, + ]); + + return $mail; + } + + public function toDiscord(): DiscordMessage + { + $message = new DiscordMessage( + title: ':check_mark: Scheduled task succeeded', + description: "Scheduled task ({$this->task->name}) succeeded.", + color: DiscordMessage::successColor(), + ); + + if ($this->url) { + $message->addField('Scheduled task', '[Link]('.$this->url.')'); + } + + return $message; + } + + public function toTelegram(): array + { + $message = "Coolify: Scheduled task ({$this->task->name}) succeeded."; + if ($this->url) { + $buttons[] = [ + 'text' => 'Open task in Coolify', + 'url' => (string) $this->url, + ]; + } + + return [ + 'message' => $message, + ]; + } + + public function toSlack(): SlackMessage + { + $title = 'Scheduled task succeeded'; + $description = "Scheduled task ({$this->task->name}) succeeded."; + + if ($this->url) { + $description .= "\n\n**Task URL:** {$this->url}"; + } + + return new SlackMessage( + title: $title, + description: $description, + color: SlackMessage::successColor() + ); + } +} From ec1c91fb75f23727f5ed91fdcd2cfd46f6932ee3 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:03:40 +0100 Subject: [PATCH 48/80] feat: notification trait --- app/Traits/HasNotificationSettings.php | 71 ++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 app/Traits/HasNotificationSettings.php diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php new file mode 100644 index 000000000..64ea85a55 --- /dev/null +++ b/app/Traits/HasNotificationSettings.php @@ -0,0 +1,71 @@ + $this->emailNotificationSettings, + 'discord' => $this->discordNotificationSettings, + 'telegram' => $this->telegramNotificationSettings, + 'slack' => $this->slackNotificationSettings, + default => null, + }; + } + + /** + * Check if a notification channel is enabled + */ + public function isNotificationEnabled(string $channel): bool + { + $settings = $this->getNotificationSettings($channel); + + return $settings?->isEnabled() ?? false; + } + + /** + * Get all enabled notification channels for an event + */ + public function getEnabledChannels(string $event): array + { + $alwaysSendEvents = [ + 'server_force_enabled', + 'server_force_disabled', + 'general', + ]; + + $channels = []; + + $channelMap = [ + 'email' => EmailChannel::class, + 'discord' => DiscordChannel::class, + 'telegram' => TelegramChannel::class, + 'slack' => SlackChannel::class, + ]; + + foreach ($channelMap as $channel => $channelClass) { + if (in_array($event, $alwaysSendEvents)) { + if ($this->isNotificationEnabled($channel)) { + $channels[] = $channelClass; + } + } else { + if ($this->isNotificationEnabled($channel) && $this->isNotificationTypeEnabled($channel, $event)) { + $channels[] = $channelClass; + } + } + } + + return $channels; + } +} From 6cab8b45985ecbb8c54f6c908d5d1710a23eb70c Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:36:23 +0100 Subject: [PATCH 49/80] feat: get discord Webhook form new table --- app/Notifications/Channels/DiscordChannel.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/Notifications/Channels/DiscordChannel.php b/app/Notifications/Channels/DiscordChannel.php index df7040f8f..362006d8e 100644 --- a/app/Notifications/Channels/DiscordChannel.php +++ b/app/Notifications/Channels/DiscordChannel.php @@ -13,10 +13,13 @@ class DiscordChannel public function send(SendsDiscord $notifiable, Notification $notification): void { $message = $notification->toDiscord(); - $webhookUrl = $notifiable->routeNotificationForDiscord(); - if (! $webhookUrl) { + + $discordSettings = $notifiable->discordNotificationSettings; + + if (! $discordSettings || ! $discordSettings->isEnabled() || ! $discordSettings->discord_webhook_url) { return; } - SendMessageToDiscordJob::dispatch($message, $webhookUrl); + + SendMessageToDiscordJob::dispatch($message, $discordSettings->discord_webhook_url); } } From dd9d10c717fc4bbcd0f2085c5fcb58db401caff8 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:36:32 +0100 Subject: [PATCH 50/80] feat: get Slack Webhook form new table --- app/Notifications/Channels/SlackChannel.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Notifications/Channels/SlackChannel.php b/app/Notifications/Channels/SlackChannel.php index 32fdbe9cf..cddb7a561 100644 --- a/app/Notifications/Channels/SlackChannel.php +++ b/app/Notifications/Channels/SlackChannel.php @@ -13,10 +13,12 @@ class SlackChannel public function send(SendsSlack $notifiable, Notification $notification): void { $message = $notification->toSlack(); - $webhookUrl = $notifiable->routeNotificationForSlack(); - if (! $webhookUrl) { + $slackSettings = $notifiable->slackNotificationSettings; + + if (! $slackSettings || ! $slackSettings->isEnabled() || ! $slackSettings->slack_webhook_url) { return; } - SendMessageToSlackJob::dispatch($message, $webhookUrl); + + SendMessageToSlackJob::dispatch($message, $slackSettings->slack_webhook_url); } } From adaef2d3413a1ca9392667d72bb95c6fabd01685 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:37:15 +0100 Subject: [PATCH 51/80] feat: use new table or instance settings for email --- app/Notifications/Channels/EmailChannel.php | 33 ++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 5394f6106..0985f4393 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -13,7 +13,7 @@ class EmailChannel { try { $this->bootConfigs($notifiable); - $recipients = $notifiable->getRecepients($notification); + $recipients = $notifiable->getRecipients($notification); if (count($recipients) === 0) { throw new Exception('No email recipients found'); } @@ -46,7 +46,9 @@ class EmailChannel private function bootConfigs($notifiable): void { - if (data_get($notifiable, 'use_instance_email_settings')) { + $emailSettings = $notifiable->emailNotificationSettings; + + if ($emailSettings->use_instance_email_settings) { $type = set_transanctional_email_settings(); if (! $type) { throw new Exception('No email settings found.'); @@ -54,24 +56,27 @@ class EmailChannel return; } - config()->set('mail.from.address', data_get($notifiable, 'smtp_from_address', 'test@example.com')); - config()->set('mail.from.name', data_get($notifiable, 'smtp_from_name', 'Test')); - if (data_get($notifiable, 'resend_enabled')) { + + config()->set('mail.from.address', $emailSettings->smtp_from_address ?? 'test@example.com'); + config()->set('mail.from.name', $emailSettings->smtp_from_name ?? 'Test'); + + if ($emailSettings->resend_enabled) { config()->set('mail.default', 'resend'); - config()->set('resend.api_key', data_get($notifiable, 'resend_api_key')); + config()->set('resend.api_key', $emailSettings->resend_api_key); } - if (data_get($notifiable, 'smtp_enabled')) { + + if ($emailSettings->smtp_enabled) { config()->set('mail.default', 'smtp'); config()->set('mail.mailers.smtp', [ 'transport' => 'smtp', - 'host' => data_get($notifiable, 'smtp_host'), - 'port' => data_get($notifiable, 'smtp_port'), - 'encryption' => data_get($notifiable, 'smtp_encryption') === 'none' ? null : data_get($notifiable, 'smtp_encryption'), - 'username' => data_get($notifiable, 'smtp_username'), - 'password' => data_get($notifiable, 'smtp_password'), - 'timeout' => data_get($notifiable, 'smtp_timeout'), + 'host' => $emailSettings->smtp_host, + 'port' => $emailSettings->smtp_port, + 'encryption' => $emailSettings->smtp_encryption === 'none' ? null : $emailSettings->smtp_encryption, + 'username' => $emailSettings->smtp_username, + 'password' => $emailSettings->smtp_password, + 'timeout' => $emailSettings->smtp_timeout, 'local_domain' => null, - 'auto_tls' => data_get($notifiable, 'smtp_encryption') === 'none' ? '0' : '', + 'auto_tls' => $emailSettings->smtp_encryption === 'none' ? '0' : '', ]); } } From 4d23835119be38f41cdada1cc2dc99fe296eb5fb Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:37:39 +0100 Subject: [PATCH 52/80] feat: use new place for settings and topic IDs for telegram --- .../Channels/TelegramChannel.php | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index 958c46c21..17d76181a 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -9,38 +9,32 @@ class TelegramChannel public function send($notifiable, $notification): void { $data = $notification->toTelegram($notifiable); - $telegramData = $notifiable->routeNotificationForTelegram(); + $settings = $notifiable->telegramNotificationSettings; + $message = data_get($data, 'message'); $buttons = data_get($data, 'buttons', []); - $telegramToken = data_get($telegramData, 'token'); - $chatId = data_get($telegramData, 'chat_id'); - $topicId = null; - $topicsInstance = get_class($notification); + $telegramToken = $settings->telegram_token; + $chatId = $settings->telegram_chat_id; + + $topicId = match (get_class($notification)) { + \App\Notifications\Test::class => $settings->telegram_notifications_test_topic_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, + default => null, + }; - switch ($topicsInstance) { - case \App\Notifications\Test::class: - $topicId = data_get($notifiable, 'telegram_notifications_test_message_thread_id'); - break; - case \App\Notifications\Application\StatusChanged::class: - case \App\Notifications\Container\ContainerRestarted::class: - case \App\Notifications\Container\ContainerStopped::class: - $topicId = data_get($notifiable, 'telegram_notifications_status_changes_message_thread_id'); - break; - case \App\Notifications\Application\DeploymentSuccess::class: - case \App\Notifications\Application\DeploymentFailed::class: - $topicId = data_get($notifiable, 'telegram_notifications_deployments_message_thread_id'); - break; - case \App\Notifications\Database\BackupSuccess::class: - case \App\Notifications\Database\BackupFailed::class: - $topicId = data_get($notifiable, 'telegram_notifications_database_backups_message_thread_id'); - break; - case \App\Notifications\ScheduledTask\TaskFailed::class: - $topicId = data_get($notifiable, 'telegram_notifications_scheduled_tasks_thread_id'); - break; - } if (! $telegramToken || ! $chatId || ! $message) { return; } + SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $topicId); } } From 07a0863401672e4db2e4236d37913bb8325a3b56 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:37:47 +0100 Subject: [PATCH 53/80] chore: remove log --- app/Notifications/Channels/TransactionalEmailChannel.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/Notifications/Channels/TransactionalEmailChannel.php b/app/Notifications/Channels/TransactionalEmailChannel.php index cc7d76ebf..761780231 100644 --- a/app/Notifications/Channels/TransactionalEmailChannel.php +++ b/app/Notifications/Channels/TransactionalEmailChannel.php @@ -7,7 +7,6 @@ use Exception; use Illuminate\Mail\Message; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Mail; -use Log; class TransactionalEmailChannel { @@ -15,8 +14,6 @@ class TransactionalEmailChannel { $settings = instanceSettings(); if (! data_get($settings, 'smtp_enabled') && ! data_get($settings, 'resend_enabled')) { - Log::info('SMTP/Resend not enabled'); - return; } $email = $notifiable->email; From 2639cf75446d1511a44672086e39671ef76035f6 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:44:10 +0100 Subject: [PATCH 54/80] fix: slack and discord url now uses text filed because encryption makes the url very long --- ..._12_05_212416_create_discord_notification_settings_table.php | 2 +- ...24_12_06_142014_create_slack_notification_settings_table.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php index 271f33ac6..b9e9bda03 100644 --- a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php +++ b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php @@ -16,7 +16,7 @@ return new class extends Migration $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('discord_enabled')->default(false); - $table->string('discord_webhook_url')->nullable(); + $table->text('discord_webhook_url')->nullable(); $table->boolean('deployment_success_discord_notifications')->default(false); $table->boolean('deployment_failure_discord_notifications')->default(true); 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 fcc4dc8ce..af46508f0 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 @@ -16,7 +16,7 @@ return new class extends Migration $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('slack_enabled')->default(false); - $table->string('slack_webhook_url')->nullable(); + $table->text('slack_webhook_url')->nullable(); $table->boolean('deployment_success_slack_notifications')->default(false); $table->boolean('deployment_failure_slack_notifications')->default(true); From 96c970ca4ea87210730881e988e5acb94bdce902 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:44:43 +0100 Subject: [PATCH 55/80] chore: use new notification trait --- app/Notifications/Test.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Notifications/Test.php b/app/Notifications/Test.php index 03f6c3296..7ae1c5286 100644 --- a/app/Notifications/Test.php +++ b/app/Notifications/Test.php @@ -2,6 +2,7 @@ namespace App\Notifications; +use App\Notifications\Channels\EmailChannel; use App\Notifications\Dto\DiscordMessage; use App\Notifications\Dto\SlackMessage; use Illuminate\Bus\Queueable; @@ -23,13 +24,13 @@ class Test extends Notification implements ShouldQueue public function via(object $notifiable): array { - return setNotificationChannels($notifiable, 'test'); + return $notifiable->getEnabledChannels('test'); } public function middleware(object $notifiable, string $channel) { return match ($channel) { - \App\Notifications\Channels\EmailChannel::class => [new RateLimited('email')], + EmailChannel::class => [new RateLimited('email')], default => [], }; } From dedfd72731a2d30fc62a30679ed469eb79f80f16 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:47:17 +0100 Subject: [PATCH 56/80] fix: notification trait fix: some events must always be enabled, so a notification is sent all the time (user cannot choose to not receive this notification). fix: check if the event is enabled before adding a channel to enabled --- app/Traits/HasNotificationSettings.php | 43 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php index 64ea85a55..5a5ae1929 100644 --- a/app/Traits/HasNotificationSettings.php +++ b/app/Traits/HasNotificationSettings.php @@ -10,6 +10,13 @@ use Illuminate\Database\Eloquent\Model; trait HasNotificationSettings { + protected $alwaysSendEvents = [ + 'server_force_enabled', + 'server_force_disabled', + 'general', + 'test', + ]; + /** * Get settings model for specific channel */ @@ -34,17 +41,31 @@ trait HasNotificationSettings return $settings?->isEnabled() ?? false; } + /** + * Check if a specific notification type is enabled for a channel + */ + public function isNotificationTypeEnabled(string $channel, string $event): bool + { + $settings = $this->getNotificationSettings($channel); + + if (! $settings || ! $this->isNotificationEnabled($channel)) { + return false; + } + + if (in_array($event, $this->alwaysSendEvents)) { + return true; + } + + $settingKey = "{$event}_{$channel}_notifications"; + + return (bool) $settings->$settingKey; + } + /** * Get all enabled notification channels for an event */ public function getEnabledChannels(string $event): array { - $alwaysSendEvents = [ - 'server_force_enabled', - 'server_force_disabled', - 'general', - ]; - $channels = []; $channelMap = [ @@ -55,14 +76,8 @@ trait HasNotificationSettings ]; foreach ($channelMap as $channel => $channelClass) { - if (in_array($event, $alwaysSendEvents)) { - if ($this->isNotificationEnabled($channel)) { - $channels[] = $channelClass; - } - } else { - if ($this->isNotificationEnabled($channel) && $this->isNotificationTypeEnabled($channel, $event)) { - $channels[] = $channelClass; - } + if ($this->isNotificationEnabled($channel) && $this->isNotificationTypeEnabled($channel, $event)) { + $channels[] = $channelClass; } } From 014c6dc44686ba2e87873caa36f71fa27dba70ba Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 20:30:39 +0100 Subject: [PATCH 57/80] chore: remove unused route --- routes/web.php | 1 - 1 file changed, 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index f7bec5be5..3570fe0ed 100644 --- a/routes/web.php +++ b/routes/web.php @@ -88,7 +88,6 @@ Route::get('/admin', AdminIndex::class)->name('admin.index'); Route::post('/forgot-password', [Controller::class, 'forgot_password'])->name('password.forgot')->middleware('throttle:forgot-password'); Route::get('/realtime', [Controller::class, 'realtime_test'])->middleware('auth'); -// Route::get('/waitlist', WaitlistIndex::class)->name('waitlist.index'); Route::get('/verify', [Controller::class, 'verify'])->middleware('auth')->name('verify.email'); Route::get('/email/verify/{id}/{hash}', [Controller::class, 'email_verify'])->middleware(['auth'])->name('verify.verify'); Route::middleware(['throttle:login'])->group(function () { From bdfd68b74fc598cbfee5d5f57181b755ec39bb54 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:41:22 +0100 Subject: [PATCH 58/80] chore: remove unused email component --- resources/views/emails/waitlist-invitation.blade.php | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 resources/views/emails/waitlist-invitation.blade.php diff --git a/resources/views/emails/waitlist-invitation.blade.php b/resources/views/emails/waitlist-invitation.blade.php deleted file mode 100644 index de8d64650..000000000 --- a/resources/views/emails/waitlist-invitation.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - -You have been invited to join the Coolify Cloud: [Get Started]({{ $loginLink }}) - From b17a61a043cbb1eb9b55ca78ae2189f2dcc6362c Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:34:17 +0100 Subject: [PATCH 59/80] feat: encrypt instance email settings --- ...ncrypt_instance_settings_email_columns.php | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php diff --git a/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php b/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php new file mode 100644 index 000000000..618b8df90 --- /dev/null +++ b/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php @@ -0,0 +1,64 @@ +exists()) { + Schema::table('instance_settings', function (Blueprint $table) { + $table->text('smtp_from_address')->change(); + $table->text('smtp_from_name')->change(); + $table->text('smtp_recipients')->change(); + $table->text('smtp_host')->change(); + $table->text('smtp_username')->change(); + }); + + $settings = DB::table('instance_settings')->get(); + foreach ($settings as $setting) { + DB::table('instance_settings')->where('id', $setting->id)->update([ + 'smtp_from_address' => Crypt::encryptString($setting->smtp_from_address), + 'smtp_from_name' => Crypt::encryptString($setting->smtp_from_name), + 'smtp_recipients' => Crypt::encryptString($setting->smtp_recipients), + 'smtp_host' => Crypt::encryptString($setting->smtp_host), + 'smtp_username' => Crypt::encryptString($setting->smtp_username), + ]); + } + } + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('instance_settings', function (Blueprint $table) { + $table->string('smtp_from_address')->change(); + $table->string('smtp_from_name')->change(); + $table->string('smtp_recipients')->change(); + $table->string('smtp_host')->change(); + $table->string('smtp_username')->change(); + }); + + if (DB::table('instance_settings')->exists()) { + $settings = DB::table('instance_settings')->get(); + foreach ($settings as $setting) { + DB::table('instance_settings')->where('id', $setting->id)->update([ + 'smtp_from_address' => Crypt::decryptString($setting->smtp_from_address), + 'smtp_from_name' => Crypt::decryptString($setting->smtp_from_name), + 'smtp_recipients' => Crypt::decryptString($setting->smtp_recipients), + 'smtp_host' => Crypt::decryptString($setting->smtp_host), + 'smtp_username' => Crypt::decryptString($setting->smtp_username), + ]); + } + } + } +}; From d62962ae6fb1d091d35f368908c4227bcf12b4e5 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:42:26 +0100 Subject: [PATCH 60/80] fix: encryption fixes - some email columns changed to text to make sure the can hold encrypted values - added backwards compatible encryption in up function and decryption in down function. - use updateOrInsert instead of just insert to avoid errors if the column already exists. --- ...eate_email_notification_settings_table.php | 8 +-- ...notification_settings_from_teams_table.php | 71 +++++++++++-------- ...notification_settings_from_teams_table.php | 34 +++++---- ...notification_settings_from_teams_table.php | 61 +++++++++------- 4 files changed, 100 insertions(+), 74 deletions(-) diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php index 6d564e331..951975a22 100644 --- a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -16,10 +16,10 @@ return new class extends Migration $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('smtp_enabled')->default(false); - $table->string('smtp_from_address')->nullable(); - $table->string('smtp_from_name')->nullable(); - $table->string('smtp_recipients')->nullable(); - $table->string('smtp_host')->nullable(); + $table->text('smtp_from_address')->nullable(); + $table->text('smtp_from_name')->nullable(); + $table->text('smtp_recipients')->nullable(); + $table->text('smtp_host')->nullable(); $table->integer('smtp_port')->nullable(); $table->string('smtp_encryption')->nullable(); $table->text('smtp_username')->nullable(); diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index dce7f13a8..da635d32d 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; @@ -12,30 +13,35 @@ return new class extends Migration $teams = DB::table('teams')->get(); foreach ($teams as $team) { - DB::table('email_notification_settings')->insert([ - 'team_id' => $team->id, - 'smtp_enabled' => $team->smtp_enabled ?? false, - 'smtp_from_address' => $team->smtp_from_address, - 'smtp_from_name' => $team->smtp_from_name, - 'smtp_recipients' => $team->smtp_recipients, - 'smtp_host' => $team->smtp_host, - 'smtp_port' => $team->smtp_port, - 'smtp_encryption' => $team->smtp_encryption, - 'smtp_username' => $team->smtp_username, - 'smtp_password' => $team->smtp_password, - 'smtp_timeout' => $team->smtp_timeout, - 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, - 'resend_enabled' => $team->resend_enabled ?? false, - 'resend_api_key' => $team->resend_api_key, - 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, - 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, - 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, - 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, - 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, - 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, - 'server_disk_usage_email_notifications' => $team->smtp_notifications_server_disk_usage ?? true, - ]); + DB::table('email_notification_settings')->updateOrInsert( + ['team_id' => $team->id], + [ + 'smtp_enabled' => $team->smtp_enabled ?? false, + 'smtp_from_address' => Crypt::encryptString($team->smtp_from_address), + 'smtp_from_name' => Crypt::encryptString($team->smtp_from_name), + 'smtp_recipients' => Crypt::encryptString($team->smtp_recipients), + 'smtp_host' => Crypt::encryptString($team->smtp_host), + 'smtp_port' => $team->smtp_port, + 'smtp_encryption' => $team->smtp_encryption, + 'smtp_username' => Crypt::encryptString($team->smtp_username), + 'smtp_password' => $team->smtp_password, + 'smtp_timeout' => $team->smtp_timeout, + + 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, + + 'resend_enabled' => $team->resend_enabled ?? false, + 'resend_api_key' => $team->resend_api_key, + + 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, + 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, + 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, + 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, + 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, + 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, + 'server_disk_usage_email_notifications' => $team->smtp_notifications_server_disk_usage ?? true, + ] + ); } Schema::table('teams', function (Blueprint $table) { @@ -76,13 +82,17 @@ return new class extends Migration $table->text('smtp_username')->nullable(); $table->text('smtp_password')->nullable(); $table->integer('smtp_timeout')->nullable(); + $table->boolean('use_instance_email_settings')->default(false); $table->boolean('resend_enabled')->default(false); + $table->text('resend_api_key')->nullable(); + $table->boolean('smtp_notifications_deployments')->default(false); $table->boolean('smtp_notifications_database_backups')->default(true); $table->boolean('smtp_notifications_scheduled_tasks')->default(false); $table->boolean('smtp_notifications_status_changes')->default(false); + $table->boolean('smtp_notifications_server_disk_usage')->default(true); }); $settings = DB::table('email_notification_settings')->get(); @@ -91,18 +101,21 @@ return new class extends Migration ->where('id', $setting->team_id) ->update([ 'smtp_enabled' => $setting->smtp_enabled, - 'smtp_from_address' => $setting->smtp_from_address, - 'smtp_from_name' => $setting->smtp_from_name, - 'smtp_recipients' => $setting->smtp_recipients, - 'smtp_host' => $setting->smtp_host, + 'smtp_from_address' => Crypt::decryptString($setting->smtp_from_address), + 'smtp_from_name' => Crypt::decryptString($setting->smtp_from_name), + 'smtp_recipients' => Crypt::decryptString($setting->smtp_recipients), + 'smtp_host' => Crypt::decryptString($setting->smtp_host), 'smtp_port' => $setting->smtp_port, 'smtp_encryption' => $setting->smtp_encryption, - 'smtp_username' => $setting->smtp_username, + 'smtp_username' => Crypt::decryptString($setting->smtp_username), 'smtp_password' => $setting->smtp_password, 'smtp_timeout' => $setting->smtp_timeout, + 'use_instance_email_settings' => $setting->use_instance_email_settings, + 'resend_enabled' => $setting->resend_enabled, 'resend_api_key' => $setting->resend_api_key, + 'smtp_notifications_deployments' => $setting->deployment_success_email_notifications || $setting->deployment_failure_email_notifications, 'smtp_notifications_database_backups' => $setting->backup_success_email_notifications || $setting->backup_failure_email_notifications, 'smtp_notifications_scheduled_tasks' => $setting->scheduled_task_success_email_notifications || $setting->scheduled_task_failure_email_notifications, diff --git a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php index 6a738dd22..228691acb 100644 --- a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; @@ -15,19 +16,22 @@ return new class extends Migration $teams = DB::table('teams')->get(); foreach ($teams as $team) { - DB::table('discord_notification_settings')->insert([ - 'team_id' => $team->id, - 'discord_enabled' => $team->discord_enabled ?? false, - 'discord_webhook_url' => $team->discord_webhook_url, - 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, - 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, - 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, - 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, - 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, - 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, - 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, - ]); + DB::table('discord_notification_settings')->updateOrInsert( + ['team_id' => $team->id], + [ + 'discord_enabled' => $team->discord_enabled ?? false, + 'discord_webhook_url' => Crypt::encryptString($team->discord_webhook_url), + + 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, + 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, + 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, + 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, + 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, + 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, + 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, + ] + ); } Schema::table('teams', function (Blueprint $table) { @@ -52,6 +56,7 @@ return new class extends Migration Schema::table('teams', function (Blueprint $table) { $table->boolean('discord_enabled')->default(false); $table->string('discord_webhook_url')->nullable(); + $table->boolean('discord_notifications_test')->default(true); $table->boolean('discord_notifications_deployments')->default(true); $table->boolean('discord_notifications_status_changes')->default(true); @@ -66,7 +71,8 @@ return new class extends Migration ->where('id', $setting->team_id) ->update([ 'discord_enabled' => $setting->discord_enabled, - 'discord_webhook_url' => $setting->discord_webhook_url, + 'discord_webhook_url' => Crypt::decryptString($setting->discord_webhook_url), + 'discord_notifications_deployments' => $setting->deployment_success_discord_notifications || $setting->deployment_failure_discord_notifications, 'discord_notifications_status_changes' => $setting->status_change_discord_notifications, 'discord_notifications_database_backups' => $setting->backup_success_discord_notifications || $setting->backup_failure_discord_notifications, 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 b706ac544..d9d4d6b16 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 @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; @@ -12,29 +13,31 @@ return new class extends Migration $teams = DB::table('teams')->get(); foreach ($teams as $team) { - DB::table('telegram_notification_settings')->insert([ - 'team_id' => $team->id, - 'telegram_enabled' => $team->telegram_enabled ?? false, - 'telegram_token' => $team->telegram_token, - 'telegram_chat_id' => $team->telegram_chat_id, + DB::table('telegram_notification_settings')->updateOrInsert( + ['team_id' => $team->id], + [ + 'telegram_enabled' => $team->telegram_enabled ?? false, + 'telegram_token' => Crypt::encryptString($team->telegram_token), + 'telegram_chat_id' => Crypt::encryptString($team->telegram_chat_id), - 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, - 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, - 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, - 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, - 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, - 'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false, - 'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true, + 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, + 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, + 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, + 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, + 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, + '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, - 'telegram_notifications_deployment_failure_topic_id' => $team->telegram_notifications_deployments_message_thread_id, - 'telegram_notifications_backup_success_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, - 'telegram_notifications_backup_failure_topic_id' => $team->telegram_notifications_database_backups_message_thread_id, - 'telegram_notifications_scheduled_task_success_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, - 'telegram_notifications_scheduled_task_failure_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id, - 'telegram_notifications_status_change_topic_id' => $team->telegram_notifications_status_changes_message_thread_id, - ]); + 'telegram_notifications_deployment_success_topic_id' => Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id), + 'telegram_notifications_deployment_failure_topic_id' => Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id), + 'telegram_notifications_backup_success_topic_id' => Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id), + 'telegram_notifications_backup_failure_topic_id' => Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id), + 'telegram_notifications_scheduled_task_success_topic_id' => Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id), + 'telegram_notifications_scheduled_task_failure_topic_id' => Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id), + 'telegram_notifications_status_change_topic_id' => Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id), + ] + ); } Schema::table('teams', function (Blueprint $table) { @@ -63,12 +66,14 @@ return new class extends Migration $table->boolean('telegram_enabled')->default(false); $table->text('telegram_token')->nullable(); $table->text('telegram_chat_id')->nullable(); + $table->boolean('telegram_notifications_test')->default(true); $table->boolean('telegram_notifications_deployments')->default(true); $table->boolean('telegram_notifications_status_changes')->default(true); $table->boolean('telegram_notifications_database_backups')->default(true); $table->boolean('telegram_notifications_scheduled_tasks')->default(true); $table->boolean('telegram_notifications_server_disk_usage')->default(true); + $table->text('telegram_notifications_test_message_thread_id')->nullable(); $table->text('telegram_notifications_deployments_message_thread_id')->nullable(); $table->text('telegram_notifications_status_changes_message_thread_id')->nullable(); @@ -82,17 +87,19 @@ return new class extends Migration ->where('id', $setting->team_id) ->update([ 'telegram_enabled' => $setting->telegram_enabled, - 'telegram_token' => $setting->telegram_token, - 'telegram_chat_id' => $setting->telegram_chat_id, + 'telegram_token' => Crypt::decryptString($setting->telegram_token), + 'telegram_chat_id' => Crypt::decryptString($setting->telegram_chat_id), + 'telegram_notifications_deployments' => $setting->deployment_success_telegram_notifications || $setting->deployment_failure_telegram_notifications, 'telegram_notifications_status_changes' => $setting->status_change_telegram_notifications, 'telegram_notifications_database_backups' => $setting->backup_success_telegram_notifications || $setting->backup_failure_telegram_notifications, '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, - 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_topic_id, - 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_topic_id, - 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_topic_id, + + 'telegram_notifications_deployments_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_deployment_success_topic_id), + 'telegram_notifications_status_changes_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_status_change_topic_id), + 'telegram_notifications_database_backups_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_backup_success_topic_id), + 'telegram_notifications_scheduled_tasks_thread_id' => Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_topic_id), ]); } } From d3ce6d814c4a158f79664c0ab64a8e8871051968 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:45:52 +0100 Subject: [PATCH 61/80] feat: use encryption in instance settings model --- app/Models/InstanceSettings.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/Models/InstanceSettings.php b/app/Models/InstanceSettings.php index 7110b8cff..5b89bb401 100644 --- a/app/Models/InstanceSettings.php +++ b/app/Models/InstanceSettings.php @@ -16,7 +16,19 @@ class InstanceSettings extends Model implements SendsEmail protected $guarded = []; protected $casts = [ + 'smtp_enabled' => 'boolean', + 'smtp_from_address' => 'encrypted', + 'smtp_from_name' => 'encrypted', + 'smtp_recipients' => 'encrypted', + 'smtp_host' => 'encrypted', + 'smtp_port' => 'integer', + 'smtp_username' => 'encrypted', 'smtp_password' => 'encrypted', + 'smtp_timeout' => 'integer', + + 'resend_enabled' => 'boolean', + 'resend_api_key' => 'encrypted', + 'allowed_ip_ranges' => 'array', 'is_auto_update_enabled' => 'boolean', 'auto_update_frequency' => 'string', From ddfd7777c293545a2399ddefd4c118841055d1d3 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:16:35 +0100 Subject: [PATCH 62/80] fix: docker cleanup email template --- resources/views/emails/docker-cleanup.blade.php | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 resources/views/emails/docker-cleanup.blade.php diff --git a/resources/views/emails/docker-cleanup.blade.php b/resources/views/emails/docker-cleanup.blade.php new file mode 100644 index 000000000..8ac0cda32 --- /dev/null +++ b/resources/views/emails/docker-cleanup.blade.php @@ -0,0 +1,4 @@ + +

Docker cleanup job has completed successfully on {{ $serverName }} server.

+

Message: {{ $message }}

+
From 96d4754a3260568570efa015518a819e3d59d5b0 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:17:23 +0100 Subject: [PATCH 63/80] Update EmailNotificationSettings.php --- app/Models/EmailNotificationSettings.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Models/EmailNotificationSettings.php b/app/Models/EmailNotificationSettings.php index 640a44b7a..ae118986f 100644 --- a/app/Models/EmailNotificationSettings.php +++ b/app/Models/EmailNotificationSettings.php @@ -40,6 +40,7 @@ class EmailNotificationSettings extends Model protected $casts = [ 'smtp_enabled' => 'boolean', 'smtp_from_address' => 'encrypted', + 'smtp_from_name' => 'encrypted', 'smtp_recipients' => 'encrypted', 'smtp_host' => 'encrypted', 'smtp_port' => 'integer', From 99eea783aea32ed84ee5d118b7d7db5530cc9ffc Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:45:47 +0100 Subject: [PATCH 64/80] feat: scheduled task success and failure notifications --- app/Jobs/ScheduledTaskJob.php | 3 +++ app/Models/Application.php | 2 +- app/Models/Service.php | 2 +- app/Notifications/ScheduledTask/TaskFailed.php | 4 ++-- app/Notifications/ScheduledTask/TaskSuccess.php | 10 +++++----- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php index 4c20a4382..90a10f3e9 100644 --- a/app/Jobs/ScheduledTaskJob.php +++ b/app/Jobs/ScheduledTaskJob.php @@ -10,6 +10,7 @@ use App\Models\Server; use App\Models\Service; use App\Models\Team; use App\Notifications\ScheduledTask\TaskFailed; +use App\Notifications\ScheduledTask\TaskSuccess; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -111,6 +112,8 @@ class ScheduledTaskJob implements ShouldQueue 'message' => $this->task_output, ]); + $this->team?->notify(new TaskSuccess($this->task, $this->task_output)); + return; } } diff --git a/app/Models/Application.php b/app/Models/Application.php index d1efd3f33..82ad0c2d1 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -327,7 +327,7 @@ class Application extends BaseModel return null; } - public function failedTaskLink($task_uuid) + public function taskLink($task_uuid) { if (data_get($this, 'environment.project.uuid')) { $route = route('project.application.scheduled-tasks', [ diff --git a/app/Models/Service.php b/app/Models/Service.php index 6d3d2024b..117677d53 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -1140,7 +1140,7 @@ class Service extends BaseModel return null; } - public function failedTaskLink($task_uuid) + public function taskLink($task_uuid) { if (data_get($this, 'environment.project.uuid')) { $route = route('project.service.scheduled-tasks', [ diff --git a/app/Notifications/ScheduledTask/TaskFailed.php b/app/Notifications/ScheduledTask/TaskFailed.php index 878eae5bc..56c410ecb 100644 --- a/app/Notifications/ScheduledTask/TaskFailed.php +++ b/app/Notifications/ScheduledTask/TaskFailed.php @@ -16,9 +16,9 @@ class TaskFailed extends CustomEmailNotification { $this->onQueue('high'); if ($task->application) { - $this->url = $task->application->failedTaskLink($task->uuid); + $this->url = $task->application->taskLink($task->uuid); } elseif ($task->service) { - $this->url = $task->service->failedTaskLink($task->uuid); + $this->url = $task->service->taskLink($task->uuid); } } diff --git a/app/Notifications/ScheduledTask/TaskSuccess.php b/app/Notifications/ScheduledTask/TaskSuccess.php index aaf9cf14b..fc79aea37 100644 --- a/app/Notifications/ScheduledTask/TaskSuccess.php +++ b/app/Notifications/ScheduledTask/TaskSuccess.php @@ -8,7 +8,7 @@ use App\Notifications\Dto\DiscordMessage; use App\Notifications\Dto\SlackMessage; use Illuminate\Notifications\Messages\MailMessage; -class TaskFailed extends CustomEmailNotification +class TaskSuccess extends CustomEmailNotification { public ?string $url = null; @@ -16,9 +16,9 @@ class TaskFailed extends CustomEmailNotification { $this->onQueue('high'); if ($task->application) { - $this->url = $task->application->failedTaskLink($task->uuid); + $this->url = $task->application->taskLink($task->uuid); } elseif ($task->service) { - $this->url = $task->service->failedTaskLink($task->uuid); + $this->url = $task->service->taskLink($task->uuid); } } @@ -31,7 +31,7 @@ class TaskFailed extends CustomEmailNotification { $mail = new MailMessage; $mail->subject("Coolify: Scheduled task ({$this->task->name}) succeeded."); - $mail->view('emails.scheduled-task-failed', [ + $mail->view('emails.scheduled-task-success', [ 'task' => $this->task, 'url' => $this->url, 'output' => $this->output, @@ -43,7 +43,7 @@ class TaskFailed extends CustomEmailNotification public function toDiscord(): DiscordMessage { $message = new DiscordMessage( - title: ':check_mark: Scheduled task succeeded', + title: ':white_check_mark: Scheduled task succeeded', description: "Scheduled task ({$this->task->name}) succeeded.", color: DiscordMessage::successColor(), ); From ba6d05b5632ce1c3a8c0a8e44912d549c28742ae Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 15:30:17 +0100 Subject: [PATCH 65/80] chore: comment status changes as it is disabled for now --- resources/views/livewire/notifications/discord.blade.php | 2 +- resources/views/livewire/notifications/email.blade.php | 2 +- resources/views/livewire/notifications/slack.blade.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index 0173e8d2e..5fec2dd39 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -34,7 +34,7 @@
- + {{-- --}}
diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 868e27ce8..a08538b7e 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -104,7 +104,7 @@
- + {{-- --}}
diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index 052581837..8cfe24cac 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -34,7 +34,7 @@
- + {{-- --}}
From b4dd7cd2638d25ec9069daa24c4698ffa9e51b2b Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 15:31:00 +0100 Subject: [PATCH 66/80] fix: add missing deployment notifications to telegram --- .../livewire/notifications/telegram.blade.php | 102 ++++++++++-------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index 790bf3143..f0ff3381b 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -1,52 +1,66 @@
Notifications | Coolify - - -
-
-

Telegram

- - Save - - @if ($telegramEnabled) - + + + +
+

Telegram

+ + Save + + @if ($telegramEnabled) + Send Test Notification - @endif -
-
- -
-
- - -
- @if ($telegramEnabled) + @endif +
+
+ +
+
+ + +
+ @if ($telegramEnabled)

Notification Settings

Select events for which you would like to receive Telegram notifications.

+
+

Deployment

+
+

Deployment Success

+
+ + +
+

Deployment Failure

+
+ + +
+ {{--

Container Status Changes

+
+ + +
--}} +
+

Backups

Backup Success

- +
- +

Backup Failure

- +
@@ -57,15 +71,13 @@

Scheduled Task Success

- +
- +

Scheduled Task Failure

- +
@@ -76,33 +88,29 @@

Docker Cleanup

- +
- +

Server Disk Usage

- +
- +

Server Reachable

- +
- +

Server Unreachable

- +
- @endif - + @endif +
From 3b5e714ed9beda02517d18ed38c3b8ddf0212067 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:04:11 +0100 Subject: [PATCH 67/80] feat: add docker cleanup success and failure notification settings columns --- ...2_05_212355_create_email_notification_settings_table.php | 3 ++- ...05_212416_create_discord_notification_settings_table.php | 3 ++- ...5_212440_create_telegram_notification_settings_table.php | 6 ++++-- ...2_06_142014_create_slack_notification_settings_table.php | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php index 951975a22..7338a8d0d 100644 --- a/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php +++ b/database/migrations/2024_12_05_212355_create_email_notification_settings_table.php @@ -38,7 +38,8 @@ return new class extends Migration $table->boolean('backup_failure_email_notifications')->default(true); $table->boolean('scheduled_task_success_email_notifications')->default(false); $table->boolean('scheduled_task_failure_email_notifications')->default(true); - $table->boolean('docker_cleanup_email_notifications')->default(false); + $table->boolean('docker_cleanup_success_email_notifications')->default(false); + $table->boolean('docker_cleanup_failure_email_notifications')->default(true); $table->boolean('server_disk_usage_email_notifications')->default(true); $table->boolean('server_reachable_email_notifications')->default(false); $table->boolean('server_unreachable_email_notifications')->default(true); diff --git a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php index b9e9bda03..0f2ced67f 100644 --- a/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php +++ b/database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php @@ -25,7 +25,8 @@ return new class extends Migration $table->boolean('backup_failure_discord_notifications')->default(true); $table->boolean('scheduled_task_success_discord_notifications')->default(false); $table->boolean('scheduled_task_failure_discord_notifications')->default(true); - $table->boolean('docker_cleanup_discord_notifications')->default(false); + $table->boolean('docker_cleanup_success_discord_notifications')->default(false); + $table->boolean('docker_cleanup_failure_discord_notifications')->default(true); $table->boolean('server_disk_usage_discord_notifications')->default(true); $table->boolean('server_reachable_discord_notifications')->default(false); $table->boolean('server_unreachable_discord_notifications')->default(true); 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 be0764a71..190d148fc 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 @@ -26,7 +26,8 @@ return new class extends Migration $table->boolean('backup_failure_telegram_notifications')->default(true); $table->boolean('scheduled_task_success_telegram_notifications')->default(false); $table->boolean('scheduled_task_failure_telegram_notifications')->default(true); - $table->boolean('docker_cleanup_telegram_notifications')->default(false); + $table->boolean('docker_cleanup_success_telegram_notifications')->default(false); + $table->boolean('docker_cleanup_failure_telegram_notifications')->default(true); $table->boolean('server_disk_usage_telegram_notifications')->default(true); $table->boolean('server_reachable_telegram_notifications')->default(false); $table->boolean('server_unreachable_telegram_notifications')->default(true); @@ -38,7 +39,8 @@ return new class extends Migration $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_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(); 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 af46508f0..78e27892e 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 @@ -25,7 +25,8 @@ return new class extends Migration $table->boolean('backup_failure_slack_notifications')->default(true); $table->boolean('scheduled_task_success_slack_notifications')->default(false); $table->boolean('scheduled_task_failure_slack_notifications')->default(true); - $table->boolean('docker_cleanup_slack_notifications')->default(false); + $table->boolean('docker_cleanup_success_slack_notifications')->default(false); + $table->boolean('docker_cleanup_failure_slack_notifications')->default(true); $table->boolean('server_disk_usage_slack_notifications')->default(true); $table->boolean('server_reachable_slack_notifications')->default(false); $table->boolean('server_unreachable_slack_notifications')->default(true); From 9453981f0bb156626bbb4699673bd20ee783df76 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:04:54 +0100 Subject: [PATCH 68/80] feat: UI for docker cleanup success and failure notification --- .../views/livewire/notifications/discord.blade.php | 3 ++- .../views/livewire/notifications/email.blade.php | 3 ++- .../views/livewire/notifications/slack.blade.php | 3 ++- .../views/livewire/notifications/telegram.blade.php | 12 +++++++++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index 5fec2dd39..7a00df6ea 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -54,7 +54,8 @@

Server

- + + diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index a08538b7e..980525cce 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -124,7 +124,8 @@

Server

- + + diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index 8cfe24cac..b1d58d72b 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -54,7 +54,8 @@

Server

- + + diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index f0ff3381b..ff60673b0 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -85,10 +85,16 @@

Server

-

Docker Cleanup

+

Docker Cleanup Success

- - + + +
+ +

Docker Cleanup Failure

+
+ +

Server Disk Usage

From 78d07f00f86f814840aa76e88c7da88f0310e724 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:11:58 +0100 Subject: [PATCH 69/80] feat: docker cleanup email views --- resources/views/emails/docker-cleanup-failed.blade.php | 8 ++++++++ resources/views/emails/docker-cleanup-success.blade.php | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 resources/views/emails/docker-cleanup-failed.blade.php create mode 100644 resources/views/emails/docker-cleanup-success.blade.php diff --git a/resources/views/emails/docker-cleanup-failed.blade.php b/resources/views/emails/docker-cleanup-failed.blade.php new file mode 100644 index 000000000..9661df084 --- /dev/null +++ b/resources/views/emails/docker-cleanup-failed.blade.php @@ -0,0 +1,8 @@ + +Docker Cleanup on {{ $serverName }} FAILED with the following error: + +
+{{ $message }}
+
+ +
diff --git a/resources/views/emails/docker-cleanup-success.blade.php b/resources/views/emails/docker-cleanup-success.blade.php new file mode 100644 index 000000000..943750456 --- /dev/null +++ b/resources/views/emails/docker-cleanup-success.blade.php @@ -0,0 +1,8 @@ + +Docker Cleanup on "{{ $serverName }}" succeeded with the following message: + +
+"{{ $message }}"
+
+ +
\ No newline at end of file From 0375db0d7c04b5c43d9d603b62aa55901e7c926c Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:12:32 +0100 Subject: [PATCH 70/80] feat: Docker cleanup success and failure notification files --- .../Server/DockerCleanupFailed.php | 59 +++++++++++++++++++ ...erCleanup.php => DockerCleanupSuccess.php} | 19 +++--- .../views/emails/docker-cleanup.blade.php | 4 -- 3 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 app/Notifications/Server/DockerCleanupFailed.php rename app/Notifications/Server/{DockerCleanup.php => DockerCleanupSuccess.php} (59%) delete mode 100644 resources/views/emails/docker-cleanup.blade.php diff --git a/app/Notifications/Server/DockerCleanupFailed.php b/app/Notifications/Server/DockerCleanupFailed.php new file mode 100644 index 000000000..d7f70e029 --- /dev/null +++ b/app/Notifications/Server/DockerCleanupFailed.php @@ -0,0 +1,59 @@ +onQueue('high'); + } + + public function via(object $notifiable): array + { + return $notifiable->getEnabledChannels('docker_cleanup_failure'); + } + + public function toMail(): MailMessage + { + $mail = new MailMessage; + $mail->subject("Coolify: [ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}"); + $mail->view('emails.docker-cleanup-failed', [ + 'serverName' => $this->server->name, + 'message' => $this->message, + ]); + + return $mail; + } + + public function toDiscord(): DiscordMessage + { + return new DiscordMessage( + title: ':cross_mark: Coolify: [ACTION REQUIRED] Docker cleanup job failed on '.$this->server->name, + description: $this->message, + color: DiscordMessage::errorColor(), + ); + } + + public function toTelegram(): array + { + return [ + 'message' => "Coolify: [ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}!\n\n{$this->message}", + ]; + } + + public function toSlack(): SlackMessage + { + return new SlackMessage( + title: 'Coolify: [ACTION REQUIRED] Docker cleanup job failed', + description: "Docker cleanup job failed on '{$this->server->name}'!\n\n{$this->message}", + color: SlackMessage::errorColor() + ); + } +} diff --git a/app/Notifications/Server/DockerCleanup.php b/app/Notifications/Server/DockerCleanupSuccess.php similarity index 59% rename from app/Notifications/Server/DockerCleanup.php rename to app/Notifications/Server/DockerCleanupSuccess.php index f4f8ffd09..eb84de787 100644 --- a/app/Notifications/Server/DockerCleanup.php +++ b/app/Notifications/Server/DockerCleanupSuccess.php @@ -8,7 +8,7 @@ use App\Notifications\Dto\DiscordMessage; use App\Notifications\Dto\SlackMessage; use Illuminate\Notifications\Messages\MailMessage; -class DockerCleanup extends CustomEmailNotification +class DockerCleanupSuccess extends CustomEmailNotification { public function __construct(public Server $server, public string $message) { @@ -17,25 +17,26 @@ class DockerCleanup extends CustomEmailNotification public function via(object $notifiable): array { - return $notifiable->getEnabledChannels('docker_cleanup'); + return $notifiable->getEnabledChannels('docker_cleanup_success'); } public function toMail(): MailMessage { $mail = new MailMessage; - $mail->subject("Coolify: Server ({$this->server->name}) docker cleanup job done!"); - $mail->view('emails.docker-cleanup', [ - 'name' => $this->server->name, + $mail->subject("Coolify: Docker cleanup job succeeded on {$this->server->name}"); + $mail->view('emails.docker-cleanup-success', [ + 'serverName' => $this->server->name, 'message' => $this->message, ]); return $mail; } + public function toDiscord(): DiscordMessage { return new DiscordMessage( - title: ':white_check_mark: Server cleanup job done', + title: ':white_check_mark: Coolify: Docker cleanup job succeeded on '.$this->server->name, description: $this->message, color: DiscordMessage::successColor(), ); @@ -44,15 +45,15 @@ class DockerCleanup extends CustomEmailNotification public function toTelegram(): array { return [ - 'message' => "Coolify: Server '{$this->server->name}' cleanup job done!\n\n{$this->message}", + 'message' => "Coolify: Docker cleanup job succeeded on {$this->server->name}!\n\n{$this->message}", ]; } public function toSlack(): SlackMessage { return new SlackMessage( - title: 'Server cleanup job done', - description: "Server '{$this->server->name}' cleanup job done!\n\n{$this->message}", + title: 'Coolify: Docker cleanup job succeeded', + description: "Docker cleanup job succeeded on '{$this->server->name}'!\n\n{$this->message}", color: SlackMessage::successColor() ); } diff --git a/resources/views/emails/docker-cleanup.blade.php b/resources/views/emails/docker-cleanup.blade.php deleted file mode 100644 index 8ac0cda32..000000000 --- a/resources/views/emails/docker-cleanup.blade.php +++ /dev/null @@ -1,4 +0,0 @@ - -

Docker cleanup job has completed successfully on {{ $serverName }} server.

-

Message: {{ $message }}

-
From eaeacb6f7ba4502a2cb70c6722e6e75d22263b52 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:12:58 +0100 Subject: [PATCH 71/80] feat: scheduled task success email --- resources/views/emails/scheduled-task-success.blade.php | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 resources/views/emails/scheduled-task-success.blade.php diff --git a/resources/views/emails/scheduled-task-success.blade.php b/resources/views/emails/scheduled-task-success.blade.php new file mode 100644 index 000000000..44ef8fa58 --- /dev/null +++ b/resources/views/emails/scheduled-task-success.blade.php @@ -0,0 +1,9 @@ + +Scheduled task ({{ $task->name }}) completed successfully with the following output: + +
+{{ $output }}
+
+ +Click [here]({{ $url }}) to view the task. +
From f36043943c24618504edd1544925a6c2c256158c Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:13:18 +0100 Subject: [PATCH 72/80] feat: send new docker cleanup notifications --- app/Jobs/DockerCleanupJob.php | 37 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index 80542e03b..103c137b9 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -4,7 +4,8 @@ namespace App\Jobs; use App\Actions\Server\CleanupDocker; use App\Models\Server; -use App\Notifications\Server\DockerCleanup; +use App\Notifications\Server\DockerCleanupFailed; +use App\Notifications\Server\DockerCleanupSuccess; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldQueue; @@ -12,7 +13,6 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\Log; class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue { @@ -38,35 +38,36 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue return; } - if ($this->manualCleanup || $this->server->settings->force_docker_cleanup) { - Log::info('DockerCleanupJob '.($this->manualCleanup ? 'manual' : 'force').' cleanup on '.$this->server->name); - CleanupDocker::run(server: $this->server); - - return; - } - $this->usageBefore = $this->server->getDiskUsage(); - if (str($this->usageBefore)->isEmpty() || $this->usageBefore === null || $this->usageBefore === 0) { - Log::info('DockerCleanupJob force cleanup on '.$this->server->name); + + if ($this->manualCleanup || $this->server->settings->force_docker_cleanup) { CleanupDocker::run(server: $this->server); + $usageAfter = $this->server->getDiskUsage(); + $this->server->team?->notify(new DockerCleanupSuccess($this->server, ($this->manualCleanup ? 'Manual' : 'Forced').' Docker cleanup job executed successfully. Disk usage before: '.$this->usageBefore.'%, Disk usage after: '.$usageAfter.'%.')); return; } + + if (str($this->usageBefore)->isEmpty() || $this->usageBefore === null || $this->usageBefore === 0) { + CleanupDocker::run(server: $this->server); + $this->server->team?->notify(new DockerCleanupSuccess($this->server, 'Docker cleanup job executed successfully, but no disk usage could be determined.')); + } + if ($this->usageBefore >= $this->server->settings->docker_cleanup_threshold) { CleanupDocker::run(server: $this->server); $usageAfter = $this->server->getDiskUsage(); - if ($usageAfter < $this->usageBefore) { - $this->server->team?->notify(new DockerCleanup($this->server, 'Saved '.($this->usageBefore - $usageAfter).'% disk space.')); - Log::info('DockerCleanupJob done: Saved '.($this->usageBefore - $usageAfter).'% disk space on '.$this->server->name); + $diskSaved = $this->usageBefore - $usageAfter; + + if ($diskSaved > 0) { + $this->server->team?->notify(new DockerCleanupSuccess($this->server, 'Saved '.$diskSaved.'% disk space. Disk usage before: '.$this->usageBefore.'%, Disk usage after: '.$usageAfter.'%.')); } else { - Log::info('DockerCleanupJob failed to save disk space on '.$this->server->name); + $this->server->team?->notify(new DockerCleanupSuccess($this->server, 'Docker cleanup job executed successfully, but no disk space was saved. Disk usage before: '.$this->usageBefore.'%, Disk usage after: '.$usageAfter.'%.')); } } else { - Log::info('No need to clean up '.$this->server->name); + $this->server->team?->notify(new DockerCleanupSuccess($this->server, 'No cleanup needed for '.$this->server->name)); } } catch (\Throwable $e) { - CleanupDocker::run(server: $this->server); - Log::error('DockerCleanupJob failed: '.$e->getMessage()); + $this->server->team?->notify(new DockerCleanupFailed($this->server, 'Docker cleanup job failed with the following error: '.$e->getMessage())); throw $e; } } From 3030df955457ae47c170742d2f2b48f817cbdc38 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:13:54 +0100 Subject: [PATCH 73/80] fix: new docker cleanup settings are now saved to the DB correctly --- app/Livewire/Notifications/Discord.php | 11 ++++++++--- app/Livewire/Notifications/Email.php | 12 +++++++++--- app/Livewire/Notifications/Slack.php | 11 ++++++++--- app/Livewire/Notifications/Telegram.php | 22 ++++++++++++++++------ 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php index c5ec471d7..c09966e53 100644 --- a/app/Livewire/Notifications/Discord.php +++ b/app/Livewire/Notifications/Discord.php @@ -42,7 +42,10 @@ class Discord extends Component public bool $scheduledTaskFailureDiscordNotifications = true; #[Validate(['boolean'])] - public bool $dockerCleanupDiscordNotifications = false; + public bool $dockerCleanupSuccessDiscordNotifications = false; + + #[Validate(['boolean'])] + public bool $dockerCleanupFailureDiscordNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageDiscordNotifications = true; @@ -78,7 +81,8 @@ class Discord extends Component $this->settings->backup_failure_discord_notifications = $this->backupFailureDiscordNotifications; $this->settings->scheduled_task_success_discord_notifications = $this->scheduledTaskSuccessDiscordNotifications; $this->settings->scheduled_task_failure_discord_notifications = $this->scheduledTaskFailureDiscordNotifications; - $this->settings->docker_cleanup_discord_notifications = $this->dockerCleanupDiscordNotifications; + $this->settings->docker_cleanup_success_discord_notifications = $this->dockerCleanupSuccessDiscordNotifications; + $this->settings->docker_cleanup_failure_discord_notifications = $this->dockerCleanupFailureDiscordNotifications; $this->settings->server_disk_usage_discord_notifications = $this->serverDiskUsageDiscordNotifications; $this->settings->server_reachable_discord_notifications = $this->serverReachableDiscordNotifications; $this->settings->server_unreachable_discord_notifications = $this->serverUnreachableDiscordNotifications; @@ -96,7 +100,8 @@ class Discord extends Component $this->backupFailureDiscordNotifications = $this->settings->backup_failure_discord_notifications; $this->scheduledTaskSuccessDiscordNotifications = $this->settings->scheduled_task_success_discord_notifications; $this->scheduledTaskFailureDiscordNotifications = $this->settings->scheduled_task_failure_discord_notifications; - $this->dockerCleanupDiscordNotifications = $this->settings->docker_cleanup_discord_notifications; + $this->dockerCleanupSuccessDiscordNotifications = $this->settings->docker_cleanup_success_discord_notifications; + $this->dockerCleanupFailureDiscordNotifications = $this->settings->docker_cleanup_failure_discord_notifications; $this->serverDiskUsageDiscordNotifications = $this->settings->server_disk_usage_discord_notifications; $this->serverReachableDiscordNotifications = $this->settings->server_reachable_discord_notifications; $this->serverUnreachableDiscordNotifications = $this->settings->server_unreachable_discord_notifications; diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index 7af25694f..83debb6ff 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -80,7 +80,10 @@ class Email extends Component public bool $scheduledTaskFailureEmailNotifications = true; #[Validate(['boolean'])] - public bool $dockerCleanupEmailNotifications = false; + public bool $dockerCleanupSuccessEmailNotifications = false; + + #[Validate(['boolean'])] + public bool $dockerCleanupFailureEmailNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageEmailNotifications = true; @@ -133,7 +136,8 @@ class Email extends Component $this->settings->backup_failure_email_notifications = $this->backupFailureEmailNotifications; $this->settings->scheduled_task_success_email_notifications = $this->scheduledTaskSuccessEmailNotifications; $this->settings->scheduled_task_failure_email_notifications = $this->scheduledTaskFailureEmailNotifications; - $this->settings->docker_cleanup_email_notifications = $this->dockerCleanupEmailNotifications; + $this->settings->docker_cleanup_success_email_notifications = $this->dockerCleanupSuccessEmailNotifications; + $this->settings->docker_cleanup_failure_email_notifications = $this->dockerCleanupFailureEmailNotifications; $this->settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; $this->settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; $this->settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; @@ -164,10 +168,12 @@ class Email extends Component $this->backupFailureEmailNotifications = $this->settings->backup_failure_email_notifications; $this->scheduledTaskSuccessEmailNotifications = $this->settings->scheduled_task_success_email_notifications; $this->scheduledTaskFailureEmailNotifications = $this->settings->scheduled_task_failure_email_notifications; - $this->dockerCleanupEmailNotifications = $this->settings->docker_cleanup_email_notifications; + $this->dockerCleanupSuccessEmailNotifications = $this->settings->docker_cleanup_success_email_notifications; + $this->dockerCleanupFailureEmailNotifications = $this->settings->docker_cleanup_failure_email_notifications; $this->serverDiskUsageEmailNotifications = $this->settings->server_disk_usage_email_notifications; $this->serverReachableEmailNotifications = $this->settings->server_reachable_email_notifications; $this->serverUnreachableEmailNotifications = $this->settings->server_unreachable_email_notifications; + } } diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php index 7fa881641..91f05f42f 100644 --- a/app/Livewire/Notifications/Slack.php +++ b/app/Livewire/Notifications/Slack.php @@ -42,7 +42,10 @@ class Slack extends Component public bool $scheduledTaskFailureSlackNotifications = true; #[Validate(['boolean'])] - public bool $dockerCleanupSlackNotifications = false; + public bool $dockerCleanupSuccessSlackNotifications = false; + + #[Validate(['boolean'])] + public bool $dockerCleanupFailureSlackNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageSlackNotifications = true; @@ -78,7 +81,8 @@ class Slack extends Component $this->settings->backup_failure_slack_notifications = $this->backupFailureSlackNotifications; $this->settings->scheduled_task_success_slack_notifications = $this->scheduledTaskSuccessSlackNotifications; $this->settings->scheduled_task_failure_slack_notifications = $this->scheduledTaskFailureSlackNotifications; - $this->settings->docker_cleanup_slack_notifications = $this->dockerCleanupSlackNotifications; + $this->settings->docker_cleanup_success_slack_notifications = $this->dockerCleanupSuccessSlackNotifications; + $this->settings->docker_cleanup_failure_slack_notifications = $this->dockerCleanupFailureSlackNotifications; $this->settings->server_disk_usage_slack_notifications = $this->serverDiskUsageSlackNotifications; $this->settings->server_reachable_slack_notifications = $this->serverReachableSlackNotifications; $this->settings->server_unreachable_slack_notifications = $this->serverUnreachableSlackNotifications; @@ -96,7 +100,8 @@ class Slack extends Component $this->backupFailureSlackNotifications = $this->settings->backup_failure_slack_notifications; $this->scheduledTaskSuccessSlackNotifications = $this->settings->scheduled_task_success_slack_notifications; $this->scheduledTaskFailureSlackNotifications = $this->settings->scheduled_task_failure_slack_notifications; - $this->dockerCleanupSlackNotifications = $this->settings->docker_cleanup_slack_notifications; + $this->dockerCleanupSuccessSlackNotifications = $this->settings->docker_cleanup_success_slack_notifications; + $this->dockerCleanupFailureSlackNotifications = $this->settings->docker_cleanup_failure_slack_notifications; $this->serverDiskUsageSlackNotifications = $this->settings->server_disk_usage_slack_notifications; $this->serverReachableSlackNotifications = $this->settings->server_reachable_slack_notifications; $this->serverUnreachableSlackNotifications = $this->settings->server_unreachable_slack_notifications; diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index c83020830..d425fd262 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -45,7 +45,10 @@ class Telegram extends Component public bool $scheduledTaskFailureTelegramNotifications = true; #[Validate(['boolean'])] - public bool $dockerCleanupTelegramNotifications = false; + public bool $dockerCleanupSuccessTelegramNotifications = false; + + #[Validate(['boolean'])] + public bool $dockerCleanupFailureTelegramNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageTelegramNotifications = true; @@ -78,7 +81,10 @@ class Telegram extends Component public ?string $telegramNotificationsScheduledTaskFailureTopicId = null; #[Validate(['nullable', 'string'])] - public ?string $telegramNotificationsDockerCleanupTopicId = null; + public ?string $telegramNotificationsDockerCleanupSuccessTopicId = null; + + #[Validate(['nullable', 'string'])] + public ?string $telegramNotificationsDockerCleanupFailureTopicId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsServerDiskUsageTopicId = null; @@ -115,7 +121,8 @@ class Telegram extends Component $this->settings->backup_failure_telegram_notifications = $this->backupFailureTelegramNotifications; $this->settings->scheduled_task_success_telegram_notifications = $this->scheduledTaskSuccessTelegramNotifications; $this->settings->scheduled_task_failure_telegram_notifications = $this->scheduledTaskFailureTelegramNotifications; - $this->settings->docker_cleanup_telegram_notifications = $this->dockerCleanupTelegramNotifications; + $this->settings->docker_cleanup_success_telegram_notifications = $this->dockerCleanupSuccessTelegramNotifications; + $this->settings->docker_cleanup_failure_telegram_notifications = $this->dockerCleanupFailureTelegramNotifications; $this->settings->server_disk_usage_telegram_notifications = $this->serverDiskUsageTelegramNotifications; $this->settings->server_reachable_telegram_notifications = $this->serverReachableTelegramNotifications; $this->settings->server_unreachable_telegram_notifications = $this->serverUnreachableTelegramNotifications; @@ -127,7 +134,8 @@ class Telegram extends Component $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_topic_id = $this->telegramNotificationsDockerCleanupTopicId; + $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; @@ -146,7 +154,8 @@ class Telegram extends Component $this->backupFailureTelegramNotifications = $this->settings->backup_failure_telegram_notifications; $this->scheduledTaskSuccessTelegramNotifications = $this->settings->scheduled_task_success_telegram_notifications; $this->scheduledTaskFailureTelegramNotifications = $this->settings->scheduled_task_failure_telegram_notifications; - $this->dockerCleanupTelegramNotifications = $this->settings->docker_cleanup_telegram_notifications; + $this->dockerCleanupSuccessTelegramNotifications = $this->settings->docker_cleanup_success_telegram_notifications; + $this->dockerCleanupFailureTelegramNotifications = $this->settings->docker_cleanup_failure_telegram_notifications; $this->serverDiskUsageTelegramNotifications = $this->settings->server_disk_usage_telegram_notifications; $this->serverReachableTelegramNotifications = $this->settings->server_reachable_telegram_notifications; $this->serverUnreachableTelegramNotifications = $this->settings->server_unreachable_telegram_notifications; @@ -158,7 +167,8 @@ class Telegram extends Component $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->telegramNotificationsDockerCleanupTopicId = $this->settings->telegram_notifications_docker_cleanup_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; From 1257ab6ff46c143a72dec5044848de6337ac1507 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 10:14:12 +0100 Subject: [PATCH 74/80] fix: ui + migrations --- app/Livewire/Notifications/Email.php | 11 +- ...notification_settings_from_teams_table.php | 102 ++++--- ...notification_settings_from_teams_table.php | 60 ++-- ...notification_settings_from_teams_table.php | 86 +++--- ...ncrypt_instance_settings_email_columns.php | 46 +-- .../livewire/notifications/discord.blade.php | 85 +++--- .../livewire/notifications/email.blade.php | 182 +++++++----- .../livewire/notifications/slack.blade.php | 91 +++--- .../livewire/notifications/telegram.blade.php | 270 ++++++++++-------- scripts/run | 12 +- 10 files changed, 532 insertions(+), 413 deletions(-) diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index 83debb6ff..dc5a35d66 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -12,6 +12,8 @@ use Livewire\Component; class Email extends Component { + protected $listeners = ['refresh' => '$refresh']; + public Team $team; public EmailNotificationSettings $settings; @@ -141,9 +143,8 @@ class Email extends Component $this->settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; $this->settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; $this->settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; - $this->settings->save(); - refreshSession(); + } else { $this->smtpEnabled = $this->settings->smtp_enabled; $this->smtpFromAddress = $this->settings->smtp_from_address; @@ -173,7 +174,6 @@ class Email extends Component $this->serverDiskUsageEmailNotifications = $this->settings->server_disk_usage_email_notifications; $this->serverReachableEmailNotifications = $this->settings->server_reachable_email_notifications; $this->serverUnreachableEmailNotifications = $this->settings->server_unreachable_email_notifications; - } } @@ -190,7 +190,6 @@ class Email extends Component public function saveModel() { $this->syncData(true); - refreshSession(); $this->dispatch('success', 'Email notifications settings updated.'); } @@ -218,6 +217,8 @@ class Email extends Component } return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } @@ -261,7 +262,6 @@ class Email extends Component $this->settings->smtp_timeout = $this->smtpTimeout; $this->settings->save(); - refreshSession(); $this->dispatch('success', 'SMTP settings updated.'); } catch (\Throwable $e) { $this->smtpEnabled = false; @@ -297,7 +297,6 @@ class Email extends Component $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->save(); - refreshSession(); $this->dispatch('success', 'Resend settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index da635d32d..f9d5ad0b4 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -13,35 +13,39 @@ return new class extends Migration $teams = DB::table('teams')->get(); foreach ($teams as $team) { - DB::table('email_notification_settings')->updateOrInsert( - ['team_id' => $team->id], - [ - 'smtp_enabled' => $team->smtp_enabled ?? false, - 'smtp_from_address' => Crypt::encryptString($team->smtp_from_address), - 'smtp_from_name' => Crypt::encryptString($team->smtp_from_name), - 'smtp_recipients' => Crypt::encryptString($team->smtp_recipients), - 'smtp_host' => Crypt::encryptString($team->smtp_host), - 'smtp_port' => $team->smtp_port, - 'smtp_encryption' => $team->smtp_encryption, - 'smtp_username' => Crypt::encryptString($team->smtp_username), - 'smtp_password' => $team->smtp_password, - 'smtp_timeout' => $team->smtp_timeout, + try { + DB::table('email_notification_settings')->updateOrInsert( + ['team_id' => $team->id], + [ + 'smtp_enabled' => $team->smtp_enabled ?? false, + 'smtp_from_address' => Crypt::encryptString($team->smtp_from_address), + 'smtp_from_name' => Crypt::encryptString($team->smtp_from_name), + 'smtp_recipients' => Crypt::encryptString($team->smtp_recipients), + 'smtp_host' => Crypt::encryptString($team->smtp_host), + 'smtp_port' => $team->smtp_port, + 'smtp_encryption' => $team->smtp_encryption, + 'smtp_username' => Crypt::encryptString($team->smtp_username), + 'smtp_password' => $team->smtp_password, + 'smtp_timeout' => $team->smtp_timeout, - 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, + 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, - 'resend_enabled' => $team->resend_enabled ?? false, - 'resend_api_key' => $team->resend_api_key, + 'resend_enabled' => $team->resend_enabled ?? false, + 'resend_api_key' => $team->resend_api_key, - 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, - 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, - 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, - 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, - 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, - 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, - 'server_disk_usage_email_notifications' => $team->smtp_notifications_server_disk_usage ?? true, - ] - ); + 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, + 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, + 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, + 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, + 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, + 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, + 'server_disk_usage_email_notifications' => $team->smtp_notifications_server_disk_usage ?? true, + ] + ); + } catch (Exception $e) { + \Log::error('Error migrating email notification settings from teams table: '.$e->getMessage()); + } } Schema::table('teams', function (Blueprint $table) { @@ -97,30 +101,34 @@ return new class extends Migration $settings = DB::table('email_notification_settings')->get(); foreach ($settings as $setting) { - DB::table('teams') - ->where('id', $setting->team_id) - ->update([ - 'smtp_enabled' => $setting->smtp_enabled, - 'smtp_from_address' => Crypt::decryptString($setting->smtp_from_address), - 'smtp_from_name' => Crypt::decryptString($setting->smtp_from_name), - 'smtp_recipients' => Crypt::decryptString($setting->smtp_recipients), - 'smtp_host' => Crypt::decryptString($setting->smtp_host), - 'smtp_port' => $setting->smtp_port, - 'smtp_encryption' => $setting->smtp_encryption, - 'smtp_username' => Crypt::decryptString($setting->smtp_username), - 'smtp_password' => $setting->smtp_password, - 'smtp_timeout' => $setting->smtp_timeout, + try { + DB::table('teams') + ->where('id', $setting->team_id) + ->update([ + 'smtp_enabled' => $setting->smtp_enabled, + 'smtp_from_address' => $setting->smtp_from_address ? Crypt::decryptString($setting->smtp_from_address) : null, + 'smtp_from_name' => $setting->smtp_from_name ? Crypt::decryptString($setting->smtp_from_name) : null, + 'smtp_recipients' => $setting->smtp_recipients ? Crypt::decryptString($setting->smtp_recipients) : null, + 'smtp_host' => $setting->smtp_host ? Crypt::decryptString($setting->smtp_host) : null, + 'smtp_port' => $setting->smtp_port, + 'smtp_encryption' => $setting->smtp_encryption, + 'smtp_username' => $setting->smtp_username ? Crypt::decryptString($setting->smtp_username) : null, + 'smtp_password' => $setting->smtp_password, + 'smtp_timeout' => $setting->smtp_timeout, - 'use_instance_email_settings' => $setting->use_instance_email_settings, + 'use_instance_email_settings' => $setting->use_instance_email_settings, - 'resend_enabled' => $setting->resend_enabled, - 'resend_api_key' => $setting->resend_api_key, + 'resend_enabled' => $setting->resend_enabled, + 'resend_api_key' => $setting->resend_api_key, - 'smtp_notifications_deployments' => $setting->deployment_success_email_notifications || $setting->deployment_failure_email_notifications, - 'smtp_notifications_database_backups' => $setting->backup_success_email_notifications || $setting->backup_failure_email_notifications, - 'smtp_notifications_scheduled_tasks' => $setting->scheduled_task_success_email_notifications || $setting->scheduled_task_failure_email_notifications, - 'smtp_notifications_status_changes' => $setting->status_change_email_notifications, - ]); + 'smtp_notifications_deployments' => $setting->deployment_success_email_notifications || $setting->deployment_failure_email_notifications, + 'smtp_notifications_database_backups' => $setting->backup_success_email_notifications || $setting->backup_failure_email_notifications, + 'smtp_notifications_scheduled_tasks' => $setting->scheduled_task_success_email_notifications || $setting->scheduled_task_failure_email_notifications, + 'smtp_notifications_status_changes' => $setting->status_change_email_notifications, + ]); + } catch (Exception $e) { + \Log::error('Error migrating email notification settings from teams table: '.$e->getMessage()); + } } } }; diff --git a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php index 228691acb..ed9e9af82 100644 --- a/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php @@ -16,22 +16,26 @@ return new class extends Migration $teams = DB::table('teams')->get(); foreach ($teams as $team) { - DB::table('discord_notification_settings')->updateOrInsert( - ['team_id' => $team->id], - [ - 'discord_enabled' => $team->discord_enabled ?? false, - 'discord_webhook_url' => Crypt::encryptString($team->discord_webhook_url), + try { + DB::table('discord_notification_settings')->updateOrInsert( + ['team_id' => $team->id], + [ + 'discord_enabled' => $team->discord_enabled ?? false, + 'discord_webhook_url' => $team->discord_webhook_url ? Crypt::encryptString($team->discord_webhook_url) : null, - 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, - 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, - 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, - 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, - 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, - 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, - 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, - ] - ); + 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, + 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, + 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, + 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, + 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, + 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, + 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, + ] + ); + } catch (Exception $e) { + \Log::error('Error migrating discord notification settings from teams table: '.$e->getMessage()); + } } Schema::table('teams', function (Blueprint $table) { @@ -67,18 +71,22 @@ return new class extends Migration $settings = DB::table('discord_notification_settings')->get(); foreach ($settings as $setting) { - DB::table('teams') - ->where('id', $setting->team_id) - ->update([ - 'discord_enabled' => $setting->discord_enabled, - 'discord_webhook_url' => Crypt::decryptString($setting->discord_webhook_url), + try { + DB::table('teams') + ->where('id', $setting->team_id) + ->update([ + 'discord_enabled' => $setting->discord_enabled, + 'discord_webhook_url' => Crypt::decryptString($setting->discord_webhook_url), - 'discord_notifications_deployments' => $setting->deployment_success_discord_notifications || $setting->deployment_failure_discord_notifications, - 'discord_notifications_status_changes' => $setting->status_change_discord_notifications, - 'discord_notifications_database_backups' => $setting->backup_success_discord_notifications || $setting->backup_failure_discord_notifications, - 'discord_notifications_scheduled_tasks' => $setting->scheduled_task_success_discord_notifications || $setting->scheduled_task_failure_discord_notifications, - 'discord_notifications_server_disk_usage' => $setting->server_disk_usage_discord_notifications, - ]); + 'discord_notifications_deployments' => $setting->deployment_success_discord_notifications || $setting->deployment_failure_discord_notifications, + 'discord_notifications_status_changes' => $setting->status_change_discord_notifications, + 'discord_notifications_database_backups' => $setting->backup_success_discord_notifications || $setting->backup_failure_discord_notifications, + 'discord_notifications_scheduled_tasks' => $setting->scheduled_task_success_discord_notifications || $setting->scheduled_task_failure_discord_notifications, + 'discord_notifications_server_disk_usage' => $setting->server_disk_usage_discord_notifications, + ]); + } catch (Exception $e) { + \Log::error('Error migrating discord notification settings from teams table: '.$e->getMessage()); + } } } }; 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 d9d4d6b16..c93569aef 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 @@ -13,31 +13,35 @@ return new class extends Migration $teams = DB::table('teams')->get(); foreach ($teams as $team) { - DB::table('telegram_notification_settings')->updateOrInsert( - ['team_id' => $team->id], - [ - 'telegram_enabled' => $team->telegram_enabled ?? false, - 'telegram_token' => Crypt::encryptString($team->telegram_token), - 'telegram_chat_id' => Crypt::encryptString($team->telegram_chat_id), + try { + DB::table('telegram_notification_settings')->updateOrInsert( + ['team_id' => $team->id], + [ + 'telegram_enabled' => $team->telegram_enabled ?? false, + 'telegram_token' => $team->telegram_token ? Crypt::encryptString($team->telegram_token) : null, + 'telegram_chat_id' => $team->telegram_chat_id ? Crypt::encryptString($team->telegram_chat_id) : null, - 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, - 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, - 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, - 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, - 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, - 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, - 'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false, - 'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true, + 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, + 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, + 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, + 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, + 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, + 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, + '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' => Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id), - 'telegram_notifications_deployment_failure_topic_id' => Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id), - 'telegram_notifications_backup_success_topic_id' => Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id), - 'telegram_notifications_backup_failure_topic_id' => Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id), - 'telegram_notifications_scheduled_task_success_topic_id' => Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id), - 'telegram_notifications_scheduled_task_failure_topic_id' => Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id), - 'telegram_notifications_status_change_topic_id' => Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id), - ] - ); + '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, + ] + ); + } catch (Exception $e) { + \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); + } } Schema::table('teams', function (Blueprint $table) { @@ -83,24 +87,28 @@ return new class extends Migration $settings = DB::table('telegram_notification_settings')->get(); foreach ($settings as $setting) { - DB::table('teams') - ->where('id', $setting->team_id) - ->update([ - 'telegram_enabled' => $setting->telegram_enabled, - 'telegram_token' => Crypt::decryptString($setting->telegram_token), - 'telegram_chat_id' => Crypt::decryptString($setting->telegram_chat_id), + try { + DB::table('teams') + ->where('id', $setting->team_id) + ->update([ + 'telegram_enabled' => $setting->telegram_enabled, + 'telegram_token' => Crypt::decryptString($setting->telegram_token), + 'telegram_chat_id' => Crypt::decryptString($setting->telegram_chat_id), - 'telegram_notifications_deployments' => $setting->deployment_success_telegram_notifications || $setting->deployment_failure_telegram_notifications, - 'telegram_notifications_status_changes' => $setting->status_change_telegram_notifications, - 'telegram_notifications_database_backups' => $setting->backup_success_telegram_notifications || $setting->backup_failure_telegram_notifications, - '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' => $setting->deployment_success_telegram_notifications || $setting->deployment_failure_telegram_notifications, + 'telegram_notifications_status_changes' => $setting->status_change_telegram_notifications, + 'telegram_notifications_database_backups' => $setting->backup_success_telegram_notifications || $setting->backup_failure_telegram_notifications, + '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' => Crypt::decryptString($setting->telegram_notifications_deployment_success_topic_id), - 'telegram_notifications_status_changes_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_status_change_topic_id), - 'telegram_notifications_database_backups_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_backup_success_topic_id), - 'telegram_notifications_scheduled_tasks_thread_id' => Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_topic_id), - ]); + 'telegram_notifications_deployments_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_deployment_success_topic_id), + 'telegram_notifications_status_changes_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_status_change_topic_id), + 'telegram_notifications_database_backups_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_backup_success_topic_id), + 'telegram_notifications_scheduled_tasks_thread_id' => Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_topic_id), + ]); + } catch (Exception $e) { + \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); + } } } }; diff --git a/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php b/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php index 618b8df90..8ccbcb4f6 100644 --- a/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php +++ b/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php @@ -15,22 +15,26 @@ return new class extends Migration { if (DB::table('instance_settings')->exists()) { Schema::table('instance_settings', function (Blueprint $table) { - $table->text('smtp_from_address')->change(); - $table->text('smtp_from_name')->change(); - $table->text('smtp_recipients')->change(); - $table->text('smtp_host')->change(); - $table->text('smtp_username')->change(); + $table->text('smtp_from_address')->nullable()->change(); + $table->text('smtp_from_name')->nullable()->change(); + $table->text('smtp_recipients')->nullable()->change(); + $table->text('smtp_host')->nullable()->change(); + $table->text('smtp_username')->nullable()->change(); }); $settings = DB::table('instance_settings')->get(); foreach ($settings as $setting) { - DB::table('instance_settings')->where('id', $setting->id)->update([ - 'smtp_from_address' => Crypt::encryptString($setting->smtp_from_address), - 'smtp_from_name' => Crypt::encryptString($setting->smtp_from_name), - 'smtp_recipients' => Crypt::encryptString($setting->smtp_recipients), - 'smtp_host' => Crypt::encryptString($setting->smtp_host), - 'smtp_username' => Crypt::encryptString($setting->smtp_username), - ]); + try { + DB::table('instance_settings')->where('id', $setting->id)->update([ + 'smtp_from_address' => $setting->smtp_from_address ? Crypt::encryptString($setting->smtp_from_address) : null, + 'smtp_from_name' => $setting->smtp_from_name ? Crypt::encryptString($setting->smtp_from_name) : null, + 'smtp_recipients' => $setting->smtp_recipients ? Crypt::encryptString($setting->smtp_recipients) : null, + 'smtp_host' => $setting->smtp_host ? Crypt::encryptString($setting->smtp_host) : null, + 'smtp_username' => $setting->smtp_username ? Crypt::encryptString($setting->smtp_username) : null, + ]); + } catch (Exception $e) { + \Log::error('Error encrypting instance settings email columns: '.$e->getMessage()); + } } } } @@ -51,13 +55,17 @@ return new class extends Migration if (DB::table('instance_settings')->exists()) { $settings = DB::table('instance_settings')->get(); foreach ($settings as $setting) { - DB::table('instance_settings')->where('id', $setting->id)->update([ - 'smtp_from_address' => Crypt::decryptString($setting->smtp_from_address), - 'smtp_from_name' => Crypt::decryptString($setting->smtp_from_name), - 'smtp_recipients' => Crypt::decryptString($setting->smtp_recipients), - 'smtp_host' => Crypt::decryptString($setting->smtp_host), - 'smtp_username' => Crypt::decryptString($setting->smtp_username), - ]); + try { + DB::table('instance_settings')->where('id', $setting->id)->update([ + 'smtp_from_address' => $setting->smtp_from_address ? Crypt::decryptString($setting->smtp_from_address) : null, + 'smtp_from_name' => $setting->smtp_from_name ? Crypt::decryptString($setting->smtp_from_name) : null, + 'smtp_recipients' => $setting->smtp_recipients ? Crypt::decryptString($setting->smtp_recipients) : null, + 'smtp_host' => $setting->smtp_host ? Crypt::decryptString($setting->smtp_host) : null, + 'smtp_username' => $setting->smtp_username ? Crypt::decryptString($setting->smtp_username) : null, + ]); + } catch (Exception $e) { + \Log::error('Error decrypting instance settings email columns: '.$e->getMessage()); + } } } } diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index 7a00df6ea..189f2f490 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -14,6 +14,10 @@ wire:click="sendTestNotification"> Send Test Notification + @else + + Send Test Notification + @endif
@@ -23,44 +27,53 @@ helper="Generate a webhook in Discord.
Example: https://discord.com/api/webhooks/...." required id="discordWebhookUrl" label="Webhook" /> - @if ($discordEnabled) -

Notification Settings

-

- Select events for which you would like to receive Discord notifications. -

-
-
-

Deployments

-
- - - {{-- --}} -
+

Notification Settings

+

+ Select events for which you would like to receive Discord notifications. +

+
+
+

Deployments

+
+ + + {{-- --}}
-
-

Backups

-
- - -
+
+
+

Backups

+
+ +
-
-

Scheduled Tasks

-
- - -
+
+
+

Scheduled Tasks

+
+ +
-
-

Server

-
- - - - - -
+
+
+

Server

+
+ + + + +
-
- @endif +
+
diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 980525cce..37bfac0e0 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -1,48 +1,58 @@
Notifications | Coolify - - -
-
-

Email

- - Save - - @if ($team->isNotificationEnabled('email') && auth()->user()->isAdminFromSession()) - - - - - Send Email - - - + + +
+
+

Email

+ + Save + + @if (auth()->user()->isAdminFromSession()) + @if ($team->isNotificationEnabled('email')) + + + + + Send Email + + + + @else + + Send Test Email + @endif - @if (isInstanceAdmin() && !$useInstanceEmailSettings) + @endif +
+ @if (!isCloud()) +
+ +
+ @endif + @if (!$useInstanceEmailSettings) +
+ + +
+ @if (isInstanceAdmin() && !$useInstanceEmailSettings) Copy from Instance Settings - @endif -
- @if (!isCloud()) -
- -
@endif - @if (!$useInstanceEmailSettings) -
- - -
- @endif - - @if (isCloud()) -
- -
@endif - @if (!$useInstanceEmailSettings) + + @if (isCloud()) +
+ +
+ @endif + @if (!$useInstanceEmailSettings)
@@ -52,7 +62,8 @@
- +
@@ -68,7 +79,8 @@
- +
@@ -81,56 +93,68 @@
- +
- +
- @endif - @if ($team->isNotificationEnabled('email') || $useInstanceEmailSettings) -

Notification Settings

-

- Select events for which you would like to receive email notifications. -

-
-
-

Deployments

-
- - - {{-- --}} -
-
-
-

Backups

-
- - -
-
-
-

Scheduled Tasks

-
- - -
-
-
-

Server

-
- - - - - -
+ @endif +

Notification Settings

+

+ Select events for which you would like to receive email notifications. +

+
+
+

Deployments

+
+ + + {{-- --}}
- @endif +
+

Backups

+
+ + +
+
+
+

Scheduled Tasks

+
+ + +
+
+
+

Server

+
+ + + + + +
+
+
diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index b1d58d72b..9ed28d4ec 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -3,7 +3,7 @@ Notifications | Coolify -
+

Slack

@@ -14,6 +14,10 @@ wire:click="sendTestNotification"> Send Test Notification + @else + + Send Test Notification + @endif
@@ -23,44 +27,51 @@ helper="Generate a webhook in Slack.
Example: https://hooks.slack.com/services/...." required id="slackWebhookUrl" label="Webhook" /> - @if ($slackEnabled) -

Notification Settings

-

- Select events for which you would like to receive Slack notifications. -

-
-
-

Deployments

-
- - - {{-- --}} -
-
-
-

Backups

-
- - -
-
-
-

Scheduled Tasks

-
- - -
-
-
-

Server

-
- - - - - -
+

Notification Settings

+

+ Select events for which you would like to receive Slack notifications. +

+
+
+

Deployments

+
+ + + {{-- --}}
- @endif -
\ No newline at end of file +
+

Backups

+
+ + +
+
+
+

Scheduled Tasks

+
+ + +
+
+
+

Server

+
+ + + + + +
+
+
+
diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index ff60673b0..f1d2cb540 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -1,122 +1,162 @@
Notifications | Coolify - - -
-
-

Telegram

- - Save - - @if ($telegramEnabled) - + + + +
+

Telegram

+ + Save + + @if ($telegramEnabled) + + Send Test Notification + + @else + Send Test Notification - @endif -
-
- -
-
- - -
- @if ($telegramEnabled) -

Notification Settings

-

- Select events for which you would like to receive Telegram notifications. -

-
-
-

Deployment

-
-

Deployment Success

-
- - -
-

Deployment Failure

-
- - -
- {{--

Container Status Changes

-
- - -
--}} -
-
-
-

Backups

-
-

Backup Success

-
- - -
- -

Backup Failure

-
- - -
-
-
- -
-

Scheduled Tasks

-
-

Scheduled Task Success

-
- - -
- -

Scheduled Task Failure

-
- - -
-
-
- -
-

Server

-
-

Docker Cleanup Success

-
- - -
- -

Docker Cleanup Failure

-
- - -
- -

Server Disk Usage

-
- - -
- -

Server Reachable

-
- - -
- -

Server Unreachable

-
- - -
-
-
-
@endif - +
+
+ +
+
+ + +
+ +

Notification Settings

+

+ Select events for which you would like to receive Telegram notifications. +

+
+
+

Deployments

+
+
+
+ +
+ +
+
+
+ +
+ +
+ {{--

Container Status Changes

+
+ + +
--}} +
+
+
+

Backups

+
+
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+ +
+

Scheduled Tasks

+
+
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+ +
+

Server

+
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+
+
+
diff --git a/scripts/run b/scripts/run index 8764ef23f..466b04530 100755 --- a/scripts/run +++ b/scripts/run @@ -32,18 +32,18 @@ function sync:bunny { } function db:reset { - bash spin exec -u webuser coolify php artisan migrate:fresh --seed + bash spin exec -u www-data coolify php artisan migrate:fresh --seed } function db:reset-prod { - bash spin exec -u webuser coolify php artisan migrate:fresh --force --seed --seeder=ProductionSeeder || + bash spin exec -u www-data coolify php artisan migrate:fresh --force --seed --seeder=ProductionSeeder || php artisan migrate:fresh --force --seed --seeder=ProductionSeeder } function coolify { - bash spin exec -u webuser coolify bash + bash spin exec -u www-data coolify sh } function coolify:root { - bash spin exec coolify bash + bash spin exec coolify sh } function coolify:proxy { docker exec -ti coolify-proxy sh @@ -58,7 +58,7 @@ function vite { } function tinker { - bash spin exec -u webuser coolify php artisan tinker + bash spin exec -u www-data coolify php artisan tinker } function default { @@ -66,4 +66,4 @@ function default { } TIMEFORMAT="Task completed in %3lR" -time "${@:-default}" \ No newline at end of file +time "${@:-default}" From 6a7b283844039200c7edfc673719af623695c1ea Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 10:50:10 +0100 Subject: [PATCH 75/80] fix: docker cleanup email notifications --- app/Notifications/Server/DockerCleanupFailed.php | 4 ++-- app/Notifications/Server/DockerCleanupSuccess.php | 5 ++--- .../views/emails/docker-cleanup-failed.blade.php | 4 ++-- .../views/emails/docker-cleanup-success.blade.php | 7 ++++--- .../views/livewire/notifications/email.blade.php | 14 ++++++-------- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/app/Notifications/Server/DockerCleanupFailed.php b/app/Notifications/Server/DockerCleanupFailed.php index d7f70e029..53714925c 100644 --- a/app/Notifications/Server/DockerCleanupFailed.php +++ b/app/Notifications/Server/DockerCleanupFailed.php @@ -25,8 +25,8 @@ class DockerCleanupFailed extends CustomEmailNotification $mail = new MailMessage; $mail->subject("Coolify: [ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}"); $mail->view('emails.docker-cleanup-failed', [ - 'serverName' => $this->server->name, - 'message' => $this->message, + 'name' => $this->server->name, + 'text' => $this->message, ]); return $mail; diff --git a/app/Notifications/Server/DockerCleanupSuccess.php b/app/Notifications/Server/DockerCleanupSuccess.php index eb84de787..85a819da2 100644 --- a/app/Notifications/Server/DockerCleanupSuccess.php +++ b/app/Notifications/Server/DockerCleanupSuccess.php @@ -25,14 +25,13 @@ class DockerCleanupSuccess extends CustomEmailNotification $mail = new MailMessage; $mail->subject("Coolify: Docker cleanup job succeeded on {$this->server->name}"); $mail->view('emails.docker-cleanup-success', [ - 'serverName' => $this->server->name, - 'message' => $this->message, + 'name' => $this->server->name, + 'text' => $this->message, ]); return $mail; } - public function toDiscord(): DiscordMessage { return new DiscordMessage( diff --git a/resources/views/emails/docker-cleanup-failed.blade.php b/resources/views/emails/docker-cleanup-failed.blade.php index 9661df084..a12f20fa8 100644 --- a/resources/views/emails/docker-cleanup-failed.blade.php +++ b/resources/views/emails/docker-cleanup-failed.blade.php @@ -1,8 +1,8 @@ -Docker Cleanup on {{ $serverName }} FAILED with the following error: +Docker Cleanup on {{ $name }} FAILED with the following error:
-{{ $message }}
+{{ $text }}
 
diff --git a/resources/views/emails/docker-cleanup-success.blade.php b/resources/views/emails/docker-cleanup-success.blade.php index 943750456..8671d74c8 100644 --- a/resources/views/emails/docker-cleanup-success.blade.php +++ b/resources/views/emails/docker-cleanup-success.blade.php @@ -1,8 +1,9 @@ -Docker Cleanup on "{{ $serverName }}" succeeded with the following message: +Docker Cleanup on {{ $name }} succeeded with the following message: +
-"{{ $message }}"
+{{ $text }}
 
-
\ No newline at end of file + diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 37bfac0e0..5b998975d 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -142,14 +142,12 @@

Server

- - - + + + Date: Wed, 11 Dec 2024 11:09:53 +0100 Subject: [PATCH 76/80] fix: general notifications does not go through email channel --- app/Traits/HasNotificationSettings.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php index 5a5ae1929..82cbda6ad 100644 --- a/app/Traits/HasNotificationSettings.php +++ b/app/Traits/HasNotificationSettings.php @@ -75,6 +75,10 @@ trait HasNotificationSettings 'slack' => SlackChannel::class, ]; + if ($event === 'general') { + unset($channelMap['email']); + } + foreach ($channelMap as $channel => $channelClass) { if ($this->isNotificationEnabled($channel) && $this->isNotificationTypeEnabled($channel, $event)) { $channels[] = $channelClass; From fcc94e63062394a202122d15adf88262a7c4422c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 11:28:56 +0100 Subject: [PATCH 77/80] fixes --- ...mail_notification_settings_from_teams_table.php | 10 +++++----- ...gram_notification_settings_from_teams_table.php | 12 ++++++------ .../views/livewire/notifications/discord.blade.php | 4 +++- .../views/livewire/notifications/email.blade.php | 7 +++++-- .../views/livewire/notifications/slack.blade.php | 4 +++- .../livewire/notifications/telegram.blade.php | 14 +++++++++----- 6 files changed, 31 insertions(+), 20 deletions(-) diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index f9d5ad0b4..235eff293 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -18,13 +18,13 @@ return new class extends Migration ['team_id' => $team->id], [ 'smtp_enabled' => $team->smtp_enabled ?? false, - 'smtp_from_address' => Crypt::encryptString($team->smtp_from_address), - 'smtp_from_name' => Crypt::encryptString($team->smtp_from_name), - 'smtp_recipients' => Crypt::encryptString($team->smtp_recipients), - 'smtp_host' => Crypt::encryptString($team->smtp_host), + 'smtp_from_address' => $team->smtp_from_address ? Crypt::encryptString($team->smtp_from_address) : null, + 'smtp_from_name' => $team->smtp_from_name ? Crypt::encryptString($team->smtp_from_name) : null, + 'smtp_recipients' => $team->smtp_recipients ? Crypt::encryptString($team->smtp_recipients) : null, + 'smtp_host' => $team->smtp_host ? Crypt::encryptString($team->smtp_host) : null, 'smtp_port' => $team->smtp_port, 'smtp_encryption' => $team->smtp_encryption, - 'smtp_username' => Crypt::encryptString($team->smtp_username), + 'smtp_username' => $team->smtp_username ? Crypt::encryptString($team->smtp_username) : null, 'smtp_password' => $team->smtp_password, 'smtp_timeout' => $team->smtp_timeout, 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 c93569aef..0c10646b9 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 @@ -92,8 +92,8 @@ return new class extends Migration ->where('id', $setting->team_id) ->update([ 'telegram_enabled' => $setting->telegram_enabled, - 'telegram_token' => Crypt::decryptString($setting->telegram_token), - 'telegram_chat_id' => Crypt::decryptString($setting->telegram_chat_id), + 'telegram_token' => $setting->telegram_token ? Crypt::decryptString($setting->telegram_token) : null, + 'telegram_chat_id' => $setting->telegram_chat_id ? Crypt::decryptString($setting->telegram_chat_id) : null, 'telegram_notifications_deployments' => $setting->deployment_success_telegram_notifications || $setting->deployment_failure_telegram_notifications, 'telegram_notifications_status_changes' => $setting->status_change_telegram_notifications, @@ -101,10 +101,10 @@ return new class extends Migration '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' => Crypt::decryptString($setting->telegram_notifications_deployment_success_topic_id), - 'telegram_notifications_status_changes_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_status_change_topic_id), - 'telegram_notifications_database_backups_message_thread_id' => Crypt::decryptString($setting->telegram_notifications_backup_success_topic_id), - 'telegram_notifications_scheduled_tasks_thread_id' => Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_topic_id), + '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, ]); } catch (Exception $e) { \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index 189f2f490..1f83ed061 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -39,7 +39,9 @@ label="Deployment Success" /> - {{-- --}} +
diff --git a/resources/views/livewire/notifications/email.blade.php b/resources/views/livewire/notifications/email.blade.php index 5b998975d..1977df516 100644 --- a/resources/views/livewire/notifications/email.blade.php +++ b/resources/views/livewire/notifications/email.blade.php @@ -119,13 +119,16 @@ label="Deployment Success" /> - {{-- --}} +

Backups

- +
diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index 9ed28d4ec..774f8e7e5 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -39,7 +39,9 @@ label="Deployment Success" /> - {{-- --}} +
diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index f1d2cb540..5dd859e9e 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -55,11 +55,15 @@
- {{--

Container Status Changes

-
- - -
--}} +
+
+ +
+ +
From c08423395c24c4d2aea8af49232db3fbb711625a Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 11:37:56 +0100 Subject: [PATCH 78/80] fixes --- ..._email_notification_settings_from_teams_table.php | 1 + ...2014_create_slack_notification_settings_table.php | 12 ++++++++++++ ...22142_encrypt_instance_settings_email_columns.php | 10 +++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php index 235eff293..384f62f06 100644 --- a/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php @@ -92,6 +92,7 @@ return new class extends Migration $table->text('resend_api_key')->nullable(); + $table->boolean('smtp_notifications_test')->default(false); $table->boolean('smtp_notifications_deployments')->default(false); $table->boolean('smtp_notifications_database_backups')->default(true); $table->boolean('smtp_notifications_scheduled_tasks')->default(false); 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 78e27892e..790e0f667 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 @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -33,6 +34,17 @@ return new class extends Migration $table->unique(['team_id']); }); + $teams = DB::table('teams')->get(); + + foreach ($teams as $team) { + try { + DB::table('slack_notification_settings')->insert([ + 'team_id' => $team->id, + ]); + } catch (\Throwable $e) { + \Log::error('Error migrating slack notification settings from teams table: '.$e->getMessage()); + } + } } /** diff --git a/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php b/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php index 8ccbcb4f6..44e0f2f47 100644 --- a/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php +++ b/database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php @@ -45,11 +45,11 @@ return new class extends Migration public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { - $table->string('smtp_from_address')->change(); - $table->string('smtp_from_name')->change(); - $table->string('smtp_recipients')->change(); - $table->string('smtp_host')->change(); - $table->string('smtp_username')->change(); + $table->string('smtp_from_address')->nullable()->change(); + $table->string('smtp_from_name')->nullable()->change(); + $table->string('smtp_recipients')->nullable()->change(); + $table->string('smtp_host')->nullable()->change(); + $table->string('smtp_username')->nullable()->change(); }); if (DB::table('instance_settings')->exists()) { From b442965976976494da7e60cfce16acceffa57ae7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 11:57:56 +0100 Subject: [PATCH 79/80] fix: test notifications to only send it to the right channel --- app/Livewire/Notifications/Discord.php | 2 +- app/Livewire/Notifications/Email.php | 3 +- app/Livewire/Notifications/Slack.php | 2 +- app/Livewire/Notifications/Telegram.php | 2 +- app/Livewire/SettingsEmail.php | 9 +- app/Notifications/Test.php | 19 ++- .../views/livewire/settings-email.blade.php | 135 +++++++++--------- 7 files changed, 99 insertions(+), 73 deletions(-) diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php index c09966e53..57007813e 100644 --- a/app/Livewire/Notifications/Discord.php +++ b/app/Livewire/Notifications/Discord.php @@ -154,7 +154,7 @@ class Discord extends Component public function sendTestNotification() { try { - $this->team->notify(new Test); + $this->team->notify(new Test(channel: 'discord')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index dc5a35d66..dc2a95e84 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -106,6 +106,7 @@ class Email extends Component $this->emails = auth()->user()->email; $this->settings = $this->team->emailNotificationSettings; $this->syncData(); + $this->testEmailAddress = auth()->user()->email; } catch (\Throwable $e) { return handleError($e, $this); } @@ -317,7 +318,7 @@ class Email extends Component 'test-email:'.$this->team->id, $perMinute = 0, function () { - $this->team?->notify(new Test($this->testEmailAddress)); + $this->team?->notify(new Test($this->testEmailAddress, 'email')); $this->dispatch('success', 'Test Email sent.'); }, $decaySeconds = 10, diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php index 91f05f42f..97464fa1c 100644 --- a/app/Livewire/Notifications/Slack.php +++ b/app/Livewire/Notifications/Slack.php @@ -154,7 +154,7 @@ class Slack extends Component public function sendTestNotification() { try { - $this->team->notify(new Test); + $this->team->notify(new Test(channel: 'slack')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index d425fd262..de2fa9cdc 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -223,7 +223,7 @@ class Telegram extends Component public function sendTestNotification() { try { - $this->team->notify(new Test); + $this->team->notify(new Test(channel: 'telegram')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index 4636a3b25..1c5edb108 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -3,8 +3,10 @@ namespace App\Livewire; use App\Models\InstanceSettings; +use App\Models\Team; use App\Notifications\Test; use Illuminate\Support\Facades\RateLimiter; +use Livewire\Attributes\Locked; use Livewire\Attributes\Validate; use Livewire\Component; @@ -12,6 +14,9 @@ class SettingsEmail extends Component { public InstanceSettings $settings; + #[Locked] + public Team $team; + #[Validate(['boolean'])] public bool $smtpEnabled = false; @@ -58,6 +63,8 @@ class SettingsEmail extends Component } $this->settings = instanceSettings(); $this->syncData(); + $this->team = auth()->user()->currentTeam(); + $this->testEmailAddress = auth()->user()->email; } public function syncData(bool $toModel = false) @@ -219,7 +226,7 @@ class SettingsEmail extends Component 'test-email:'.$this->team->id, $perMinute = 0, function () { - $this->team?->notify(new Test($this->testEmailAddress)); + $this->team?->notify(new Test($this->testEmailAddress, 'email')); $this->dispatch('success', 'Test Email sent.'); }, $decaySeconds = 10, diff --git a/app/Notifications/Test.php b/app/Notifications/Test.php index 7ae1c5286..da9098500 100644 --- a/app/Notifications/Test.php +++ b/app/Notifications/Test.php @@ -2,7 +2,10 @@ namespace App\Notifications; +use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; +use App\Notifications\Channels\SlackChannel; +use App\Notifications\Channels\TelegramChannel; use App\Notifications\Dto\DiscordMessage; use App\Notifications\Dto\SlackMessage; use Illuminate\Bus\Queueable; @@ -17,14 +20,26 @@ class Test extends Notification implements ShouldQueue public $tries = 5; - public function __construct(public ?string $emails = null) + public function __construct(public ?string $emails = null, public ?string $channel = null) { $this->onQueue('high'); } public function via(object $notifiable): array { - return $notifiable->getEnabledChannels('test'); + if ($this->channel) { + $channels = match ($this->channel) { + 'email' => [EmailChannel::class], + 'discord' => [DiscordChannel::class], + 'telegram' => [TelegramChannel::class], + 'slack' => [SlackChannel::class], + default => [], + }; + } else { + $channels = $notifiable->getEnabledChannels('test'); + } + + return $channels; } public function middleware(object $notifiable, string $channel) diff --git a/resources/views/livewire/settings-email.blade.php b/resources/views/livewire/settings-email.blade.php index 81ee4878e..19c77971c 100644 --- a/resources/views/livewire/settings-email.blade.php +++ b/resources/views/livewire/settings-email.blade.php @@ -1,78 +1,81 @@
Transactional Email | Coolify - - -
-
-

Transactional Email

- - Save - - @if (is_transactional_emails_enabled() && auth()->user()->isAdminFromSession()) + + + +
+

Transactional Email

+ + Save + + @if (is_transactional_emails_enabled() && auth()->user()->isAdminFromSession()) - + Send Email - @endif -
-
Instance wide email settings for password resets, invitations, etc.
-
- - -
- -
-
-
-
-

SMTP Server

- - Save - -
-
- -
-
-
- - - - - - - -
-
- - - -
-
-
-
-
-
-
-

Resend

- - Save - -
-
- -
-
-
- -
-
-
-
+ @endif
+
Instance wide email settings for password resets, invitations, etc.
+
+ + +
+ +
+
+
+
+

SMTP Server

+ + Save + +
+
+ +
+
+
+ + + + + + + +
+
+ + + +
+
+
+
+
+
+
+

Resend

+ + Save + +
+
+ +
+
+
+ +
+
+
+
+
From 9ffae89a71a971e8b78fff0075dff84062643285 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 12:04:58 +0100 Subject: [PATCH 80/80] fix: remove resale_license from db as well --- app/Livewire/Settings/Index.php | 5 -- .../2024_12_10_122143_drop_resale_license.php | 30 +++++++++ database/seeders/InstanceSettingsSeeder.php | 1 - .../livewire/subscription/index.blade.php | 64 +++++++++---------- 4 files changed, 60 insertions(+), 40 deletions(-) create mode 100644 database/migrations/2024_12_10_122143_drop_resale_license.php diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php index c1be35ced..7adb0f8a7 100644 --- a/app/Livewire/Settings/Index.php +++ b/app/Livewire/Settings/Index.php @@ -23,9 +23,6 @@ class Index extends Component #[Validate('nullable|string|max:255')] public ?string $fqdn = null; - #[Validate('nullable|string|max:255')] - public ?string $resale_license = null; - #[Validate('required|integer|min:1025|max:65535')] public int $public_port_min; @@ -83,7 +80,6 @@ class Index extends Component } else { $this->settings = instanceSettings(); $this->fqdn = $this->settings->fqdn; - $this->resale_license = $this->settings->resale_license; $this->public_port_min = $this->settings->public_port_min; $this->public_port_max = $this->settings->public_port_max; $this->custom_dns_servers = $this->settings->custom_dns_servers; @@ -122,7 +118,6 @@ class Index extends Component } $this->settings->fqdn = $this->fqdn; - $this->settings->resale_license = $this->resale_license; $this->settings->public_port_min = $this->public_port_min; $this->settings->public_port_max = $this->public_port_max; $this->settings->custom_dns_servers = $this->custom_dns_servers; diff --git a/database/migrations/2024_12_10_122143_drop_resale_license.php b/database/migrations/2024_12_10_122143_drop_resale_license.php new file mode 100644 index 000000000..aaf498c3b --- /dev/null +++ b/database/migrations/2024_12_10_122143_drop_resale_license.php @@ -0,0 +1,30 @@ +dropColumn('is_resale_license_active'); + $table->dropColumn('resale_license'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('instance_settings', function (Blueprint $table) { + $table->boolean('is_resale_license_active')->default(false); + $table->longText('resale_license')->nullable(); + }); + } +}; diff --git a/database/seeders/InstanceSettingsSeeder.php b/database/seeders/InstanceSettingsSeeder.php index 35fc8506b..7f2deb3a6 100644 --- a/database/seeders/InstanceSettingsSeeder.php +++ b/database/seeders/InstanceSettingsSeeder.php @@ -16,7 +16,6 @@ class InstanceSettingsSeeder extends Seeder InstanceSettings::create([ 'id' => 0, 'is_registration_enabled' => true, - 'is_resale_license_active' => true, 'smtp_enabled' => true, 'smtp_host' => 'coolify-mail', 'smtp_port' => 1025, diff --git a/resources/views/livewire/subscription/index.blade.php b/resources/views/livewire/subscription/index.blade.php index 5131ebd56..c29fdae89 100644 --- a/resources/views/livewire/subscription/index.blade.php +++ b/resources/views/livewire/subscription/index.blade.php @@ -2,42 +2,38 @@ Subscribe | Coolify - @if ($settings->is_resale_license_active) - @if (auth()->user()->isAdminFromSession()) -
-
-

Subscriptions

- @if (subscriptionProvider() === 'stripe' && $alreadySubscribed) - Manage My Subscription - @endif -
- @if (request()->query->get('cancelled')) -
- - - - Something went wrong with your subscription. Please try again or contact - support. -
+ @if (auth()->user()->isAdminFromSession()) +
+
+

Subscriptions

+ @if (subscriptionProvider() === 'stripe' && $alreadySubscribed) + Manage My Subscription @endif +
+ @if (request()->query->get('cancelled')) +
+ + + + Something went wrong with your subscription. Please try again or contact + support. +
+ @endif - @if (config('subscription.provider') === 'stripe') - - @endif -
- @else -
-
-

Subscription

-
-
You are not an admin or have been removed from this team. If this does not make sense, please contact - us.
-
- @endif + @if (config('subscription.provider') === 'stripe') + + @endif +
@else -
Resale license is not active. Please contact your instance admin.
+
+
+

Subscription

+
+
You are not an admin or have been removed from this team. If this does not make sense, please contact + us.
+
@endif