Refactor code for domain usage and validation
This commit is contained in:
		@@ -163,18 +163,16 @@ class General extends Component
 | 
			
		||||
    }
 | 
			
		||||
    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 @@ class General extends Component
 | 
			
		||||
            $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.<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> 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 @@ class General extends Component
 | 
			
		||||
            }
 | 
			
		||||
            $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.<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> 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 @@ class General extends Component
 | 
			
		||||
            }
 | 
			
		||||
            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.<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help.");
 | 
			
		||||
                        }
 | 
			
		||||
                        check_domain_usage(resource: $this->application);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if ($this->application->settings->is_raw_compose_deployment_enabled) {
 | 
			
		||||
                    $this->application->parseRawCompose();
 | 
			
		||||
                } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class ServiceApplicationView extends Component
 | 
			
		||||
    public function submit()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            check_fqdn_usage($this->application);
 | 
			
		||||
            check_domain_usage(resource: $this->application);
 | 
			
		||||
            $this->validate();
 | 
			
		||||
            $this->application->save();
 | 
			
		||||
            updateCompose($this->application);
 | 
			
		||||
 
 | 
			
		||||
@@ -59,23 +59,37 @@ class Configuration extends Component
 | 
			
		||||
 | 
			
		||||
    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.<br><br>Make sure you have added the DNS records correctly.<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> 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!');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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:<br> {$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: <br><br>{$app->name}.");
 | 
			
		||||
                    }
 | 
			
		||||
                } else if ($domain) {
 | 
			
		||||
                    throw new \RuntimeException("Domain $naked_domain is already in use by another resource called: <br><br>{$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: <br><br>{$app->name}.");
 | 
			
		||||
                    }
 | 
			
		||||
                } else if ($domain) {
 | 
			
		||||
                    throw new \RuntimeException("Domain $naked_domain is already in use by another resource called: <br><br>{$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.");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- 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"></x-forms.input>
 | 
			
		||||
                                        @if (!data_get($parsedServiceDomains, "$serviceName.domain"))
 | 
			
		||||
                                            <x-forms.button wire:click="generateDomain('{{ $serviceName }}')">Generate
 | 
			
		||||
                                                Domain</x-forms.button>
 | 
			
		||||
                                        @endif
 | 
			
		||||
                                        <x-forms.button wire:click="generateDomain('{{ $serviceName }}')">Generate
 | 
			
		||||
                                            Domain</x-forms.button>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                @endif
 | 
			
		||||
                            @endforeach
 | 
			
		||||
@@ -205,10 +203,10 @@
 | 
			
		||||
 | 
			
		||||
                    </div>
 | 
			
		||||
                    @if ($this->application->is_github_based() && !$this->application->is_public_repository())
 | 
			
		||||
                    <div class="pb-4">
 | 
			
		||||
                        <x-forms.textarea helper="Gitignore-style rules to filter Git based webhook deployments."
 | 
			
		||||
                            placeholder="src/pages/**" id="application.watch_paths" label="Watch Paths" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                        <div class="pb-4">
 | 
			
		||||
                            <x-forms.textarea helper="Gitignore-style rules to filter Git based webhook deployments."
 | 
			
		||||
                                placeholder="src/pages/**" id="application.watch_paths" label="Watch Paths" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    <x-forms.input
 | 
			
		||||
                        helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user