diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index c2891c1321..0dcb024cad 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -1248,6 +1248,9 @@ class ApplicationsController extends Controller $this->authorize('create', Application::class); + // removeUnnecessaryFieldsFromRequest() strips force_domain_override before the docker_compose_domains checks run. + $forceDomainOverride = $request->boolean('force_domain_override'); + if ($request->instant_deploy) { abort_unless($request->user()->tokenCan('deploy') || $request->user()->tokenCan('root'), 403, 'Missing required permissions: deploy'); } @@ -1501,7 +1504,7 @@ class ApplicationsController extends Controller }); $duplicates = $urls->duplicates()->unique()->values(); - if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { + if ($duplicates->isNotEmpty() && ! $forceDomainOverride) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed.'; } @@ -1522,7 +1525,7 @@ class ApplicationsController extends Controller ], 422); } - if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { + if ($result['hasConflicts'] && ! $forceDomainOverride) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], @@ -1769,7 +1772,7 @@ class ApplicationsController extends Controller }); $duplicates = $urls->duplicates()->unique()->values(); - if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { + if ($duplicates->isNotEmpty() && ! $forceDomainOverride) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed. '; } @@ -1790,7 +1793,7 @@ class ApplicationsController extends Controller ], 422); } - if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { + if ($result['hasConflicts'] && ! $forceDomainOverride) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], @@ -2002,7 +2005,7 @@ class ApplicationsController extends Controller }); $duplicates = $urls->duplicates()->unique()->values(); - if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { + if ($duplicates->isNotEmpty() && ! $forceDomainOverride) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed.'; } @@ -2023,7 +2026,7 @@ class ApplicationsController extends Controller ], 422); } - if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { + if ($result['hasConflicts'] && ! $forceDomainOverride) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], diff --git a/tests/Feature/Api/ApplicationDomainValidationApiTest.php b/tests/Feature/Api/ApplicationDomainValidationApiTest.php index 88533ce760..cb9b4007ba 100644 --- a/tests/Feature/Api/ApplicationDomainValidationApiTest.php +++ b/tests/Feature/Api/ApplicationDomainValidationApiTest.php @@ -9,6 +9,7 @@ use App\Models\StandaloneDocker; use App\Models\Team; use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Queue; use Visus\Cuid2\Cuid2; uses(RefreshDatabase::class); @@ -84,3 +85,28 @@ it('rejects wildcard domains on application creation', function (string $proxyTy expect(Application::count())->toBe($count); })->with([ProxyTypes::NONE->value, ProxyTypes::TRAEFIK->value]); + +it('honours force_domain_override for conflicting docker_compose_domains on application creation', function (bool $force, int $expectedStatus) { + Queue::fake(); + $this->server->settings()->update(['is_reachable' => true, 'is_usable' => true]); + $this->application->update(['fqdn' => 'https://shared.example.com']); + + $this->withToken($this->bearerToken) + ->postJson('/api/v1/applications/public', [ + 'project_uuid' => $this->project->uuid, + 'environment_uuid' => $this->environment->uuid, + 'server_uuid' => $this->server->uuid, + 'git_repository' => 'https://gitlab.com/coollabsio/coolify-examples', + 'git_branch' => 'v4.x', + 'build_pack' => 'dockercompose', + 'docker_compose_domains' => [ + ['name' => 'web', 'domain' => 'https://shared.example.com'], + ['name' => 'api', 'domain' => 'https://shared.example.com'], + ], + 'force_domain_override' => $force, + ]) + ->assertStatus($expectedStatus); +})->with([ + 'without override' => [false, 422], + 'with override' => [true, 201], +]);