From 42d0589d324c34660ea44bbcb7c9d7437c1c00c8 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 7 Feb 2022 13:25:15 +0100 Subject: [PATCH 01/13] fix: permissions and collections schema --- app/controllers/api/database.php | 57 +++++------ app/controllers/api/projects.php | 8 +- app/init.php | 4 +- app/realtime.php | 12 +-- app/tasks/usage.php | 16 ++-- app/workers/database.php | 10 +- composer.json | 2 +- composer.lock | 160 +++++++++++++++++-------------- src/Appwrite/Resque/Worker.php | 4 +- 9 files changed, 144 insertions(+), 129 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 46b9897201..53767d1641 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -111,7 +111,7 @@ function createAttribute(string $collectionId, Document $attribute, Response $re } $dbForProject->deleteCachedDocument('collections', $collectionId); - $dbForProject->deleteCachedCollection('collection_' . $collectionId); + $dbForProject->deleteCachedCollection('collection_' . $collection->getInternalId()); // Pass clone of $attribute object to workers // so we can later modify Document to fit response model @@ -166,7 +166,7 @@ App::post('/v1/database/collections') $collectionId = $collectionId == 'unique()' ? $dbForProject->getId() : $collectionId; try { - $collection = $dbForProject->createDocument('collections', new Document([ + $dbForProject->createDocument('collections', new Document([ '$id' => $collectionId, '$read' => $read ?? [], // Collection permissions for collection documents (based on permission model) '$write' => $write ?? [], // Collection permissions for collection documents (based on permission model) @@ -177,8 +177,9 @@ App::post('/v1/database/collections') 'name' => $name, 'search' => implode(' ', [$collectionId, $name]), ])); + $collection = $dbForProject->getDocument('collections', $collectionId); - $dbForProject->createCollection('collection_' . $collectionId); + $dbForProject->createCollection('collection_' . $collection->getInternalId()); } catch (DuplicateException $th) { throw new Exception('Collection already exists', 409); } catch (LimitException $th) { @@ -402,7 +403,8 @@ App::get('/v1/database/:collectionId/usage') /** @var Utopia\Database\Database $dbForProject */ /** @var Utopia\Registry\Registry $register */ - $collection = $dbForProject->getCollection('collection_' . $collectionId); + $collectionDocument = $dbForProject->getDocument('collections', $collectionId); + $collection = $dbForProject->getCollection('collection_' . $collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception('Collection not found', 404); @@ -513,7 +515,8 @@ App::get('/v1/database/collections/:collectionId/logs') /** @var Utopia\Locale\Locale $locale */ /** @var MaxMind\Db\Reader $geodb */ - $collection = $dbForProject->getCollection('collection_' . $collectionId); + $collectionDocument = $dbForProject->getDocument('collections', $collectionId); + $collection = $dbForProject->getCollection('collection_' . $collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception('Collection not found', 404); @@ -676,7 +679,7 @@ App::delete('/v1/database/collections/:collectionId') throw new Exception('Failed to remove collection from DB', 500); } - $dbForProject->deleteCachedCollection('collection_' . $collectionId); + $dbForProject->deleteCachedCollection('collection_' . $collection->getInternalId()); $deletes ->setParam('type', DELETE_TYPE_DOCUMENT) @@ -1259,7 +1262,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key') } $dbForProject->deleteCachedDocument('collections', $collectionId); - $dbForProject->deleteCachedCollection('collection_' . $collectionId); + $dbForProject->deleteCachedCollection('collection_' . $collection->getInternalId()); $database ->setParam('type', DATABASE_TYPE_DELETE_ATTRIBUTE) @@ -1641,9 +1644,9 @@ App::post('/v1/database/collections/:collectionId/documents') try { if ($collection->getAttribute('permission') === 'collection') { /** @var Document $document */ - $document = Authorization::skip(fn() => $dbForProject->createDocument('collection_' . $collectionId, new Document($data))); + $document = Authorization::skip(fn() => $dbForProject->createDocument('collection_' . $collection->getInternalId(), new Document($data))); } else { - $document = $dbForProject->createDocument('collection_' . $collectionId, new Document($data)); + $document = $dbForProject->createDocument('collection_' . $collection->getInternalId(), new Document($data)); } $document->setAttribute('$collection', $collectionId); } @@ -1741,8 +1744,8 @@ App::get('/v1/database/collections/:collectionId/documents') $cursorDocument = null; if (!empty($cursor)) { $cursorDocument = $collection->getAttribute('permission') === 'collection' - ? Authorization::skip(fn () => $dbForProject->getDocument('collection_' . $collectionId, $cursor)) - : $dbForProject->getDocument('collection_' . $collectionId, $cursor); + ? Authorization::skip(fn () => $dbForProject->getDocument('collection_' . $collection->getInternalId(), $cursor)) + : $dbForProject->getDocument('collection_' . $collection->getInternalId(), $cursor); if ($cursorDocument->isEmpty()) { throw new Exception("Document '{$cursor}' for the 'cursor' value not found.", 400); @@ -1751,11 +1754,11 @@ App::get('/v1/database/collections/:collectionId/documents') if ($collection->getAttribute('permission') === 'collection') { /** @var Document[] $documents */ - $documents = Authorization::skip(fn() => $dbForProject->find('collection_' . $collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $cursorDocument ?? null, $cursorDirection)); - $sum = Authorization::skip(fn() => $dbForProject->count('collection_' . $collectionId, $queries, APP_LIMIT_COUNT)); + $documents = Authorization::skip(fn() => $dbForProject->find('collection_' . $collection->getInternalId(), $queries, $limit, $offset, $orderAttributes, $orderTypes, $cursorDocument ?? null, $cursorDirection)); + $sum = Authorization::skip(fn() => $dbForProject->count('collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT)); } else { - $documents = $dbForProject->find('collection_' . $collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $cursorDocument ?? null, $cursorDirection); - $sum = $dbForProject->count('collection_' . $collectionId, $queries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('collection_' . $collection->getInternalId(), $queries, $limit, $offset, $orderAttributes, $orderTypes, $cursorDocument ?? null, $cursorDirection); + $sum = $dbForProject->count('collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); } /** @@ -1817,9 +1820,9 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->getAttribute('permission') === 'collection') { /** @var Document $document */ - $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collectionId, $documentId)); + $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId)); } else { - $document = $dbForProject->getDocument('collection_' . $collectionId, $documentId); + $document = $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId); } /** @@ -1871,7 +1874,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId/logs') throw new Exception('Collection not found', 404); } - $document = $dbForProject->getDocument('collection_' . $collectionId, $documentId); + $document = $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId); if ($document->isEmpty()) { throw new Exception('No document found', 404); @@ -1980,9 +1983,9 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') throw new Exception('Unauthorized permissions', 401); } - $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collectionId, $documentId)); + $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId)); } else { - $document = $dbForProject->getDocument('collection_' . $collectionId, $documentId); + $document = $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId); } @@ -2030,9 +2033,9 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') try { if ($collection->getAttribute('permission') === 'collection') { /** @var Document $document */ - $document = Authorization::skip(fn() => $dbForProject->updateDocument('collection_' . $collection->getId(), $document->getId(), new Document($data))); + $document = Authorization::skip(fn() => $dbForProject->updateDocument('collection_' . $collection->getInternalId(), $document->getId(), new Document($data))); } else { - $document = $dbForProject->updateDocument('collection_' . $collection->getId(), $document->getId(), new Document($data)); + $document = $dbForProject->updateDocument('collection_' . $collection->getInternalId(), $document->getId(), new Document($data)); } /** * Reset $collection attribute to remove prefix. @@ -2115,9 +2118,9 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->getAttribute('permission') === 'collection') { /** @var Document $document */ - $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collectionId, $documentId)); + $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId)); } else { - $document = $dbForProject->getDocument('collection_' . $collectionId, $documentId); + $document = $dbForProject->getDocument('collection_' . $collection->getInternalId(), $documentId); } if ($document->isEmpty()) { @@ -2125,12 +2128,12 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') } if ($collection->getAttribute('permission') === 'collection') { - Authorization::skip(fn() => $dbForProject->deleteDocument('collection_' . $collectionId, $documentId)); + Authorization::skip(fn() => $dbForProject->deleteDocument('collection_' . $collection->getInternalId(), $documentId)); } else { - $dbForProject->deleteDocument('collection_' . $collectionId, $documentId); + $dbForProject->deleteDocument('collection_' . $collection->getInternalId(), $documentId); } - $dbForProject->deleteCachedDocument('collection_' . $collectionId, $documentId); + $dbForProject->deleteCachedDocument('collection_' . $collection->getInternalId(), $documentId); /** * Reset $collection attribute to remove prefix. diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index b65eb5db7b..50889d86e8 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -101,10 +101,10 @@ App::post('/v1/projects') 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), ])); + /** @var array $collections */ + $collections = Config::getParam('collections', []); - $collections = Config::getParam('collections', []); /** @var array $collections */ - - $dbForProject->setNamespace('_project_' . $project->getId()); + $dbForProject->setNamespace("_{$project->getId()}"); $dbForProject->create('appwrite'); $audit = new Audit($dbForProject); @@ -266,7 +266,7 @@ App::get('/v1/projects/:projectId/usage') ], ]; - $dbForProject->setNamespace('_project_' . $projectId); + $dbForProject->setNamespace("_{$projectId}"); $metrics = [ 'requests', diff --git a/app/init.php b/app/init.php index a45ac69aea..23992e2b1b 100644 --- a/app/init.php +++ b/app/init.php @@ -804,7 +804,7 @@ App::setResource('dbForProject', function($db, $cache, $project) { $database = new Database(new MariaDB($db), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace('_project_'.$project->getId()); + $database->setNamespace("_{$project->getId()}"); return $database; }, ['db', 'cache', 'project']); @@ -814,7 +814,7 @@ App::setResource('dbForConsole', function($db, $cache) { $database = new Database(new MariaDB($db), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace('_project_console'); + $database->setNamespace('_console'); return $database; }, ['db', 'cache']); diff --git a/app/realtime.php b/app/realtime.php index b2ddf67634..d72af7f606 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -137,7 +137,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume */ go(function () use ($register, $containerId, &$statsDocument, $logError) { try { - [$database, $returnDatabase] = getDatabase($register, '_project_console'); + [$database, $returnDatabase] = getDatabase($register, '_console'); $document = new Document([ '$id' => $database->getId(), '$collection' => 'realtime', @@ -190,7 +190,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume } try { - [$database, $returnDatabase] = getDatabase($register, '_project_console'); + [$database, $returnDatabase] = getDatabase($register, '_console'); $statsDocument ->setAttribute('timestamp', time()) @@ -217,7 +217,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, */ if ($realtime->hasSubscriber('console', 'role:member', 'project')) { - [$database, $returnDatabase] = getDatabase($register, '_project_console'); + [$database, $returnDatabase] = getDatabase($register, '_console'); $payload = []; @@ -321,7 +321,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, return; } - [$database, $returnDatabase] = getDatabase($register, '_project_' . $projectId); + [$database, $returnDatabase] = getDatabase($register, "_{$projectId}"); $user = $database->getDocument('users', $userId); @@ -397,7 +397,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $cache = new Cache(new RedisCache($redis)); $database = new Database(new MariaDB($db), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace('_project_' . $project->getId()); + $database->setNamespace("_{$project->getId()}"); /* * Project Check @@ -504,7 +504,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $cache = new Cache(new RedisCache($redis)); $database = new Database(new MariaDB($db), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace('_project_' . $realtime->connections[$connection]['projectId']); + $database->setNamespace("_{$realtime->connections[$connection]['projectId']}"); /* * Abuse Check diff --git a/app/tasks/usage.php b/app/tasks/usage.php index e341dad3d8..d2180dbb72 100644 --- a/app/tasks/usage.php +++ b/app/tasks/usage.php @@ -223,7 +223,7 @@ $cli $dbForConsole = new Database(new MariaDB($db), $cacheAdapter); $dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); $dbForConsole->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $dbForConsole->setNamespace('_project_console'); + $dbForConsole->setNamespace('_console'); $latestTime = []; @@ -289,7 +289,7 @@ $cli $projectId = $point['projectId']; if (!empty($projectId) && $projectId !== 'console') { - $dbForProject->setNamespace('_project_' . $projectId); + $dbForProject->setNamespace("_{$projectId}"); $metricUpdated = $metric; if (!empty($groupBy)) { @@ -369,7 +369,7 @@ $cli $projectId = $project->getId(); // Get total storage - $dbForProject->setNamespace('_project_' . $projectId); + $dbForProject->setNamespace("_{$projectId}"); $storageTotal = $dbForProject->sum('files', 'sizeOriginal') + $dbForProject->sum('tags', 'size'); $time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes @@ -433,7 +433,7 @@ $cli foreach ($collections as $collection => $options) { try { - $dbForProject->setNamespace("_project_{$projectId}"); + $dbForProject->setNamespace("_{$projectId}"); $count = $dbForProject->count($collection); $metricPrefix = $options['metricPrefix'] ?? ''; $metric = empty($metricPrefix) ? "{$collection}.count" : "{$metricPrefix}.{$collection}.count"; @@ -488,7 +488,7 @@ $cli $subCollectionCounts = []; //total project level count of sub collections do { // Loop over all the parent collection document for each sub collection - $dbForProject->setNamespace("_project_{$projectId}"); + $dbForProject->setNamespace("_{$projectId}"); $parents = $dbForProject->find($collection, [], 100, cursor: $latestParent); // Get all the parents for the sub collections for example for documents, this will get all the collections if (empty($parents)) { @@ -499,12 +499,12 @@ $cli foreach ($parents as $parent) { foreach ($subCollections as $subCollection => $subOptions) { // Sub collection counts, like database.collections.collectionId.documents.count - $dbForProject->setNamespace("_project_{$projectId}"); + $dbForProject->setNamespace("_{$projectId}"); $count = $dbForProject->count($parent->getId()); $subCollectionCounts[$subCollection] = ($subCollectionCounts[$subCollection] ?? 0) + $count; // Project level counts for sub collections like database.documents.count - $dbForProject->setNamespace("_project_{$projectId}"); + $dbForProject->setNamespace("_{$projectId}"); $metric = empty($metricPrefix) ? "{$collection}.{$parent->getId()}.{$subCollection}.count" : "{$metricPrefix}.{$collection}.{$parent->getId()}.{$subCollection}.count"; $time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes @@ -554,7 +554,7 @@ $cli * Inserting project level counts for sub collections like database.documents.count */ foreach ($subCollectionCounts as $subCollection => $count) { - $dbForProject->setNamespace("_project_{$projectId}"); + $dbForProject->setNamespace("_{$projectId}"); $metric = empty($metricPrefix) ? "{$subCollection}.count" : "{$metricPrefix}.{$subCollection}.count"; diff --git a/app/workers/database.php b/app/workers/database.php index 94318e8cec..d95ce122d0 100644 --- a/app/workers/database.php +++ b/app/workers/database.php @@ -86,7 +86,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if(!$dbForProject->createAttribute('collection_' . $collectionId, $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if(!$dbForProject->createAttribute('collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); @@ -135,7 +135,7 @@ class DatabaseV1 extends Worker // - failed: attribute was never created // - stuck: attribute was available but cannot be removed try { - if($status !== 'failed' && !$dbForProject->deleteAttribute('collection_' . $collectionId, $key)) { + if($status !== 'failed' && !$dbForProject->deleteAttribute('collection_' . $collection->getInternalId(), $key)) { throw new Exception('Failed to delete Attribute'); } $dbForProject->deleteDocument('attributes', $attribute->getId()); @@ -210,7 +210,7 @@ class DatabaseV1 extends Worker } $dbForProject->deleteCachedDocument('collections', $collectionId); - $dbForProject->deleteCachedCollection('collection_' . $collectionId); + $dbForProject->deleteCachedCollection('collection_' . $collection->getInternalId()); } /** @@ -233,7 +233,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if(!$dbForProject->createIndex('collection_' . $collectionId, $key, $type, $attributes, $lengths, $orders)) { + if(!$dbForProject->createIndex('collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new Exception('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -276,7 +276,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if($status !== 'failed' && !$dbForProject->deleteIndex('collection_' . $collectionId, $key)) { + if($status !== 'failed' && !$dbForProject->deleteIndex('collection_' . $collection->getInternalId(), $key)) { throw new Exception('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); diff --git a/composer.json b/composer.json index e7bd6646a9..0eca952873 100644 --- a/composer.json +++ b/composer.json @@ -46,7 +46,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.14.*", + "utopia-php/database": "dev-fix-perms as 0.14.99", "utopia-php/locale": "0.4.*", "utopia-php/orchestration": "0.2.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index 91440e4a7a..145c13d227 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ab493f0a7f01a1105f8bc5caaf9b928b", + "content-hash": "eba5438fb1baf147ea65b20bba4dd5e8", "packages": [ { "name": "adhocore/jwt", @@ -1766,12 +1766,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -2141,16 +2141,16 @@ }, { "name": "utopia-php/database", - "version": "0.14.0", + "version": "dev-fix-perms", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "2f2527bb080cf578fba327ea2ec637064561d403" + "reference": "195fd16b69c0cd388c16051826ec59fa4647a610" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/2f2527bb080cf578fba327ea2ec637064561d403", - "reference": "2f2527bb080cf578fba327ea2ec637064561d403", + "url": "https://api.github.com/repos/utopia-php/database/zipball/195fd16b69c0cd388c16051826ec59fa4647a610", + "reference": "195fd16b69c0cd388c16051826ec59fa4647a610", "shasum": "" }, "require": { @@ -2198,9 +2198,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.14.0" + "source": "https://github.com/utopia-php/database/tree/fix-perms" }, - "time": "2022-01-21T16:34:34+00:00" + "time": "2022-02-07T12:09:11+00:00" }, { "name": "utopia-php/domains", @@ -2688,16 +2688,16 @@ }, { "name": "utopia-php/swoole", - "version": "0.3.2", + "version": "0.3.3", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "2b714eddf77cd5eda1889219c9656d7c0a63ce73" + "reference": "8312df69233b5dcd3992de88f131f238002749de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/2b714eddf77cd5eda1889219c9656d7c0a63ce73", - "reference": "2b714eddf77cd5eda1889219c9656d7c0a63ce73", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/8312df69233b5dcd3992de88f131f238002749de", + "reference": "8312df69233b5dcd3992de88f131f238002749de", "shasum": "" }, "require": { @@ -2738,9 +2738,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.3.2" + "source": "https://github.com/utopia-php/swoole/tree/0.3.3" }, - "time": "2021-12-13T15:37:41+00:00" + "time": "2022-01-20T09:58:43+00:00" }, { "name": "utopia-php/system", @@ -3037,12 +3037,12 @@ } }, "autoload": { - "psr-4": { - "Amp\\ByteStream\\": "lib" - }, "files": [ "lib/functions.php" - ] + ], + "psr-4": { + "Amp\\ByteStream\\": "lib" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3132,23 +3132,23 @@ }, { "name": "composer/pcre", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2" + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/3d322d715c43a1ac36c7fe215fa59336265500f2", - "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1", + "phpstan/phpstan": "^1.3", "phpstan/phpstan-strict-rules": "^1.1", "symfony/phpunit-bridge": "^4.2 || ^5" }, @@ -3183,7 +3183,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.0" + "source": "https://github.com/composer/pcre/tree/1.0.1" }, "funding": [ { @@ -3199,27 +3199,27 @@ "type": "tidelift" } ], - "time": "2021-12-06T15:17:27+00:00" + "time": "2022-01-21T20:24:37+00:00" }, { "name": "composer/semver", - "version": "3.2.7", + "version": "3.2.9", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "deac27056b57e46faf136fae7b449eeaa71661ee" + "reference": "a951f614bd64dcd26137bc9b7b2637ddcfc57649" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/deac27056b57e46faf136fae7b449eeaa71661ee", - "reference": "deac27056b57e46faf136fae7b449eeaa71661ee", + "url": "https://api.github.com/repos/composer/semver/zipball/a951f614bd64dcd26137bc9b7b2637ddcfc57649", + "reference": "a951f614bd64dcd26137bc9b7b2637ddcfc57649", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.54", + "phpstan/phpstan": "^1.4", "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", @@ -3264,7 +3264,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.7" + "source": "https://github.com/composer/semver/tree/3.2.9" }, "funding": [ { @@ -3280,7 +3280,7 @@ "type": "tidelift" } ], - "time": "2022-01-04T09:57:54+00:00" + "time": "2022-02-04T13:58:43+00:00" }, { "name": "composer/xdebug-handler", @@ -3703,6 +3703,9 @@ "require": { "php": "^7.1 || ^8.0" }, + "replace": { + "myclabs/deep-copy": "self.version" + }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", @@ -3710,12 +3713,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5721,16 +5724,16 @@ }, { "name": "symfony/console", - "version": "v6.0.2", + "version": "v6.0.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "dd434fa8d69325e5d210f63070014d889511fcb3" + "reference": "22e8efd019c3270c4f79376234a3f8752cd25490" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/dd434fa8d69325e5d210f63070014d889511fcb3", - "reference": "dd434fa8d69325e5d210f63070014d889511fcb3", + "url": "https://api.github.com/repos/symfony/console/zipball/22e8efd019c3270c4f79376234a3f8752cd25490", + "reference": "22e8efd019c3270c4f79376234a3f8752cd25490", "shasum": "" }, "require": { @@ -5796,7 +5799,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.2" + "source": "https://github.com/symfony/console/tree/v6.0.3" }, "funding": [ { @@ -5812,7 +5815,7 @@ "type": "tidelift" } ], - "time": "2021-12-27T21:05:08+00:00" + "time": "2022-01-26T17:23:29+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -5845,12 +5848,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5926,12 +5929,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -6090,12 +6093,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6222,16 +6225,16 @@ }, { "name": "symfony/string", - "version": "v6.0.2", + "version": "v6.0.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "bae261d0c3ac38a1f802b4dfed42094296100631" + "reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/bae261d0c3ac38a1f802b4dfed42094296100631", - "reference": "bae261d0c3ac38a1f802b4dfed42094296100631", + "url": "https://api.github.com/repos/symfony/string/zipball/522144f0c4c004c80d56fa47e40e17028e2eefc2", + "reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2", "shasum": "" }, "require": { @@ -6287,7 +6290,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.2" + "source": "https://github.com/symfony/string/tree/v6.0.3" }, "funding": [ { @@ -6303,7 +6306,7 @@ "type": "tidelift" } ], - "time": "2021-12-16T22:13:01+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "textalk/websocket", @@ -6406,16 +6409,16 @@ }, { "name": "twig/twig", - "version": "v2.14.10", + "version": "v2.14.11", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "95fb194cd4dd6ac373a27af2bde2bad5d3f27aba" + "reference": "66baa66f29ee30e487e05f1679903e36eb01d727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/95fb194cd4dd6ac373a27af2bde2bad5d3f27aba", - "reference": "95fb194cd4dd6ac373a27af2bde2bad5d3f27aba", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/66baa66f29ee30e487e05f1679903e36eb01d727", + "reference": "66baa66f29ee30e487e05f1679903e36eb01d727", "shasum": "" }, "require": { @@ -6470,7 +6473,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v2.14.10" + "source": "https://github.com/twigphp/Twig/tree/v2.14.11" }, "funding": [ { @@ -6482,7 +6485,7 @@ "type": "tidelift" } ], - "time": "2022-01-03T21:13:26+00:00" + "time": "2022-02-04T06:57:25+00:00" }, { "name": "vimeo/psalm", @@ -6561,13 +6564,13 @@ } }, "autoload": { - "psr-4": { - "Psalm\\": "src/Psalm/" - }, "files": [ "src/functions.php", "src/spl_object_id.php" - ] + ], + "psr-4": { + "Psalm\\": "src/Psalm/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6642,9 +6645,18 @@ "time": "2015-12-17T08:42:14+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-fix-perms", + "alias": "0.14.99", + "alias_normalized": "0.14.99.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -6666,5 +6678,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.1.0" } diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index b9ed5af275..d9bad8b90c 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -178,10 +178,10 @@ abstract class Worker if (!$projectId) { throw new \Exception('ProjectID not provided - cannot get database'); } - $namespace = "_project_{$projectId}"; + $namespace = "_{$projectId}"; break; case self::DATABASE_CONSOLE: - $namespace = "_project_console"; + $namespace = "_console"; $sleep = 5; // ConsoleDB needs extra sleep time to ensure tables are created break; default: From ccff540e70f2e572b0def7163d4d0e4d496bbf5a Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 17 Feb 2022 19:24:50 +0100 Subject: [PATCH 02/13] feat: migration --- app/tasks/migrate.php | 8 +- src/Appwrite/Migration/Migration.php | 28 +++- src/Appwrite/Migration/Version/V12.php | 170 +++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 6 deletions(-) diff --git a/app/tasks/migrate.php b/app/tasks/migrate.php index 416f936d4c..ff0705eb32 100644 --- a/app/tasks/migrate.php +++ b/app/tasks/migrate.php @@ -46,7 +46,13 @@ $cli $offset = 0; $projects = [$console]; $count = 0; - $totalProjects = $consoleDB->count('projects') + 1; + + try { + $totalProjects = $consoleDB->count('projects') + 1; + } catch (\Throwable $th) { + $consoleDB->setNamespace('_console'); + $totalProjects = $consoleDB->count('projects') + 1; + } $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; $migration = new $class(); diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index d00318f212..19dba9a4fa 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -38,6 +38,26 @@ abstract class Migration '0.13.0' => 'V12', ]; + /** + * @var array + */ + protected array $collections; + + public function __construct() + { + $this->collections = array_merge([ + '_metadata' => [ + '$id' => '_metadata' + ], + 'audit' => [ + '$id' => 'audit' + ], + 'abuse' => [ + '$id' => 'abuse' + ] + ], Config::getParam('collections', [])); + } + /** * Set project for migration. * @@ -51,7 +71,7 @@ abstract class Migration { $this->project = $project; $this->projectDB = $projectDB; - $this->projectDB->setNamespace('_project_' . $this->project->getId()); + $this->projectDB->setNamespace('_' . $this->project->getId()); $this->consoleDB = $consoleDB; @@ -67,10 +87,7 @@ abstract class Migration { Runtime::enableCoroutine(SWOOLE_HOOK_ALL); - /** @var array $collections */ - $collections = Config::getParam('collections', []); - - foreach ($collections as $collection) { + foreach ($this->collections as $collection) { $sum = 0; $nextDocument = null; $collectionCount = $this->projectDB->count($collection['$id']); @@ -114,6 +131,7 @@ abstract class Migration try { $new = $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); } catch (\Throwable $th) { + var_dump($th->getTraceAsString()); Console::error('Failed to update document: ' . $th->getMessage()); return; diff --git a/src/Appwrite/Migration/Version/V12.php b/src/Appwrite/Migration/Version/V12.php index 9b9376abac..5835f66dac 100644 --- a/src/Appwrite/Migration/Version/V12.php +++ b/src/Appwrite/Migration/Version/V12.php @@ -4,17 +4,178 @@ namespace Appwrite\Migration\Version; use Appwrite\Migration\Migration; use Utopia\CLI\Console; +use Utopia\Database\Database; use Utopia\Database\Document; class V12 extends Migration { + /** + * @var \PDO $pdo + */ + private $pdo; + public function execute(): void { + global $register; Console::log('Migrating project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + $this->pdo = $register->get('db'); + + Console::info('Migrating Project Schemas'); + $this->migrateProjectSchema($this->project->getId()); + + /** + * Switch to migrated Console Project + */ + if ($this->project->getId() === 'console') { + $this->consoleDB->setNamespace('_console'); + $this->projectDB->setNamespace('_console'); + } + + Console::info('Migrating Permissions'); + $this->fixPermissions(); + Console::info('Migrating Collections'); + $this->fixCollections(); + Console::info('Migrating Documents'); $this->forEachDocument([$this, 'fixDocument']); } + /** + * Migrate Project Tables. + * + * @param string $projectId + * @return void + * @throws \Exception + * @throws \PDOException + */ + private function migrateProjectSchema(string $projectId): void + { + /** + * Remove empty generated Console Project. + */ + if ($this->projectDB->getNamespace() === '_project_console') { + $all = []; + foreach ($this->collections as $collection) { + $all[] = "_{$projectId}_{$collection['$id']}"; + $all[] = "_{$projectId}_{$collection['$id']}_perms"; + } + $this->pdo->prepare('DROP TABLE IF EXISTS ' . implode(', ', $all) . ';')->execute(); + } elseif ($this->projectDB->getNamespace() === '_console') { + return; + } + + /** + * Rename Database Tables. + */ + foreach ($this->collections as $collection) { + $id = $collection['$id']; + + $this->pdo->prepare("ALTER TABLE IF EXISTS _project_{$projectId}_{$id} RENAME TO _{$projectId}_{$id}")->execute(); + $this->pdo->prepare("CREATE TABLE IF NOT EXISTS _{$projectId}_{$id}_perms ( + `_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `_type` VARCHAR(12) NOT NULL, + `_permission` VARCHAR(255) NOT NULL, + `_document` VARCHAR(255) NOT NULL, + PRIMARY KEY (`_id`), + UNIQUE INDEX `_index1` (`_type`,`_document`,`_permission`), + INDEX `_index2` (`_permission`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;")->execute(); + } + } + + /** + * Migrate all Collection Structure. + * + * @return void + */ + protected function fixCollections(): void + { + foreach ($this->collections as $collection) { + $id = $collection['$id']; + Console::log("- {$id}"); + switch ($id) { + case 'sessions': + try { + $this->projectDB->renameAttribute($id, 'providerToken', 'providerAccessToken'); + } catch (\Throwable $th) { + Console::warning("'providerAccessToken' from {$id}: {$th->getMessage()}"); + } + try { + $this->projectDB->createAttribute(collection: $id, id: 'providerRefreshToken', type: Database::VAR_STRING, size: 16384, signed: true, required: true, filters: ['encrypt']); + } catch (\Throwable $th) { + Console::warning("'providerRefreshToken' from {$id}: {$th->getMessage()}"); + } + try { + $this->projectDB->createAttribute(collection: $id, id: 'providerAccessTokenExpiry', type: Database::VAR_INTEGER, size: 0, required: true); + } catch (\Throwable $th) { + Console::warning("'providerAccessTokenExpiry' from {$id}: {$th->getMessage()}"); + } + break; + } + usleep(100000); + } + } + + /** + * Migrate all Permission to new System with dedicated Table. + * @return void + * @throws \Exception + */ + protected function fixPermissions() + { + foreach ($this->collections as $collection) { + $id = $collection['$id']; + Console::log("- {$collection['$id']}"); + $nextDocument = null; + + do { + $documents = $this->projectDB->find($id, limit: $this->limit, cursor: $nextDocument); + $count = count($documents); + + \Co\run(function (array $documents) { + foreach ($documents as $document) { + go(function (Document $document) { + $sql = "SELECT _read, _write FROM `{$this->projectDB->getDefaultDatabase()}`.`{$this->projectDB->getNamespace()}_{$document->getCollection()}` WHERE _uid = {$this->pdo->quote($document->getid())}"; + $stmt = $this->pdo->prepare($sql); + $stmt->execute(); + + $permissions = $stmt->fetch(); + + $read = json_decode($permissions['_read'] ?? null) ?? []; + $write = json_decode($permissions['_write'] ?? null) ?? []; + + $permissions = []; + foreach ($read as $permission) { + $permissions[] = "('read', '{$permission}', '{$document->getId()}')"; + } + + foreach ($write as $permission) { + $permissions[] = "('write', '{$permission}', '{$document->getId()}')"; + } + + if (!empty($permissions)) { + $queryPermissions = "INSERT IGNORE INTO `{$this->projectDB->getDefaultDatabase()}`.`{$this->projectDB->getNamespace()}_{$document->getCollection()}_perms` (_type, _permission, _document) VALUES " . implode(', ', $permissions); + $stmtPermissions = $this->pdo->prepare($queryPermissions); + $stmtPermissions->execute(); + } + }, $document); + } + }, $documents); + + if ($count !== $this->limit) { + $nextDocument = null; + } else { + $nextDocument = end($documents); + } + } while (!is_null($nextDocument)); + } + + /** + * Timeout to give MariaDB some room to breath + */ + usleep(100000); + } + protected function fixDocument(Document $document) { switch ($document->getCollection()) { @@ -92,6 +253,15 @@ class V12 extends Migration } break; + + case 'sessions': + $document + ->setAttribute('providerRefreshToken', '') + ->setAttribute('providerAccessTokenExpiry', 0) + ->setAttribute('providerAccessToken', $document->getAttribute('providerToken', '')) + ->removeAttribute('providerToken'); + + break; } return $document; From 8271f87e44c5fedb949015cf1a87a5250e19c884 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 17 Feb 2022 20:22:51 +0100 Subject: [PATCH 03/13] fix: multiple migrations --- src/Appwrite/Migration/Version/V12.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V12.php b/src/Appwrite/Migration/Version/V12.php index 5835f66dac..73177b61fb 100644 --- a/src/Appwrite/Migration/Version/V12.php +++ b/src/Appwrite/Migration/Version/V12.php @@ -53,7 +53,7 @@ class V12 extends Migration /** * Remove empty generated Console Project. */ - if ($this->projectDB->getNamespace() === '_project_console') { + if ($this->consoleDB->getNamespace() === '_project_console' && $projectId === 'console') { $all = []; foreach ($this->collections as $collection) { $all[] = "_{$projectId}_{$collection['$id']}"; From 087c755b111b5114b3861cd2abce05ef5a3df62e Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 18 Feb 2022 10:14:44 +0100 Subject: [PATCH 04/13] tests: add timeout to realtime disconnect --- tests/e2e/Services/Realtime/RealtimeBase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/Services/Realtime/RealtimeBase.php b/tests/e2e/Services/Realtime/RealtimeBase.php index 4357bec383..62bb7f5d3b 100644 --- a/tests/e2e/Services/Realtime/RealtimeBase.php +++ b/tests/e2e/Services/Realtime/RealtimeBase.php @@ -48,6 +48,7 @@ trait RealtimeBase $this->assertEquals('error', $payload['type']); $this->assertEquals(1008, $payload['data']['code']); $this->assertEquals('Missing channels', $payload['data']['message']); + \usleep(250000); // 250ms $this->expectException(ConnectionException::class); // Check if server disconnnected client $client->close(); } From 568479bcfd52dc0b7827f45f4974e41db0a222b4 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 21 Feb 2022 20:57:52 +0100 Subject: [PATCH 05/13] chore: update composer deps --- composer.json | 2 +- composer.lock | 85 +++++++++++++++++++++++---------------------------- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/composer.json b/composer.json index d910d3f6b4..b305b75f1a 100644 --- a/composer.json +++ b/composer.json @@ -46,7 +46,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-fix-perms as 0.14.99", + "utopia-php/database": "0.15.*", "utopia-php/locale": "0.4.*", "utopia-php/orchestration": "0.2.*", "utopia-php/registry": "0.5.*", diff --git a/composer.lock b/composer.lock index fa21f62a7b..5decac9ba0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "85bddee9d6951fa078bee158e8b9bd5a", + "content-hash": "616810ade71f45030c2c678e2d90c51d", "packages": [ { "name": "adhocore/jwt", @@ -2141,16 +2141,16 @@ }, { "name": "utopia-php/database", - "version": "dev-fix-perms", + "version": "0.15.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "49c74b0d8455c616895b794b24496f32f0e91b5a" + "reference": "19d581575ac20bf2e81ffa63ad0e0b52aa96d0a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/49c74b0d8455c616895b794b24496f32f0e91b5a", - "reference": "49c74b0d8455c616895b794b24496f32f0e91b5a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/19d581575ac20bf2e81ffa63ad0e0b52aa96d0a8", + "reference": "19d581575ac20bf2e81ffa63ad0e0b52aa96d0a8", "shasum": "" }, "require": { @@ -2198,9 +2198,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/fix-perms" + "source": "https://github.com/utopia-php/database/tree/0.15.0" }, - "time": "2022-02-17T14:32:38+00:00" + "time": "2022-02-21T18:04:57+00:00" }, { "name": "utopia-php/domains", @@ -2258,16 +2258,16 @@ }, { "name": "utopia-php/framework", - "version": "0.19.6", + "version": "0.19.7", "source": { "type": "git", "url": "https://github.com/utopia-php/framework.git", - "reference": "7d9b28365fb794001cb34dd028659452d4e71b7d" + "reference": "f17afe77a21873b9be18ebc05283813468b4283a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/framework/zipball/7d9b28365fb794001cb34dd028659452d4e71b7d", - "reference": "7d9b28365fb794001cb34dd028659452d4e71b7d", + "url": "https://api.github.com/repos/utopia-php/framework/zipball/f17afe77a21873b9be18ebc05283813468b4283a", + "reference": "f17afe77a21873b9be18ebc05283813468b4283a", "shasum": "" }, "require": { @@ -2301,9 +2301,9 @@ ], "support": { "issues": "https://github.com/utopia-php/framework/issues", - "source": "https://github.com/utopia-php/framework/tree/0.19.6" + "source": "https://github.com/utopia-php/framework/tree/0.19.7" }, - "time": "2022-02-10T17:05:22+00:00" + "time": "2022-02-18T00:04:49+00:00" }, { "name": "utopia-php/image", @@ -2917,16 +2917,16 @@ "packages-dev": [ { "name": "amphp/amp", - "version": "v2.6.1", + "version": "v2.6.2", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", - "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae" + "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", - "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", + "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", "shasum": "" }, "require": { @@ -2948,13 +2948,13 @@ } }, "autoload": { - "psr-4": { - "Amp\\": "lib" - }, "files": [ "lib/functions.php", "lib/Internal/functions.php" - ] + ], + "psr-4": { + "Amp\\": "lib" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2979,7 +2979,7 @@ } ], "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "http://amphp.org/amp", + "homepage": "https://amphp.org/amp", "keywords": [ "async", "asynchronous", @@ -2994,7 +2994,7 @@ "support": { "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.1" + "source": "https://github.com/amphp/amp/tree/v2.6.2" }, "funding": [ { @@ -3002,7 +3002,7 @@ "type": "github" } ], - "time": "2021-09-23T18:43:08+00:00" + "time": "2022-02-20T17:52:18+00:00" }, { "name": "amphp/byte-stream", @@ -3966,16 +3966,16 @@ }, { "name": "phar-io/version", - "version": "3.1.1", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "15a90844ad40f127afd244c0cad228de2a80052a" + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/15a90844ad40f127afd244c0cad228de2a80052a", - "reference": "15a90844ad40f127afd244c0cad228de2a80052a", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { @@ -4011,9 +4011,9 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.1" + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "time": "2022-02-07T21:56:48+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -4244,16 +4244,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.10", + "version": "9.2.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687" + "reference": "665a1ac0a763c51afc30d6d130dac0813092b17f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687", - "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/665a1ac0a763c51afc30d6d130dac0813092b17f", + "reference": "665a1ac0a763c51afc30d6d130dac0813092b17f", "shasum": "" }, "require": { @@ -4309,7 +4309,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.11" }, "funding": [ { @@ -4317,7 +4317,7 @@ "type": "github" } ], - "time": "2021-12-05T09:12:13+00:00" + "time": "2022-02-18T12:46:09+00:00" }, { "name": "phpunit/php-file-iterator", @@ -6645,18 +6645,9 @@ "time": "2015-12-17T08:42:14+00:00" } ], - "aliases": [ - { - "package": "utopia-php/database", - "version": "dev-fix-perms", - "alias": "0.14.99", - "alias_normalized": "0.14.99.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From b05a4c71ce2efdfbab3a9a15fe3a61435387b21f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 21 Feb 2022 21:53:23 +0000 Subject: [PATCH 06/13] tests: fix user search tests --- tests/e2e/Services/Users/UsersBase.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 3084ff5e28..3257ce7755 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -149,7 +149,21 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'manchester-united.co.uk' + 'search' => '*united.co.uk' + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertIsArray($response['body']); + $this->assertIsArray($response['body']['users']); + $this->assertIsInt($response['body']['sum']); + $this->assertEquals(1, $response['body']['sum']); + $this->assertCount(1, $response['body']['users']); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => '*manchester*' ]); $this->assertEquals($response['headers']['status-code'], 200); From 61d7e9083debf0f1a724975550ccd939d052e967 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 22 Feb 2022 10:35:54 +0100 Subject: [PATCH 07/13] chore: update composer deps --- composer.lock | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/composer.lock b/composer.lock index 5decac9ba0..be3d2fc931 100644 --- a/composer.lock +++ b/composer.lock @@ -2141,16 +2141,16 @@ }, { "name": "utopia-php/database", - "version": "0.15.0", + "version": "0.15.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "19d581575ac20bf2e81ffa63ad0e0b52aa96d0a8" + "reference": "eb4f61ec40d697acdfd574638ecd075e4f44b864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/19d581575ac20bf2e81ffa63ad0e0b52aa96d0a8", - "reference": "19d581575ac20bf2e81ffa63ad0e0b52aa96d0a8", + "url": "https://api.github.com/repos/utopia-php/database/zipball/eb4f61ec40d697acdfd574638ecd075e4f44b864", + "reference": "eb4f61ec40d697acdfd574638ecd075e4f44b864", "shasum": "" }, "require": { @@ -2198,9 +2198,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.15.0" + "source": "https://github.com/utopia-php/database/tree/0.15.1" }, - "time": "2022-02-21T18:04:57+00:00" + "time": "2022-02-22T09:33:37+00:00" }, { "name": "utopia-php/domains", @@ -3703,9 +3703,6 @@ "require": { "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" - }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", @@ -6669,5 +6666,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.2.0" } From a831aca7782b1dedc1052b69bd6b94acaacbf471 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 22 Feb 2022 10:39:33 +0100 Subject: [PATCH 08/13] tests: adapt search tests --- tests/e2e/Services/Users/UsersBase.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 3257ce7755..cf2887081d 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -149,7 +149,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => '*united.co.uk' + 'search' => 'united.co.uk' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -163,7 +163,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => '*manchester*' + 'search' => 'man' ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -179,6 +179,7 @@ trait UsersBase ], $this->getHeaders()), [ 'search' => $data['userId'] ]); + $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['users']); From c5c53105f21421ca3f9fc41961c6045667f5c0e9 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 28 Feb 2022 10:31:15 +0100 Subject: [PATCH 09/13] fix: remove leftover --- src/Appwrite/Migration/Migration.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index f26a289767..2f08e8815f 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -131,7 +131,6 @@ abstract class Migration try { $new = $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); } catch (\Throwable $th) { - var_dump($th->getTraceAsString()); Console::error('Failed to update document: ' . $th->getMessage()); return; From 70fa9ff29da4fff5e4592cbdd5116de93c5ef455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Feb 2022 10:41:39 +0000 Subject: [PATCH 10/13] Improved Token passing --- app/controllers/general.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index afe9a5f5e2..9450a5fd55 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -552,11 +552,8 @@ App::get('/.well-known/acme-challenge') throw new Exception('Invalid challenge token.', 400); } - $filePath = '/.well-known/acme-challenge' . $token; - $base = \realpath(APP_STORAGE_CERTIFICATES); - $path = \str_replace('/.well-known/acme-challenge/', '', $filePath); - $absolute = \realpath($base.'/.well-known/acme-challenge/'.$path); + $absolute = \realpath($base.'/.well-known/acme-challenge/'.$token); if (!$base) { throw new Exception('Storage error', 500, Exception::GENERAL_SERVER_ERROR); From b5de295fbd7b9f97fdf6c65ea1eaa5c6dae4afa9 Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Wed, 23 Feb 2022 16:09:05 +0530 Subject: [PATCH 11/13] Add line breaks in CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 341ffcd0fb..f689852093 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,9 +48,9 @@ $ git checkout -b [name_of_your_new_branch] $ git push origin [name_of_your_new_branch] ``` -5. Submit your changes for review +5. Submit your changes for review If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button. -6. Start a Pull Request +6. Start a Pull Request Now submit the pull request and click on `Create pull request`. 7. Get a code review approval/reject 8. After approval, merge your PR From f2c063817df034758ee5a533442bba9faf8f39cb Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 28 Feb 2022 10:45:22 +0100 Subject: [PATCH 12/13] Revert "Improved Token passing" This reverts commit 70fa9ff29da4fff5e4592cbdd5116de93c5ef455. --- app/controllers/general.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9450a5fd55..afe9a5f5e2 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -552,8 +552,11 @@ App::get('/.well-known/acme-challenge') throw new Exception('Invalid challenge token.', 400); } + $filePath = '/.well-known/acme-challenge' . $token; + $base = \realpath(APP_STORAGE_CERTIFICATES); - $absolute = \realpath($base.'/.well-known/acme-challenge/'.$token); + $path = \str_replace('/.well-known/acme-challenge/', '', $filePath); + $absolute = \realpath($base.'/.well-known/acme-challenge/'.$path); if (!$base) { throw new Exception('Storage error', 500, Exception::GENERAL_SERVER_ERROR); From 3ceb80ea8afabd11fefe800451e669c0b14e35b7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 28 Feb 2022 10:45:24 +0100 Subject: [PATCH 13/13] Revert "Add line breaks in CONTRIBUTING.md" This reverts commit b5de295fbd7b9f97fdf6c65ea1eaa5c6dae4afa9. --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f689852093..341ffcd0fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,9 +48,9 @@ $ git checkout -b [name_of_your_new_branch] $ git push origin [name_of_your_new_branch] ``` -5. Submit your changes for review +5. Submit your changes for review If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button. -6. Start a Pull Request +6. Start a Pull Request Now submit the pull request and click on `Create pull request`. 7. Get a code review approval/reject 8. After approval, merge your PR