fix: check domain on new app via api
This commit is contained in:
parent
b86924bc0e
commit
dbc235d84a
@ -37,7 +37,7 @@ public function create_application(Request $request)
|
|||||||
{
|
{
|
||||||
|
|
||||||
ray()->clearAll();
|
ray()->clearAll();
|
||||||
$allowedFields = ['project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy'];
|
$allowedFields = ['project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile'];
|
||||||
$teamId = get_team_id_from_token();
|
$teamId = get_team_id_from_token();
|
||||||
if (is_null($teamId)) {
|
if (is_null($teamId)) {
|
||||||
return invalid_token();
|
return invalid_token();
|
||||||
@ -94,9 +94,6 @@ public function create_application(Request $request)
|
|||||||
if (! $environment) {
|
if (! $environment) {
|
||||||
return response()->json(['error' => 'Environment not found.'], 404);
|
return response()->json(['error' => 'Environment not found.'], 404);
|
||||||
}
|
}
|
||||||
if (! $request->has('name')) {
|
|
||||||
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
|
|
||||||
}
|
|
||||||
$server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first();
|
$server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first();
|
||||||
if (! $server) {
|
if (! $server) {
|
||||||
return response()->json(['error' => 'Server not found.'], 404);
|
return response()->json(['error' => 'Server not found.'], 404);
|
||||||
@ -110,6 +107,9 @@ public function create_application(Request $request)
|
|||||||
}
|
}
|
||||||
$destination = $destinations->first();
|
$destination = $destinations->first();
|
||||||
if ($type === 'public') {
|
if ($type === 'public') {
|
||||||
|
if (! $request->has('name')) {
|
||||||
|
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
|
||||||
|
}
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
sharedDataApplications(),
|
sharedDataApplications(),
|
||||||
'git_repository' => 'string|required',
|
'git_repository' => 'string|required',
|
||||||
@ -151,6 +151,9 @@ public function create_application(Request $request)
|
|||||||
|
|
||||||
return response()->json(serialize_api_response($application));
|
return response()->json(serialize_api_response($application));
|
||||||
} elseif ($type === 'private-gh-app') {
|
} elseif ($type === 'private-gh-app') {
|
||||||
|
if (! $request->has('name')) {
|
||||||
|
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
|
||||||
|
}
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
sharedDataApplications(),
|
sharedDataApplications(),
|
||||||
'git_repository' => 'string|required',
|
'git_repository' => 'string|required',
|
||||||
@ -204,6 +207,9 @@ public function create_application(Request $request)
|
|||||||
|
|
||||||
return response()->json(serialize_api_response($application));
|
return response()->json(serialize_api_response($application));
|
||||||
} elseif ($type === 'private-deploy-key') {
|
} elseif ($type === 'private-deploy-key') {
|
||||||
|
if (! $request->has('name')) {
|
||||||
|
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
|
||||||
|
}
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
sharedDataApplications(),
|
sharedDataApplications(),
|
||||||
'git_repository' => 'string|required',
|
'git_repository' => 'string|required',
|
||||||
@ -249,6 +255,75 @@ public function create_application(Request $request)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response()->json(serialize_api_response($application));
|
||||||
|
} elseif ($type === 'dockerfile') {
|
||||||
|
if (! $request->has('name')) {
|
||||||
|
$request->offsetSet('name', 'dockerfile-'.new Cuid2(7));
|
||||||
|
}
|
||||||
|
$validator = customApiValidator($request->all(), [
|
||||||
|
sharedDataApplications(),
|
||||||
|
'dockerfile' => 'string|required',
|
||||||
|
]);
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => $validator->errors(),
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
$return = $this->validateDataApplications($request, $server);
|
||||||
|
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
if (! isBase64Encoded($request->dockerfile)) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => [
|
||||||
|
'dockerfile' => 'The dockerfile should be base64 encoded.',
|
||||||
|
],
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
$dockerFile = base64_decode($request->dockerfile);
|
||||||
|
if (mb_detect_encoding($dockerFile, 'ASCII', true) === false) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => [
|
||||||
|
'dockerfile' => 'The dockerfile should be base64 encoded.',
|
||||||
|
],
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
$dockerFile = base64_decode($request->dockerfile);
|
||||||
|
$this->removeUnnecessaryFieldsFromRequest($request);
|
||||||
|
|
||||||
|
$port = get_port_from_dockerfile($request->dockerfile);
|
||||||
|
if (! $port) {
|
||||||
|
$port = 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
$application = new Application();
|
||||||
|
$application->fill($request->all());
|
||||||
|
$application->fqdn = $fqdn;
|
||||||
|
$application->ports_exposes = $port;
|
||||||
|
$application->build_pack = 'dockerfile';
|
||||||
|
$application->dockerfile = $dockerFile;
|
||||||
|
$application->destination_id = $destination->id;
|
||||||
|
$application->destination_type = $destination->getMorphClass();
|
||||||
|
$application->environment_id = $environment->id;
|
||||||
|
|
||||||
|
$application->git_repository = 'coollabsio/coolify';
|
||||||
|
$application->git_branch = 'main';
|
||||||
|
$application->save();
|
||||||
|
|
||||||
|
if ($instantDeploy) {
|
||||||
|
$deployment_uuid = new Cuid2(7);
|
||||||
|
|
||||||
|
queue_application_deployment(
|
||||||
|
application: $application,
|
||||||
|
deployment_uuid: $deployment_uuid,
|
||||||
|
no_questions_asked: true,
|
||||||
|
is_api: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json(serialize_api_response($application));
|
return response()->json(serialize_api_response($application));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,6 +901,8 @@ private function removeUnnecessaryFieldsFromRequest(Request $request)
|
|||||||
|
|
||||||
private function validateDataApplications(Request $request, Server $server)
|
private function validateDataApplications(Request $request, Server $server)
|
||||||
{
|
{
|
||||||
|
$teamId = get_team_id_from_token();
|
||||||
|
|
||||||
// Validate ports_mappings
|
// Validate ports_mappings
|
||||||
if ($request->has('ports_mappings')) {
|
if ($request->has('ports_mappings')) {
|
||||||
$ports = [];
|
$ports = [];
|
||||||
@ -881,6 +958,14 @@ private function validateDataApplications(Request $request, Server $server)
|
|||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
if (checkIfDomainIsAlreadyUsed($fqdn, $teamId)) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed.',
|
||||||
|
'errors' => [
|
||||||
|
'domains' => 'One of the domain is already used.',
|
||||||
|
],
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,7 +502,7 @@ public function checkSentinel()
|
|||||||
$sentinel_found = json_decode($sentinel_found, true);
|
$sentinel_found = json_decode($sentinel_found, true);
|
||||||
$status = data_get($sentinel_found, '0.State.Status', 'exited');
|
$status = data_get($sentinel_found, '0.State.Status', 'exited');
|
||||||
if ($status !== 'running') {
|
if ($status !== 'running') {
|
||||||
ray('Sentinel is not running, starting it...');
|
// ray('Sentinel is not running, starting it...');
|
||||||
PullSentinelImageJob::dispatch($this);
|
PullSentinelImageJob::dispatch($this);
|
||||||
} else {
|
} else {
|
||||||
// ray('Sentinel is running');
|
// ray('Sentinel is running');
|
||||||
|
@ -27,6 +27,11 @@ public function restart()
|
|||||||
instant_remote_process(["docker restart {$container_id}"], $this->service->server);
|
instant_remote_process(["docker restart {$container_id}"], $this->service->server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function ownedByCurrentTeamAPI(int $teamId)
|
||||||
|
{
|
||||||
|
return ServiceApplication::whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name');
|
||||||
|
}
|
||||||
|
|
||||||
public function isLogDrainEnabled()
|
public function isLogDrainEnabled()
|
||||||
{
|
{
|
||||||
return data_get($this, 'is_log_drain_enabled', false);
|
return data_get($this, 'is_log_drain_enabled', false);
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
|
use function PHPUnit\Framework\isEmpty;
|
||||||
|
|
||||||
function base_configuration_dir(): string
|
function base_configuration_dir(): string
|
||||||
{
|
{
|
||||||
return '/data/coolify';
|
return '/data/coolify';
|
||||||
@ -2129,6 +2131,75 @@ function ip_match($ip, $cidrs, &$match = null)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
function checkIfDomainIsAlreadyUsed(Collection|array $domains, ?string $teamId = null)
|
||||||
|
{
|
||||||
|
if (is_null($teamId)) {
|
||||||
|
return response()->json(['error' => 'Team ID is required.'], 400);
|
||||||
|
}
|
||||||
|
if (is_array($domains)) {
|
||||||
|
$domains = collect($domains);
|
||||||
|
}
|
||||||
|
|
||||||
|
$domains = $domains->map(function ($domain) {
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return str($domain);
|
||||||
|
});
|
||||||
|
$applications = Application::ownedByCurrentTeamAPI($teamId)->get('fqdn');
|
||||||
|
$serviceApplications = ServiceApplication::ownedByCurrentTeamAPI($teamId)->get('fqdn');
|
||||||
|
$domainFound = false;
|
||||||
|
foreach ($applications as $app) {
|
||||||
|
if (is_null($app->fqdn)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
|
||||||
|
foreach ($list_of_domains as $domain) {
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
$naked_domain = str($domain)->value();
|
||||||
|
if ($domains->contains($naked_domain)) {
|
||||||
|
$domainFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($domainFound) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach ($serviceApplications as $app) {
|
||||||
|
if (isEmpty($app->fqdn)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
|
||||||
|
foreach ($list_of_domains as $domain) {
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
$naked_domain = str($domain)->value();
|
||||||
|
if ($domains->contains($naked_domain)) {
|
||||||
|
$domainFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($domainFound) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$settings = InstanceSettings::get();
|
||||||
|
if (data_get($settings, 'fqdn')) {
|
||||||
|
$domain = data_get($settings, 'fqdn');
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
$naked_domain = str($domain)->value();
|
||||||
|
if ($domains->contains($naked_domain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
function check_domain_usage(ServiceApplication|Application|null $resource = null, ?string $domain = null)
|
function check_domain_usage(ServiceApplication|Application|null $resource = null, ?string $domain = null)
|
||||||
{
|
{
|
||||||
if ($resource) {
|
if ($resource) {
|
||||||
|
Loading…
Reference in New Issue
Block a user