diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index c6b8f2e51..7c3700107 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -163,18 +163,16 @@ public function loadComposeFile($isInit = false) } public function generateDomain(string $serviceName) { - $domain = $this->parsedServiceDomains[$serviceName]['domain'] ?? null; - if (!$domain) { - $uuid = new Cuid2(7); - $domain = generateFqdn($this->application->destination->server, $uuid); - $this->parsedServiceDomains[$serviceName]['domain'] = $domain; - $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains); - $this->application->save(); - } + $uuid = new Cuid2(7); + $domain = generateFqdn($this->application->destination->server, $uuid); + $this->parsedServiceDomains[$serviceName]['domain'] = $domain; + $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains); + $this->application->save(); + $this->dispatch('success', 'Domain generated.'); return $domain; } - public function updatedApplicationBaseDirectory() { - raY('asdf'); + public function updatedApplicationBaseDirectory() + { if ($this->application->build_pack === 'dockercompose') { $this->loadComposeFile(); } @@ -206,30 +204,47 @@ public function getWildcardDomain() $fqdn = generateFqdn($server, $this->application->uuid); $this->application->fqdn = $fqdn; $this->application->save(); - $this->updatedApplicationFqdn(); + $this->dispatch('success', 'Wildcard domain generated.'); } } - public function resetDefaultLabels($showToaster = true) + public function resetDefaultLabels() { $this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n"); $this->ports_exposes = $this->application->ports_exposes; - $this->submit($showToaster); + + $this->application->custom_labels = base64_encode($this->customLabels); + $this->application->save(); } - public function updatedApplicationFqdn() + public function checkFqdns($showToaster = true) { - $this->application->fqdn = str($this->application->fqdn)->replaceEnd(',', '')->trim(); - $this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim(); - $this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) { - return str($domain)->trim()->lower(); - }); - $this->application->fqdn = $this->application->fqdn->unique()->implode(','); - $this->application->save(); - $this->resetDefaultLabels(false); + if (data_get($this->application, 'fqdn')) { + $domains = str($this->application->fqdn)->trim()->explode(','); + if ($this->application->additional_servers->count() === 0) { + foreach ($domains as $domain) { + if (!validate_dns_entry($domain, $this->application->destination->server)) { + $showToaster && $this->dispatch('error', "Validating DNS ($domain) failed.", "Make sure you have added the DNS records correctly.

Check this documentation for further help."); + } + } + } + check_domain_usage(resource: $this->application); + $this->application->fqdn = $domains->implode(','); + } } public function submit($showToaster = true) { try { + $this->application->fqdn = str($this->application->fqdn)->replaceEnd(',', '')->trim(); + $this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim(); + $this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) { + return str($domain)->trim()->lower(); + }); + $this->application->fqdn = $this->application->fqdn->unique()->implode(','); + + $this->checkFqdns(); + + $this->application->save(); + if (!$this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') { $this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n"); $this->application->custom_labels = base64_encode($this->customLabels); @@ -241,25 +256,14 @@ public function submit($showToaster = true) } $this->validate(); if ($this->ports_exposes !== $this->application->ports_exposes) { - $this->resetDefaultLabels(false); + $this->resetDefaultLabels(); } if (data_get($this->application, 'build_pack') === 'dockerimage') { $this->validate([ 'application.docker_registry_image_name' => 'required', ]); } - if (data_get($this->application, 'fqdn')) { - $domains = str($this->application->fqdn)->trim()->explode(','); - if ($this->application->additional_servers->count() === 0) { - foreach ($domains as $domain) { - if (!validate_dns_entry($domain, $this->application->destination->server)) { - $showToaster && $this->dispatch('error', "Validating DNS ($domain) failed.", "Make sure you have added the DNS records correctly.

Check this documentation for further help."); - } - } - } - check_fqdn_usage($this->application); - $this->application->fqdn = $domains->implode(','); - } + if (data_get($this->application, 'custom_docker_run_options')) { $this->application->custom_docker_run_options = str($this->application->custom_docker_run_options)->trim(); } @@ -277,6 +281,15 @@ public function submit($showToaster = true) } if ($this->application->build_pack === 'dockercompose') { $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains); + foreach ($this->parsedServiceDomains as $serviceName => $service) { + $domain = data_get($service, 'domain'); + if ($domain) { + if (!validate_dns_entry($domain, $this->application->destination->server)) { + $showToaster && $this->dispatch('error', "Validating DNS ($domain) failed.", "Make sure you have added the DNS records correctly.

Check this documentation for further help."); + } + check_domain_usage(resource: $this->application); + } + } if ($this->application->settings->is_raw_compose_deployment_enabled) { $this->application->parseRawCompose(); } else { diff --git a/app/Livewire/Project/Service/ServiceApplicationView.php b/app/Livewire/Project/Service/ServiceApplicationView.php index ca9723a3a..dfa2baced 100644 --- a/app/Livewire/Project/Service/ServiceApplicationView.php +++ b/app/Livewire/Project/Service/ServiceApplicationView.php @@ -65,7 +65,7 @@ public function mount() public function submit() { try { - check_fqdn_usage($this->application); + check_domain_usage(resource: $this->application); $this->validate(); $this->application->save(); updateCompose($this->application); diff --git a/app/Livewire/Settings/Configuration.php b/app/Livewire/Settings/Configuration.php index 79ff3bcb6..fbc88785d 100644 --- a/app/Livewire/Settings/Configuration.php +++ b/app/Livewire/Settings/Configuration.php @@ -59,23 +59,37 @@ public function instantSave() public function submit() { - $this->resetErrorBag(); - if ($this->settings->public_port_min > $this->settings->public_port_max) { - $this->addError('settings.public_port_min', 'The minimum port must be lower than the maximum port.'); - return; + try { + $error_show = false; + $this->server = Server::findOrFail(0); + $this->resetErrorBag(); + if ($this->settings->public_port_min > $this->settings->public_port_max) { + $this->addError('settings.public_port_min', 'The minimum port must be lower than the maximum port.'); + return; + } + $this->validate(); + + if ($this->settings->is_dns_validation_enabled) { + if (!validate_dns_entry($this->settings->fqdn, $this->server)) { + $this->dispatch('error', "Validating DNS ({$this->settings->fqdn}) failed.

Make sure you have added the DNS records correctly.

Check this documentation for further help."); + $error_show = true; + } + } + check_domain_usage(domain: $this->settings->fqdn); + $this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->replaceEnd(',', '')->trim(); + $this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->trim()->explode(',')->map(function ($dns) { + return str($dns)->trim()->lower(); + }); + $this->settings->custom_dns_servers = $this->settings->custom_dns_servers->unique(); + $this->settings->custom_dns_servers = $this->settings->custom_dns_servers->implode(','); + + $this->settings->save(); + $this->server->setupDynamicProxyConfiguration(); + if (!$error_show) { + $this->dispatch('success', 'Instance settings updated successfully!'); + } + } catch (\Exception $e) { + return handleError($e, $this); } - $this->validate(); - - $this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->replaceEnd(',', '')->trim(); - $this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->trim()->explode(',')->map(function ($dns) { - return str($dns)->trim()->lower(); - }); - $this->settings->custom_dns_servers = $this->settings->custom_dns_servers->unique(); - $this->settings->custom_dns_servers = $this->settings->custom_dns_servers->implode(','); - - $this->settings->save(); - $this->server = Server::findOrFail(0); - $this->server->setupDynamicProxyConfiguration(); - $this->dispatch('success', 'Instance settings updated successfully!'); } } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 4e25bd616..f10ab6638 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1857,13 +1857,26 @@ function ip_match($ip, $cidrs, &$match = null) } return false; } -function check_fqdn_usage(ServiceApplication|Application $own_resource) +function check_domain_usage(ServiceApplication|Application|null $resource = null, ?string $domain = null) { - $domains = collect($own_resource->fqdns)->map(function ($domain) { + if ($resource) { + if ($resource->getMorphClass() === 'App\Models\Application' && $resource->build_pack === 'dockercompose') { + $domains = data_get(json_decode($resource->docker_compose_domains, true), "*.domain"); + ray($domains); + $domains = collect($domains); + } else { + $domains = collect($resource->fqdns); + } + } else if ($domain) { + $domains = collect($domain); + } else { + throw new \RuntimeException("No resource or FQDN provided."); + } + $domains = $domains->map(function ($domain) { if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); } - return str($domain)->replace('http://', '')->replace('https://', ''); + return str($domain); }); $apps = Application::all(); foreach ($apps as $app) { @@ -1872,10 +1885,15 @@ function check_fqdn_usage(ServiceApplication|Application $own_resource) if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); } - $naked_domain = str($domain)->replace('http://', '')->replace('https://', '')->value(); + $naked_domain = str($domain)->value(); if ($domains->contains($naked_domain)) { - if ($app->uuid !== $own_resource->uuid) { - throw new \RuntimeException("Domain $naked_domain is already in use by another resource:
{$app->name}."); + if (data_get($resource, 'uuid')) { + ray($resource->uuid, $app->uuid); + if ($resource->uuid !== $app->uuid) { + throw new \RuntimeException("Domain $naked_domain is already in use by another resource called:

{$app->name}."); + } + } else if ($domain) { + throw new \RuntimeException("Domain $naked_domain is already in use by another resource called:

{$app->name}."); } } } @@ -1887,12 +1905,29 @@ function check_fqdn_usage(ServiceApplication|Application $own_resource) if (str($domain)->endsWith('/')) { $domain = str($domain)->beforeLast('/'); } - $naked_domain = str($domain)->replace('http://', '')->replace('https://', '')->value(); + $naked_domain = str($domain)->value(); if ($domains->contains($naked_domain)) { - if ($app->uuid !== $own_resource->uuid) { - throw new \RuntimeException("Domain $naked_domain is already in use by another resource."); + if (data_get($resource, 'uuid')) { + if ($resource->uuid !== $app->uuid) { + throw new \RuntimeException("Domain $naked_domain is already in use by another resource called:

{$app->name}."); + } + } else if ($domain) { + throw new \RuntimeException("Domain $naked_domain is already in use by another resource called:

{$app->name}."); } } } } + if ($resource) { + $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)) { + throw new \RuntimeException("Domain $naked_domain is already in use by this Coolify instance."); + } + } + } } diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index 7f950dfa4..00c204f46 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -59,10 +59,8 @@ helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.

Example
- http://app.coolify.io, https://cloud.coolify.io/dashboard
- http://app.coolify.io/api/v3
- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. " label="Domains for {{ str($serviceName)->headline() }}" id="parsedServiceDomains.{{ $serviceName }}.domain"> - @if (!data_get($parsedServiceDomains, "$serviceName.domain")) - Generate - Domain - @endif + Generate + Domain @endif @endforeach @@ -205,10 +203,10 @@ class="underline" href="https://coolify.io/docs/knowledge-base/docker/registry" @if ($this->application->is_github_based() && !$this->application->is_public_repository()) -
- -
+
+ +
@endif