refactor: improve validation error handling and coding standards
Changes:
1. Add explicit try-catch blocks around validateDockerComposeForInjection()
in API endpoints to return proper 422 JSON responses with validation errors
2. Rename $service_payload to $servicePayload for PSR-12 compliance (camelCase)
API endpoints now properly handle validation failures:
- One-click service creation (line 334)
- Custom compose service creation (line 480)
- Service update endpoint (line 808)
All return consistent error format:
{
"message": "Validation failed.",
"errors": {
"docker_compose_raw": "Invalid Docker Compose service name: ..."
}
}
Livewire components already have proper exception handling via handleError().
All 60 security tests pass (176 assertions).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
cb1f571eb4
commit
fa8393184f
1 changed files with 33 additions and 6 deletions
|
|
@ -331,9 +331,18 @@ public function create_service(Request $request)
|
||||||
$dockerComposeRaw = base64_decode($oneClickService);
|
$dockerComposeRaw = base64_decode($oneClickService);
|
||||||
|
|
||||||
// Validate for command injection BEFORE creating service
|
// Validate for command injection BEFORE creating service
|
||||||
validateDockerComposeForInjection($dockerComposeRaw);
|
try {
|
||||||
|
validateDockerComposeForInjection($dockerComposeRaw);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => [
|
||||||
|
'docker_compose_raw' => $e->getMessage(),
|
||||||
|
],
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
$service_payload = [
|
$servicePayload = [
|
||||||
'name' => "$oneClickServiceName-".str()->random(10),
|
'name' => "$oneClickServiceName-".str()->random(10),
|
||||||
'docker_compose_raw' => $dockerComposeRaw,
|
'docker_compose_raw' => $dockerComposeRaw,
|
||||||
'environment_id' => $environment->id,
|
'environment_id' => $environment->id,
|
||||||
|
|
@ -343,9 +352,9 @@ public function create_service(Request $request)
|
||||||
'destination_type' => $destination->getMorphClass(),
|
'destination_type' => $destination->getMorphClass(),
|
||||||
];
|
];
|
||||||
if ($oneClickServiceName === 'cloudflared') {
|
if ($oneClickServiceName === 'cloudflared') {
|
||||||
data_set($service_payload, 'connect_to_docker_network', true);
|
data_set($servicePayload, 'connect_to_docker_network', true);
|
||||||
}
|
}
|
||||||
$service = Service::create($service_payload);
|
$service = Service::create($servicePayload);
|
||||||
$service->name = "$oneClickServiceName-".$service->uuid;
|
$service->name = "$oneClickServiceName-".$service->uuid;
|
||||||
$service->save();
|
$service->save();
|
||||||
if ($oneClickDotEnvs?->count() > 0) {
|
if ($oneClickDotEnvs?->count() > 0) {
|
||||||
|
|
@ -468,7 +477,16 @@ public function create_service(Request $request)
|
||||||
$dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
|
$dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
|
||||||
|
|
||||||
// Validate for command injection BEFORE saving to database
|
// Validate for command injection BEFORE saving to database
|
||||||
validateDockerComposeForInjection($dockerComposeRaw);
|
try {
|
||||||
|
validateDockerComposeForInjection($dockerComposeRaw);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => [
|
||||||
|
'docker_compose_raw' => $e->getMessage(),
|
||||||
|
],
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
$connectToDockerNetwork = $request->connect_to_docker_network ?? false;
|
$connectToDockerNetwork = $request->connect_to_docker_network ?? false;
|
||||||
$instantDeploy = $request->instant_deploy ?? false;
|
$instantDeploy = $request->instant_deploy ?? false;
|
||||||
|
|
@ -787,7 +805,16 @@ public function update_by_uuid(Request $request)
|
||||||
$dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
|
$dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
|
||||||
|
|
||||||
// Validate for command injection BEFORE saving to database
|
// Validate for command injection BEFORE saving to database
|
||||||
validateDockerComposeForInjection($dockerComposeRaw);
|
try {
|
||||||
|
validateDockerComposeForInjection($dockerComposeRaw);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => [
|
||||||
|
'docker_compose_raw' => $e->getMessage(),
|
||||||
|
],
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
$service->docker_compose_raw = $dockerComposeRaw;
|
$service->docker_compose_raw = $dockerComposeRaw;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue