fix(service): block UI editing of file volumes exceeding 5 MiB

Large host files mounted via Docker volumes caused the storages page to
become unusable — full file content was stored in the encrypted mediumText
column and serialised into the Livewire payload, crashing the browser.

- Add MAX_CONTENT_SIZE (5 MiB), BINARY_PLACEHOLDER, and TOO_LARGE_PLACEHOLDER
  constants to LocalFileVolume
- Check remote file size via stat/wc before cat in loadStorageOnServer and
  saveStorageOnServer; store placeholder instead of content when limit exceeded
- Expose is_too_large computed attribute (appended for Livewire serialisation)
- Guard submit, instantSave, and syncData in FileStorage Livewire component
- Truncate oversized content in Storage::refreshStorages to prevent payload bloat
- Show distinct warning banner in file-storage blade; mark textarea readonly and
  hide Save/Convert buttons for too-large files
- Add unit tests covering constants, computed flags, and toArray serialisation

Fixes #4701
This commit is contained in:
Andras Bacsai committed 2026-04-28 22:36:56 +02:00
1 parent 092ea3bb7f
commit eaaf258f25
5 files changed
+134 -13

No files matched your search

+15 -1
View File
@@ -63,13 +63,16 @@ class FileStorage extends Component
$this->fs_path = $this->fileStorage->fs_path;
}
$this->isReadOnly = $this->fileStorage->shouldBeReadOnlyInUI();
$this->isReadOnly = $this->fileStorage->shouldBeReadOnlyInUI() || $this->fileStorage->is_too_large;
$this->syncData();
}
public function syncData(bool $toModel = false): void
{
if ($toModel) {
if ($this->fileStorage->is_too_large) {
return;
}
$this->validate();
// Sync to model
@@ -172,6 +175,12 @@ class FileStorage extends Component
{
$this->authorize('update', $this->resource);
if ($this->fileStorage->is_too_large) {
$this->dispatch('error', 'File on server is too large to edit from the UI.');
return;
}
$original = $this->fileStorage->getOriginal();
try {
$this->validate();
@@ -197,6 +206,11 @@ class FileStorage extends Component
public function instantSave(): void
{
$this->authorize('update', $this->resource);
if ($this->fileStorage->is_too_large) {
$this->dispatch('error', 'File on server is too large to edit from the UI.');
return;
}
$this->syncData(true);
$this->dispatch('success', 'File updated.');
}
+5 -1
View File
@@ -69,7 +69,11 @@ class Storage extends Component
public function refreshStorages()
{
$this->fileStorage = $this->resource->fileStorages()->get();
$this->fileStorage = $this->resource->fileStorages()->get()->each(function (LocalFileVolume $fs) {
if (strlen((string) $fs->content) > LocalFileVolume::MAX_CONTENT_SIZE) {
$fs->content = LocalFileVolume::TOO_LARGE_PLACEHOLDER;
}
});
$this->resource->load('persistentStorages.resource');
}