From e4dd9bc9f98310e53982ce5ea17b0a35238ff363 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sat, 26 Oct 2024 17:07:15 +0200 Subject: [PATCH 01/10] Use custom domain in create site endpoint --- .../Platform/Modules/Sites/Http/Sites/CreateSite.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php index c8e30a5ab9..bf4ac62aeb 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php @@ -64,6 +64,7 @@ class CreateSite extends Base ->param('buildCommand', '', new Text(8192, 0), 'Build Command.', true) ->param('outputDirectory', '', new Text(8192, 0), 'Output Directory for site.', true) ->param('fallbackRedirect', '', new Text(8192, 0), 'Fallback Redirect URL for site in case a route is not found.', true) + ->param('subDomain', '', new CustomId(), 'Unique custom sub-domain. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true) ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for API key auto-generated for every execution. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.', true) //TODO: Update description of scopes ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true) ->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the site.', true) @@ -92,7 +93,7 @@ class CreateSite extends Base ->callback([$this, 'action']); } - public function action(string $siteId, string $name, string $framework, bool $enabled, string $installCommand, string $buildCommand, string $outputDirectory, string $fallbackRedirect, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) + public function action(string $siteId, string $name, string $framework, bool $enabled, string $installCommand, string $buildCommand, string $outputDirectory, string $fallbackRedirect, string $subDomain, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) { $siteId = ($siteId == 'unique()') ? ID::unique() : $siteId; @@ -215,7 +216,7 @@ class CreateSite extends Base $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); if (!empty($sitesDomain)) { $ruleId = ID::unique(); - $routeSubdomain = ID::unique(); + $routeSubdomain = $subDomain ?? ID::unique(); $domain = "{$routeSubdomain}.{$sitesDomain}"; $rule = Authorization::skip( From 6ac81dea19a383be291800cb6412f1dca593d86b Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sat, 26 Oct 2024 18:34:58 +0200 Subject: [PATCH 02/10] Check if subdomain exists before creating site --- composer.lock | 12 ++++----- .../Modules/Sites/Http/Sites/CreateSite.php | 25 +++++++++++++++---- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index a7e95a95ca..91e9210fd8 100644 --- a/composer.lock +++ b/composer.lock @@ -157,16 +157,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.16.2", + "version": "0.16.4", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "c33005e3eaaf2d427e9fd1077d5335e31f4d36f9" + "reference": "7e4741337b9373f77210396e68eca539018cabd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/c33005e3eaaf2d427e9fd1077d5335e31f4d36f9", - "reference": "c33005e3eaaf2d427e9fd1077d5335e31f4d36f9", + "url": "https://api.github.com/repos/appwrite/runtimes/zipball/7e4741337b9373f77210396e68eca539018cabd1", + "reference": "7e4741337b9373f77210396e68eca539018cabd1", "shasum": "" }, "require": { @@ -206,9 +206,9 @@ ], "support": { "issues": "https://github.com/appwrite/runtimes/issues", - "source": "https://github.com/appwrite/runtimes/tree/0.16.2" + "source": "https://github.com/appwrite/runtimes/tree/0.16.4" }, - "time": "2024-10-09T15:02:52+00:00" + "time": "2024-10-26T10:39:59+00:00" }, { "name": "beberlei/assert", diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php index bf4ac62aeb..18daaeae53 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php @@ -18,6 +18,7 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -95,6 +96,25 @@ class CreateSite extends Base public function action(string $siteId, string $name, string $framework, bool $enabled, string $installCommand, string $buildCommand, string $outputDirectory, string $fallbackRedirect, string $subDomain, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) { + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $ruleId = ''; + $routeSubdomain = ''; + $domain = ''; + + if (!empty($sitesDomain)) { + $ruleId = ID::unique(); + $routeSubdomain = $subDomain ?? ID::unique(); + $domain = "{$routeSubdomain}.{$sitesDomain}"; + + $subDomain = Authorization::skip(fn () => $dbForConsole->findOne('rules', [ + Query::equal('domain', [$domain]) + ])); + + if (!empty($subDomain)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Subdomain already exists. Please choose a different subdomain.'); + } + } + $siteId = ($siteId == 'unique()') ? ID::unique() : $siteId; $allowList = \array_filter(\explode(',', System::getEnv('_APP_SITES_FRAMEWORKS', ''))); @@ -213,12 +233,7 @@ class CreateSite extends Base ->setTemplate($template); } - $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); if (!empty($sitesDomain)) { - $ruleId = ID::unique(); - $routeSubdomain = $subDomain ?? ID::unique(); - $domain = "{$routeSubdomain}.{$sitesDomain}"; - $rule = Authorization::skip( fn () => $dbForConsole->createDocument('rules', new Document([ '$id' => $ruleId, From 86a68c50bcc62e9caf69c610bcf7dedada986e3e Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 11:32:43 +0100 Subject: [PATCH 03/10] Rename subdomain --- .../Platform/Modules/Sites/Http/Sites/CreateSite.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php index 77d4ec70a1..2db8cf68a3 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/CreateSite.php @@ -64,7 +64,7 @@ class CreateSite extends Base ->param('buildCommand', '', new Text(8192, 0), 'Build Command.', true) ->param('outputDirectory', '', new Text(8192, 0), 'Output Directory for site.', true) ->param('fallbackRedirect', '', new Text(8192, 0), 'Fallback Redirect URL for site in case a route is not found.', true) - ->param('subDomain', '', new CustomId(), 'Unique custom sub-domain. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true) + ->param('subdomain', '', new CustomId(), 'Unique custom sub-domain. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true) ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true) ->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the site.', true) ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the site.', true) @@ -92,7 +92,7 @@ class CreateSite extends Base ->callback([$this, 'action']); } - public function action(string $siteId, string $name, string $framework, bool $enabled, string $installCommand, string $buildCommand, string $outputDirectory, string $fallbackRedirect, string $subDomain, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) + public function action(string $siteId, string $name, string $framework, bool $enabled, string $installCommand, string $buildCommand, string $outputDirectory, string $fallbackRedirect, string $subdomain, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) { $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $ruleId = ''; @@ -101,14 +101,14 @@ class CreateSite extends Base if (!empty($sitesDomain)) { $ruleId = ID::unique(); - $routeSubdomain = $subDomain ?? ID::unique(); + $routeSubdomain = $subdomain ?? ID::unique(); $domain = "{$routeSubdomain}.{$sitesDomain}"; - $subDomain = Authorization::skip(fn () => $dbForConsole->findOne('rules', [ + $subdomain = Authorization::skip(fn () => $dbForConsole->findOne('rules', [ Query::equal('domain', [$domain]) ])); - if (!empty($subDomain)) { + if (!empty($subdomain)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Subdomain already exists. Please choose a different subdomain.'); } } From 6b2160f3882443fe469055c8071058c3033f0047 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 11:33:56 +0100 Subject: [PATCH 04/10] Fix vcs deployments --- app/controllers/api/vcs.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 753fd043c8..9021c6c518 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -200,11 +200,10 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId 'resourceInternalId' => $resourceInternalId, 'resourceType' => $resourceCollection, 'entrypoint' => $resource->getAttribute('entrypoint', ''), - 'commands' => $resource->getAttribute('commands', []), + 'commands' => $resource->getAttribute('commands', ''), 'installCommand' => $resource->getAttribute('installCommand', ''), 'buildCommand' => $resource->getAttribute('buildCommand', ''), 'outputDirectory' => $resource->getAttribute('outputDirectory', ''), - 'fallbackRedirect' => $resource->getAttribute('fallbackRedirect', ''), 'type' => 'vcs', 'installationId' => $installationId, 'installationInternalId' => $installationInternalId, From 302a135e5a79ffcf64cedc96ee9c37f41d8b5ac6 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 11:52:22 +0100 Subject: [PATCH 05/10] Fix health tests --- tests/e2e/Services/Health/HealthCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 8360af542e..7a8b3ab7cb 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -467,7 +467,7 @@ class HealthCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('/CN=appwrite.io', $response['body']['name']); $this->assertEquals('appwrite.io', $response['body']['subjectSN']); - $this->assertEquals("Let's Encrypt", $response['body']['issuerOrganisation']); + $this->assertEquals('Google Trust Services', $response['body']['issuerOrganisation']); $this->assertIsInt($response['body']['validFrom']); $this->assertIsInt($response['body']['validTo']); From 83807ed2479db7b4f8048a300b12b99e89ac78b3 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 12:56:56 +0100 Subject: [PATCH 06/10] Fix projects tests --- app/controllers/api/proxy.php | 20 ++++++------------- .../Projects/ProjectsCustomServerTest.php | 10 ++++++++++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index d749946826..3411ebafd5 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -54,19 +54,12 @@ App::post('/v1/proxy/rules') $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - switch ($resourceType) { - case 'function': - if (str_ends_with($domain, $functionsDomain)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.'); - } - break; - case 'site': - if (str_ends_with($domain, $sitesDomain)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.'); - } - break; + if ($functionsDomain != '' && str_ends_with($domain, $functionsDomain)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.'); + } + if ($sitesDomain != '' && str_ends_with($domain, $sitesDomain)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your sites domain or it\'s subdomain to specific resource. Please use different domain.'); } - if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); @@ -111,8 +104,7 @@ App::post('/v1/proxy/rules') break; case 'site': if (empty($resourceId)) { - // todo: use site relecant exception - throw new Exception(Exception::FUNCTION_NOT_FOUND); + throw new Exception(Exception::SITE_NOT_FOUND); } $site = $dbForProject->getDocument('sites', $resourceId); diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index cc976b78f6..f81290e707 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -44,5 +44,15 @@ class ProjectsCustomServerTest extends Scope ]); $this->assertEquals(400, $response['headers']['status-code']); + + // prevent sites domain + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [ + 'resourceType' => 'api', + 'domain' => $sitesDomain, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); } } From 0c2db53ee8d41d05545b616da9aafa4667f99d26 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 14:11:53 +0100 Subject: [PATCH 07/10] Address PR Comments --- app/controllers/api/proxy.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 3411ebafd5..ada8d2453c 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -54,11 +54,12 @@ App::post('/v1/proxy/rules') $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - if ($functionsDomain != '' && str_ends_with($domain, $functionsDomain)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.'); - } - if ($sitesDomain != '' && str_ends_with($domain, $sitesDomain)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your sites domain or it\'s subdomain to specific resource. Please use different domain.'); + if ( + ($functionsDomain !== '' && str_ends_with($domain, $functionsDomain)) || + ($sitesDomain !== '' && str_ends_with($domain, $sitesDomain)) + ) { + // TODO: Refactor later + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions or sites domain or their subdomains to a specific resource. Please use a different domain.'); } if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) { From 77a70cad71b6ed40606d74ca5f853e6d9fd3d00d Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 15:31:00 +0100 Subject: [PATCH 08/10] Add endpoint to check subdomain availability --- app/controllers/api/proxy.php | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index ada8d2453c..56982bee38 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -371,3 +371,39 @@ App::patch('/v1/proxy/rules/:ruleId/verification') $response->dynamic($rule, Response::MODEL_PROXY_RULE); }); + +App::get('/v1/proxy/subdomains') + ->desc('Check if subdomain is available') + ->groups(['api', 'proxy']) + ->label('scope', 'rules.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'proxy') + ->label('sdk.method', 'checkSubdomain') + ->label('sdk.description', '/docs/references/proxy/check-subdomain.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_NONE) + ->param('resourceType', null, new WhiteList(['function', 'site']), 'Action definition for the rule. Possible values are "api", "function" and "site"') + ->param('subdomain', '', new Text(256), 'Subdomain name.') + ->inject('response') + ->inject('dbForConsole') + ->action(function (string $resourceType, string $subdomain, Response $response, Database $dbForConsole) { + $resourceDomain = $resourceType === 'site' ? System::getEnv('_APP_DOMAIN_SITES', '') : System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $domain = $subdomain . '.' . $resourceDomain; + + $document = $dbForConsole->findOne('rules', [ + Query::equal('domain', [$domain]), + ]); + + if ($document && !$document->isEmpty()) { + return $response->json([ + 'success' => false, + 'message' => 'Subdomain is already taken.' + ], Response::STATUS_CODE_CONFLICT); + } + + return $response->json([ + 'success' => true, + 'message' => 'Subdomain is available.' + ], Response::STATUS_CODE_OK); + }); From e7e1cfa12eec30f014dcbf56bf71d2a9d8dee82f Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 15:32:29 +0100 Subject: [PATCH 09/10] Update desc --- app/controllers/api/proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 56982bee38..aee3df9235 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -383,7 +383,7 @@ App::get('/v1/proxy/subdomains') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_NONE) - ->param('resourceType', null, new WhiteList(['function', 'site']), 'Action definition for the rule. Possible values are "api", "function" and "site"') + ->param('resourceType', null, new WhiteList(['function', 'site']), 'Action definition for the rule. Possible values are "function" and "site"') ->param('subdomain', '', new Text(256), 'Subdomain name.') ->inject('response') ->inject('dbForConsole') From 44e76b4eaaae22047201bd18ed592ec85acd7aba Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 27 Oct 2024 15:35:18 +0100 Subject: [PATCH 10/10] Add a todo --- app/controllers/api/proxy.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index aee3df9235..3b061a85c2 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -388,6 +388,7 @@ App::get('/v1/proxy/subdomains') ->inject('response') ->inject('dbForConsole') ->action(function (string $resourceType, string $subdomain, Response $response, Database $dbForConsole) { + //TODO: Add tests for this endpoint $resourceDomain = $resourceType === 'site' ? System::getEnv('_APP_DOMAIN_SITES', '') : System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); $domain = $subdomain . '.' . $resourceDomain;