238 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| use App\Models\Application;
 | |
| use App\Models\ServiceApplication;
 | |
| use Illuminate\Support\Collection;
 | |
| 
 | |
| function checkDomainUsage(ServiceApplication|Application|null $resource = null, ?string $domain = null)
 | |
| {
 | |
|     $conflicts = [];
 | |
| 
 | |
|     // Get the current team for filtering
 | |
|     $currentTeam = null;
 | |
|     if ($resource) {
 | |
|         $currentTeam = $resource->team();
 | |
|     }
 | |
| 
 | |
|     if ($resource) {
 | |
|         if ($resource->getMorphClass() === Application::class && $resource->build_pack === 'dockercompose') {
 | |
|             $domains = data_get(json_decode($resource->docker_compose_domains, true), '*.domain');
 | |
|             $domains = collect($domains);
 | |
|         } else {
 | |
|             $domains = collect($resource->fqdns);
 | |
|         }
 | |
|     } elseif ($domain) {
 | |
|         $domains = collect([$domain]);
 | |
|     } else {
 | |
|         return ['conflicts' => [], 'hasConflicts' => false];
 | |
|     }
 | |
| 
 | |
|     $domains = $domains->map(function ($domain) {
 | |
|         if (str($domain)->endsWith('/')) {
 | |
|             $domain = str($domain)->beforeLast('/');
 | |
|         }
 | |
| 
 | |
|         return str($domain);
 | |
|     });
 | |
| 
 | |
|     // Filter applications by team if we have a current team
 | |
|     $appsQuery = Application::query();
 | |
|     if ($currentTeam) {
 | |
|         $appsQuery = $appsQuery->whereHas('environment.project', function ($query) use ($currentTeam) {
 | |
|             $query->where('team_id', $currentTeam->id);
 | |
|         });
 | |
|     }
 | |
|     $apps = $appsQuery->get();
 | |
|     foreach ($apps as $app) {
 | |
|         $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)) {
 | |
|                 if (data_get($resource, 'uuid')) {
 | |
|                     if ($resource->uuid !== $app->uuid) {
 | |
|                         $conflicts[] = [
 | |
|                             'domain' => $naked_domain,
 | |
|                             'resource_name' => $app->name,
 | |
|                             'resource_link' => $app->link(),
 | |
|                             'resource_type' => 'application',
 | |
|                             'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
 | |
|                         ];
 | |
|                     }
 | |
|                 } elseif ($domain) {
 | |
|                     $conflicts[] = [
 | |
|                         'domain' => $naked_domain,
 | |
|                         'resource_name' => $app->name,
 | |
|                         'resource_link' => $app->link(),
 | |
|                         'resource_type' => 'application',
 | |
|                         'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
 | |
|                     ];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Filter service applications by team if we have a current team
 | |
|     $serviceAppsQuery = ServiceApplication::query();
 | |
|     if ($currentTeam) {
 | |
|         $serviceAppsQuery = $serviceAppsQuery->whereHas('service.environment.project', function ($query) use ($currentTeam) {
 | |
|             $query->where('team_id', $currentTeam->id);
 | |
|         });
 | |
|     }
 | |
|     $apps = $serviceAppsQuery->get();
 | |
|     foreach ($apps as $app) {
 | |
|         $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)) {
 | |
|                 if (data_get($resource, 'uuid')) {
 | |
|                     if ($resource->uuid !== $app->uuid) {
 | |
|                         $conflicts[] = [
 | |
|                             'domain' => $naked_domain,
 | |
|                             'resource_name' => $app->service->name,
 | |
|                             'resource_link' => $app->service->link(),
 | |
|                             'resource_type' => 'service',
 | |
|                             'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
 | |
|                         ];
 | |
|                     }
 | |
|                 } elseif ($domain) {
 | |
|                     $conflicts[] = [
 | |
|                         'domain' => $naked_domain,
 | |
|                         'resource_name' => $app->service->name,
 | |
|                         'resource_link' => $app->service->link(),
 | |
|                         'resource_type' => 'service',
 | |
|                         'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
 | |
|                     ];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($resource) {
 | |
|         $settings = instanceSettings();
 | |
|         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)) {
 | |
|                 $conflicts[] = [
 | |
|                     'domain' => $naked_domain,
 | |
|                     'resource_name' => 'Coolify Instance',
 | |
|                     'resource_link' => '#',
 | |
|                     'resource_type' => 'instance',
 | |
|                     'message' => "Domain $naked_domain is already in use by this Coolify instance",
 | |
|                 ];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return [
 | |
|         'conflicts' => $conflicts,
 | |
|         'hasConflicts' => count($conflicts) > 0,
 | |
|     ];
 | |
| }
 | |
| 
 | |
| function checkIfDomainIsAlreadyUsedViaAPI(Collection|array $domains, ?string $teamId = null, ?string $uuid = null)
 | |
| {
 | |
|     $conflicts = [];
 | |
| 
 | |
|     if (is_null($teamId)) {
 | |
|         return ['error' => 'Team ID is required.'];
 | |
|     }
 | |
|     if (is_array($domains)) {
 | |
|         $domains = collect($domains);
 | |
|     }
 | |
| 
 | |
|     $domains = $domains->map(function ($domain) {
 | |
|         if (str($domain)->endsWith('/')) {
 | |
|             $domain = str($domain)->beforeLast('/');
 | |
|         }
 | |
| 
 | |
|         return str($domain);
 | |
|     });
 | |
| 
 | |
|     // Check applications within the same team
 | |
|     $applications = Application::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid', 'name', 'id']);
 | |
|     $serviceApplications = ServiceApplication::ownedByCurrentTeamAPI($teamId)->with('service:id,name')->get(['fqdn', 'uuid', 'id', 'service_id']);
 | |
| 
 | |
|     if ($uuid) {
 | |
|         $applications = $applications->filter(fn ($app) => $app->uuid !== $uuid);
 | |
|         $serviceApplications = $serviceApplications->filter(fn ($app) => $app->uuid !== $uuid);
 | |
|     }
 | |
| 
 | |
|     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)) {
 | |
|                 $conflicts[] = [
 | |
|                     'domain' => $naked_domain,
 | |
|                     'resource_name' => $app->name,
 | |
|                     'resource_uuid' => $app->uuid,
 | |
|                     'resource_type' => 'application',
 | |
|                     'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
 | |
|                 ];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     foreach ($serviceApplications as $app) {
 | |
|         if (str($app->fqdn)->isEmpty()) {
 | |
|             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)) {
 | |
|                 $conflicts[] = [
 | |
|                     'domain' => $naked_domain,
 | |
|                     'resource_name' => $app->service->name ?? 'Unknown Service',
 | |
|                     'resource_uuid' => $app->uuid,
 | |
|                     'resource_type' => 'service',
 | |
|                     'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
 | |
|                 ];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Check instance-level domain
 | |
|     $settings = instanceSettings();
 | |
|     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)) {
 | |
|             $conflicts[] = [
 | |
|                 'domain' => $naked_domain,
 | |
|                 'resource_name' => 'Coolify Instance',
 | |
|                 'resource_uuid' => null,
 | |
|                 'resource_type' => 'instance',
 | |
|                 'message' => "Domain $naked_domain is already in use by this Coolify instance",
 | |
|             ];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return [
 | |
|         'conflicts' => $conflicts,
 | |
|         'hasConflicts' => count($conflicts) > 0,
 | |
|     ];
 | |
| }
 | 
