From 82085df58a839a47b910a1f511196492aeccf558 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Mon, 30 Aug 2021 09:33:45 +0200 Subject: [PATCH 01/13] Migrated project platforms to it's own collection --- app/config/collections2.php | 107 ++++++++++++++++++++++++++++++- app/controllers/api/projects.php | 36 ++++++----- app/init.php | 12 ++++ 3 files changed, 138 insertions(+), 17 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index 8079bdd7c8..1e4e4fb306 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -511,7 +511,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => true, - 'filters' => ['json'], + 'filters' => ['subQueryProjectPlatforms'], ], [ '$id' => 'webhooks', @@ -558,6 +558,111 @@ $collections = [ ], ], + 'projectsPlatforms' => [ + '$collection' => Database::METADATA, + '$id' => 'projectsPlatforms', + 'name' => 'projectsPlatforms', + '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], + ], + ], + ], + 'users' => [ '$collection' => Database::METADATA, '$id' => 'users', diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index b83dff6d9e..2dc5ce9ac8 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1047,8 +1047,13 @@ App::post('/v1/projects/:projectId/platforms') throw new Exception('Project not found', 404); } + $teamId = $project->getAttribute("teamId"); + $platform = new Document([ + 'projectId' => $project->getId(), '$id' => $dbForConsole->getId(), + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], 'type' => $type, 'name' => $name, 'key' => $key, @@ -1058,9 +1063,8 @@ App::post('/v1/projects/:projectId/platforms') 'dateUpdated' => \time(), ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('platforms', $platform, Document::SET_TYPE_APPEND) - ); + $dbForConsole->createDocument("projectsPlatforms", $platform); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($platform, Response::MODEL_PLATFORM); @@ -1083,13 +1087,17 @@ App::get('/v1/projects/:projectId/platforms') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ + // TODO: Implement pagination + $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception('Project not found', 404); } - $platforms = $project->getAttribute('platforms', []); + $platforms = $dbForConsole->find('projectsPlatforms', [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); $response->dynamic(new Document([ 'platforms' => $platforms, @@ -1121,7 +1129,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $project->find('$id', $platformId, 'platforms'); + $platform = $dbForConsole->getDocument("projectsPlatforms", $platformId); if (empty($platform) || !$platform instanceof Document) { throw new Exception('Platform not found', 404); @@ -1158,7 +1166,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $project->find('$id', $platformId, 'platforms'); + $platform = $dbForConsole->getDocument("projectsPlatforms", $platformId); if (empty($platform) || !$platform instanceof Document) { throw new Exception('Platform not found', 404); @@ -1172,15 +1180,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('projectsPlatforms', $platform->getId(), $platform); - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->dynamic($platform, Response::MODEL_PLATFORM); }); @@ -1208,11 +1210,13 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - if (!$project->findAndRemove('$id', $platformId, 'platforms')) { + $deleteRecord = $dbForConsole->deleteDocument("projectsPlatforms", $platformId); + + if($deleteRecord == false) { throw new Exception('Platform not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->noContent(); }); diff --git a/app/init.php b/app/init.php index 57f2dc7130..4da737ebbe 100644 --- a/app/init.php +++ b/app/init.php @@ -200,6 +200,18 @@ Database::addFilter('subQueryIndexes', } ); +Database::addFilter('subQueryProjectPlatforms', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return $database + ->find('projectsPlatforms', [ + new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, []); + } +); + Database::addFilter('encrypt', function($value) { $key = App::getEnv('_APP_OPENSSL_KEY_V1'); From 8009adc11d478f83507203c9f94212cf9805fd67 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Mon, 30 Aug 2021 16:24:50 +0200 Subject: [PATCH 02/13] Migrated project services, providers, domains, webhooks and keys to it's own collection --- app/config/collections2.php | 378 ++++++++++++++++++++++++++++++- app/config/services.php | 4 + app/controllers/api/projects.php | 244 ++++++++++++++------ app/init.php | 86 ++++++- 4 files changed, 629 insertions(+), 83 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index 1e4e4fb306..a29a9728c8 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -478,7 +478,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['json'], + 'filters' => ['subQueryProjectServices'], ], [ '$id' => 'auths', @@ -500,7 +500,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['json'], + 'filters' => ['subQueryProjectProviders'], ], [ '$id' => 'platforms', @@ -510,7 +510,7 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, + 'array' => false, 'filters' => ['subQueryProjectPlatforms'], ], [ @@ -521,8 +521,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryProjectWebhooks'], ], [ '$id' => 'keys', @@ -532,8 +532,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryProjectKeys'], ], [ '$id' => 'domains', @@ -543,8 +543,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => null, - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryProjectDomains'], ], ], 'indexes' => [ @@ -663,6 +663,366 @@ $collections = [ ], ], + 'projectsServices' => [ + '$collection' => Database::METADATA, + '$id' => 'projectsServices', + 'name' => 'projectsServices', + 'attributes' => [ + [ + '$id' => 'projectId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'key', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'status', + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + '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], + ], + ], + ], + + 'projectProviders' => [ + '$collection' => Database::METADATA, + '$id' => 'projectProviders', + 'name' => 'projectProviders', + 'attributes' => [ + [ + '$id' => 'projectId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'key', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'appId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'appSecret', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + '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], + ], + ], + ], + + 'projectDomains' => [ + '$collection' => Database::METADATA, + '$id' => 'projectDomains', + 'name' => 'projectDomains', + '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], + ], + ], + ], + + 'projectKeys' => [ + '$collection' => Database::METADATA, + '$id' => 'projectKeys', + 'name' => 'projectKeys', + '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], + ], + ], + ], + + 'projectWebhooks' => [ + '$collection' => Database::METADATA, + '$id' => 'projectWebhooks', + 'name' => 'projectWebhooks', + '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 2dc5ce9ac8..15dee15f8d 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -7,6 +7,7 @@ use Appwrite\Network\Validator\Domain as DomainValidator; use Appwrite\Network\Validator\URL; use Appwrite\Utopia\Response; use Utopia\App; +use Utopia\CLI\CLI; use Utopia\Config\Config; use Utopia\Database\Document; use Utopia\Database\Query; @@ -92,14 +93,17 @@ App::post('/v1/projects') 'legalCity' => $legalCity, 'legalAddress' => $legalAddress, 'legalTaxId' => $legalTaxId, - 'services' => new stdClass(), - 'platforms' => [], - 'webhooks' => [], - 'keys' => [], - 'domains' => [], - 'auths' => $auths, + 'services' => null, + 'platforms' => null, + 'providers' => null, + 'webhooks' => null, + 'keys' => null, + 'domains' => null, + 'auths' => null ])); + // TODO: Implement write of auths from $auths + $collections = Config::getParam('collections2', []); /** @var array $collections */ $dbForInternal->setNamespace('project_' . $project->getId() . '_internal'); @@ -468,12 +472,13 @@ App::patch('/v1/projects/:projectId/service') ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), function($element) {return $element['optional'];})), true), 'Service name.') - ->param('status', null, new Boolean(), 'Service status.') + ->param('status', true, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') - ->action(function ($projectId, $service, $status, $response, $dbForConsole) { + ->action(function ($projectId, $serviceKey, $status, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ + /** @var Boolean $status */ $project = $dbForConsole->getDocument('projects', $projectId); @@ -481,11 +486,37 @@ App::patch('/v1/projects/:projectId/service') throw new Exception('Project not found', 404); } - $services = $project->getAttribute('services', []); - $services[$service] = $status; + $service = $dbForConsole->findOne("projectsServices", [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), + new Query('key', Query::TYPE_EQUAL, [$serviceKey]), + ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); + // TODO: Implement delete method. Do we delete for "true" or for "false"? Same for auth!!!! + if($service == false || $service->isEmpty()) { + $teamId = $project->getAttribute("teamId"); + $service = new Document([ + '$id' => $dbForConsole->getId(), + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + 'projectId' => $project->getId(), + 'key' => $serviceKey, + 'status' => $status, + ]); + + $dbForConsole->createDocument("projectsServices", $service); + + $dbForConsole->purgeDocument('projects', $project->getId()); + } else { + if($service->getAttribute("status") != $status) { + $service->setAttribute("status", $status); + $dbForConsole->updateDocument("projectsServices", $service->getId(), $service); + + $dbForConsole->purgeDocument('projects', $project->getId()); + } + } + + $project = $dbForConsole->getDocument('projects', $projectId); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -505,7 +536,7 @@ App::patch('/v1/projects/:projectId/oauth2') ->param('secret', '', new text(512), 'Provider secret key. Max length: 512 chars.', true) ->inject('response') ->inject('dbForConsole') - ->action(function ($projectId, $provider, $appId, $secret, $response, $dbForConsole) { + ->action(function ($projectId, $providerKey, $appId, $secret, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ @@ -515,12 +546,41 @@ App::patch('/v1/projects/:projectId/oauth2') throw new Exception('Project not found', 404); } - $providers = $project->getAttribute('providers', []); - $providers[$provider . 'Appid'] = $appId; - $providers[$provider . 'Secret'] = $secret; + $provider = $dbForConsole->findOne("projectProviders", [ + new Query('key', Query::TYPE_EQUAL, [$providerKey]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), + ]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('providers', $providers)); + if($provider && !$provider->isEmpty()) { + // Provider exists + $provider->setAttribute("appId", $appId) + ->setAttribute("appSecret", $secret); + + $dbForConsole->updateDocument("projectProviders", $provider->getId(), $provider); + + $dbForConsole->purgeDocument("projects", $project->getId()); + } else { + // Provider does not exist yet + + $teamId = $project->getAttribute("teamId"); + + $provider = new Document([ + '$id' => $dbForConsole->getId(), + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + 'projectId' => $project->getId(), + 'key' => $providerKey, + 'appId' => $appId, + 'appSecret' => $secret + ]); + + $dbForConsole->createDocument("projectProviders", $provider); + + $dbForConsole->purgeDocument("projects", $project->getId()); + } + + $project = $dbForConsole->getDocument('projects', $projectId); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -674,8 +734,13 @@ App::post('/v1/projects/:projectId/webhooks') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); + $teamId = $project->getAttribute("teamId"); + $webhook = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + 'projectId' => $project->getId(), 'name' => $name, 'events' => $events, 'url' => $url, @@ -684,9 +749,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("projectWebhooks", $webhook); + + $dbForConsole->purgeDocument("projects", $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($webhook, Response::MODEL_WEBHOOK); @@ -715,7 +780,9 @@ App::get('/v1/projects/:projectId/webhooks') throw new Exception('Project not found', 404); } - $webhooks = $project->getAttribute('webhooks', []); + $webhooks = $dbForConsole->find("projectWebhooks", [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); $response->dynamic(new Document([ 'webhooks' => $webhooks, @@ -747,9 +814,9 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $project->find('$id', $webhookId, 'webhooks'); + $webhook = $dbForConsole->getDocument('projectWebhooks', $webhookId); - if (empty($webhook) || !$webhook instanceof Document) { + if ($webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -788,22 +855,23 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $webhook = $project->find('$id', $webhookId, 'webhooks'); + $webhook = $dbForConsole->getDocument('projectWebhooks', $webhookId); - if (empty($webhook) || !$webhook instanceof Document) { + if ($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("projectWebhooks", $webhook->getId(), $webhook); + + $dbForConsole->purgeDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -831,11 +899,15 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - if (!$project->findAndRemove('$id', $webhookId, 'webhooks')) { + $webhook = $dbForConsole->getDocument("projectWebhooks", $webhookId); + + if($webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument("projectWebhooks", $webhook->getId()); + + $dbForConsole->purgeDocument('projects', $project->getId()); $response->noContent(); }); @@ -867,18 +939,24 @@ App::post('/v1/projects/:projectId/keys') throw new Exception('Project not found', 404); } + $teamId = $project->getAttribute("teamId"); + $key = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '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("projectKeys", $key); + + $dbForConsole->purgeDocument("projects", $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); + var_dump(Response::STATUS_CODE_CREATED); $response->dynamic($key, Response::MODEL_KEY); }); @@ -905,7 +983,10 @@ App::get('/v1/projects/:projectId/keys') throw new Exception('Project not found', 404); } - $keys = $project->getAttribute('keys', []); + // TODO: Implement pagination + $keys = $dbForConsole->find("projectKeys", [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), + ]); $response->dynamic(new Document([ 'keys' => $keys, @@ -928,15 +1009,18 @@ 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->getDocument("projectKeys", $keyId); - if (empty($key) || !$key instanceof Document) { + if ($key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -969,18 +1053,18 @@ App::put('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $project->find('$id', $keyId, 'keys'); + $key = $dbForConsole->getDocument("projectKeys", $keyId); - if (empty($key) || !$key instanceof Document) { + if ($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("projectKeys", $key->getId(), $key); + + $dbForConsole->purgeDocument('projects', $project->getId()); $response->dynamic($key, Response::MODEL_KEY); }); @@ -1008,11 +1092,15 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - if (!$project->findAndRemove('$id', $keyId, 'keys')) { + $key = $dbForConsole->getDocument("projectKeys", $keyId); + + if($key->isEmpty()) { throw new Exception('Key not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument("projectKeys", $key->getId()); + + $dbForConsole->purgeDocument('projects', $project->getId()); $response->noContent(); }); @@ -1050,10 +1138,10 @@ App::post('/v1/projects/:projectId/platforms') $teamId = $project->getAttribute("teamId"); $platform = new Document([ - 'projectId' => $project->getId(), '$id' => $dbForConsole->getId(), '$read' => ['team:' . $teamId], '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + 'projectId' => $project->getId(), 'type' => $type, 'name' => $name, 'key' => $key, @@ -1063,7 +1151,8 @@ App::post('/v1/projects/:projectId/platforms') 'dateUpdated' => \time(), ]); - $dbForConsole->createDocument("projectsPlatforms", $platform); + $platform = $dbForConsole->createDocument("projectsPlatforms", $platform); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); @@ -1087,14 +1176,13 @@ App::get('/v1/projects/:projectId/platforms') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ - // TODO: Implement pagination - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception('Project not found', 404); } + // TODO: Implement pagination $platforms = $dbForConsole->find('projectsPlatforms', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1131,7 +1219,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForConsole->getDocument("projectsPlatforms", $platformId); - if (empty($platform) || !$platform instanceof Document) { + if ($platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1168,7 +1256,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForConsole->getDocument("projectsPlatforms", $platformId); - if (empty($platform) || !$platform instanceof Document) { + if ($platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1247,9 +1335,12 @@ App::post('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $document = $project->find('domain', $domain, 'domains'); + $document = $dbForConsole->findOne("projectDomains", [ + 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); } @@ -1259,10 +1350,15 @@ App::post('/v1/projects/:projectId/domains') throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.', 500); } + $teamId = $project->getAttribute("teamId"); + $domain = new Domain($domain); $domain = new Document([ '$id' => $dbForConsole->getId(), + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + 'projectId' => $project->getId(), 'updated' => \time(), 'domain' => $domain->get(), 'tld' => $domain->getSuffix(), @@ -1271,9 +1367,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("projectDomains", $domain); + + $dbForConsole->purgeDocument("projects", $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($domain, Response::MODEL_DOMAIN); @@ -1302,7 +1398,8 @@ App::get('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $domains = $project->getAttribute('domains', []); + // TODO: Implement pagination + $domains = $dbForConsole->find("projectDomains", []); $response->dynamic(new Document([ 'domains' => $domains, @@ -1334,9 +1431,9 @@ App::get('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $project->find('$id', $domainId, 'domains'); + $domain = $dbForConsole->getDocument("projectDomains", $domainId); - if (empty($domain) || !$domain instanceof Document) { + if ($domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1367,9 +1464,9 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Project not found', 404); } - $domain = $project->find('$id', $domainId, 'domains'); + $domain = $dbForConsole->getDocument("projectDomains", $domainId); - if (empty($domain) || !$domain instanceof Document) { + if ($domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1389,11 +1486,10 @@ 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'); + $domain->setAttribute("verification", true); - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->updateDocument("projectDomains", $domain->getId(), $domain); + $dbForConsole->purgeDocument("projects", $project->getId()); // Issue a TLS certificate when domain is verified Resque::enqueue('v1-certificates', 'CertificatesV1', [ @@ -1428,13 +1524,15 @@ App::delete('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $project->find('$id', $domainId, 'domains'); + $domain = $dbForConsole->getDocument("projectDomains", $domainId); - if (!$project->findAndRemove('$id', $domainId, 'domains')) { + if ($domain->isEmpty()) { throw new Exception('Domain not found', 404); } - $dbForConsole->updateDocument('projects', $project->getId(), $project); + $dbForConsole->deleteDocument("projectDomains", $domain->getId()); + + $dbForConsole->purgeDocument("projects", $project->getId()); $deletes ->setParam('type', DELETE_TYPE_CERTIFICATES) diff --git a/app/init.php b/app/init.php index 4da737ebbe..704788b25e 100644 --- a/app/init.php +++ b/app/init.php @@ -30,6 +30,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; @@ -181,6 +182,7 @@ Database::addFilter('subQueryAttributes', return null; }, function($value, Document $document, Database $database) { + // TODO: Maybe implement pagination? return $database ->find('attributes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) @@ -193,6 +195,7 @@ Database::addFilter('subQueryIndexes', return null; }, function($value, Document $document, Database $database) { + // TODO: Maybe implement pagination? return $database ->find('indexes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) @@ -205,13 +208,94 @@ Database::addFilter('subQueryProjectPlatforms', return null; }, function($value, Document $document, Database $database) { + // TODO: Implement pagination return $database ->find('projectsPlatforms', [ - new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 100, 0, []); } ); +Database::addFilter('subQueryProjectDomains', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + // TODO: Implement pagination + return $database + ->find('projectDomains', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, []); + } +); + +Database::addFilter('subQueryProjectKeys', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + // TODO: Implement pagination + return $database + ->find('projectKeys', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, []); + } +); + +Database::addFilter('subQueryProjectWebhooks', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + // TODO: Implement pagination + return $database + ->find('projectWebhooks', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, []); + } +); + +Database::addFilter('subQueryProjectServices', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + // TODO: Implement pagination + $services = $database + ->find('projectsServices', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, []); + + $responseJson = []; + foreach($services as $service) { + $responseJson[$service->getAttribute("key")] = $service->getAttribute("status", true); + } + + return $responseJson; + } +); + +Database::addFilter('subQueryProjectProviders', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + // TODO: Implement pagination + $providers = $database + ->find('projectProviders', [ + new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, []); + + $responseJson = []; + foreach($providers as $provider) { + $responseJson[$provider->getAttribute("key") . 'Appid'] = $provider->getAttribute("appId"); + $responseJson[$provider->getAttribute("key") . 'Secret'] = $provider->getAttribute("appSecret"); + } + + return $responseJson; + } +); + Database::addFilter('encrypt', function($value) { $key = App::getEnv('_APP_OPENSSL_KEY_V1'); From abfe47787bb2d317884a293963ad641bbda3a9f0 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Mon, 30 Aug 2021 17:16:42 +0200 Subject: [PATCH 03/13] Added TODO --- app/controllers/api/projects.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 15dee15f8d..845dc69b0f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -23,6 +23,8 @@ use Utopia\Validator\WhiteList; use Utopia\Audit\Audit; use Utopia\Abuse\Adapters\TimeLimit; +// TODO: Meldiron is lazy person from JS who uses "" instead of ''. Yell at him if this comment is still here. We dont want "" in PHP + App::init(function ($project) { /** @var Utopia\Database\Document $project */ From 577ab9c3ad27bed118f5ce4b90b48f03472d3119 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Wed, 1 Sep 2021 09:03:22 +0200 Subject: [PATCH 04/13] Fixed permissions, improved database filter docs, added 404 platform update test --- app/controllers/api/projects.php | 37 ++++++------------- app/init.php | 2 + .../Projects/ProjectsConsoleClientTest.php | 12 ++++++ 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 845dc69b0f..8b6a59df46 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -495,12 +495,10 @@ App::patch('/v1/projects/:projectId/service') // TODO: Implement delete method. Do we delete for "true" or for "false"? Same for auth!!!! if($service == false || $service->isEmpty()) { - $teamId = $project->getAttribute("teamId"); - $service = new Document([ '$id' => $dbForConsole->getId(), - '$read' => ['team:' . $teamId], - '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '$read' => ['role:all'], + '$write' => ['role:all'], 'projectId' => $project->getId(), 'key' => $serviceKey, 'status' => $status, @@ -565,12 +563,10 @@ App::patch('/v1/projects/:projectId/oauth2') } else { // Provider does not exist yet - $teamId = $project->getAttribute("teamId"); - $provider = new Document([ '$id' => $dbForConsole->getId(), - '$read' => ['team:' . $teamId], - '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '$read' => ['role:all'], + '$write' => ['role:all'], 'projectId' => $project->getId(), 'key' => $providerKey, 'appId' => $appId, @@ -736,12 +732,10 @@ App::post('/v1/projects/:projectId/webhooks') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $teamId = $project->getAttribute("teamId"); - $webhook = new Document([ '$id' => $dbForConsole->getId(), - '$read' => ['team:' . $teamId], - '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '$read' => ['role:all'], + '$write' => ['role:all'], 'projectId' => $project->getId(), 'name' => $name, 'events' => $events, @@ -941,12 +935,10 @@ App::post('/v1/projects/:projectId/keys') throw new Exception('Project not found', 404); } - $teamId = $project->getAttribute("teamId"); - $key = new Document([ '$id' => $dbForConsole->getId(), - '$read' => ['team:' . $teamId], - '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '$read' => ['role:all'], + '$write' => ['role:all'], 'projectId' => $project->getId(), 'name' => $name, 'scopes' => $scopes, @@ -958,7 +950,6 @@ App::post('/v1/projects/:projectId/keys') $dbForConsole->purgeDocument("projects", $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); - var_dump(Response::STATUS_CODE_CREATED); $response->dynamic($key, Response::MODEL_KEY); }); @@ -1137,12 +1128,10 @@ App::post('/v1/projects/:projectId/platforms') throw new Exception('Project not found', 404); } - $teamId = $project->getAttribute("teamId"); - $platform = new Document([ '$id' => $dbForConsole->getId(), - '$read' => ['team:' . $teamId], - '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '$read' => ['role:all'], + '$write' => ['role:all'], 'projectId' => $project->getId(), 'type' => $type, 'name' => $name, @@ -1352,14 +1341,12 @@ App::post('/v1/projects/:projectId/domains') throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.', 500); } - $teamId = $project->getAttribute("teamId"); - $domain = new Domain($domain); $domain = new Document([ '$id' => $dbForConsole->getId(), - '$read' => ['team:' . $teamId], - '$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'], + '$read' => ['role:all'], + '$write' => ['role:all'], 'projectId' => $project->getId(), 'updated' => \time(), 'domain' => $domain->get(), diff --git a/app/init.php b/app/init.php index 704788b25e..7c44ba12e6 100644 --- a/app/init.php +++ b/app/init.php @@ -142,6 +142,8 @@ if(!empty($user) || !empty($pass)) { /** * DB Filters + * + * Make sure the value of an attribute that uses sub-query filters is set to 'null' otherwise the filters might not work properly */ DatabaseOld::addFilter('json', function($value) { diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 4d83efb416..f090158cd0 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -7,6 +7,7 @@ use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; use Tests\E2E\Services\Projects\ProjectsBase; use Tests\E2E\Client; +use function array_merge; class ProjectsConsoleClientTest extends Scope { @@ -1430,6 +1431,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; } From 182630ed203e2174e2138bcdc3b397fff7799114 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Wed, 1 Sep 2021 09:52:43 +0200 Subject: [PATCH 05/13] Rollbacked auth attribute, set subquery limits to 5000, Replaced " with ' --- app/controllers/api/projects.php | 100 ++++++++++++++----------------- app/init.php | 30 ++++------ 2 files changed, 57 insertions(+), 73 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 8b6a59df46..cdc43d7b1a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -23,8 +23,6 @@ use Utopia\Validator\WhiteList; use Utopia\Audit\Audit; use Utopia\Abuse\Adapters\TimeLimit; -// TODO: Meldiron is lazy person from JS who uses "" instead of ''. Yell at him if this comment is still here. We dont want "" in PHP - App::init(function ($project) { /** @var Utopia\Database\Document $project */ @@ -101,11 +99,9 @@ App::post('/v1/projects') 'webhooks' => null, 'keys' => null, 'domains' => null, - 'auths' => null + 'auths' => $auths ])); - // TODO: Implement write of auths from $auths - $collections = Config::getParam('collections2', []); /** @var array $collections */ $dbForInternal->setNamespace('project_' . $project->getId() . '_internal'); @@ -116,7 +112,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) { @@ -488,12 +484,11 @@ App::patch('/v1/projects/:projectId/service') throw new Exception('Project not found', 404); } - $service = $dbForConsole->findOne("projectsServices", [ + $service = $dbForConsole->findOne('projectsServices', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), new Query('key', Query::TYPE_EQUAL, [$serviceKey]), ]); - // TODO: Implement delete method. Do we delete for "true" or for "false"? Same for auth!!!! if($service == false || $service->isEmpty()) { $service = new Document([ '$id' => $dbForConsole->getId(), @@ -504,13 +499,13 @@ App::patch('/v1/projects/:projectId/service') 'status' => $status, ]); - $dbForConsole->createDocument("projectsServices", $service); + $dbForConsole->createDocument('projectsServices', $service); $dbForConsole->purgeDocument('projects', $project->getId()); } else { - if($service->getAttribute("status") != $status) { - $service->setAttribute("status", $status); - $dbForConsole->updateDocument("projectsServices", $service->getId(), $service); + if($service->getAttribute('status') != $status) { + $service->setAttribute('status', $status); + $dbForConsole->updateDocument('projectsServices', $service->getId(), $service); $dbForConsole->purgeDocument('projects', $project->getId()); } @@ -546,7 +541,7 @@ App::patch('/v1/projects/:projectId/oauth2') throw new Exception('Project not found', 404); } - $provider = $dbForConsole->findOne("projectProviders", [ + $provider = $dbForConsole->findOne('projectProviders', [ new Query('key', Query::TYPE_EQUAL, [$providerKey]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), ]); @@ -554,12 +549,12 @@ App::patch('/v1/projects/:projectId/oauth2') if($provider && !$provider->isEmpty()) { // Provider exists - $provider->setAttribute("appId", $appId) - ->setAttribute("appSecret", $secret); + $provider->setAttribute('appId', $appId) + ->setAttribute('appSecret', $secret); - $dbForConsole->updateDocument("projectProviders", $provider->getId(), $provider); + $dbForConsole->updateDocument('projectProviders', $provider->getId(), $provider); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->purgeDocument('projects', $project->getId()); } else { // Provider does not exist yet @@ -573,9 +568,9 @@ App::patch('/v1/projects/:projectId/oauth2') 'appSecret' => $secret ]); - $dbForConsole->createDocument("projectProviders", $provider); + $dbForConsole->createDocument('projectProviders', $provider); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->purgeDocument('projects', $project->getId()); } $project = $dbForConsole->getDocument('projects', $projectId); @@ -745,9 +740,9 @@ App::post('/v1/projects/:projectId/webhooks') 'httpPass' => $httpPass, ]); - $webhook = $dbForConsole->createDocument("projectWebhooks", $webhook); + $webhook = $dbForConsole->createDocument('projectWebhooks', $webhook); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($webhook, Response::MODEL_WEBHOOK); @@ -776,7 +771,7 @@ App::get('/v1/projects/:projectId/webhooks') throw new Exception('Project not found', 404); } - $webhooks = $dbForConsole->find("projectWebhooks", [ + $webhooks = $dbForConsole->find('projectWebhooks', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -865,7 +860,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('httpUser', $httpUser) ->setAttribute('httpPass', $httpPass); - $dbForConsole->updateDocument("projectWebhooks", $webhook->getId(), $webhook); + $dbForConsole->updateDocument('projectWebhooks', $webhook->getId(), $webhook); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -895,13 +890,13 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $dbForConsole->getDocument("projectWebhooks", $webhookId); + $webhook = $dbForConsole->getDocument('projectWebhooks', $webhookId); if($webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } - $dbForConsole->deleteDocument("projectWebhooks", $webhook->getId()); + $dbForConsole->deleteDocument('projectWebhooks', $webhook->getId()); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -945,9 +940,9 @@ App::post('/v1/projects/:projectId/keys') 'secret' => \bin2hex(\random_bytes(128)), ]); - $key = $dbForConsole->createDocument("projectKeys", $key); + $key = $dbForConsole->createDocument('projectKeys', $key); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($key, Response::MODEL_KEY); @@ -976,10 +971,9 @@ App::get('/v1/projects/:projectId/keys') throw new Exception('Project not found', 404); } - // TODO: Implement pagination - $keys = $dbForConsole->find("projectKeys", [ + $keys = $dbForConsole->find('projectKeys', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), - ]); + ], 5000); $response->dynamic(new Document([ 'keys' => $keys, @@ -1011,7 +1005,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->getDocument("projectKeys", $keyId); + $key = $dbForConsole->getDocument('projectKeys', $keyId); if ($key->isEmpty()) { throw new Exception('Key not found', 404); @@ -1046,7 +1040,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->getDocument("projectKeys", $keyId); + $key = $dbForConsole->getDocument('projectKeys', $keyId); if ($key->isEmpty()) { throw new Exception('Key not found', 404); @@ -1055,7 +1049,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key->setAttribute('name', $name) ->setAttribute('scopes', $scopes); - $dbForConsole->updateDocument("projectKeys", $key->getId(), $key); + $dbForConsole->updateDocument('projectKeys', $key->getId(), $key); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1085,13 +1079,13 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->getDocument("projectKeys", $keyId); + $key = $dbForConsole->getDocument('projectKeys', $keyId); if($key->isEmpty()) { throw new Exception('Key not found', 404); } - $dbForConsole->deleteDocument("projectKeys", $key->getId()); + $dbForConsole->deleteDocument('projectKeys', $key->getId()); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1142,7 +1136,7 @@ App::post('/v1/projects/:projectId/platforms') 'dateUpdated' => \time(), ]); - $platform = $dbForConsole->createDocument("projectsPlatforms", $platform); + $platform = $dbForConsole->createDocument('projectsPlatforms', $platform); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1173,10 +1167,9 @@ App::get('/v1/projects/:projectId/platforms') throw new Exception('Project not found', 404); } - // TODO: Implement pagination $platforms = $dbForConsole->find('projectsPlatforms', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) - ]); + ], 5000); $response->dynamic(new Document([ 'platforms' => $platforms, @@ -1208,7 +1201,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->getDocument("projectsPlatforms", $platformId); + $platform = $dbForConsole->getDocument('projectsPlatforms', $platformId); if ($platform->isEmpty()) { throw new Exception('Platform not found', 404); @@ -1245,7 +1238,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->getDocument("projectsPlatforms", $platformId); + $platform = $dbForConsole->getDocument('projectsPlatforms', $platformId); if ($platform->isEmpty()) { throw new Exception('Platform not found', 404); @@ -1289,7 +1282,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $deleteRecord = $dbForConsole->deleteDocument("projectsPlatforms", $platformId); + $deleteRecord = $dbForConsole->deleteDocument('projectsPlatforms', $platformId); if($deleteRecord == false) { throw new Exception('Platform not found', 404); @@ -1326,7 +1319,7 @@ App::post('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $document = $dbForConsole->findOne("projectDomains", [ + $document = $dbForConsole->findOne('projectDomains', [ new Query('domain', Query::TYPE_EQUAL, [$domain]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), ]); @@ -1356,9 +1349,9 @@ App::post('/v1/projects/:projectId/domains') 'certificateId' => null, ]); - $domain = $dbForConsole->createDocument("projectDomains", $domain); + $domain = $dbForConsole->createDocument('projectDomains', $domain); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($domain, Response::MODEL_DOMAIN); @@ -1387,8 +1380,7 @@ App::get('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - // TODO: Implement pagination - $domains = $dbForConsole->find("projectDomains", []); + $domains = $dbForConsole->find('projectDomains', [], 5000); $response->dynamic(new Document([ 'domains' => $domains, @@ -1420,7 +1412,7 @@ App::get('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->getDocument("projectDomains", $domainId); + $domain = $dbForConsole->getDocument('projectDomains', $domainId); if ($domain->isEmpty()) { throw new Exception('Domain not found', 404); @@ -1453,7 +1445,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->getDocument("projectDomains", $domainId); + $domain = $dbForConsole->getDocument('projectDomains', $domainId); if ($domain->isEmpty()) { throw new Exception('Domain not found', 404); @@ -1475,10 +1467,10 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Failed to verify domain', 401); } - $domain->setAttribute("verification", true); + $domain->setAttribute('verification', true); - $dbForConsole->updateDocument("projectDomains", $domain->getId(), $domain); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->updateDocument('projectDomains', $domain->getId(), $domain); + $dbForConsole->purgeDocument('projects', $project->getId()); // Issue a TLS certificate when domain is verified Resque::enqueue('v1-certificates', 'CertificatesV1', [ @@ -1513,15 +1505,15 @@ App::delete('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->getDocument("projectDomains", $domainId); + $domain = $dbForConsole->getDocument('projectDomains', $domainId); if ($domain->isEmpty()) { throw new Exception('Domain not found', 404); } - $dbForConsole->deleteDocument("projectDomains", $domain->getId()); + $dbForConsole->deleteDocument('projectDomains', $domain->getId()); - $dbForConsole->purgeDocument("projects", $project->getId()); + $dbForConsole->purgeDocument('projects', $project->getId()); $deletes ->setParam('type', DELETE_TYPE_CERTIFICATES) diff --git a/app/init.php b/app/init.php index 7c44ba12e6..adb42fbdd6 100644 --- a/app/init.php +++ b/app/init.php @@ -184,11 +184,10 @@ Database::addFilter('subQueryAttributes', return null; }, function($value, Document $document, Database $database) { - // TODO: Maybe implement pagination? return $database ->find('attributes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); } ); @@ -197,11 +196,10 @@ Database::addFilter('subQueryIndexes', return null; }, function($value, Document $document, Database $database) { - // TODO: Maybe implement pagination? return $database ->find('indexes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); } ); @@ -210,11 +208,10 @@ Database::addFilter('subQueryProjectPlatforms', return null; }, function($value, Document $document, Database $database) { - // TODO: Implement pagination return $database ->find('projectsPlatforms', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); } ); @@ -223,11 +220,10 @@ Database::addFilter('subQueryProjectDomains', return null; }, function($value, Document $document, Database $database) { - // TODO: Implement pagination return $database ->find('projectDomains', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); } ); @@ -236,11 +232,10 @@ Database::addFilter('subQueryProjectKeys', return null; }, function($value, Document $document, Database $database) { - // TODO: Implement pagination return $database ->find('projectKeys', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); } ); @@ -249,11 +244,10 @@ Database::addFilter('subQueryProjectWebhooks', return null; }, function($value, Document $document, Database $database) { - // TODO: Implement pagination return $database ->find('projectWebhooks', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); } ); @@ -262,15 +256,14 @@ Database::addFilter('subQueryProjectServices', return null; }, function($value, Document $document, Database $database) { - // TODO: Implement pagination $services = $database ->find('projectsServices', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); $responseJson = []; foreach($services as $service) { - $responseJson[$service->getAttribute("key")] = $service->getAttribute("status", true); + $responseJson[$service->getAttribute('key')] = $service->getAttribute('status', true); } return $responseJson; @@ -282,16 +275,15 @@ Database::addFilter('subQueryProjectProviders', return null; }, function($value, Document $document, Database $database) { - // TODO: Implement pagination $providers = $database ->find('projectProviders', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 100, 0, []); + ], 5000, 0, []); $responseJson = []; foreach($providers as $provider) { - $responseJson[$provider->getAttribute("key") . 'Appid'] = $provider->getAttribute("appId"); - $responseJson[$provider->getAttribute("key") . 'Secret'] = $provider->getAttribute("appSecret"); + $responseJson[$provider->getAttribute('key') . 'Appid'] = $provider->getAttribute('appId'); + $responseJson[$provider->getAttribute('key') . 'Secret'] = $provider->getAttribute('appSecret'); } return $responseJson; From 51b1a7e72c8aa3152d790c1165b01e1b0b9917e4 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Wed, 1 Sep 2021 10:25:54 +0200 Subject: [PATCH 06/13] Removed re-selecting queries, improved selecting from sub-tables --- app/controllers/api/projects.php | 122 +++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 37 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index cdc43d7b1a..97a914bafc 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -473,7 +473,7 @@ App::patch('/v1/projects/:projectId/service') ->param('status', true, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') - ->action(function ($projectId, $serviceKey, $status, $response, $dbForConsole) { + ->action(function ($projectId, $service, $status, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ /** @var Boolean $status */ @@ -484,34 +484,38 @@ App::patch('/v1/projects/:projectId/service') throw new Exception('Project not found', 404); } - $service = $dbForConsole->findOne('projectsServices', [ + $document = $dbForConsole->findOne('projectsServices', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), - new Query('key', Query::TYPE_EQUAL, [$serviceKey]), + new Query('key', Query::TYPE_EQUAL, [$service]), ]); - if($service == false || $service->isEmpty()) { - $service = new Document([ + if($document == false || $document->isEmpty()) { + $document = new Document([ '$id' => $dbForConsole->getId(), '$read' => ['role:all'], '$write' => ['role:all'], 'projectId' => $project->getId(), - 'key' => $serviceKey, + 'key' => $service, 'status' => $status, ]); - $dbForConsole->createDocument('projectsServices', $service); + $dbForConsole->createDocument('projectsServices', $document); + + $project + ->setAttribute('services', $document, Document::SET_TYPE_APPEND); $dbForConsole->purgeDocument('projects', $project->getId()); } else { - if($service->getAttribute('status') != $status) { - $service->setAttribute('status', $status); - $dbForConsole->updateDocument('projectsServices', $service->getId(), $service); + if($document->getAttribute('status') != $status) { + $document->setAttribute('status', $status); + $dbForConsole->updateDocument('projectsServices', $document->getId(), $document); + + $project->findAndReplace('$id', $document->getId(), $document, 'services'); $dbForConsole->purgeDocument('projects', $project->getId()); } } - $project = $dbForConsole->getDocument('projects', $projectId); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -554,6 +558,8 @@ App::patch('/v1/projects/:projectId/oauth2') $dbForConsole->updateDocument('projectProviders', $provider->getId(), $provider); + $project->findAndReplace('$id', $provider->getId(), $provider, 'providers'); + $dbForConsole->purgeDocument('projects', $project->getId()); } else { // Provider does not exist yet @@ -570,10 +576,12 @@ App::patch('/v1/projects/:projectId/oauth2') $dbForConsole->createDocument('projectProviders', $provider); + $project + ->setAttribute('providers', $provider, Document::SET_TYPE_APPEND); + $dbForConsole->purgeDocument('projects', $project->getId()); } - $project = $dbForConsole->getDocument('projects', $projectId); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -805,9 +813,12 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $dbForConsole->getDocument('projectWebhooks', $webhookId); + $webhook = $dbForConsole->findOne('projectWebhooks', [ + new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($webhook->isEmpty()) { + if ($webhook == false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -846,9 +857,12 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $webhook = $dbForConsole->getDocument('projectWebhooks', $webhookId); + $webhook = $dbForConsole->findOne('projectWebhooks', [ + new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($webhook->isEmpty()) { + if ($webhook == false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -890,9 +904,12 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $dbForConsole->getDocument('projectWebhooks', $webhookId); + $webhook = $dbForConsole->findOne('projectWebhooks', [ + new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if($webhook->isEmpty()) { + if($webhook == false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -1005,9 +1022,12 @@ App::get('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->getDocument('projectKeys', $keyId); + $key = $dbForConsole->findOne('projectKeys', [ + new Query('_uid', Query::TYPE_EQUAL, [$keyId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($key->isEmpty()) { + if ($key !== true || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -1040,9 +1060,12 @@ App::put('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->getDocument('projectKeys', $keyId); + $key = $dbForConsole->findOne('projectKeys', [ + new Query('_uid', Query::TYPE_EQUAL, [$keyId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($key->isEmpty()) { + if ($key == false || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -1079,9 +1102,12 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->getDocument('projectKeys', $keyId); + $key = $dbForConsole->findOne('projectKeys', [ + new Query('_uid', Query::TYPE_EQUAL, [$keyId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if($key->isEmpty()) { + if($key == false || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -1201,9 +1227,12 @@ App::get('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->getDocument('projectsPlatforms', $platformId); + $platform = $dbForConsole->findOne('projectsPlatforms', [ + new Query('_uid', Query::TYPE_EQUAL, [$platformId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($platform->isEmpty()) { + if ($platform == false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1238,9 +1267,12 @@ App::put('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->getDocument('projectsPlatforms', $platformId); + $platform = $dbForConsole->findOne('projectsPlatforms', [ + new Query('_uid', Query::TYPE_EQUAL, [$platformId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($platform->isEmpty()) { + if ($platform == false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1282,12 +1314,17 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $deleteRecord = $dbForConsole->deleteDocument('projectsPlatforms', $platformId); + $platform = $dbForConsole->findOne('projectsPlatforms', [ + new Query('_uid', Query::TYPE_EQUAL, [$platformId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if($deleteRecord == false) { + if ($platform == false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } + $dbForConsole->deleteDocument('projectsPlatforms', $platformId); + $dbForConsole->purgeDocument('projects', $project->getId()); $response->noContent(); @@ -1380,7 +1417,9 @@ App::get('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $domains = $dbForConsole->find('projectDomains', [], 5000); + $domains = $dbForConsole->find('projectDomains', [ + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ], 5000); $response->dynamic(new Document([ 'domains' => $domains, @@ -1412,9 +1451,12 @@ App::get('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->getDocument('projectDomains', $domainId); + $domain = $dbForConsole->findOne('projectDomains', [ + new Query('_uid', Query::TYPE_EQUAL, [$domainId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($domain->isEmpty()) { + if ($domain == false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1445,9 +1487,12 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->getDocument('projectDomains', $domainId); + $domain = $dbForConsole->findOne('projectDomains', [ + new Query('_uid', Query::TYPE_EQUAL, [$domainId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($domain->isEmpty()) { + if ($domain == false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1505,9 +1550,12 @@ App::delete('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->getDocument('projectDomains', $domainId); + $domain = $dbForConsole->findOne('projectDomains', [ + new Query('_uid', Query::TYPE_EQUAL, [$domainId]), + new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) + ]); - if ($domain->isEmpty()) { + if ($domain == false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } From 0ab76a1c6f0ae30a07c881a05245f8eeae3767c1 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Wed, 1 Sep 2021 10:43:35 +0200 Subject: [PATCH 07/13] Update sub-collection names and filter names, improved error log, fixed docs typo --- app/config/collections2.php | 48 +++++++++---------- app/controllers/api/projects.php | 74 +++++++++++++++--------------- app/init.php | 24 +++++----- src/Appwrite/Database/Database.php | 4 +- 4 files changed, 75 insertions(+), 75 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index a29a9728c8..df2f2dbab7 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -478,7 +478,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProjectServices'], + 'filters' => ['subQueryServices'], ], [ '$id' => 'auths', @@ -500,7 +500,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProjectProviders'], + 'filters' => ['subQueryProviders'], ], [ '$id' => 'platforms', @@ -511,7 +511,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProjectPlatforms'], + 'filters' => ['subQueryPlatforms'], ], [ '$id' => 'webhooks', @@ -522,7 +522,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProjectWebhooks'], + 'filters' => ['subQueryWebhooks'], ], [ '$id' => 'keys', @@ -533,7 +533,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProjectKeys'], + 'filters' => ['subQueryKeys'], ], [ '$id' => 'domains', @@ -544,7 +544,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProjectDomains'], + 'filters' => ['subQueryDomains'], ], ], 'indexes' => [ @@ -558,10 +558,10 @@ $collections = [ ], ], - 'projectsPlatforms' => [ + 'platforms' => [ '$collection' => Database::METADATA, - '$id' => 'projectsPlatforms', - 'name' => 'projectsPlatforms', + '$id' => 'platforms', + 'name' => 'platforms', 'attributes' => [ [ '$id' => 'projectId', @@ -663,10 +663,10 @@ $collections = [ ], ], - 'projectsServices' => [ + 'services' => [ '$collection' => Database::METADATA, - '$id' => 'projectsServices', - 'name' => 'projectsServices', + '$id' => 'services', + 'name' => 'services', 'attributes' => [ [ '$id' => 'projectId', @@ -713,10 +713,10 @@ $collections = [ ], ], - 'projectProviders' => [ + 'providers' => [ '$collection' => Database::METADATA, - '$id' => 'projectProviders', - 'name' => 'projectProviders', + '$id' => 'providers', + 'name' => 'providers', 'attributes' => [ [ '$id' => 'projectId', @@ -774,10 +774,10 @@ $collections = [ ], ], - 'projectDomains' => [ + 'domains' => [ '$collection' => Database::METADATA, - '$id' => 'projectDomains', - 'name' => 'projectDomains', + '$id' => 'domains', + 'name' => 'domains', 'attributes' => [ [ '$id' => 'projectId', @@ -868,10 +868,10 @@ $collections = [ ], ], - 'projectKeys' => [ + 'keys' => [ '$collection' => Database::METADATA, - '$id' => 'projectKeys', - 'name' => 'projectKeys', + '$id' => 'keys', + 'name' => 'keys', 'attributes' => [ [ '$id' => 'projectId', @@ -929,10 +929,10 @@ $collections = [ ], ], - 'projectWebhooks' => [ + 'webhooks' => [ '$collection' => Database::METADATA, - '$id' => 'projectWebhooks', - 'name' => 'projectWebhooks', + '$id' => 'webhooks', + 'name' => 'webhooks', 'attributes' => [ [ '$id' => 'projectId', diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 97a914bafc..42cb3ebc1b 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -217,7 +217,7 @@ App::get('/v1/projects/:projectId') }); App::get('/v1/projects/:projectId/usage') - ->desc('Get Project') + ->desc('Get Project Usage') ->groups(['api', 'projects']) ->label('scope', 'projects.read') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) @@ -484,7 +484,7 @@ App::patch('/v1/projects/:projectId/service') throw new Exception('Project not found', 404); } - $document = $dbForConsole->findOne('projectsServices', [ + $document = $dbForConsole->findOne('services', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), new Query('key', Query::TYPE_EQUAL, [$service]), ]); @@ -499,7 +499,7 @@ App::patch('/v1/projects/:projectId/service') 'status' => $status, ]); - $dbForConsole->createDocument('projectsServices', $document); + $dbForConsole->createDocument('services', $document); $project ->setAttribute('services', $document, Document::SET_TYPE_APPEND); @@ -508,7 +508,7 @@ App::patch('/v1/projects/:projectId/service') } else { if($document->getAttribute('status') != $status) { $document->setAttribute('status', $status); - $dbForConsole->updateDocument('projectsServices', $document->getId(), $document); + $dbForConsole->updateDocument('services', $document->getId(), $document); $project->findAndReplace('$id', $document->getId(), $document, 'services'); @@ -545,7 +545,7 @@ App::patch('/v1/projects/:projectId/oauth2') throw new Exception('Project not found', 404); } - $provider = $dbForConsole->findOne('projectProviders', [ + $provider = $dbForConsole->findOne('providers', [ new Query('key', Query::TYPE_EQUAL, [$providerKey]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), ]); @@ -556,7 +556,7 @@ App::patch('/v1/projects/:projectId/oauth2') $provider->setAttribute('appId', $appId) ->setAttribute('appSecret', $secret); - $dbForConsole->updateDocument('projectProviders', $provider->getId(), $provider); + $dbForConsole->updateDocument('providers', $provider->getId(), $provider); $project->findAndReplace('$id', $provider->getId(), $provider, 'providers'); @@ -574,7 +574,7 @@ App::patch('/v1/projects/:projectId/oauth2') 'appSecret' => $secret ]); - $dbForConsole->createDocument('projectProviders', $provider); + $dbForConsole->createDocument('providers', $provider); $project ->setAttribute('providers', $provider, Document::SET_TYPE_APPEND); @@ -748,7 +748,7 @@ App::post('/v1/projects/:projectId/webhooks') 'httpPass' => $httpPass, ]); - $webhook = $dbForConsole->createDocument('projectWebhooks', $webhook); + $webhook = $dbForConsole->createDocument('webhooks', $webhook); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -779,7 +779,7 @@ App::get('/v1/projects/:projectId/webhooks') throw new Exception('Project not found', 404); } - $webhooks = $dbForConsole->find('projectWebhooks', [ + $webhooks = $dbForConsole->find('webhooks', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -813,7 +813,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $dbForConsole->findOne('projectWebhooks', [ + $webhook = $dbForConsole->findOne('webhooks', [ new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -857,7 +857,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $webhook = $dbForConsole->findOne('projectWebhooks', [ + $webhook = $dbForConsole->findOne('webhooks', [ new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -874,7 +874,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('httpUser', $httpUser) ->setAttribute('httpPass', $httpPass); - $dbForConsole->updateDocument('projectWebhooks', $webhook->getId(), $webhook); + $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -904,7 +904,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Project not found', 404); } - $webhook = $dbForConsole->findOne('projectWebhooks', [ + $webhook = $dbForConsole->findOne('webhooks', [ new Query('_uid', Query::TYPE_EQUAL, [$webhookId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -913,7 +913,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception('Webhook not found', 404); } - $dbForConsole->deleteDocument('projectWebhooks', $webhook->getId()); + $dbForConsole->deleteDocument('webhooks', $webhook->getId()); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -957,7 +957,7 @@ App::post('/v1/projects/:projectId/keys') 'secret' => \bin2hex(\random_bytes(128)), ]); - $key = $dbForConsole->createDocument('projectKeys', $key); + $key = $dbForConsole->createDocument('keys', $key); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -988,7 +988,7 @@ App::get('/v1/projects/:projectId/keys') throw new Exception('Project not found', 404); } - $keys = $dbForConsole->find('projectKeys', [ + $keys = $dbForConsole->find('keys', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), ], 5000); @@ -1022,12 +1022,12 @@ App::get('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->findOne('projectKeys', [ + $key = $dbForConsole->findOne('keys', [ new Query('_uid', Query::TYPE_EQUAL, [$keyId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($key !== true || $key->isEmpty()) { + if ($key == false || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -1060,7 +1060,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->findOne('projectKeys', [ + $key = $dbForConsole->findOne('keys', [ new Query('_uid', Query::TYPE_EQUAL, [$keyId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1072,7 +1072,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key->setAttribute('name', $name) ->setAttribute('scopes', $scopes); - $dbForConsole->updateDocument('projectKeys', $key->getId(), $key); + $dbForConsole->updateDocument('keys', $key->getId(), $key); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1102,7 +1102,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception('Project not found', 404); } - $key = $dbForConsole->findOne('projectKeys', [ + $key = $dbForConsole->findOne('keys', [ new Query('_uid', Query::TYPE_EQUAL, [$keyId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1111,7 +1111,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception('Key not found', 404); } - $dbForConsole->deleteDocument('projectKeys', $key->getId()); + $dbForConsole->deleteDocument('keys', $key->getId()); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1162,7 +1162,7 @@ App::post('/v1/projects/:projectId/platforms') 'dateUpdated' => \time(), ]); - $platform = $dbForConsole->createDocument('projectsPlatforms', $platform); + $platform = $dbForConsole->createDocument('platforms', $platform); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1193,7 +1193,7 @@ App::get('/v1/projects/:projectId/platforms') throw new Exception('Project not found', 404); } - $platforms = $dbForConsole->find('projectsPlatforms', [ + $platforms = $dbForConsole->find('platforms', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ], 5000); @@ -1227,7 +1227,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->findOne('projectsPlatforms', [ + $platform = $dbForConsole->findOne('platforms', [ new Query('_uid', Query::TYPE_EQUAL, [$platformId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1267,7 +1267,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->findOne('projectsPlatforms', [ + $platform = $dbForConsole->findOne('platforms', [ new Query('_uid', Query::TYPE_EQUAL, [$platformId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1284,7 +1284,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->setAttribute('hostname', $hostname) ; - $dbForConsole->updateDocument('projectsPlatforms', $platform->getId(), $platform); + $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1314,7 +1314,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Project not found', 404); } - $platform = $dbForConsole->findOne('projectsPlatforms', [ + $platform = $dbForConsole->findOne('platforms', [ new Query('_uid', Query::TYPE_EQUAL, [$platformId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1323,7 +1323,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception('Platform not found', 404); } - $dbForConsole->deleteDocument('projectsPlatforms', $platformId); + $dbForConsole->deleteDocument('platforms', $platformId); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1356,7 +1356,7 @@ App::post('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $document = $dbForConsole->findOne('projectDomains', [ + $document = $dbForConsole->findOne('domains', [ new Query('domain', Query::TYPE_EQUAL, [$domain]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), ]); @@ -1386,7 +1386,7 @@ App::post('/v1/projects/:projectId/domains') 'certificateId' => null, ]); - $domain = $dbForConsole->createDocument('projectDomains', $domain); + $domain = $dbForConsole->createDocument('domains', $domain); $dbForConsole->purgeDocument('projects', $project->getId()); @@ -1417,7 +1417,7 @@ App::get('/v1/projects/:projectId/domains') throw new Exception('Project not found', 404); } - $domains = $dbForConsole->find('projectDomains', [ + $domains = $dbForConsole->find('domains', [ new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ], 5000); @@ -1451,7 +1451,7 @@ App::get('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->findOne('projectDomains', [ + $domain = $dbForConsole->findOne('domains', [ new Query('_uid', Query::TYPE_EQUAL, [$domainId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1487,7 +1487,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->findOne('projectDomains', [ + $domain = $dbForConsole->findOne('domains', [ new Query('_uid', Query::TYPE_EQUAL, [$domainId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1514,7 +1514,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') $domain->setAttribute('verification', true); - $dbForConsole->updateDocument('projectDomains', $domain->getId(), $domain); + $dbForConsole->updateDocument('domains', $domain->getId(), $domain); $dbForConsole->purgeDocument('projects', $project->getId()); // Issue a TLS certificate when domain is verified @@ -1550,7 +1550,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId') throw new Exception('Project not found', 404); } - $domain = $dbForConsole->findOne('projectDomains', [ + $domain = $dbForConsole->findOne('domains', [ new Query('_uid', Query::TYPE_EQUAL, [$domainId]), new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); @@ -1559,7 +1559,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId') throw new Exception('Domain not found', 404); } - $dbForConsole->deleteDocument('projectDomains', $domain->getId()); + $dbForConsole->deleteDocument('domains', $domain->getId()); $dbForConsole->purgeDocument('projects', $project->getId()); diff --git a/app/init.php b/app/init.php index adb42fbdd6..e30b7f696d 100644 --- a/app/init.php +++ b/app/init.php @@ -203,61 +203,61 @@ Database::addFilter('subQueryIndexes', } ); -Database::addFilter('subQueryProjectPlatforms', +Database::addFilter('subQueryPlatforms', function($value) { return null; }, function($value, Document $document, Database $database) { return $database - ->find('projectsPlatforms', [ + ->find('platforms', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 5000, 0, []); } ); -Database::addFilter('subQueryProjectDomains', +Database::addFilter('subQueryDomains', function($value) { return null; }, function($value, Document $document, Database $database) { return $database - ->find('projectDomains', [ + ->find('domains', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 5000, 0, []); } ); -Database::addFilter('subQueryProjectKeys', +Database::addFilter('subQueryKeys', function($value) { return null; }, function($value, Document $document, Database $database) { return $database - ->find('projectKeys', [ + ->find('keys', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 5000, 0, []); } ); -Database::addFilter('subQueryProjectWebhooks', +Database::addFilter('subQueryWebhooks', function($value) { return null; }, function($value, Document $document, Database $database) { return $database - ->find('projectWebhooks', [ + ->find('webhooks', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 5000, 0, []); } ); -Database::addFilter('subQueryProjectServices', +Database::addFilter('subQueryServices', function($value) { return null; }, function($value, Document $document, Database $database) { $services = $database - ->find('projectsServices', [ + ->find('services', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 5000, 0, []); @@ -270,13 +270,13 @@ Database::addFilter('subQueryProjectServices', } ); -Database::addFilter('subQueryProjectProviders', +Database::addFilter('subQueryProviders', function($value) { return null; }, function($value, Document $document, Database $database) { $providers = $database - ->find('projectProviders', [ + ->find('providers', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) ], 5000, 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 { From 524abc80d70fbec15820b92763247c6cf0097499 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Thu, 2 Sep 2021 11:38:24 +0200 Subject: [PATCH 08/13] Rollback of services and providers sub-collections --- app/config/collections2.php | 4 +- app/controllers/api/projects.php | 71 ++++---------------------------- app/init.php | 39 ------------------ 3 files changed, 11 insertions(+), 103 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index df2f2dbab7..29375bec5c 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -478,7 +478,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryServices'], + 'filters' => ['json'], ], [ '$id' => 'auths', @@ -500,7 +500,7 @@ $collections = [ 'required' => false, 'default' => null, 'array' => false, - 'filters' => ['subQueryProviders'], + 'filters' => ['json'], ], [ '$id' => 'platforms', diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 42cb3ebc1b..973df927d4 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -93,9 +93,9 @@ App::post('/v1/projects') 'legalCity' => $legalCity, 'legalAddress' => $legalAddress, 'legalTaxId' => $legalTaxId, - 'services' => null, + 'services' => new stdClass(), 'platforms' => null, - 'providers' => null, + 'providers' => [], 'webhooks' => null, 'keys' => null, 'domains' => null, @@ -484,37 +484,10 @@ App::patch('/v1/projects/:projectId/service') throw new Exception('Project not found', 404); } - $document = $dbForConsole->findOne('services', [ - new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), - new Query('key', Query::TYPE_EQUAL, [$service]), - ]); + $services = $project->getAttribute('services', []); + $services[$service] = $status; - if($document == false || $document->isEmpty()) { - $document = new Document([ - '$id' => $dbForConsole->getId(), - '$read' => ['role:all'], - '$write' => ['role:all'], - 'projectId' => $project->getId(), - 'key' => $service, - 'status' => $status, - ]); - - $dbForConsole->createDocument('services', $document); - - $project - ->setAttribute('services', $document, Document::SET_TYPE_APPEND); - - $dbForConsole->purgeDocument('projects', $project->getId()); - } else { - if($document->getAttribute('status') != $status) { - $document->setAttribute('status', $status); - $dbForConsole->updateDocument('services', $document->getId(), $document); - - $project->findAndReplace('$id', $document->getId(), $document, 'services'); - - $dbForConsole->purgeDocument('projects', $project->getId()); - } - } + $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -550,37 +523,11 @@ App::patch('/v1/projects/:projectId/oauth2') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), ]); - if($provider && !$provider->isEmpty()) { - // Provider exists + $providers = $project->getAttribute('providers', []); + $providers[$provider . 'Appid'] = $appId; + $providers[$provider . 'Secret'] = $secret; - $provider->setAttribute('appId', $appId) - ->setAttribute('appSecret', $secret); - - $dbForConsole->updateDocument('providers', $provider->getId(), $provider); - - $project->findAndReplace('$id', $provider->getId(), $provider, 'providers'); - - $dbForConsole->purgeDocument('projects', $project->getId()); - } else { - // Provider does not exist yet - - $provider = new Document([ - '$id' => $dbForConsole->getId(), - '$read' => ['role:all'], - '$write' => ['role:all'], - 'projectId' => $project->getId(), - 'key' => $providerKey, - 'appId' => $appId, - 'appSecret' => $secret - ]); - - $dbForConsole->createDocument('providers', $provider); - - $project - ->setAttribute('providers', $provider, Document::SET_TYPE_APPEND); - - $dbForConsole->purgeDocument('projects', $project->getId()); - } + $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('providers', $providers)); $response->dynamic($project, Response::MODEL_PROJECT); }); diff --git a/app/init.php b/app/init.php index e30b7f696d..86c69ae599 100644 --- a/app/init.php +++ b/app/init.php @@ -251,45 +251,6 @@ Database::addFilter('subQueryWebhooks', } ); -Database::addFilter('subQueryServices', - function($value) { - return null; - }, - function($value, Document $document, Database $database) { - $services = $database - ->find('services', [ - new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 5000, 0, []); - - $responseJson = []; - foreach($services as $service) { - $responseJson[$service->getAttribute('key')] = $service->getAttribute('status', true); - } - - return $responseJson; - } -); - -Database::addFilter('subQueryProviders', - function($value) { - return null; - }, - function($value, Document $document, Database $database) { - $providers = $database - ->find('providers', [ - new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], 5000, 0, []); - - $responseJson = []; - foreach($providers as $provider) { - $responseJson[$provider->getAttribute('key') . 'Appid'] = $provider->getAttribute('appId'); - $responseJson[$provider->getAttribute('key') . 'Secret'] = $provider->getAttribute('appSecret'); - } - - return $responseJson; - } -); - Database::addFilter('encrypt', function($value) { $key = App::getEnv('_APP_OPENSSL_KEY_V1'); From 0fa6c764132cb4efc34aaa128818436a62448958 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Thu, 2 Sep 2021 13:12:10 +0200 Subject: [PATCH 09/13] Bug fix, tests are now green --- app/controllers/api/projects.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 973df927d4..0c8d254c22 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -508,7 +508,7 @@ App::patch('/v1/projects/:projectId/oauth2') ->param('secret', '', new text(512), 'Provider secret key. Max length: 512 chars.', true) ->inject('response') ->inject('dbForConsole') - ->action(function ($projectId, $providerKey, $appId, $secret, $response, $dbForConsole) { + ->action(function ($projectId, $provider, $appId, $secret, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ @@ -518,11 +518,6 @@ App::patch('/v1/projects/:projectId/oauth2') throw new Exception('Project not found', 404); } - $provider = $dbForConsole->findOne('providers', [ - new Query('key', Query::TYPE_EQUAL, [$providerKey]), - new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), - ]); - $providers = $project->getAttribute('providers', []); $providers[$provider . 'Appid'] = $appId; $providers[$provider . 'Secret'] = $secret; From e9124f28c722603102d1dd73d0987966e73a1a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 11 Sep 2021 19:29:17 +0200 Subject: [PATCH 10/13] Removed unnecessary array_merge import Co-authored-by: Eldad A. Fux --- tests/e2e/Services/Projects/ProjectsConsoleClientTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index f090158cd0..2f91663c98 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -7,7 +7,6 @@ use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; use Tests\E2E\Services\Projects\ProjectsBase; use Tests\E2E\Client; -use function array_merge; class ProjectsConsoleClientTest extends Scope { From d3e02db31f670aef41ac8e16ad66a023cdf69b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 14 Sep 2021 08:57:55 +0200 Subject: [PATCH 11/13] Apply suggestions from code review Co-authored-by: kodumbeats --- app/controllers/api/projects.php | 36 +++++++++++++++++--------------- app/init.php | 4 ++-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 0c8d254c22..f726371922 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -760,7 +760,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($webhook == false || $webhook->isEmpty()) { + if ($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -804,7 +804,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($webhook == false || $webhook->isEmpty()) { + if ($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -814,7 +814,8 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('url', $url) ->setAttribute('security', $security) ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass); + ->setAttribute('httpPass', $httpPass) + ; $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); @@ -851,7 +852,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if($webhook == false || $webhook->isEmpty()) { + if($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404); } @@ -969,7 +970,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($key == false || $key->isEmpty()) { + if ($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -1007,12 +1008,14 @@ App::put('/v1/projects/:projectId/keys/:keyId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($key == false || $key->isEmpty()) { + if ($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404); } - $key->setAttribute('name', $name) - ->setAttribute('scopes', $scopes); + $key + ->setAttribute('name', $name) + ->setAttribute('scopes', $scopes) + ; $dbForConsole->updateDocument('keys', $key->getId(), $key); @@ -1049,7 +1052,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if($key == false || $key->isEmpty()) { + if($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404); } @@ -1174,7 +1177,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($platform == false || $platform->isEmpty()) { + if ($platform === false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1214,7 +1217,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($platform == false || $platform->isEmpty()) { + if ($platform === false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1261,7 +1264,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($platform == false || $platform->isEmpty()) { + if ($platform === false || $platform->isEmpty()) { throw new Exception('Platform not found', 404); } @@ -1398,7 +1401,7 @@ App::get('/v1/projects/:projectId/domains/:domainId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($domain == false || $domain->isEmpty()) { + if ($domain === false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1434,7 +1437,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($domain == false || $domain->isEmpty()) { + if ($domain === false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } @@ -1454,9 +1457,8 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') throw new Exception('Failed to verify domain', 401); } - $domain->setAttribute('verification', true); - $dbForConsole->updateDocument('domains', $domain->getId(), $domain); + $dbForConsole->updateDocument('domains', $domain->getId(), $domain->setAttribute('verification', true)); $dbForConsole->purgeDocument('projects', $project->getId()); // Issue a TLS certificate when domain is verified @@ -1497,7 +1499,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if ($domain == false || $domain->isEmpty()) { + if ($domain === false || $domain->isEmpty()) { throw new Exception('Domain not found', 404); } diff --git a/app/init.php b/app/init.php index 86c69ae599..7892ac8a10 100644 --- a/app/init.php +++ b/app/init.php @@ -187,7 +187,7 @@ Database::addFilter('subQueryAttributes', return $database ->find('attributes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) - ], 5000, 0, []); + ], 1017, 0, []); } ); @@ -199,7 +199,7 @@ Database::addFilter('subQueryIndexes', return $database ->find('indexes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) - ], 5000, 0, []); + ], 64, 0, []); } ); From ba6c52861711e98ad84ac9a2ee70a11fbdfb5785 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Tue, 14 Sep 2021 08:58:19 +0200 Subject: [PATCH 12/13] Apply suggestions from code review 2 --- app/config/collections2.php | 111 ------------------------------- app/controllers/api/projects.php | 2 +- 2 files changed, 1 insertion(+), 112 deletions(-) diff --git a/app/config/collections2.php b/app/config/collections2.php index 29375bec5c..97d6db253c 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -663,117 +663,6 @@ $collections = [ ], ], - 'services' => [ - '$collection' => Database::METADATA, - '$id' => 'services', - 'name' => 'services', - 'attributes' => [ - [ - '$id' => 'projectId', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'key', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'status', - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - '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], - ], - ], - ], - - 'providers' => [ - '$collection' => Database::METADATA, - '$id' => 'providers', - 'name' => 'providers', - 'attributes' => [ - [ - '$id' => 'projectId', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'key', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'appId', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'appSecret', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - '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], - ], - ], - ], - 'domains' => [ '$collection' => Database::METADATA, '$id' => 'domains', diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index f726371922..8e99f200a7 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -470,7 +470,7 @@ App::patch('/v1/projects/:projectId/service') ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), function($element) {return $element['optional'];})), true), 'Service name.') - ->param('status', true, new Boolean(), 'Service status.') + ->param('status', null, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') ->action(function ($projectId, $service, $status, $response, $dbForConsole) { From 7ce2ca45b4405ba84c67ea53d698d018e64fefa6 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 6 Oct 2021 13:56:44 +0200 Subject: [PATCH 13/13] fix cache purge in projects api --- app/controllers/api/projects.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index f87176af08..2acb095a2a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -597,7 +597,7 @@ App::post('/v1/projects/:projectId/webhooks') $webhook = $dbForConsole->createDocument('webhooks', $webhook); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($webhook, Response::MODEL_WEBHOOK); @@ -724,7 +724,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -763,7 +763,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') $dbForConsole->deleteDocument('webhooks', $webhook->getId()); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -807,7 +807,7 @@ App::post('/v1/projects/:projectId/keys') $key = $dbForConsole->createDocument('keys', $key); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($key, Response::MODEL_KEY); @@ -924,7 +924,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($key, Response::MODEL_KEY); }); @@ -963,7 +963,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') $dbForConsole->deleteDocument('keys', $key->getId()); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1014,7 +1014,7 @@ App::post('/v1/projects/:projectId/platforms') $platform = $dbForConsole->createDocument('platforms', $platform); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($platform, Response::MODEL_PLATFORM); @@ -1136,7 +1136,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($platform, Response::MODEL_PLATFORM); }); @@ -1175,7 +1175,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') $dbForConsole->deleteDocument('platforms', $platformId); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1238,7 +1238,7 @@ App::post('/v1/projects/:projectId/domains') $domain = $dbForConsole->createDocument('domains', $domain); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($domain, Response::MODEL_DOMAIN); @@ -1364,7 +1364,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') $dbForConsole->updateDocument('domains', $domain->getId(), $domain->setAttribute('verification', true)); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); // Issue a TLS certificate when domain is verified Resque::enqueue('v1-certificates', 'CertificatesV1', [ @@ -1410,7 +1410,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId') $dbForConsole->deleteDocument('domains', $domain->getId()); - $dbForConsole->purgeDocument('projects', $project->getId()); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); $deletes ->setParam('type', DELETE_TYPE_CERTIFICATES)