diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 7aadc10ef3..cc55cdb5f5 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -9,10 +9,12 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Domain; +use Utopia\Validator\Text; use Utopia\Validator\WhiteList; class Get extends Action @@ -21,20 +23,20 @@ class Get extends Action public static function getName() { - return 'getResourceAvailability'; + return 'getResources'; } public function __construct() { $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('v1/console/resources/:resourceId') + ->setHttpPath('v1/console/resources') ->desc('Check resource ID availability') ->groups(['api', 'projects']) ->label('scope', 'rules.read') ->label('sdk', new Method( namespace: 'console', - name: 'getResourceAvailability', + name: 'getResource', description: <<label('abuse-limit', 10) ->label('abuse-key', 'userId:{userId}, url:{url}') ->label('abuse-time', 60) - ->param('resourceId', '', new UID(), 'ID of the resource.') + ->param('value', '', new Text(256), 'Resource value.') ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') ->inject('dbForPlatform') ->callback([$this, 'action']); } - public function action(string $resourceId, string $type, Response $response, Database $dbForPlatform) + public function action(string $value, string $type, Response $response, Database $dbForPlatform) { - $document = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', $resourceId)); + if ($type == 'rules') { + $validator = new Domain($value); - if (!$document->isEmpty()) { - throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); + if (!$validator->isValid($value)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription()); + } + + $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$value]), + ])); + + if (!$document->isEmpty()) { + throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); + } + + $response->noContent(); } - $response->noContent(); + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid type'); } } diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index d5a378616c..ab374dcdff 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -11,7 +11,6 @@ use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\System\System; class SitesCustomServerTest extends Scope { @@ -1294,49 +1293,73 @@ class SitesCustomServerTest extends Scope $this->assertNotEmpty($site['body']['$id']); $this->assertEquals('Test Site', $site['body']['name']); - $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - $domain = "test-site.{$sitesDomain}"; - $ruleId1 = \md5($domain); + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('resourceId', [$siteId]) + ] + ]); - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId1, [ + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertNotEmpty($rule['body']['rules'][0]['domain']); + + $domain = $rule['body']['rules'][0]['domain']; + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', + 'value' => $domain, ]); - $this->assertEquals(409, $response['headers']['status-code']); // subdomain unavailable + $this->assertEquals(409, $response['headers']['status-code']); // domain unavailable - $domain = "non-existent-subdomain.{$sitesDomain}"; - $ruleId2 = \md5($domain); + $nonExistingDomain = "non-existent-subdomain.sites.localhost"; - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId2, [ + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', + 'value' => $nonExistingDomain, ]); - $this->assertEquals(204, $response['headers']['status-code']); // subdomain available + $this->assertEquals(204, $response['headers']['status-code']); // domain available $this->cleanupSite($siteId); - sleep(1); + $this->assertEventually(function () use ($siteId) { + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('resourceId', [$siteId]) + ] + ]); - $response = $this->client->call(Client::METHOD_GET, '/console/resources/' . $ruleId1, [ + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertEmpty($rule['body']['rules']); + }, 1000, 500); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-project' => 'console', ], [ 'type' => 'rules', + 'value' => $domain, ]); - $this->assertEquals(204, $response['headers']['status-code']); // subdomain available as site is deleted + $this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted } // TODO: Add tests for deletion of resources when site is deleted