From 71131804f6f4be4c42c2fb6b75f7197331bdeccb Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:47:33 +0200 Subject: [PATCH] fix: require notification and log drain fields only when enabled (#12232) --- app/Livewire/Notifications/Discord.php | 2 +- app/Livewire/Notifications/Pushover.php | 4 +- app/Livewire/Notifications/Slack.php | 2 +- app/Livewire/Notifications/Telegram.php | 4 +- app/Livewire/Notifications/Webhook.php | 2 +- .../livewire/notifications/discord.blade.php | 2 +- .../livewire/notifications/pushover.blade.php | 4 +- .../livewire/notifications/slack.blade.php | 2 +- .../livewire/notifications/telegram.blade.php | 4 +- .../livewire/notifications/webhook.blade.php | 2 +- .../livewire/server/log-drains.blade.php | 10 ++--- tests/Feature/EnableActionButtonsTest.php | 43 +++++++++++++++++++ .../LogDrain/CustomLogDrainValidationTest.php | 13 ++++++ 13 files changed, 75 insertions(+), 19 deletions(-) diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php index 469e47605c..46f6739833 100644 --- a/app/Livewire/Notifications/Discord.php +++ b/app/Livewire/Notifications/Discord.php @@ -22,7 +22,7 @@ class Discord extends Component #[Validate(['boolean'])] public bool $discordEnabled = false; - #[Validate(['nullable', new SafeWebhookUrl])] + #[Validate(['required_if:discordEnabled,true', 'nullable', new SafeWebhookUrl])] public ?string $discordWebhookUrl = null; #[Validate(['boolean'])] diff --git a/app/Livewire/Notifications/Pushover.php b/app/Livewire/Notifications/Pushover.php index a2fe63a0f8..ee09cc7393 100644 --- a/app/Livewire/Notifications/Pushover.php +++ b/app/Livewire/Notifications/Pushover.php @@ -26,10 +26,10 @@ class Pushover extends Component #[Validate(['boolean'])] public bool $pushoverEnabled = false; - #[Validate(['nullable', 'string'])] + #[Validate(['required_if:pushoverEnabled,true', 'nullable', 'string'])] public ?string $pushoverUserKey = null; - #[Validate(['nullable', 'string'])] + #[Validate(['required_if:pushoverEnabled,true', 'nullable', 'string'])] public ?string $pushoverApiToken = null; #[Validate(['boolean'])] diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php index 70ec6f786e..2a6fbfbb55 100644 --- a/app/Livewire/Notifications/Slack.php +++ b/app/Livewire/Notifications/Slack.php @@ -27,7 +27,7 @@ class Slack extends Component #[Validate(['boolean'])] public bool $slackEnabled = false; - #[Validate(['nullable', new SafeWebhookUrl])] + #[Validate(['required_if:slackEnabled,true', 'nullable', new SafeWebhookUrl])] public ?string $slackWebhookUrl = null; #[Validate(['boolean'])] diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index f6edb89d3e..f45bc9045c 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -27,10 +27,10 @@ class Telegram extends Component #[Validate(['boolean'])] public bool $telegramEnabled = false; - #[Validate(['nullable', 'string'])] + #[Validate(['required_if:telegramEnabled,true', 'nullable', 'string'])] public ?string $telegramToken = null; - #[Validate(['nullable', 'string'])] + #[Validate(['required_if:telegramEnabled,true', 'nullable', 'string'])] public ?string $telegramChatId = null; #[Validate(['boolean'])] diff --git a/app/Livewire/Notifications/Webhook.php b/app/Livewire/Notifications/Webhook.php index 9b20695cc7..e382ee4394 100644 --- a/app/Livewire/Notifications/Webhook.php +++ b/app/Livewire/Notifications/Webhook.php @@ -22,7 +22,7 @@ class Webhook extends Component #[Validate(['boolean'])] public bool $webhookEnabled = false; - #[Validate(['nullable', new SafeWebhookUrl])] + #[Validate(['required_if:webhookEnabled,true', 'nullable', new SafeWebhookUrl])] public ?string $webhookUrl = null; #[Validate(['boolean'])] diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index 9e3921f514..a372d53fb5 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -25,7 +25,7 @@ ]" />
@can('update', $settings) - @else diff --git a/resources/views/livewire/notifications/pushover.blade.php b/resources/views/livewire/notifications/pushover.blade.php index 40661fc976..8f9f756b27 100644 --- a/resources/views/livewire/notifications/pushover.blade.php +++ b/resources/views/livewire/notifications/pushover.blade.php @@ -17,9 +17,9 @@
@can('update', $settings) - - @else diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index f3ccd8256d..a00d6aa786 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -18,7 +18,7 @@
@can('update', $settings) - @else diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index 8ab110e62e..b87a3549df 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -17,9 +17,9 @@
@can('update', $settings) - - @else diff --git a/resources/views/livewire/notifications/webhook.blade.php b/resources/views/livewire/notifications/webhook.blade.php index fde9054b8d..49e99e8353 100644 --- a/resources/views/livewire/notifications/webhook.blade.php +++ b/resources/views/livewire/notifications/webhook.blade.php @@ -18,7 +18,7 @@
@can('update', $settings) - @else diff --git a/resources/views/livewire/server/log-drains.blade.php b/resources/views/livewire/server/log-drains.blade.php index ac908a7c9d..425b4a2bdd 100644 --- a/resources/views/livewire/server/log-drains.blade.php +++ b/resources/views/livewire/server/log-drains.blade.php @@ -35,10 +35,10 @@ ['value' => true, 'label' => 'Enabled'], ]" :disabled="$isLogDrainAxiomEnabled || $isLogDrainCustomEnabled || !auth()->user()->can('update', $server)" /> - - true, 'label' => 'Enabled'], ]" :disabled="$isLogDrainNewRelicEnabled || $isLogDrainCustomEnabled || !auth()->user()->can('update', $server)" /> - -
@@ -73,7 +73,7 @@ :disabled="$isLogDrainNewRelicEnabled || $isLogDrainAxiomEnabled || !auth()->user()->can('update', $server)" />
- discordNotificationSettings->fresh()->discord_ping_enabled)->toBeTrue(); }); + +it('saves cleared notification provider fields while the provider is disabled', function (string $component, string $settingsRelation, array $savedSettings, array $properties) { + [, $team] = actingAsEnableActionOwner(); + $team->{$settingsRelation}->update($savedSettings); + + $test = Livewire::test($component); + foreach ($properties as $property) { + $test->set($property, ''); + } + $test->call('submit') + ->assertHasNoErrors() + ->assertDispatched('success'); + + $settings = $team->{$settingsRelation}->fresh(); + foreach (array_keys($savedSettings) as $column) { + expect($settings->{$column})->toBeEmpty(); + } +})->with([ + 'discord' => [Discord::class, 'discordNotificationSettings', ['discord_webhook_url' => 'https://discord.com/api/webhooks/1/abc'], ['discordWebhookUrl']], + 'slack' => [Slack::class, 'slackNotificationSettings', ['slack_webhook_url' => 'https://hooks.slack.com/services/T/B/C'], ['slackWebhookUrl']], + 'telegram' => [Telegram::class, 'telegramNotificationSettings', ['telegram_token' => '123:abc', 'telegram_chat_id' => '42'], ['telegramToken', 'telegramChatId']], + 'pushover' => [Pushover::class, 'pushoverNotificationSettings', ['pushover_user_key' => 'user', 'pushover_api_token' => 'token'], ['pushoverUserKey', 'pushoverApiToken']], + 'webhook' => [Webhook::class, 'webhookNotificationSettings', ['webhook_url' => 'https://hooks.example.com/coolify'], ['webhookUrl']], +]); + +it('rejects cleared notification provider fields while the provider is enabled', function (string $component, string $settingsRelation, array $savedSettings, string $property) { + [, $team] = actingAsEnableActionOwner(); + $team->{$settingsRelation}->update($savedSettings); + + Livewire::test($component) + ->set($property, '') + ->call('submit') + ->assertNotDispatched('success') + ->assertDispatched('error'); + + expect($team->{$settingsRelation}->fresh()->{array_keys($savedSettings)[1]})->not->toBeEmpty(); +})->with([ + 'discord' => [Discord::class, 'discordNotificationSettings', ['discord_enabled' => true, 'discord_webhook_url' => 'https://discord.com/api/webhooks/1/abc'], 'discordWebhookUrl'], + 'slack' => [Slack::class, 'slackNotificationSettings', ['slack_enabled' => true, 'slack_webhook_url' => 'https://hooks.slack.com/services/T/B/C'], 'slackWebhookUrl'], + 'telegram' => [Telegram::class, 'telegramNotificationSettings', ['telegram_enabled' => true, 'telegram_token' => '123:abc', 'telegram_chat_id' => '42'], 'telegramToken'], + 'pushover' => [Pushover::class, 'pushoverNotificationSettings', ['pushover_enabled' => true, 'pushover_user_key' => 'user', 'pushover_api_token' => 'token'], 'pushoverUserKey'], + 'webhook' => [Webhook::class, 'webhookNotificationSettings', ['webhook_enabled' => true, 'webhook_url' => 'https://hooks.example.com/coolify'], 'webhookUrl'], +]); diff --git a/tests/Feature/LogDrain/CustomLogDrainValidationTest.php b/tests/Feature/LogDrain/CustomLogDrainValidationTest.php index b1667590b0..e12e43c12d 100644 --- a/tests/Feature/LogDrain/CustomLogDrainValidationTest.php +++ b/tests/Feature/LogDrain/CustomLogDrainValidationTest.php @@ -200,3 +200,16 @@ test('the UI does not enable an unsupported custom log drain', function () { expect((bool) $this->server->settings->fresh()->is_logdrain_custom_enabled)->toBeFalse(); }); + +test('the UI saves a cleared custom config while the custom log drain is disabled', function () { + $this->actingAs($this->user); + $this->server->settings->update(['logdrain_custom_config' => SAFE_CUSTOM_LOG_DRAIN_CONFIG]); + + Livewire::test(LogDrains::class, ['server_uuid' => $this->server->uuid]) + ->set('logDrainCustomConfig', '') + ->call('submit') + ->assertHasNoErrors() + ->assertDispatched('success'); + + expect($this->server->settings->fresh()->logdrain_custom_config)->toBeEmpty(); +});