diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php
index 6521ef7ba..6188651a1 100644
--- a/app/Http/Controllers/Api/ApplicationsController.php
+++ b/app/Http/Controllers/Api/ApplicationsController.php
@@ -18,6 +18,7 @@
use App\Rules\ValidGitBranch;
use App\Rules\ValidGitRepositoryUrl;
use App\Services\DockerImageParser;
+use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Validator;
@@ -3944,6 +3945,12 @@ private function validateDataApplications(Request $request, Server $server)
new OA\Response(
response: 200,
description: 'All storages by application UUID.',
+ content: new OA\JsonContent(
+ properties: [
+ new OA\Property(property: 'persistent_storages', type: 'array', items: new OA\Items(type: 'object')),
+ new OA\Property(property: 'file_storages', type: 'array', items: new OA\Items(type: 'object')),
+ ],
+ ),
),
new OA\Response(
response: 401,
@@ -3959,7 +3966,7 @@ private function validateDataApplications(Request $request, Server $server)
),
]
)]
- public function storages(Request $request)
+ public function storages(Request $request): JsonResponse
{
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
@@ -4022,6 +4029,7 @@ public function storages(Request $request)
'host_path' => ['type' => 'string', 'nullable' => true, 'description' => 'The host path (persistent only, not allowed for read-only storages).'],
'content' => ['type' => 'string', 'nullable' => true, 'description' => 'The file content (file only, not allowed for read-only storages).'],
],
+ additionalProperties: false,
),
),
],
@@ -4030,6 +4038,7 @@ public function storages(Request $request)
new OA\Response(
response: 200,
description: 'Storage updated.',
+ content: new OA\JsonContent(type: 'object'),
),
new OA\Response(
response: 401,
@@ -4043,9 +4052,13 @@ public function storages(Request $request)
response: 404,
ref: '#/components/responses/404',
),
+ new OA\Response(
+ response: 422,
+ ref: '#/components/responses/422',
+ ),
]
)]
- public function update_storage(Request $request)
+ public function update_storage(Request $request): JsonResponse
{
$teamId = getTeamIdFromToken();
@@ -4117,6 +4130,21 @@ public function update_storage(Request $request)
], 422);
}
+ // Reject fields that don't apply to the given storage type
+ if (! $isReadOnly) {
+ $typeSpecificInvalidFields = $request->type === 'persistent'
+ ? array_intersect(['content'], array_keys($request->all()))
+ : array_intersect(['name', 'host_path'], array_keys($request->all()));
+
+ if (! empty($typeSpecificInvalidFields)) {
+ return response()->json([
+ 'message' => 'Validation failed.',
+ 'errors' => collect($typeSpecificInvalidFields)
+ ->mapWithKeys(fn ($field) => [$field => "Field '{$field}' is not valid for type '{$request->type}'."]),
+ ], 422);
+ }
+ }
+
// Always allowed
if ($request->has('is_preview_suffix_enabled')) {
$storage->is_preview_suffix_enabled = $request->is_preview_suffix_enabled;
diff --git a/app/Livewire/Project/Service/FileStorage.php b/app/Livewire/Project/Service/FileStorage.php
index 71da07eb0..844e37854 100644
--- a/app/Livewire/Project/Service/FileStorage.php
+++ b/app/Livewire/Project/Service/FileStorage.php
@@ -194,9 +194,11 @@ public function submit()
}
}
- public function instantSave()
+ public function instantSave(): void
{
- $this->submit();
+ $this->authorize('update', $this->resource);
+ $this->syncData(true);
+ $this->dispatch('success', 'File updated.');
}
public function render()
diff --git a/app/Livewire/Project/Shared/Storages/Show.php b/app/Livewire/Project/Shared/Storages/Show.php
index 72b330845..eee5a0776 100644
--- a/app/Livewire/Project/Shared/Storages/Show.php
+++ b/app/Livewire/Project/Shared/Storages/Show.php
@@ -72,9 +72,10 @@ public function mount()
$this->isReadOnly = $this->storage->shouldBeReadOnlyInUI();
}
- public function instantSave()
+ public function instantSave(): void
{
$this->authorize('update', $this->resource);
+ $this->validate();
$this->syncData(true);
$this->storage->save();
diff --git a/openapi.json b/openapi.json
index d1dadcaf0..5477420ab 100644
--- a/openapi.json
+++ b/openapi.json
@@ -3463,7 +3463,28 @@
],
"responses": {
"200": {
- "description": "All storages by application UUID."
+ "description": "All storages by application UUID.",
+ "content": {
+ "application\/json": {
+ "schema": {
+ "properties": {
+ "persistent_storages": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "file_storages": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
},
"401": {
"$ref": "#\/components\/responses\/401"
@@ -3545,14 +3566,22 @@
"description": "The file content (file only, not allowed for read-only storages)."
}
},
- "type": "object"
+ "type": "object",
+ "additionalProperties": false
}
}
}
},
"responses": {
"200": {
- "description": "Storage updated."
+ "description": "Storage updated.",
+ "content": {
+ "application\/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
},
"401": {
"$ref": "#\/components\/responses\/401"
@@ -3562,6 +3591,9 @@
},
"404": {
"$ref": "#\/components\/responses\/404"
+ },
+ "422": {
+ "$ref": "#\/components\/responses\/422"
}
},
"security": [
diff --git a/openapi.yaml b/openapi.yaml
index 74af3aa13..dd03f9c42 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -2188,6 +2188,13 @@ paths:
responses:
'200':
description: 'All storages by application UUID.'
+ content:
+ application/json:
+ schema:
+ properties:
+ persistent_storages: { type: array, items: { type: object } }
+ file_storages: { type: array, items: { type: object } }
+ type: object
'401':
$ref: '#/components/responses/401'
'400':
@@ -2246,15 +2253,22 @@ paths:
nullable: true
description: 'The file content (file only, not allowed for read-only storages).'
type: object
+ additionalProperties: false
responses:
'200':
description: 'Storage updated.'
+ content:
+ application/json:
+ schema:
+ type: object
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
+ '422':
+ $ref: '#/components/responses/422'
security:
-
bearerAuth: []
diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php
index 24612098b..4bd88d761 100644
--- a/resources/views/livewire/project/service/file-storage.blade.php
+++ b/resources/views/livewire/project/service/file-storage.blade.php
@@ -15,13 +15,15 @@