From aa016e685dc47defc43031d43ee762571699b916 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 9 Nov 2026 17:51:58 +0100 Subject: [PATCH] fix(cache): accept numbers that Redis returns as strings The root setup window and the scanner disk usage checked is_int() on cached values, but the Redis store returns numbers as strings. The setup window was closed right after each start. Co-Authored-By: Claude Opus 5.5 --- .changes/closed-root-account-setup-window-right.md | 4 ++++ .changes/missing-scanner-disk-usage-on-the.md | 6 ++++++ .../Controllers/Api/ServerImageScanningController.php | 3 +-- app/Jobs/PrepareImageScannerJob.php | 10 ++++++++++ app/Livewire/ImageScan/ServerImageScanning.php | 4 ++-- app/Support/RootSetupWindow.php | 5 ++++- 6 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 .changes/closed-root-account-setup-window-right.md create mode 100644 .changes/missing-scanner-disk-usage-on-the.md diff --git a/.changes/closed-root-account-setup-window-right.md b/.changes/closed-root-account-setup-window-right.md new file mode 100644 index 0000000000..956ed3be50 --- /dev/null +++ b/.changes/closed-root-account-setup-window-right.md @@ -0,0 +1,4 @@ +--- +type: fixed +--- +Closed root account setup window right after a fresh install, so the first account could not be created on the `Register` page diff --git a/.changes/missing-scanner-disk-usage-on-the.md b/.changes/missing-scanner-disk-usage-on-the.md new file mode 100644 index 0000000000..9e0d2b28d3 --- /dev/null +++ b/.changes/missing-scanner-disk-usage-on-the.md @@ -0,0 +1,6 @@ +--- +type: fixed +--- +Missing scanner disk usage on the `Image Scanning` page of a server and in the `scanner_disk_used_bytes` API field + +- The `Delete scanner data` button also stays hidden now after the scanner data is deleted diff --git a/app/Http/Controllers/Api/ServerImageScanningController.php b/app/Http/Controllers/Api/ServerImageScanningController.php index f2de7bee64..c5a831e0eb 100644 --- a/app/Http/Controllers/Api/ServerImageScanningController.php +++ b/app/Http/Controllers/Api/ServerImageScanningController.php @@ -27,7 +27,6 @@ class ServerImageScanningController extends Controller $state = Cache::get(PrepareImageScannerJob::stateCacheKey($server)); $failedStep = Cache::get(PrepareImageScannerJob::failedStepCacheKey($server)); $builtAt = Cache::get(PrepareImageScannerJob::builtAtCacheKey($server)); - $diskUsed = Cache::get(PrepareImageScannerJob::diskUsedCacheKey($server)); return [ 'is_image_scan_enabled' => (bool) $server->settings->is_image_scan_enabled, @@ -35,7 +34,7 @@ class ServerImageScanningController extends Controller 'scanner_state' => is_string($state) ? $state : null, 'scanner_failed_step' => is_string($failedStep) ? $failedStep : null, 'scanner_built_at' => is_string($builtAt) ? CarbonImmutable::parse($builtAt)->toIso8601String() : null, - 'scanner_disk_used_bytes' => is_int($diskUsed) ? $diskUsed : null, + 'scanner_disk_used_bytes' => PrepareImageScannerJob::diskUsedBytes($server), ]; } diff --git a/app/Jobs/PrepareImageScannerJob.php b/app/Jobs/PrepareImageScannerJob.php index 535738d354..ff9f76803f 100644 --- a/app/Jobs/PrepareImageScannerJob.php +++ b/app/Jobs/PrepareImageScannerJob.php @@ -86,6 +86,16 @@ class PrepareImageScannerJob implements ShouldBeEncrypted, ShouldBeUnique, Shoul return self::stateCacheKey($server).':disk-used'; } + /** + * The Redis store returns numbers as strings, so the cached value is not always an int. + */ + public static function diskUsedBytes(Server $server): ?int + { + $bytes = Cache::get(self::diskUsedCacheKey($server)); + + return is_numeric($bytes) ? (int) $bytes : null; + } + public static function failedStepCacheKey(Server $server): string { return self::stateCacheKey($server).':failed-step'; diff --git a/app/Livewire/ImageScan/ServerImageScanning.php b/app/Livewire/ImageScan/ServerImageScanning.php index b770ae7780..036deea430 100644 --- a/app/Livewire/ImageScan/ServerImageScanning.php +++ b/app/Livewire/ImageScan/ServerImageScanning.php @@ -154,7 +154,7 @@ class ServerImageScanning extends Component $state = Cache::get(PrepareImageScannerJob::stateCacheKey($this->server)); $builtAt = Cache::get(PrepareImageScannerJob::builtAtCacheKey($this->server)); $failedStep = Cache::get(PrepareImageScannerJob::failedStepCacheKey($this->server)); - $diskUsed = Cache::get(PrepareImageScannerJob::diskUsedCacheKey($this->server)); + $diskUsed = PrepareImageScannerJob::diskUsedBytes($this->server); return view('livewire.image-scan.server-image-scanning', [ 'enabled' => (bool) $this->server->settings->is_image_scan_enabled, @@ -169,7 +169,7 @@ class ServerImageScanning extends Component ->map(fn (array $image) => ImageRef::parse($image['repo'])->registry) ->unique() ->implode(', '), - 'diskUsed' => is_int($diskUsed) ? formatBytes($diskUsed, 1) : null, + 'diskUsed' => $diskUsed !== null ? formatBytes($diskUsed, 1) : null, // Hide the delete action only when the server is known to be empty. Missing cache data can still mean data on disk. 'hasScannerData' => is_string($state) || $diskUsed !== 0, 'toolVersions' => collect(['syft' => 'Syft', 'grype' => 'Grype', 'regctl' => 'regctl']) diff --git a/app/Support/RootSetupWindow.php b/app/Support/RootSetupWindow.php index 728e34092f..d775a5083b 100644 --- a/app/Support/RootSetupWindow.php +++ b/app/Support/RootSetupWindow.php @@ -28,11 +28,14 @@ class RootSetupWindow Cache::forever(self::CACHE_KEY, now()->addMinutes(self::MINUTES)->getTimestamp()); } + /** + * The Redis store returns numbers as strings, so the value is not always an int. + */ public static function isOpen(): bool { $closesAt = Cache::get(self::CACHE_KEY); - return is_int($closesAt) && now()->getTimestamp() < $closesAt; + return is_numeric($closesAt) && now()->getTimestamp() < (int) $closesAt; } public static function isPending(): bool