diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index 3dac22efb3..1286f34282 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -239,6 +239,11 @@ class ApplicationsController extends Controller } } + private function extraApplicationFieldMessage(string $field): string + { + return $field === 'fqdn' ? 'Use the domains field to set application URLs.' : 'This field is not allowed.'; + } + /** * Expose sensitive fields on eager-loaded nested Server + ServerSetting * relations for callers with the `read:sensitive` or `root` token ability. @@ -1315,7 +1320,7 @@ class ApplicationsController extends Controller $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { - $errors->add($field, 'This field is not allowed.'); + $errors->add($field, $this->extraApplicationFieldMessage($field)); } } @@ -3394,7 +3399,7 @@ class ApplicationsController extends Controller $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { - $errors->add($field, 'This field is not allowed.'); + $errors->add($field, $this->extraApplicationFieldMessage($field)); } } diff --git a/tests/Feature/ApplicationFqdnFieldApiTest.php b/tests/Feature/ApplicationFqdnFieldApiTest.php new file mode 100644 index 0000000000..dc7fa07c1f --- /dev/null +++ b/tests/Feature/ApplicationFqdnFieldApiTest.php @@ -0,0 +1,71 @@ + InstanceSettings::firstOrCreate(['id' => 0])); + + $this->team = Team::factory()->create(); + $this->user = User::factory()->create(); + $this->team->members()->attach($this->user->id, ['role' => 'owner']); + session(['currentTeam' => $this->team]); + + $plainTextToken = Str::random(40); + $token = $this->user->tokens()->create([ + 'name' => 'fqdn-field-api-test-'.Str::random(6), + 'token' => hash('sha256', $plainTextToken), + 'abilities' => ['*'], + 'team_id' => $this->team->id, + ]); + $this->bearerToken = $token->getKey().'|'.$plainTextToken; + + $this->server = Server::factory()->create(['team_id' => $this->team->id]); + $this->destination = StandaloneDocker::where('server_id', $this->server->id)->first(); + $this->project = Project::factory()->create(['team_id' => $this->team->id]); + $this->environment = Environment::factory()->create(['project_id' => $this->project->id]); +}); + +test('PATCH with fqdn points the caller to the domains field', function () { + $application = Application::factory()->create([ + 'environment_id' => $this->environment->id, + 'destination_id' => $this->destination->id, + 'destination_type' => $this->destination->getMorphClass(), + 'fqdn' => 'https://app.example.com', + ]); + + $this->withToken($this->bearerToken) + ->patchJson("/api/v1/applications/{$application->uuid}", [ + 'fqdn' => 'https://new.example.com', + 'unknown_field' => 'value', + ]) + ->assertUnprocessable() + ->assertJsonPath('errors.fqdn', ['Use the domains field to set application URLs.']) + ->assertJsonPath('errors.unknown_field', ['This field is not allowed.']); + + expect($application->fresh()->fqdn)->toBe('https://app.example.com'); +}); + +test('POST create with fqdn points the caller to the domains field', function () { + $this->withToken($this->bearerToken) + ->postJson('/api/v1/applications/dockerimage', [ + 'project_uuid' => $this->project->uuid, + 'environment_uuid' => $this->environment->uuid, + 'server_uuid' => $this->server->uuid, + 'docker_registry_image_name' => 'nginx', + 'ports_exposes' => '80', + 'fqdn' => 'https://new.example.com', + ]) + ->assertUnprocessable() + ->assertJsonPath('errors.fqdn', ['Use the domains field to set application URLs.']); +});