fix: Improve read-only volume detection and UI messaging

- Add isServiceResource() and shouldBeReadOnlyInUI() to LocalFileVolume
- Update path matching to handle leading slashes in volume comparisons
- Update FileStorage and Show components to use shouldBeReadOnlyInUI()
- Show consolidated warning message for service/compose resources in all.blade.php
- Remove redundant per-volume warnings for service resources
- Clean up configuration.blade.php formatting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2025-12-11 21:25:33 +01:00
parent 475cfd78cd
commit 9bc33d65ab
7 changed files with 49 additions and 26 deletions

View File

@@ -209,6 +209,23 @@ class LocalFileVolume extends BaseModel
return $query->get()->where('plain_mount_path', $path);
}
// Check if this volume belongs to a service resource
public function isServiceResource(): bool
{
return in_array($this->resource_type, [
'App\Models\ServiceApplication',
'App\Models\ServiceDatabase',
]);
}
// Determine if this volume should be read-only in the UI
// File/directory mounts can be edited even for services
public function shouldBeReadOnlyInUI(): bool
{
// Check for explicit :ro flag in compose (existing logic)
return $this->isReadOnlyVolume();
}
// Check if this volume is read-only by parsing the docker-compose content
public function isReadOnlyVolume(): bool
{
@@ -251,8 +268,12 @@ class LocalFileVolume extends BaseModel
$containerPath = $parts[1];
$options = $parts[2] ?? null;
// Match based on mount_path (container path)
if ($containerPath === $this->mount_path) {
// Match based on mount_path
// Remove leading slash from mount_path if present for comparison
$mountPath = str($this->mount_path)->ltrim('/')->toString();
$containerPathClean = str($containerPath)->ltrim('/')->toString();
if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) {
return $options === 'ro';
}
}
@@ -261,8 +282,12 @@ class LocalFileVolume extends BaseModel
$containerPath = data_get($volume, 'target');
$readOnly = data_get($volume, 'read_only', false);
// Match based on mount_path (container path)
if ($containerPath === $this->mount_path) {
// Match based on mount_path
// Remove leading slash from mount_path if present for comparison
$mountPath = str($this->mount_path)->ltrim('/')->toString();
$containerPathClean = str($containerPath)->ltrim('/')->toString();
if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) {
return $readOnly === true;
}
}