From 9bfa683d3c1a40944857d0f7567f810b7187bb08 Mon Sep 17 00:00:00 2001 From: Konstantinos Tsouvalis Date: Wed, 10 Jun 2026 13:04:31 +0300 Subject: [PATCH 1/6] feat: toggle backup enable/disable from server index actions menu --- app/Livewire/DatabaseServer/Index.php | 9 +++++++++ lang/es.json | 2 ++ lang/fr.json | 2 ++ resources/views/livewire/database-server/index.blade.php | 8 ++++++++ 4 files changed, 21 insertions(+) diff --git a/app/Livewire/DatabaseServer/Index.php b/app/Livewire/DatabaseServer/Index.php index 827a0c4e..26378887 100644 --- a/app/Livewire/DatabaseServer/Index.php +++ b/app/Livewire/DatabaseServer/Index.php @@ -160,6 +160,15 @@ public function runBackupAll(string $serverId, TriggerBackupAction $action): voi $this->triggerAllBackups($server, $action); } + public function toggleBackupsEnabled(string $id): void + { + $server = DatabaseServer::findOrFail($id); + + $this->authorize('viewForm', $server); + + $server->update(['backups_enabled' => ! $server->backups_enabled]); + } + public function render(): View { $servers = DatabaseServerQuery::buildFromParams( diff --git a/lang/es.json b/lang/es.json index 0fab7fce..9fa59290 100644 --- a/lang/es.json +++ b/lang/es.json @@ -207,6 +207,7 @@ "Detected databases:": "Bases detectadas:", "Disable": "Desactivar", "Disable 2FA": "Desactivar 2FA", + "Disable Backup": "Desactivar backup", "Disabled": "Desactivado", "Discord (Bot)": "Discord (Bot)", "Discord (Webhook)": "Discord (Webhook)", @@ -238,6 +239,7 @@ "Email password reset link": "Enviar enlace de restablecimiento de contraseña", "Enable": "Activar", "Enable 2FA": "Activar 2FA", + "Enable Backup": "Activar backup", "Enable GitHub OAuth authentication.": "Activar autenticación OAuth de GitHub.", "Enable GitLab OAuth authentication.": "Activar autenticación OAuth de GitLab.", "Enable Google OAuth authentication.": "Activar autenticación OAuth de Google.", diff --git a/lang/fr.json b/lang/fr.json index 5c6830bf..761e82f4 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -207,6 +207,7 @@ "Detected databases:": "Bases détectées :", "Disable": "Désactiver", "Disable 2FA": "Désactiver 2FA", + "Disable Backup": "Désactiver les sauvegardes", "Disabled": "Désactivé", "Discord (Bot)": "Discord (Bot)", "Discord (Webhook)": "Discord (Webhook)", @@ -238,6 +239,7 @@ "Email password reset link": "Envoyer le lien de réinitialisation", "Enable": "Activer", "Enable 2FA": "Activer 2FA", + "Enable Backup": "Activer les sauvegardes", "Enable GitHub OAuth authentication.": "Activer l’authentification OAuth GitHub.", "Enable GitLab OAuth authentication.": "Activer l’authentification OAuth GitLab.", "Enable Google OAuth authentication.": "Activer l’authentification OAuth Google.", diff --git a/resources/views/livewire/database-server/index.blade.php b/resources/views/livewire/database-server/index.blade.php index ec287733..735030c7 100644 --- a/resources/views/livewire/database-server/index.blade.php +++ b/resources/views/livewire/database-server/index.blade.php @@ -150,6 +150,14 @@ class="text-info" /> wire:click="confirmRestore('{{ $server->id }}')" spinner class="text-success" /> @endcan + @can('viewForm', $server) + + @endcan @can('viewForm', $server) From 4f4323b0d26fe8200a47e56aea78f002e135a3f9 Mon Sep 17 00:00:00 2001 From: Konstantinos Tsouvalis Date: Wed, 10 Jun 2026 13:11:41 +0300 Subject: [PATCH 2/6] feat: add tests for enabling and disabling backups from the server index --- tests/Feature/DatabaseServer/IndexTest.php | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/Feature/DatabaseServer/IndexTest.php b/tests/Feature/DatabaseServer/IndexTest.php index c62d460d..6a34d1c8 100644 --- a/tests/Feature/DatabaseServer/IndexTest.php +++ b/tests/Feature/DatabaseServer/IndexTest.php @@ -106,3 +106,26 @@ $snapshotBackupIds = $snapshots->pluck('backup_id')->sort()->values(); expect($snapshotBackupIds->all())->toBe($backupIds->all()); }); + +test('admin can disable backups for a server from the index', function () { + $user = User::factory()->create(); + $server = DatabaseServer::factory()->create(['backups_enabled' => true]); + + Livewire::actingAs($user) + ->test(Index::class) + ->call('toggleBackupsEnabled', $server->id); + + expect($server->fresh()->backups_enabled)->toBeFalse(); +}); + +test('admin can enable backups for a server from the index', function () { + $user = User::factory()->create(); + $server = DatabaseServer::factory()->create(['backups_enabled' => false]); + + Livewire::actingAs($user) + ->test(Index::class) + ->call('toggleBackupsEnabled', $server->id); + + expect($server->fresh()->backups_enabled)->toBeTrue(); +}); + From dd3b06abd201b58b4f506b4251824bd082af2b25 Mon Sep 17 00:00:00 2001 From: Konstantinos Tsouvalis Date: Wed, 10 Jun 2026 13:41:07 +0300 Subject: [PATCH 3/6] feat: implement toggle functionality for enabling/disabling backups on server show page --- app/Livewire/DatabaseServer/Show.php | 8 +++++++ .../livewire/database-server/show.blade.php | 9 ++++++++ tests/Feature/DatabaseServer/ShowTest.php | 22 +++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/app/Livewire/DatabaseServer/Show.php b/app/Livewire/DatabaseServer/Show.php index ed587412..a7cb94fb 100644 --- a/app/Livewire/DatabaseServer/Show.php +++ b/app/Livewire/DatabaseServer/Show.php @@ -63,6 +63,14 @@ public function runBackupAll(TriggerBackupAction $action): void $this->triggerAllBackups($this->server, $action); } + public function toggleBackupsEnabled(): void + { + $this->authorize('viewForm', $this->server); + + $this->server->update(['backups_enabled' => ! $this->server->backups_enabled]); + } + + public function confirmRestore(): void { $this->authorize('restore', $this->server); diff --git a/resources/views/livewire/database-server/show.blade.php b/resources/views/livewire/database-server/show.blade.php index 0c38dfe0..0ff24e0c 100644 --- a/resources/views/livewire/database-server/show.blade.php +++ b/resources/views/livewire/database-server/show.blade.php @@ -96,6 +96,15 @@ class="btn-outline btn-info btn-sm" /> @endcan + @can('viewForm', $server) + + @endcan @can('viewForm', $server) diff --git a/tests/Feature/DatabaseServer/ShowTest.php b/tests/Feature/DatabaseServer/ShowTest.php index 8aa2d49a..7da85e7e 100644 --- a/tests/Feature/DatabaseServer/ShowTest.php +++ b/tests/Feature/DatabaseServer/ShowTest.php @@ -82,3 +82,25 @@ ->call('confirmRestore') ->assertSet('showRedisRestoreModal', true); }); + +test('admin can disable backups for a server from the show page', function () { + $user = User::factory()->create(); + $server = DatabaseServer::factory()->create(['backups_enabled' => true]); + + Livewire::actingAs($user) + ->test(Show::class, ['server' => $server]) + ->call('toggleBackupsEnabled'); + + expect($server->fresh()->backups_enabled)->toBeFalse(); +}); + +test('admin can enable backups for a server from the show page', function () { + $user = User::factory()->create(); + $server = DatabaseServer::factory()->create(['backups_enabled' => false]); + + Livewire::actingAs($user) + ->test(Show::class, ['server' => $server]) + ->call('toggleBackupsEnabled'); + + expect($server->fresh()->backups_enabled)->toBeTrue(); +}); From 304f763e8755f5023bb87474b5ba6479fb0b0caa Mon Sep 17 00:00:00 2001 From: Konstantinos Tsouvalis Date: Wed, 10 Jun 2026 14:23:40 +0300 Subject: [PATCH 4/6] feat: add toast feedback and fix test names for toggleBackupsEnabled --- app/Livewire/DatabaseServer/Index.php | 7 +++++++ app/Livewire/DatabaseServer/Show.php | 7 +++++++ lang/es.json | 2 ++ lang/fr.json | 2 ++ tests/Feature/DatabaseServer/IndexTest.php | 4 ++-- tests/Feature/DatabaseServer/ShowTest.php | 4 ++-- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/Livewire/DatabaseServer/Index.php b/app/Livewire/DatabaseServer/Index.php index 26378887..5264f1ed 100644 --- a/app/Livewire/DatabaseServer/Index.php +++ b/app/Livewire/DatabaseServer/Index.php @@ -167,8 +167,15 @@ public function toggleBackupsEnabled(string $id): void $this->authorize('viewForm', $server); $server->update(['backups_enabled' => ! $server->backups_enabled]); + + $this->success( + title: $server->backups_enabled + ? __('Backups enabled successfully!') + : __('Backups disabled successfully!') + ); } + public function render(): View { $servers = DatabaseServerQuery::buildFromParams( diff --git a/app/Livewire/DatabaseServer/Show.php b/app/Livewire/DatabaseServer/Show.php index a7cb94fb..a0dc4072 100644 --- a/app/Livewire/DatabaseServer/Show.php +++ b/app/Livewire/DatabaseServer/Show.php @@ -68,9 +68,16 @@ public function toggleBackupsEnabled(): void $this->authorize('viewForm', $this->server); $this->server->update(['backups_enabled' => ! $this->server->backups_enabled]); + + $this->success( + title: $this->server->backups_enabled + ? __('Backups enabled successfully!') + : __('Backups disabled successfully!') + ); } + public function confirmRestore(): void { $this->authorize('restore', $this->server); diff --git a/lang/es.json b/lang/es.json index 9fa59290..8a66d05e 100644 --- a/lang/es.json +++ b/lang/es.json @@ -85,6 +85,8 @@ "Backup file not found.": "Archivo de backup no encontrado.", "Backup schedule deleted.": "Programación de backup eliminada.", "Backup schedule saved.": "Programación de backup guardada.", + "Backups enabled successfully!": "Backups activados correctamente.", + "Backups disabled successfully!": "Backups desactivados correctamente.", "Backups will be stored in the specified root directory on the FTP server. Enable SSL/TLS for encrypted connections (FTPS).": "Los backups se almacenarán en el directorio raíz especificado en el servidor FTP. Active SSL/TLS para conexiones cifradas (FTPS).", "Backups will be stored in the specified root directory on the SFTP server.": "Los backups se almacenarán en el directorio raíz especificado en el servidor SFTP.", "Base URL of your Gotify server (e.g. https://gotify.example.com).": "URL base de su servidor Gotify (ej.: https://gotify.example.com).", diff --git a/lang/fr.json b/lang/fr.json index 761e82f4..a9a5f7ca 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -85,6 +85,8 @@ "Backup file not found.": "Fichier de sauvegarde introuvable.", "Backup schedule deleted.": "Planning de sauvegarde supprimé.", "Backup schedule saved.": "Planning de sauvegarde enregistré.", + "Backups enabled successfully!": "Sauvegardes activées avec succès !", + "Backups disabled successfully!": "Sauvegardes désactivées avec succès !", "Backups will be stored in the specified root directory on the FTP server. Enable SSL/TLS for encrypted connections (FTPS).": "Les sauvegardes seront stockées dans le répertoire racine spécifié sur le serveur FTP. Activez SSL/TLS pour les connexions chiffrées (FTPS).", "Backups will be stored in the specified root directory on the SFTP server.": "Les sauvegardes seront stockées dans le répertoire racine spécifié sur le serveur SFTP.", "Base URL of your Gotify server (e.g. https://gotify.example.com).": "URL de base de votre serveur Gotify (ex. : https://gotify.example.com).", diff --git a/tests/Feature/DatabaseServer/IndexTest.php b/tests/Feature/DatabaseServer/IndexTest.php index 6a34d1c8..58d53a4f 100644 --- a/tests/Feature/DatabaseServer/IndexTest.php +++ b/tests/Feature/DatabaseServer/IndexTest.php @@ -107,7 +107,7 @@ expect($snapshotBackupIds->all())->toBe($backupIds->all()); }); -test('admin can disable backups for a server from the index', function () { +test('user can disable backups for a server from the index', function () { $user = User::factory()->create(); $server = DatabaseServer::factory()->create(['backups_enabled' => true]); @@ -118,7 +118,7 @@ expect($server->fresh()->backups_enabled)->toBeFalse(); }); -test('admin can enable backups for a server from the index', function () { +test('user can enable backups for a server from the index', function () { $user = User::factory()->create(); $server = DatabaseServer::factory()->create(['backups_enabled' => false]); diff --git a/tests/Feature/DatabaseServer/ShowTest.php b/tests/Feature/DatabaseServer/ShowTest.php index 7da85e7e..4262908e 100644 --- a/tests/Feature/DatabaseServer/ShowTest.php +++ b/tests/Feature/DatabaseServer/ShowTest.php @@ -83,7 +83,7 @@ ->assertSet('showRedisRestoreModal', true); }); -test('admin can disable backups for a server from the show page', function () { +test('user can disable backups for a server from the show page', function () { $user = User::factory()->create(); $server = DatabaseServer::factory()->create(['backups_enabled' => true]); @@ -94,7 +94,7 @@ expect($server->fresh()->backups_enabled)->toBeFalse(); }); -test('admin can enable backups for a server from the show page', function () { +test('user can enable backups for a server from the show page', function () { $user = User::factory()->create(); $server = DatabaseServer::factory()->create(['backups_enabled' => false]); From 2391b3545dee304fcb86280e0ee846cbffd20b7f Mon Sep 17 00:00:00 2001 From: Konstantinos Tsouvalis Date: Wed, 10 Jun 2026 15:08:42 +0300 Subject: [PATCH 5/6] fix: hide toggle when no backup configuration exists --- .../livewire/database-server/index.blade.php | 14 ++++++++------ .../livewire/database-server/show.blade.php | 16 +++++++++------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/resources/views/livewire/database-server/index.blade.php b/resources/views/livewire/database-server/index.blade.php index 735030c7..a3d6ce75 100644 --- a/resources/views/livewire/database-server/index.blade.php +++ b/resources/views/livewire/database-server/index.blade.php @@ -151,12 +151,14 @@ class="text-info" /> class="text-success" /> @endcan @can('viewForm', $server) - + @if($server->backups->isNotEmpty()) + + @endif @endcan @can('viewForm', $server) class="btn-outline btn-success btn-sm" /> @endcan @can('viewForm', $server) - + @if($server->backups->isNotEmpty()) + + @endif @endcan @can('viewForm', $server) Date: Wed, 10 Jun 2026 22:01:33 +0200 Subject: [PATCH 6/6] fix: use update policy for backup toggle and restrict it to the index - Replace viewForm with update authorization (viewForm allows demo users, which must not mutate backups_enabled) - Remove the toggle from the show page; keep it on the index only - Consolidate toggle tests and add demo-user authorization test --- app/Livewire/DatabaseServer/Index.php | 3 +-- app/Livewire/DatabaseServer/Show.php | 15 ------------- .../livewire/database-server/index.blade.php | 2 +- .../livewire/database-server/show.blade.php | 11 ---------- tests/Feature/DatabaseServer/IndexTest.php | 8 +------ tests/Feature/DatabaseServer/ShowTest.php | 22 ------------------- 6 files changed, 3 insertions(+), 58 deletions(-) diff --git a/app/Livewire/DatabaseServer/Index.php b/app/Livewire/DatabaseServer/Index.php index 5264f1ed..9e7cba9f 100644 --- a/app/Livewire/DatabaseServer/Index.php +++ b/app/Livewire/DatabaseServer/Index.php @@ -164,7 +164,7 @@ public function toggleBackupsEnabled(string $id): void { $server = DatabaseServer::findOrFail($id); - $this->authorize('viewForm', $server); + $this->authorize('update', $server); $server->update(['backups_enabled' => ! $server->backups_enabled]); @@ -175,7 +175,6 @@ public function toggleBackupsEnabled(string $id): void ); } - public function render(): View { $servers = DatabaseServerQuery::buildFromParams( diff --git a/app/Livewire/DatabaseServer/Show.php b/app/Livewire/DatabaseServer/Show.php index a0dc4072..ed587412 100644 --- a/app/Livewire/DatabaseServer/Show.php +++ b/app/Livewire/DatabaseServer/Show.php @@ -63,21 +63,6 @@ public function runBackupAll(TriggerBackupAction $action): void $this->triggerAllBackups($this->server, $action); } - public function toggleBackupsEnabled(): void - { - $this->authorize('viewForm', $this->server); - - $this->server->update(['backups_enabled' => ! $this->server->backups_enabled]); - - $this->success( - title: $this->server->backups_enabled - ? __('Backups enabled successfully!') - : __('Backups disabled successfully!') - ); - } - - - public function confirmRestore(): void { $this->authorize('restore', $this->server); diff --git a/resources/views/livewire/database-server/index.blade.php b/resources/views/livewire/database-server/index.blade.php index a3d6ce75..e72ee2a4 100644 --- a/resources/views/livewire/database-server/index.blade.php +++ b/resources/views/livewire/database-server/index.blade.php @@ -150,7 +150,7 @@ class="text-info" /> wire:click="confirmRestore('{{ $server->id }}')" spinner class="text-success" /> @endcan - @can('viewForm', $server) + @can('update', $server) @if($server->backups->isNotEmpty()) @endcan - @can('viewForm', $server) - @if($server->backups->isNotEmpty()) - - @endif - @endcan @can('viewForm', $server) diff --git a/tests/Feature/DatabaseServer/IndexTest.php b/tests/Feature/DatabaseServer/IndexTest.php index 58d53a4f..4ee115ef 100644 --- a/tests/Feature/DatabaseServer/IndexTest.php +++ b/tests/Feature/DatabaseServer/IndexTest.php @@ -107,7 +107,7 @@ expect($snapshotBackupIds->all())->toBe($backupIds->all()); }); -test('user can disable backups for a server from the index', function () { +test('user can toggle backups for a server from the index', function () { $user = User::factory()->create(); $server = DatabaseServer::factory()->create(['backups_enabled' => true]); @@ -116,11 +116,6 @@ ->call('toggleBackupsEnabled', $server->id); expect($server->fresh()->backups_enabled)->toBeFalse(); -}); - -test('user can enable backups for a server from the index', function () { - $user = User::factory()->create(); - $server = DatabaseServer::factory()->create(['backups_enabled' => false]); Livewire::actingAs($user) ->test(Index::class) @@ -128,4 +123,3 @@ expect($server->fresh()->backups_enabled)->toBeTrue(); }); - diff --git a/tests/Feature/DatabaseServer/ShowTest.php b/tests/Feature/DatabaseServer/ShowTest.php index 4262908e..8aa2d49a 100644 --- a/tests/Feature/DatabaseServer/ShowTest.php +++ b/tests/Feature/DatabaseServer/ShowTest.php @@ -82,25 +82,3 @@ ->call('confirmRestore') ->assertSet('showRedisRestoreModal', true); }); - -test('user can disable backups for a server from the show page', function () { - $user = User::factory()->create(); - $server = DatabaseServer::factory()->create(['backups_enabled' => true]); - - Livewire::actingAs($user) - ->test(Show::class, ['server' => $server]) - ->call('toggleBackupsEnabled'); - - expect($server->fresh()->backups_enabled)->toBeFalse(); -}); - -test('user can enable backups for a server from the show page', function () { - $user = User::factory()->create(); - $server = DatabaseServer::factory()->create(['backups_enabled' => false]); - - Livewire::actingAs($user) - ->test(Show::class, ['server' => $server]) - ->call('toggleBackupsEnabled'); - - expect($server->fresh()->backups_enabled)->toBeTrue(); -});