Merge pull request #6315 from Jacxk/fix/service-update-required-params
fix(api): made services patch endpoint attributes optional
This commit is contained in:
		| @@ -377,14 +377,118 @@ class ServicesController extends Controller | |||||||
| 
 | 
 | ||||||
|             return response()->json(['message' => 'Service not found.', 'valid_service_types' => $serviceKeys], 404); |             return response()->json(['message' => 'Service not found.', 'valid_service_types' => $serviceKeys], 404); | ||||||
|         } elseif (filled($request->docker_compose_raw)) { |         } elseif (filled($request->docker_compose_raw)) { | ||||||
|  |             $allowedFields = ['name', 'description', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'docker_compose_raw', 'connect_to_docker_network']; | ||||||
| 
 | 
 | ||||||
|             $service = new Service; |             $validator = customApiValidator($request->all(), [ | ||||||
|             $result = $this->upsert_service($request, $service, $teamId); |                 'project_uuid' => 'string|required', | ||||||
|             if ($result instanceof \Illuminate\Http\JsonResponse) { |                 'environment_name' => 'string|nullable', | ||||||
|                 return $result; |                 'environment_uuid' => 'string|nullable', | ||||||
|  |                 'server_uuid' => 'string|required', | ||||||
|  |                 'destination_uuid' => 'string', | ||||||
|  |                 'name' => 'string|max:255', | ||||||
|  |                 'description' => 'string|nullable', | ||||||
|  |                 'instant_deploy' => 'boolean', | ||||||
|  |                 'connect_to_docker_network' => 'boolean', | ||||||
|  |                 'docker_compose_raw' => 'string|required', | ||||||
|  |             ]); | ||||||
|  | 
 | ||||||
|  |             $extraFields = array_diff(array_keys($request->all()), $allowedFields); | ||||||
|  |             if ($validator->fails() || ! empty($extraFields)) { | ||||||
|  |                 $errors = $validator->errors(); | ||||||
|  |                 if (! empty($extraFields)) { | ||||||
|  |                     foreach ($extraFields as $field) { | ||||||
|  |                         $errors->add($field, 'This field is not allowed.'); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|             return response()->json(serializeApiResponse($result))->setStatusCode(201); |                 return response()->json([ | ||||||
|  |                     'message' => 'Validation failed.', | ||||||
|  |                     'errors' => $errors, | ||||||
|  |                 ], 422); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             $environmentUuid = $request->environment_uuid; | ||||||
|  |             $environmentName = $request->environment_name; | ||||||
|  |             if (blank($environmentUuid) && blank($environmentName)) { | ||||||
|  |                 return response()->json(['message' => 'You need to provide at least one of environment_name or environment_uuid.'], 422); | ||||||
|  |             } | ||||||
|  |             $serverUuid = $request->server_uuid; | ||||||
|  |             $projectUuid = $request->project_uuid; | ||||||
|  |             $project = Project::whereTeamId($teamId)->whereUuid($projectUuid)->first(); | ||||||
|  |             if (! $project) { | ||||||
|  |                 return response()->json(['message' => 'Project not found.'], 404); | ||||||
|  |             } | ||||||
|  |             $environment = $project->environments()->where('name', $environmentName)->first(); | ||||||
|  |             if (! $environment) { | ||||||
|  |                 $environment = $project->environments()->where('uuid', $environmentUuid)->first(); | ||||||
|  |             } | ||||||
|  |             if (! $environment) { | ||||||
|  |                 return response()->json(['message' => 'Environment not found.'], 404); | ||||||
|  |             } | ||||||
|  |             $server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first(); | ||||||
|  |             if (! $server) { | ||||||
|  |                 return response()->json(['message' => 'Server not found.'], 404); | ||||||
|  |             } | ||||||
|  |             $destinations = $server->destinations(); | ||||||
|  |             if ($destinations->count() == 0) { | ||||||
|  |                 return response()->json(['message' => 'Server has no destinations.'], 400); | ||||||
|  |             } | ||||||
|  |             if ($destinations->count() > 1 && ! $request->has('destination_uuid')) { | ||||||
|  |                 return response()->json(['message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); | ||||||
|  |             } | ||||||
|  |             $destination = $destinations->first(); | ||||||
|  |             if (! isBase64Encoded($request->docker_compose_raw)) { | ||||||
|  |                 return response()->json([ | ||||||
|  |                     'message' => 'Validation failed.', | ||||||
|  |                     'errors' => [ | ||||||
|  |                         'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', | ||||||
|  |                     ], | ||||||
|  |                 ], 422); | ||||||
|  |             } | ||||||
|  |             $dockerComposeRaw = base64_decode($request->docker_compose_raw); | ||||||
|  |             if (mb_detect_encoding($dockerComposeRaw, 'ASCII', true) === false) { | ||||||
|  |                 return response()->json([ | ||||||
|  |                     'message' => 'Validation failed.', | ||||||
|  |                     'errors' => [ | ||||||
|  |                         'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', | ||||||
|  |                     ], | ||||||
|  |                 ], 422); | ||||||
|  |             } | ||||||
|  |             $dockerCompose = base64_decode($request->docker_compose_raw); | ||||||
|  |             $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); | ||||||
|  | 
 | ||||||
|  |             $connectToDockerNetwork = $request->connect_to_docker_network ?? false; | ||||||
|  |             $instantDeploy = $request->instant_deploy ?? false; | ||||||
|  | 
 | ||||||
|  |             $service = new Service; | ||||||
|  |             $service->name = $request->name ?? 'service-'.str()->random(10); | ||||||
|  |             $service->description = $request->description; | ||||||
|  |             $service->docker_compose_raw = $dockerComposeRaw; | ||||||
|  |             $service->environment_id = $environment->id; | ||||||
|  |             $service->server_id = $server->id; | ||||||
|  |             $service->destination_id = $destination->id; | ||||||
|  |             $service->destination_type = $destination->getMorphClass(); | ||||||
|  |             $service->connect_to_docker_network = $connectToDockerNetwork; | ||||||
|  |             $service->save(); | ||||||
|  | 
 | ||||||
|  |             $service->parse(isNew: true); | ||||||
|  |             if ($instantDeploy) { | ||||||
|  |                 StartService::dispatch($service); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             $domains = $service->applications()->get()->pluck('fqdn')->sort(); | ||||||
|  |             $domains = $domains->map(function ($domain) { | ||||||
|  |                 if (count(explode(':', $domain)) > 2) { | ||||||
|  |                     return str($domain)->beforeLast(':')->value(); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 return $domain; | ||||||
|  |             })->values(); | ||||||
|  | 
 | ||||||
|  |             return response()->json([ | ||||||
|  |                 'uuid' => $service->uuid, | ||||||
|  |                 'domains' => $domains, | ||||||
|  |             ])->setStatusCode(201); | ||||||
|         } else { |         } else { | ||||||
|             return response()->json(['message' => 'No service type or docker_compose_raw provided.'], 400); |             return response()->json(['message' => 'No service type or docker_compose_raw provided.'], 400); | ||||||
|         } |         } | ||||||
| @@ -550,7 +654,6 @@ class ServicesController extends Controller | |||||||
|                     mediaType: 'application/json', |                     mediaType: 'application/json', | ||||||
|                     schema: new OA\Schema( |                     schema: new OA\Schema( | ||||||
|                         type: 'object', |                         type: 'object', | ||||||
|                         required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid', 'docker_compose_raw'], |  | ||||||
|                         properties: [ |                         properties: [ | ||||||
|                             'name' => ['type' => 'string', 'description' => 'The service name.'], |                             'name' => ['type' => 'string', 'description' => 'The service name.'], | ||||||
|                             'description' => ['type' => 'string', 'description' => 'The service description.'], |                             'description' => ['type' => 'string', 'description' => 'The service description.'], | ||||||
| @@ -615,28 +718,14 @@ class ServicesController extends Controller | |||||||
|             return response()->json(['message' => 'Service not found.'], 404); |             return response()->json(['message' => 'Service not found.'], 404); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         $result = $this->upsert_service($request, $service, $teamId); |         $allowedFields = ['name', 'description', 'instant_deploy', 'docker_compose_raw', 'connect_to_docker_network']; | ||||||
|         if ($result instanceof \Illuminate\Http\JsonResponse) { |  | ||||||
|             return $result; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         return response()->json(serializeApiResponse($result))->setStatusCode(200); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private function upsert_service(Request $request, Service $service, string $teamId) |  | ||||||
|     { |  | ||||||
|         $allowedFields = ['name', 'description', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'docker_compose_raw', 'connect_to_docker_network']; |  | ||||||
|         $validator = customApiValidator($request->all(), [ |         $validator = customApiValidator($request->all(), [ | ||||||
|             'project_uuid' => 'string|required', |  | ||||||
|             'environment_name' => 'string|nullable', |  | ||||||
|             'environment_uuid' => 'string|nullable', |  | ||||||
|             'server_uuid' => 'string|required', |  | ||||||
|             'destination_uuid' => 'string', |  | ||||||
|             'name' => 'string|max:255', |             'name' => 'string|max:255', | ||||||
|             'description' => 'string|nullable', |             'description' => 'string|nullable', | ||||||
|             'instant_deploy' => 'boolean', |             'instant_deploy' => 'boolean', | ||||||
|             'connect_to_docker_network' => 'boolean', |             'connect_to_docker_network' => 'boolean', | ||||||
|             'docker_compose_raw' => 'string|required', |             'docker_compose_raw' => 'string|nullable', | ||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         $extraFields = array_diff(array_keys($request->all()), $allowedFields); |         $extraFields = array_diff(array_keys($request->all()), $allowedFields); | ||||||
| @@ -653,37 +742,7 @@ class ServicesController extends Controller | |||||||
|                 'errors' => $errors, |                 'errors' => $errors, | ||||||
|             ], 422); |             ], 422); | ||||||
|         } |         } | ||||||
| 
 |         if ($request->has('docker_compose_raw')) { | ||||||
|         $environmentUuid = $request->environment_uuid; |  | ||||||
|         $environmentName = $request->environment_name; |  | ||||||
|         if (blank($environmentUuid) && blank($environmentName)) { |  | ||||||
|             return response()->json(['message' => 'You need to provide at least one of environment_name or environment_uuid.'], 422); |  | ||||||
|         } |  | ||||||
|         $serverUuid = $request->server_uuid; |  | ||||||
|         $instantDeploy = $request->instant_deploy ?? false; |  | ||||||
|         $project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first(); |  | ||||||
|         if (! $project) { |  | ||||||
|             return response()->json(['message' => 'Project not found.'], 404); |  | ||||||
|         } |  | ||||||
|         $environment = $project->environments()->where('name', $environmentName)->first(); |  | ||||||
|         if (! $environment) { |  | ||||||
|             $environment = $project->environments()->where('uuid', $environmentUuid)->first(); |  | ||||||
|         } |  | ||||||
|         if (! $environment) { |  | ||||||
|             return response()->json(['message' => 'Environment not found.'], 404); |  | ||||||
|         } |  | ||||||
|         $server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first(); |  | ||||||
|         if (! $server) { |  | ||||||
|             return response()->json(['message' => 'Server not found.'], 404); |  | ||||||
|         } |  | ||||||
|         $destinations = $server->destinations(); |  | ||||||
|         if ($destinations->count() == 0) { |  | ||||||
|             return response()->json(['message' => 'Server has no destinations.'], 400); |  | ||||||
|         } |  | ||||||
|         if ($destinations->count() > 1 && ! $request->has('destination_uuid')) { |  | ||||||
|             return response()->json(['message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); |  | ||||||
|         } |  | ||||||
|         $destination = $destinations->first(); |  | ||||||
|             if (! isBase64Encoded($request->docker_compose_raw)) { |             if (! isBase64Encoded($request->docker_compose_raw)) { | ||||||
|                 return response()->json([ |                 return response()->json([ | ||||||
|                     'message' => 'Validation failed.', |                     'message' => 'Validation failed.', | ||||||
| @@ -703,20 +762,22 @@ class ServicesController extends Controller | |||||||
|             } |             } | ||||||
|             $dockerCompose = base64_decode($request->docker_compose_raw); |             $dockerCompose = base64_decode($request->docker_compose_raw); | ||||||
|             $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); | ||||||
|         $connectToDockerNetwork = $request->connect_to_docker_network ?? false; |  | ||||||
| 
 |  | ||||||
|         $service->name = $request->name ?? null; |  | ||||||
|         $service->description = $request->description ?? null; |  | ||||||
|             $service->docker_compose_raw = $dockerComposeRaw; |             $service->docker_compose_raw = $dockerComposeRaw; | ||||||
|         $service->environment_id = $environment->id; |         } | ||||||
|         $service->server_id = $server->id; | 
 | ||||||
|         $service->destination_id = $destination->id; |         if ($request->has('name')) { | ||||||
|         $service->destination_type = $destination->getMorphClass(); |             $service->name = $request->name; | ||||||
|         $service->connect_to_docker_network = $connectToDockerNetwork; |         } | ||||||
|  |         if ($request->has('description')) { | ||||||
|  |             $service->description = $request->description; | ||||||
|  |         } | ||||||
|  |         if ($request->has('connect_to_docker_network')) { | ||||||
|  |             $service->connect_to_docker_network = $request->connect_to_docker_network; | ||||||
|  |         } | ||||||
|         $service->save(); |         $service->save(); | ||||||
| 
 | 
 | ||||||
|         $service->parse(); |         $service->parse(); | ||||||
|         if ($instantDeploy) { |         if ($request->instant_deploy) { | ||||||
|             StartService::dispatch($service); |             StartService::dispatch($service); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -729,10 +790,10 @@ class ServicesController extends Controller | |||||||
|             return $domain; |             return $domain; | ||||||
|         })->values(); |         })->values(); | ||||||
| 
 | 
 | ||||||
|         return [ |         return response()->json([ | ||||||
|             'uuid' => $service->uuid, |             'uuid' => $service->uuid, | ||||||
|             'domains' => $domains, |             'domains' => $domains, | ||||||
|         ]; |         ])->setStatusCode(200); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[OA\Get(
 |     #[OA\Get(
 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Andras Bacsai
					Andras Bacsai