From 09d8ba0d89ac0cbed091d06530ce317f1e2918b4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:03:12 +0200 Subject: [PATCH] fix(api): prevent partial server updates on invalid disk schedule --- .../Controllers/Api/ServersController.php | 21 +++++++++------- .../Feature/ServerUpdatePrivateKeyApiTest.php | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/Api/ServersController.php b/app/Http/Controllers/Api/ServersController.php index 9b008d90c..5082bd856 100644 --- a/app/Http/Controllers/Api/ServersController.php +++ b/app/Http/Controllers/Api/ServersController.php @@ -705,9 +705,7 @@ class ServersController extends Controller $validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) { return str($proxyType->value)->lower(); }); - if ($validProxyTypes->contains(str($request->proxy_type)->lower())) { - $server->changeProxy($request->proxy_type, async: true); - } else { + if (! $validProxyTypes->contains(str($request->proxy_type)->lower())) { return response()->json(['message' => 'Invalid proxy type.'], 422); } } @@ -719,12 +717,6 @@ class ServersController extends Controller } $updateFields['private_key_id'] = $privateKey->id; } - $server->update($updateFields); - if ($request->is_build_server) { - $server->settings()->update([ - 'is_build_server' => $request->is_build_server, - ]); - } if ($request->has('server_disk_usage_check_frequency') && ! validate_cron_expression($request->server_disk_usage_check_frequency)) { return response()->json([ @@ -733,11 +725,22 @@ class ServersController extends Controller ], 422); } + $server->update($updateFields); + if ($request->is_build_server) { + $server->settings()->update([ + 'is_build_server' => $request->is_build_server, + ]); + } + $advancedSettings = $request->only(['concurrent_builds', 'dynamic_timeout', 'deployment_queue_limit', 'server_disk_usage_notification_threshold', 'server_disk_usage_check_frequency', 'connection_timeout']); if (! empty($advancedSettings)) { $server->settings()->update(array_filter($advancedSettings, fn ($value) => ! is_null($value))); } + if ($request->proxy_type) { + $server->changeProxy($request->proxy_type, async: true); + } + if ($request->instant_validate) { ValidateServer::dispatch($server); } diff --git a/tests/Feature/ServerUpdatePrivateKeyApiTest.php b/tests/Feature/ServerUpdatePrivateKeyApiTest.php index e3f315f24..a6e407168 100644 --- a/tests/Feature/ServerUpdatePrivateKeyApiTest.php +++ b/tests/Feature/ServerUpdatePrivateKeyApiTest.php @@ -92,3 +92,28 @@ it('keeps the existing private key when private_key_uuid is omitted', function ( expect($server->name)->toBe('Renamed Server') ->and($server->private_key_id)->toBe($this->oldPrivateKey->id); }); + +it('rejects an invalid disk usage check frequency without partially updating the server', function () { + $this->server->proxy->set('type', 'TRAEFIK'); + $this->server->save(); + $this->server->settings()->update(['is_build_server' => false]); + + patchServerUpdatePrivateKeyApi($this, $this->server, $this->bearerToken, [ + 'name' => 'Renamed Server', + 'is_build_server' => true, + 'proxy_type' => 'none', + 'server_disk_usage_check_frequency' => 'not a valid schedule', + ])->assertUnprocessable() + ->assertJson([ + 'message' => 'Validation failed.', + 'errors' => [ + 'server_disk_usage_check_frequency' => ['Invalid Cron / Human expression for Disk Usage Check Frequency.'], + ], + ]); + + $server = $this->server->fresh(); + + expect($server->name)->not->toBe('Renamed Server') + ->and($server->settings->is_build_server)->toBeFalse() + ->and($server->proxy->get('type'))->toBe('TRAEFIK'); +});