diff --git a/app/config/collections2.php b/app/config/collections2.php index e99233c4a3..bc78efea75 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -510,8 +510,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryPlatforms'], ], [ '$id' => 'webhooks', @@ -521,8 +521,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryWebhooks'], ], [ '$id' => 'keys', @@ -532,8 +532,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryKeys'], ], [ '$id' => 'domains', @@ -543,8 +543,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryDomains'], ], ], 'indexes' => [ @@ -558,6 +558,360 @@ $collections = [ ], ], + 'platforms' => [ + '$collection' => Database::METADATA, + '$id' => 'platforms', + 'name' => 'platforms', + 'attributes' => [ + [ + '$id' => 'projectId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'type', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'name', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'key', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'store', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'hostname', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'dateCreated', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'dateUpdated', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_project', + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'domains' => [ + '$collection' => Database::METADATA, + '$id' => 'domains', + 'name' => 'domains', + 'attributes' => [ + [ + '$id' => 'projectId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'updated', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'domain', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'tld', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'registerable', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'verification', + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'certificateId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_project', + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'keys' => [ + '$collection' => Database::METADATA, + '$id' => 'keys', + 'name' => 'keys', + 'attributes' => [ + [ + '$id' => 'projectId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'name', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'scopes', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => 'secret', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, // var_dump of \bin2hex(\random_bytes(128)) => string(256) + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_project', + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'webhooks' => [ + '$collection' => Database::METADATA, + '$id' => 'webhooks', + 'name' => 'webhooks', + 'attributes' => [ + [ + '$id' => 'projectId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'name', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'url', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'httpUser', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'httpPass', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'security', + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'events', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_project', + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + 'users' => [ '$collection' => Database::METADATA, '$id' => 'users', diff --git a/app/config/services.php b/app/config/services.php index 09ea35f746..17375c360a 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -5,6 +5,7 @@ return [ 'key' => 'homepage', 'name' => 'Homepage', 'subtitle' => '', + 'description' => '', 'controller' => 'web/home.php', 'sdk' => false, 'docs' => false, @@ -16,6 +17,8 @@ return [ 'console' => [ 'key' => 'console', 'name' => 'Console', + 'subtitle' => '', + 'description' => '', 'controller' => 'web/console.php', 'sdk' => false, 'docs' => false, @@ -93,6 +96,7 @@ return [ 'key' => 'projects', 'name' => 'Projects', 'subtitle' => 'The Project service allows you to manage all the projects in your Appwrite server.', + 'description' => '', 'controller' => 'api/projects.php', 'sdk' => true, 'docs' => true, diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 4baf99e084..2acb095a2a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -8,6 +8,7 @@ use Appwrite\Network\Validator\URL; use Appwrite\Utopia\Response; use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; +use Utopia\CLI\CLI; use Utopia\Audit\Audit; use Utopia\Config\Config; use Utopia\Database\Database; @@ -94,12 +95,13 @@ App::post('/v1/projects') 'legalCity' => $legalCity, 'legalAddress' => $legalAddress, 'legalTaxId' => $legalTaxId, - 'services' => new \stdClass(), - 'platforms' => [], - 'webhooks' => [], - 'keys' => [], - 'domains' => [], - 'auths' => $auths, + 'services' => new stdClass(), + 'platforms' => null, + 'providers' => [], + 'webhooks' => null, + 'keys' => null, + 'domains' => null, + 'auths' => $auths ])); $collections = Config::getParam('collections2', []); /** @var array $collections */ @@ -112,7 +114,7 @@ App::post('/v1/projects') $audit = new Audit($dbForInternal); $audit->setup(); - $adapter = new TimeLimit("", 0, 1, $dbForInternal); + $adapter = new TimeLimit('', 0, 1, $dbForInternal); $adapter->setup(); foreach ($collections as $key => $collection) { @@ -379,6 +381,7 @@ App::patch('/v1/projects/:projectId/service') ->action(function ($projectId, $service, $status, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ + /** @var Boolean $status */ $project = $dbForConsole->getDocument('projects', $projectId); @@ -581,6 +584,9 @@ App::post('/v1/projects/:projectId/webhooks') $webhook = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['role:all'], + '$write' => ['role:all'], + 'projectId' => $project->getId(), 'name' => $name, 'events' => $events, 'url' => $url, @@ -589,9 +595,9 @@ App::post('/v1/projects/:projectId/webhooks') 'httpPass' => $httpPass, ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('webhooks', $webhook, Document::SET_TYPE_APPEND) - ); + $webhook = $dbForConsole->createDocument('webhooks', $webhook); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($webhook, Response::MODEL_WEBHOOK); @@ -620,7 +626,9 @@ App::get('/v1/projects/:projectId/webhooks') throw new Exception('Project not found', 404); } - $webhooks = $project->getAttribute('webhooks', []); + $webhooks = $dbForConsole->find('webhooks', [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); $response->dynamic(new Document([ 'webhooks' => $webhooks, @@ -652,9 +660,12 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $project->find('$id', $webhookId, 'webhooks'); + $webhook = $dbForConsole->findOne('webhooks', [ + new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($webhook) || !$webhook instanceof Document) { + if ($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -693,22 +704,27 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $webhook = $project->find('$id', $webhookId, 'webhooks'); + $webhook = $dbForConsole->findOne('webhooks', [ + new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($webhook) || !$webhook instanceof Document) { + if ($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } - $project->findAndReplace('$id', $webhook->getId(), $webhook - ->setAttribute('name', $name) - ->setAttribute('events', $events) - ->setAttribute('url', $url) - ->setAttribute('security', $security) - ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass) - , 'webhooks'); + $webhook + ->setAttribute('name', $name) + ->setAttribute('events', $events) + ->setAttribute('url', $url) + ->setAttribute('security', $security) + ->setAttribute('httpUser', $httpUser) + ->setAttribute('httpPass', $httpPass) + ; - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -736,11 +752,18 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - if (!$project->findAndRemove('$id', $webhookId, 'webhooks')) { + $webhook = $dbForConsole->findOne('webhooks', [ + new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); + + if($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument('webhooks', $webhook->getId()); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -774,14 +797,17 @@ App::post('/v1/projects/:projectId/keys') $key = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['role:all'], + '$write' => ['role:all'], + 'projectId' => $project->getId(), 'name' => $name, 'scopes' => $scopes, 'secret' => \bin2hex(\random_bytes(128)), ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('keys', $key, Document::SET_TYPE_APPEND) - ); + $key = $dbForConsole->createDocument('keys', $key); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($key, Response::MODEL_KEY); @@ -810,7 +836,9 @@ App::get('/v1/projects/:projectId/keys') throw new Exception('Project not found', 404); } - $keys = $project->getAttribute('keys', []); + $keys = $dbForConsole->find('keys', [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), + ], 5000); $response->dynamic(new Document([ 'keys' => $keys, @@ -833,15 +861,21 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function ($projectId, $keyId, $response, $dbForConsole) { + /** @var Appwrite\Utopia\Response $response */ + /** @var Utopia\Database\Database $dbForConsole */ + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception('Project not found', 404); } - $key = $project->find('$id', $keyId, 'keys'); + $key = $dbForConsole->findOne('keys', [ + new Query('_uid', Query::TYPE_EQUAL, [$keyId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($key) || !$key instanceof Document) { + if ($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -874,18 +908,23 @@ App::put('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $project->find('$id', $keyId, 'keys'); + $key = $dbForConsole->findOne('keys', [ + new Query('_uid', Query::TYPE_EQUAL, [$keyId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($key) || !$key instanceof Document) { + if ($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404); } - $project->findAndReplace('$id', $key->getId(), $key - ->setAttribute('name', $name) - ->setAttribute('scopes', $scopes) - , 'keys'); + $key + ->setAttribute('name', $name) + ->setAttribute('scopes', $scopes) + ; - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->updateDocument('keys', $key->getId(), $key); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($key, Response::MODEL_KEY); }); @@ -913,11 +952,18 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - if (!$project->findAndRemove('$id', $keyId, 'keys')) { + $key = $dbForConsole->findOne('keys', [ + new Query('_uid', Query::TYPE_EQUAL, [$keyId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); + + if($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument('keys', $key->getId()); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -954,6 +1000,9 @@ App::post('/v1/projects/:projectId/platforms') $platform = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['role:all'], + '$write' => ['role:all'], + 'projectId' => $project->getId(), 'type' => $type, 'name' => $name, 'key' => $key, @@ -963,9 +1012,9 @@ App::post('/v1/projects/:projectId/platforms') 'dateUpdated' => \time(), ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('platforms', $platform, Document::SET_TYPE_APPEND) - ); + $platform = $dbForConsole->createDocument('platforms', $platform); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($platform, Response::MODEL_PLATFORM); @@ -994,7 +1043,9 @@ App::get('/v1/projects/:projectId/platforms') throw new Exception('Project not found', 404); } - $platforms = $project->getAttribute('platforms', []); + $platforms = $dbForConsole->find('platforms', [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ], 5000); $response->dynamic(new Document([ 'platforms' => $platforms, @@ -1026,9 +1077,12 @@ App::get('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $project->find('$id', $platformId, 'platforms'); + $platform = $dbForConsole->findOne('platforms', [ + new Query('_uid', Query::TYPE_EQUAL, [$platformId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($platform) || !$platform instanceof Document) { + if ($platform === false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1063,9 +1117,12 @@ App::put('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $project->find('$id', $platformId, 'platforms'); + $platform = $dbForConsole->findOne('platforms', [ + new Query('_uid', Query::TYPE_EQUAL, [$platformId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($platform) || !$platform instanceof Document) { + if ($platform === false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1077,15 +1134,9 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->setAttribute('hostname', $hostname) ; - $project->findAndReplace('$id', $platform->getId(), $platform - ->setAttribute('name', $name) - ->setAttribute('dateUpdated', \time()) - ->setAttribute('key', $key) - ->setAttribute('store', $store) - ->setAttribute('hostname', $hostname) - , 'platforms'); + $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($platform, Response::MODEL_PLATFORM); }); @@ -1113,11 +1164,18 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - if (!$project->findAndRemove('$id', $platformId, 'platforms')) { + $platform = $dbForConsole->findOne('platforms', [ + new Query('_uid', Query::TYPE_EQUAL, [$platformId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); + + if ($platform === false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument('platforms', $platformId); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1148,9 +1206,12 @@ App::post('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $document = $project->find('domain', $domain, 'domains'); + $document = $dbForConsole->findOne('domains', [ + new Query('domain', Query::TYPE_EQUAL, [$domain]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), + ]); - if ($document) { + if ($document && !$document->isEmpty()) { throw new Exception('Domain already exists', 409); } @@ -1164,6 +1225,9 @@ App::post('/v1/projects/:projectId/domains') $domain = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['role:all'], + '$write' => ['role:all'], + 'projectId' => $project->getId(), 'updated' => \time(), 'domain' => $domain->get(), 'tld' => $domain->getSuffix(), @@ -1172,9 +1236,9 @@ App::post('/v1/projects/:projectId/domains') 'certificateId' => null, ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('domains', $domain, Document::SET_TYPE_APPEND) - ); + $domain = $dbForConsole->createDocument('domains', $domain); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($domain, Response::MODEL_DOMAIN); @@ -1203,7 +1267,9 @@ App::get('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $domains = $project->getAttribute('domains', []); + $domains = $dbForConsole->find('domains', [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ], 5000); $response->dynamic(new Document([ 'domains' => $domains, @@ -1235,9 +1301,12 @@ App::get('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $project->find('$id', $domainId, 'domains'); + $domain = $dbForConsole->findOne('domains', [ + new Query('_uid', Query::TYPE_EQUAL, [$domainId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($domain) || !$domain instanceof Document) { + if ($domain === false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1268,9 +1337,12 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Project not found', 404); } - $domain = $project->find('$id', $domainId, 'domains'); + $domain = $dbForConsole->findOne('domains', [ + new Query('_uid', Query::TYPE_EQUAL, [$domainId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (empty($domain) || !$domain instanceof Document) { + if ($domain === false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1290,11 +1362,9 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Failed to verify domain', 401); } - $project->findAndReplace('$id', $domain->getId(), $domain - ->setAttribute('verification', true) - , 'domains'); - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->updateDocument('domains', $domain->getId(), $domain->setAttribute('verification', true)); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); // Issue a TLS certificate when domain is verified Resque::enqueue('v1-certificates', 'CertificatesV1', [ @@ -1329,13 +1399,18 @@ App::delete('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $project->find('$id', $domainId, 'domains'); + $domain = $dbForConsole->findOne('domains', [ + new Query('_uid', Query::TYPE_EQUAL, [$domainId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if (!$project->findAndRemove('$id', $domainId, 'domains')) { + if ($domain === false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument('domains', $domain->getId()); + + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $deletes ->setParam('type', DELETE_TYPE_CERTIFICATES) diff --git a/app/init.php b/app/init.php index bcd2232cc1..8f6998bd71 100644 --- a/app/init.php +++ b/app/init.php @@ -31,6 +31,7 @@ use Appwrite\Network\Validator\URL; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Stats\Stats; use Utopia\App; +use Utopia\CLI\Console; use Utopia\View; use Utopia\Config\Config; use Utopia\Locale\Locale; @@ -240,6 +241,54 @@ Database::addFilter('subQueryIndexes', return $database ->find('indexes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) + ], 64, 0, []); + } +); + +Database::addFilter('subQueryPlatforms', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return $database + ->find('platforms', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], $database->getIndexLimit(), 0, []); + } +); + +Database::addFilter('subQueryDomains', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return $database + ->find('domains', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], $database->getIndexLimit(), 0, []); + } +); + +Database::addFilter('subQueryKeys', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return $database + ->find('keys', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], $database->getIndexLimit(), 0, []); + } +); + +Database::addFilter('subQueryWebhooks', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return $database + ->find('webhooks', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], $database->getIndexLimit(), 0, []); } ); diff --git a/src/Appwrite/Database/Database.php b/src/Appwrite/Database/Database.php index e6cfa001d1..37978ab65f 100644 --- a/src/Appwrite/Database/Database.php +++ b/src/Appwrite/Database/Database.php @@ -577,7 +577,7 @@ class Database { if (!isset(self::$filters[$name])) { return $value; - throw new Exception('Filter not found'); + throw new Exception("Filter '{$name}' not found"); } try { @@ -599,7 +599,7 @@ class Database { if (!isset(self::$filters[$name])) { return $value; - throw new Exception('Filter not found'); + throw new Exception("Filter '{$name}' not found"); } try { diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 1842891492..6bde76dc11 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1422,6 +1422,17 @@ class ProjectsConsoleClientTest extends Scope /** * Test for FAILURE */ + $response = $this->client->call(Client::METHOD_PUT, '/projects/'.$id.'/platforms/error', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Flutter App (Android) 2', + 'key' => 'com.example.android2', + 'store' => '', + 'hostname' => '', + ]); + + $this->assertEquals(404, $response['headers']['status-code']); return $data; }