From 464b913e90bd2dcf62b22334902dcf4a287d1ade Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 22 Nov 2023 21:32:36 +1300 Subject: [PATCH 01/61] Update for function name change --- app/cli.php | 2 +- app/http.php | 2 +- app/init.php | 44 ++++++++----------- appwrite.json | 4 ++ src/Appwrite/Migration/Migration.php | 2 +- src/Appwrite/Migration/Version/V15.php | 18 ++++---- src/Appwrite/Migration/Version/V18.php | 4 +- src/Appwrite/Migration/Version/V19.php | 2 +- src/Appwrite/Platform/Tasks/CalcTierStats.php | 2 +- .../Platform/Tasks/DeleteOrphanedProjects.php | 6 +-- src/Appwrite/Platform/Tasks/Hamster.php | 2 +- 11 files changed, 42 insertions(+), 46 deletions(-) create mode 100644 appwrite.json diff --git a/app/cli.php b/app/cli.php index 643a615c46..d3e44ea398 100644 --- a/app/cli.php +++ b/app/cli.php @@ -71,7 +71,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { $collections = Config::getParam('collections', [])['console']; $last = \array_key_last($collections); - if (!($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */ + if (!($dbForConsole->exists($dbForConsole->getDatabase(), $last))) { /** TODO cache ready variable using registry */ throw new Exception('Tables not ready yet.'); } diff --git a/app/http.php b/app/http.php index fe1ed48724..781df53e98 100644 --- a/app/http.php +++ b/app/http.php @@ -147,7 +147,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { $dbForConsole->createCollection($key, $attributes, $indexes); } - if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) { + if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) { Console::success('[Setup] - Creating default bucket...'); $dbForConsole->createDocument('buckets', new Document([ '$id' => ID::custom('default'), diff --git a/app/init.php b/app/init.php index 2c0219eec2..69dcdc737b 100644 --- a/app/init.php +++ b/app/init.php @@ -12,11 +12,11 @@ if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } -ini_set('memory_limit', '512M'); -ini_set('display_errors', 1); -ini_set('display_startup_errors', 1); -ini_set('default_socket_timeout', -1); -error_reporting(E_ALL); +\ini_set('memory_limit', '512M'); +\ini_set('display_errors', 1); +\ini_set('display_startup_errors', 1); +\ini_set('default_socket_timeout', -1); +\error_reporting(E_ALL); use Appwrite\Event\Migration; use Appwrite\Extend\Exception; @@ -34,6 +34,7 @@ use Appwrite\OpenSSL\OpenSSL; use Appwrite\URL\URL as AppwriteURL; use Appwrite\Usage\Stats; use Utopia\App; +use Utopia\CLI\Console; use Utopia\Logger\Logger; use Utopia\Cache\Adapter\Redis as RedisCache; use Utopia\Cache\Cache; @@ -653,14 +654,13 @@ $register->set('pools', function () { foreach ($connections as $key => $connection) { $type = $connection['type'] ?? ''; - $dsns = $connection['dsns'] ?? ''; - $multipe = $connection['multiple'] ?? false; + $multiple = $connection['multiple'] ?? false; $schemes = $connection['schemes'] ?? []; $config = []; $dsns = explode(',', $connection['dsns'] ?? ''); foreach ($dsns as &$dsn) { $dsn = explode('=', $dsn); - $name = ($multipe) ? $key . '_' . $dsn[0] : $key; + $name = ($multiple) ? $key . '_' . $dsn[0] : $key; $dsn = $dsn[1] ?? ''; $config[] = $name; if (empty($dsn)) { @@ -732,7 +732,7 @@ $register->set('pools', function () { default => null }; - $adapter->setDefaultDatabase($dsn->getPath()); + $adapter->setDatabase($dsn->getPath()); break; case 'pubsub': $adapter = $resource(); @@ -1136,8 +1136,7 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) { $dbAdapter = $pools ->get('console') ->pop() - ->getResource() - ; + ->getResource(); $database = new Database($dbAdapter, $cache); @@ -1247,21 +1246,14 @@ function getDevice($root): Device Console::warning($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); } - switch ($device) { - case Storage::DEVICE_S3: - return new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case STORAGE::DEVICE_DO_SPACES: - return new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_BACKBLAZE: - return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_LINODE: - return new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_WASABI: - return new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_LOCAL: - default: - return new Local($root); - } + return match ($device) { + Storage::DEVICE_S3 => new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl), + STORAGE::DEVICE_DO_SPACES => new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl), + Storage::DEVICE_BACKBLAZE => new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl), + Storage::DEVICE_LINODE => new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl), + Storage::DEVICE_WASABI => new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl), + default => new Local($root), + }; } else { switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) { case Storage::DEVICE_LOCAL: diff --git a/appwrite.json b/appwrite.json new file mode 100644 index 0000000000..e3d948ed1a --- /dev/null +++ b/appwrite.json @@ -0,0 +1,4 @@ +{ + "projectId": "console", + "projectName": "" +} \ No newline at end of file diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 8f68e31be4..de26941a5a 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -388,7 +388,7 @@ abstract class Migration */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void { - $stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); + $stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); try { $stmt->execute(); diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index 60f5fa20ab..9d8af4482a 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -295,7 +295,7 @@ class V15 extends Migration protected function removeWritePermissions(string $table): void { try { - $this->pdo->prepare("DELETE FROM `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); + $this->pdo->prepare("DELETE FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); } catch (\Throwable $th) { Console::warning("Remove 'write' permissions from {$table}: {$th->getMessage()}"); } @@ -311,7 +311,7 @@ class V15 extends Migration */ protected function getSQLColumnTypes(string $table): array { - $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->projectDB->getDefaultDatabase()}'"); + $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->projectDB->getDatabase()}'"); $query->execute(); return array_reduce($query->fetchAll(), function (array $carry, array $item) { @@ -333,8 +333,8 @@ class V15 extends Migration if ($columns[$attribute] === 'int') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); - $this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); + $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); $columns[$attribute] = 'varchar'; } catch (\Throwable $th) { Console::warning($th->getMessage()); @@ -343,7 +343,7 @@ class V15 extends Migration if ($columns[$attribute] === 'varchar') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -389,7 +389,7 @@ class V15 extends Migration if (!array_key_exists('_permissions', $columns)) { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { Console::warning("Add '_permissions' column to '{$table}': {$th->getMessage()}"); } @@ -410,7 +410,7 @@ class V15 extends Migration { $table ??= $document->getCollection(); - $query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); + $query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); $query->execute(); $results = $query->fetchAll(); $permissions = []; @@ -1472,9 +1472,9 @@ class V15 extends Migration $from = $this->pdo->quote($from); $to = $this->pdo->quote($to); - $this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); + $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); + Console::warning("Migrating steps from {$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); } } diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index 839269f940..12d573e549 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -244,7 +244,7 @@ class V18 extends Migration /** * Create 'documentSecurity' column */ - $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); + $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -253,7 +253,7 @@ class V18 extends Migration /** * Set 'documentSecurity' column to 1 if NULL */ - $this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); + $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index b9ccf3c302..c04a3b03de 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -50,7 +50,7 @@ class V19 extends Migration protected function migrateDomains(): void { - if ($this->consoleDB->exists($this->consoleDB->getDefaultDatabase(), 'domains')) { + if ($this->consoleDB->exists($this->consoleDB->getDatabase(), 'domains')) { foreach ($this->documentsIterator('domains') as $domain) { $status = 'created'; if ($domain->getAttribute('verification', false)) { diff --git a/src/Appwrite/Platform/Tasks/CalcTierStats.php b/src/Appwrite/Platform/Tasks/CalcTierStats.php index 2a2bc20af9..e5a9550666 100644 --- a/src/Appwrite/Platform/Tasks/CalcTierStats.php +++ b/src/Appwrite/Platform/Tasks/CalcTierStats.php @@ -122,7 +122,7 @@ class CalcTierStats extends Action ->getResource(); $dbForProject = new Database($adapter, $cache); - $dbForProject->setDefaultDatabase('appwrite'); + $dbForProject->setDatabase('appwrite'); $dbForProject->setNamespace('_' . $project->getInternalId()); /** Get Project ID */ diff --git a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php index 757b29c1b6..5a04df04ba 100644 --- a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php +++ b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php @@ -90,12 +90,12 @@ class DeleteOrphanedProjects extends Action ->getResource(); $dbForProject = new Database($adapter, $cache); - $dbForProject->setDefaultDatabase('appwrite'); + $dbForProject->setDatabase('appwrite'); $dbForProject->setNamespace('_' . $project->getInternalId()); $collectionsCreated = 0; $cnt++; - if ($dbForProject->exists($dbForProject->getDefaultDatabase(), Database::METADATA)) { + if ($dbForProject->exists($dbForProject->getDatabase(), Database::METADATA)) { $collectionsCreated = $dbForProject->count(Database::METADATA); } @@ -123,7 +123,7 @@ class DeleteOrphanedProjects extends Action $dbForConsole->deleteDocument('projects', $project->getId()); $dbForConsole->deleteCachedDocument('projects', $project->getId()); - if ($dbForProject->exists($dbForProject->getDefaultDatabase(), Database::METADATA)) { + if ($dbForProject->exists($dbForProject->getDatabase(), Database::METADATA)) { try { $dbForProject->deleteCollection(Database::METADATA); $dbForProject->deleteCachedCollection(Database::METADATA); diff --git a/src/Appwrite/Platform/Tasks/Hamster.php b/src/Appwrite/Platform/Tasks/Hamster.php index 1d5d3b0b26..0947da65d9 100644 --- a/src/Appwrite/Platform/Tasks/Hamster.php +++ b/src/Appwrite/Platform/Tasks/Hamster.php @@ -81,7 +81,7 @@ class Hamster extends Action ->getResource(); $dbForProject = new Database($adapter, $cache); - $dbForProject->setDefaultDatabase('appwrite'); + $dbForProject->setDatabase('appwrite'); $dbForProject->setNamespace('_' . $project->getInternalId()); $statsPerProject = []; From eb5fc0797fc4b190d1668b6cd6582078aa6e81c8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 23 Nov 2023 00:43:32 +1300 Subject: [PATCH 02/61] Update abuse/audit --- composer.json | 6 ++--- composer.lock | 69 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/composer.json b/composer.json index a24feca83b..0d62b47988 100644 --- a/composer.json +++ b/composer.json @@ -43,13 +43,13 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.13.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.33.*", + "utopia-php/abuse": "dev-feat-isolation-modes as 0.33.0", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.35.*", + "utopia-php/audit": "dev-feat-isolation-modes as 0.35.0", "utopia-php/cache": "0.8.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.45.*", + "utopia-php/database": "dev-feat-isolation-mode as 0.45.2", "utopia-php/domains": "0.3.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.31.0", diff --git a/composer.lock b/composer.lock index d362f3aa9c..3f9bf551d2 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": "69bc2e21a65b78344393706b39d789b4", + "content-hash": "2c23008af30193734b6717a41632aa54", "packages": [ { "name": "adhocore/jwt", @@ -1615,23 +1615,23 @@ }, { "name": "utopia-php/abuse", - "version": "0.33.0", + "version": "dev-feat-isolation-modes", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "1ba8d5f2793885cbf779e3b5b9d886968af43d2c" + "reference": "171eda04bfc53e5e24bdb36230ae84fe686ac2ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/1ba8d5f2793885cbf779e3b5b9d886968af43d2c", - "reference": "1ba8d5f2793885cbf779e3b5b9d886968af43d2c", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/171eda04bfc53e5e24bdb36230ae84fe686ac2ee", + "reference": "171eda04bfc53e5e24bdb36230ae84fe686ac2ee", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.45.*" + "utopia-php/database": "dev-feat-isolation-mode as 0.45.0" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1658,9 +1658,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.33.0" + "source": "https://github.com/utopia-php/abuse/tree/feat-isolation-modes" }, - "time": "2023-11-01T08:51:33+00:00" + "time": "2023-11-22T09:49:43+00:00" }, { "name": "utopia-php/analytics", @@ -1710,21 +1710,21 @@ }, { "name": "utopia-php/audit", - "version": "0.35.0", + "version": "dev-feat-isolation-modes", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "ed9366ef05556da040de7a8b570f4160c7d8ea4a" + "reference": "b561fa872c60e28afda02b4428ad5a2444099c44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/ed9366ef05556da040de7a8b570f4160c7d8ea4a", - "reference": "ed9366ef05556da040de7a8b570f4160c7d8ea4a", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/b561fa872c60e28afda02b4428ad5a2444099c44", + "reference": "b561fa872c60e28afda02b4428ad5a2444099c44", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.45.*" + "utopia-php/database": "dev-feat-isolation-mode as 0.45.0" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1751,9 +1751,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.35.0" + "source": "https://github.com/utopia-php/audit/tree/feat-isolation-modes" }, - "time": "2023-11-01T08:51:29+00:00" + "time": "2023-11-22T09:49:57+00:00" }, { "name": "utopia-php/cache", @@ -1906,16 +1906,16 @@ }, { "name": "utopia-php/database", - "version": "0.45.2", + "version": "dev-feat-isolation-mode", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "dc789f2c1fd8b5ee07ff883e11c9ad7970824788" + "reference": "b7bcc9b373242a9e494b0b7bbf78dfa54333727c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/dc789f2c1fd8b5ee07ff883e11c9ad7970824788", - "reference": "dc789f2c1fd8b5ee07ff883e11c9ad7970824788", + "url": "https://api.github.com/repos/utopia-php/database/zipball/b7bcc9b373242a9e494b0b7bbf78dfa54333727c", + "reference": "b7bcc9b373242a9e494b0b7bbf78dfa54333727c", "shasum": "" }, "require": { @@ -1956,9 +1956,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.45.2" + "source": "https://github.com/utopia-php/database/tree/feat-isolation-mode" }, - "time": "2023-11-15T03:38:47+00:00" + "time": "2023-11-22T07:58:21+00:00" }, { "name": "utopia-php/domains", @@ -5796,9 +5796,32 @@ "time": "2023-08-28T11:09:02+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/abuse", + "version": "dev-feat-isolation-modes", + "alias": "0.33.0", + "alias_normalized": "0.33.0.0" + }, + { + "package": "utopia-php/audit", + "version": "dev-feat-isolation-modes", + "alias": "0.35.0", + "alias_normalized": "0.35.0.0" + }, + { + "package": "utopia-php/database", + "version": "dev-feat-isolation-mode", + "alias": "0.45.2", + "alias_normalized": "0.45.2.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/abuse": 20, + "utopia-php/audit": 20, + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From cefc1b6519e8f34e7aeb71d2d5c6704f8117b3e3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 23 Nov 2023 01:11:48 +1300 Subject: [PATCH 03/61] Add base share tables check when creating project --- app/controllers/api/projects.php | 64 +++++++++++++++++--------------- app/init.php | 5 ++- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index b8f8ac4727..eb41728c6e 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -77,7 +77,6 @@ App::post('/v1/projects') ->inject('pools') ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools) { - $team = $dbForConsole->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -85,13 +84,22 @@ App::post('/v1/projects') } $auth = Config::getParam('auth', []); - $auths = ['limit' => 0, 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT, 'passwordHistory' => 0, 'passwordDictionary' => false, 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, 'personalDataCheck' => false]; - foreach ($auth as $index => $method) { + $auths = [ + 'limit' => 0, + 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT, + 'passwordHistory' => 0, + 'passwordDictionary' => false, + 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, + 'personalDataCheck' => false + ]; + foreach ($auth as $method) { $auths[$method['key'] ?? ''] = true; } $projectId = ($projectId == 'unique()') ? ID::unique() : $projectId; + $dbForConsole->setTenant($projectId); + $backups['database_db_fra1_v14x_02'] = ['from' => '03:00', 'to' => '05:00']; $backups['database_db_fra1_v14x_03'] = ['from' => '00:00', 'to' => '02:00']; $backups['database_db_fra1_v14x_04'] = ['from' => '00:00', 'to' => '02:00']; @@ -133,6 +141,9 @@ App::post('/v1/projects') throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); } + static $counter = 0; + $shareTables = $counter++ % 2 === 0; + try { $project = $dbForConsole->createDocument('projects', new Document([ '$id' => $projectId, @@ -166,12 +177,21 @@ App::post('/v1/projects') 'search' => implode(' ', [$projectId, $name]), 'database' => $database ])); - } catch (Duplicate $th) { + } catch (Duplicate) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); } $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); - $dbForProject->setNamespace("_{$project->getInternalId()}"); + + if ($shareTables) { + $dbForProject + ->setShareTables(true) + ->setTenant($project->getId()); + } else { + $dbForProject + ->setNamespace("_{$project->getInternalId()}"); + } + $dbForProject->create(); $audit = new Audit($dbForProject); @@ -188,33 +208,19 @@ App::post('/v1/projects') continue; } - $attributes = []; - $indexes = []; + $attributes = \array_map(function (array $attribute) { + return new Document($attribute); + }, $collection['attributes']); - foreach ($collection['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => $attribute['$id'], - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } + $indexes = \array_map(function (array $index) { + return new Document($index); + }, $collection['indexes']); - foreach ($collection['indexes'] as $index) { - $indexes[] = new Document([ - '$id' => $index['$id'], - 'type' => $index['type'], - 'attributes' => $index['attributes'], - 'lengths' => $index['lengths'], - 'orders' => $index['orders'], - ]); + try { + $dbForProject->createCollection($key, $attributes, $indexes); + } catch (Duplicate) { + // Collection already exists } - $dbForProject->createCollection($key, $attributes, $indexes); } $response diff --git a/app/init.php b/app/init.php index 69dcdc737b..035952d77f 100644 --- a/app/init.php +++ b/app/init.php @@ -1132,7 +1132,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); -App::setResource('dbForConsole', function (Group $pools, Cache $cache) { +App::setResource('dbForConsole', function (Group $pools, Cache $cache, Document $project) { $dbAdapter = $pools ->get('console') ->pop() @@ -1141,13 +1141,14 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) { $database = new Database($dbAdapter, $cache); $database + ->setTenant($project->getId()) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); return $database; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'project']); App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools From f44543f083784d812b86434fb36436296b5238ff Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 23 Nov 2023 01:12:19 +1300 Subject: [PATCH 04/61] Add shareTables attribute to project --- app/config/collections.php | 11 +++++++++++ app/controllers/api/projects.php | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/config/collections.php b/app/config/collections.php index db229ce87a..60eeaf40a8 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3268,6 +3268,17 @@ $consoleCollections = array_merge([ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('shareTables'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('logo'), 'type' => Database::VAR_STRING, diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index eb41728c6e..8461fb2777 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -175,7 +175,8 @@ App::post('/v1/projects') 'keys' => null, 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), - 'database' => $database + 'database' => $database, + 'shareTables' => $shareTables, ])); } catch (Duplicate) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); From 35163ff52a092765a5024e864cc5e9c8ae8b5e78 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 23 Nov 2023 01:13:24 +1300 Subject: [PATCH 05/61] Check project shareTables status when configuring databases --- app/cli.php | 2 +- app/init.php | 35 +++++++++++++++++++++-------------- app/worker.php | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/app/cli.php b/app/cli.php index d3e44ea398..c341c4849c 100644 --- a/app/cli.php +++ b/app/cli.php @@ -24,7 +24,7 @@ use Utopia\Registry\Registry; Authorization::disable(); -CLI::setResource('register', fn()=>$register); +CLI::setResource('register', fn() => $register); CLI::setResource('cache', function ($pools) { $list = Config::getParam('pools-cache', []); diff --git a/app/init.php b/app/init.php index 035952d77f..a8e205f1ee 100644 --- a/app/init.php +++ b/app/init.php @@ -1129,6 +1129,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); + if ($project->getAttribute('shareTables')) { + $database + ->setNamespace('') + ->setShareTables(true) + ->setTenant($project->getId()); + } + return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); @@ -1153,22 +1160,31 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache, Document App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - $getProjectDB = function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForConsole; } $databaseName = $project->getAttribute('database'); - if (isset($databases[$databaseName])) { - $database = $databases[$databaseName]; - + $configure = (function (Database $database) use ($project) { $database ->setNamespace('_' . $project->getInternalId()) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); + if ($project->getAttribute('shareTables')) { + $database + ->setNamespace('') + ->setShareTables(true) + ->setTenant($project->getId()); + } + }); + + if (isset($databases[$databaseName])) { + $database = $databases[$databaseName]; + $configure($database); return $database; } @@ -1178,19 +1194,10 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->getResource(); $database = new Database($dbAdapter, $cache); - $databases[$databaseName] = $database; - - $database - ->setNamespace('_' . $project->getInternalId()) - ->setMetadata('host', \gethostname()) - ->setMetadata('project', $project->getId()) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - + $configure($database); return $database; }; - - return $getProjectDB; }, ['pools', 'dbForConsole', 'cache']); App::setResource('cache', function (Group $pools) { diff --git a/app/worker.php b/app/worker.php index 32a8b9804e..98dc9e682e 100644 --- a/app/worker.php +++ b/app/worker.php @@ -61,15 +61,25 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, } $pools = $register->get('pools'); - $database = $pools + + $adapter = $pools ->get($project->getAttribute('database')) ->pop() - ->getResource() - ; + ->getResource(); - $adapter = new Database($database, $cache); - $adapter->setNamespace('_' . $project->getInternalId()); - return $adapter; + $database = new Database($adapter, $cache); + + if ($project->getAttribute('shareTables')) { + $database + ->setShareTables(true) + ->setTenant($project->getId()); + } else { + $database + ->setNamespace('_' . $project->getInternalId()); + } + + + return $database; }, ['cache', 'register', 'message', 'dbForConsole']); Server::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { @@ -84,7 +94,14 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - $database->setNamespace('_' . $project->getInternalId()); + if ($project->getAttribute('shareTables')) { + $database + ->setShareTables(true) + ->setTenant($project->getId()); + } else { + $database + ->setNamespace('_' . $project->getInternalId()); + } return $database; } @@ -97,7 +114,14 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; - $database->setNamespace('_' . $project->getInternalId()); + if ($project->getAttribute('shareTables')) { + $database + ->setShareTables(true) + ->setTenant($project->getId()); + } else { + $database + ->setNamespace('_' . $project->getInternalId()); + } return $database; }; From 7b8e37b03d757507bdea9c8670f7e7d4248257dd Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 27 Nov 2023 15:22:05 +1300 Subject: [PATCH 06/61] Update method names --- app/controllers/api/account.php | 38 ++++++++-------- app/controllers/api/avatars.php | 2 +- app/controllers/api/databases.php | 38 ++++++++-------- app/controllers/api/projects.php | 20 ++++----- app/controllers/api/teams.php | 12 ++--- app/controllers/api/users.php | 4 +- app/controllers/general.php | 9 ++-- app/controllers/shared/api.php | 2 +- app/init.php | 29 ++++++------ composer.lock | 8 ++-- src/Appwrite/Migration/Version/V15.php | 4 +- src/Appwrite/Migration/Version/V17.php | 32 +++++++------- src/Appwrite/Migration/Version/V18.php | 6 +-- src/Appwrite/Migration/Version/V19.php | 44 +++++++++---------- .../Platform/Tasks/DeleteOrphanedProjects.php | 6 +-- src/Appwrite/Platform/Workers/Databases.php | 20 ++++----- src/Appwrite/Platform/Workers/Deletes.php | 8 ++-- src/Appwrite/Platform/Workers/Migrations.php | 2 +- 18 files changed, 145 insertions(+), 139 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index c210b19f4f..175c759bbc 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -248,7 +248,7 @@ App::post('/v1/account/sessions/email') $dbForProject->updateDocument('users', $user->getId(), $user); } - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -567,7 +567,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $currentDocument = $dbForProject->getDocument('sessions', $current); if (!$currentDocument->isEmpty()) { $dbForProject->deleteDocument('sessions', $currentDocument->getId()); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); } } @@ -755,7 +755,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $session->setAttribute('expire', $expire); @@ -985,7 +985,7 @@ App::post('/v1/account/sessions/magic-url') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); if (empty($url)) { $url = $request->getProtocol() . '://' . $request->getHostname() . '/auth/magic-url'; @@ -1164,7 +1164,7 @@ App::put('/v1/account/sessions/magic-url') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $tokens = $user->getAttribute('tokens', []); @@ -1173,7 +1173,7 @@ App::put('/v1/account/sessions/magic-url') * the recovery token but actually we don't need it anymore. */ $dbForProject->deleteDocument('tokens', $token); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $user->setAttribute('emailVerification', true); @@ -1311,7 +1311,7 @@ App::post('/v1/account/sessions/phone') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); @@ -1415,14 +1415,14 @@ App::put('/v1/account/sessions/phone') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); /** * We act like we're updating and validating * the recovery token but actually we don't need it anymore. */ $dbForProject->deleteDocument('tokens', $token); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $user->setAttribute('phoneVerification', true); @@ -1569,7 +1569,7 @@ App::post('/v1/account/sessions/anonymous') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $queueForEvents ->setParam('userId', $user->getId()) @@ -2203,7 +2203,7 @@ App::delete('/v1/account/sessions/:sessionId') ; } - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $queueForEvents ->setParam('userId', $user->getId()) @@ -2284,7 +2284,7 @@ App::patch('/v1/account/sessions/:sessionId') $dbForProject->updateDocument('sessions', $sessionId, $session); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; @@ -2355,7 +2355,7 @@ App::delete('/v1/account/sessions') } } - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $queueForEvents ->setParam('userId', $user->getId()) @@ -2441,7 +2441,7 @@ App::post('/v1/account/recovery') Permission::delete(Role::user($profile->getId())), ])); - $dbForProject->deleteCachedDocument('users', $profile->getId()); + $dbForProject->purgeCachedDocument('users', $profile->getId()); $url = Template::parseURL($url); $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $profile->getId(), 'secret' => $secret, 'expire' => $expire]); @@ -2620,7 +2620,7 @@ App::put('/v1/account/recovery') * the recovery token but actually we don't need it anymore. */ $dbForProject->deleteDocument('tokens', $recovery); - $dbForProject->deleteCachedDocument('users', $profile->getId()); + $dbForProject->purgeCachedDocument('users', $profile->getId()); $queueForEvents ->setParam('userId', $profile->getId()) @@ -2692,7 +2692,7 @@ App::post('/v1/account/verification') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $url = Template::parseURL($url); $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $verificationSecret, 'expire' => $expire]); @@ -2842,7 +2842,7 @@ App::put('/v1/account/verification') * the verification token but actually we don't need it anymore. */ $dbForProject->deleteDocument('tokens', $verification); - $dbForProject->deleteCachedDocument('users', $profile->getId()); + $dbForProject->purgeCachedDocument('users', $profile->getId()); $queueForEvents ->setParam('userId', $userId) @@ -2917,7 +2917,7 @@ App::post('/v1/account/verification/phone') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); @@ -3001,7 +3001,7 @@ App::put('/v1/account/verification/phone') * We act like we're updating and validating the verification token but actually we don't need it anymore. */ $dbForProject->deleteDocument('tokens', $verification); - $dbForProject->deleteCachedDocument('users', $profile->getId()); + $dbForProject->purgeCachedDocument('users', $profile->getId()); $queueForEvents ->setParam('userId', $user->getId()) diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index e0d967eb00..19e0f3cf92 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -116,7 +116,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { $index = 0; do { diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f47e3f8265..e9120e3b6c 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -153,13 +153,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); } catch (\Exception $e) { - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); throw $e; } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -197,13 +197,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); } catch (\Exception $e) { - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); throw $e; } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } $queueForDatabase @@ -358,7 +358,7 @@ function updateAttribute( $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); $relatedAttribute->setAttribute('options', $relatedOptions); $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); } } else { $dbForProject->updateAttribute( @@ -371,7 +371,7 @@ function updateAttribute( } $attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId()); $queueForEvents ->setContext('collection', $collection) @@ -708,8 +708,8 @@ App::delete('/v1/databases/:databaseId') throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->deleteCachedDocument('databases', $database->getId()); - $dbForProject->deleteCachedCollection('databases_' . $database->getInternalId()); + $dbForProject->purgeCachedDocument('databases', $database->getId()); + $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_DATABASE) @@ -1093,7 +1093,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) @@ -2321,8 +2321,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); @@ -2343,8 +2343,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } @@ -2528,7 +2528,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) @@ -2701,7 +2701,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 8461fb2777..72af60b44a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -941,7 +941,7 @@ App::post('/v1/projects/:projectId/webhooks') $webhook = $dbForConsole->createDocument('webhooks', $webhook); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1062,7 +1062,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('httpPass', $httpPass); $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -1101,7 +1101,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') $webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64))); $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -1138,7 +1138,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') $dbForConsole->deleteDocument('webhooks', $webhook->getId()); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1188,7 +1188,7 @@ App::post('/v1/projects/:projectId/keys') $key = $dbForConsole->createDocument('keys', $key); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1302,7 +1302,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->dynamic($key, Response::MODEL_KEY); }); @@ -1339,7 +1339,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') $dbForConsole->deleteDocument('keys', $key->getId()); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1389,7 +1389,7 @@ App::post('/v1/projects/:projectId/platforms') $platform = $dbForConsole->createDocument('platforms', $platform); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1504,7 +1504,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->dynamic($platform, Response::MODEL_PLATFORM); }); @@ -1541,7 +1541,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') $dbForConsole->deleteDocument('platforms', $platformId); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 2ee351f469..745e5ccbd2 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -114,7 +114,7 @@ App::post('/v1/teams') ]); $membership = $dbForProject->createDocument('memberships', $membership); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); } $queueForEvents->setParam('teamId', $team->getId()); @@ -536,7 +536,7 @@ App::post('/v1/teams/:teamId/memberships') $team->setAttribute('total', $team->getAttribute('total', 0) + 1); $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); - $dbForProject->deleteCachedDocument('users', $invitee->getId()); + $dbForProject->purgeCachedDocument('users', $invitee->getId()); } else { try { $membership = $dbForProject->createDocument('memberships', $membership); @@ -843,7 +843,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') /** * Replace membership on profile */ - $dbForProject->deleteCachedDocument('users', $profile->getId()); + $dbForProject->purgeCachedDocument('users', $profile->getId()); $queueForEvents ->setParam('teamId', $team->getId()) @@ -958,13 +958,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') Permission::delete(Role::user($user->getId())), ])); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); Authorization::setRole(Role::user($userId)->toString()); $membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); @@ -1043,7 +1043,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB'); } - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 0869453cc9..3853f08753 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1114,7 +1114,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId') } $dbForProject->deleteDocument('sessions', $session->getId()); - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $queueForEvents ->setParam('userId', $user->getId()) @@ -1158,7 +1158,7 @@ App::delete('/v1/users/:userId/sessions') //TODO: fix this } - $dbForProject->deleteCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $user->getId()); $queueForEvents ->setParam('userId', $user->getId()) diff --git a/app/controllers/general.php b/app/controllers/general.php index cf383b6710..8bf01f1123 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -232,7 +232,9 @@ App::init() Request::setRoute($route); if ($route === null) { - return $response->setStatusCode(404)->send('Not Found'); + return $response + ->setStatusCode(404) + ->send('Not Found'); } $requestFormat = $request->getHeader('x-appwrite-response-format', App::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', '')); @@ -511,7 +513,7 @@ App::init() if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DateTime::now()); $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); } $sdkValidator = new WhiteList($servers, true); @@ -525,7 +527,7 @@ App::init() /** Update access time as well */ $key->setAttribute('accessedAt', Datetime::now()); $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); } } } @@ -678,6 +680,7 @@ App::error() Console::error('[Error] Message: ' . $message); Console::error('[Error] File: ' . $file); Console::error('[Error] Line: ' . $line); + Console::error('[Error] Trace: ' . $error->getTraceAsString()); } /** Handle Utopia Errors */ diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index b37d76a816..e5e2ab847b 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -350,7 +350,7 @@ App::shutdown() $session = array_shift($sessions); $dbForProject->deleteDocument('sessions', $session->getId()); } - $dbForProject->deleteCachedDocument('users', $userId); + $dbForProject->purgeCachedDocument('users', $userId); }); App::shutdown() diff --git a/app/init.php b/app/init.php index a8e205f1ee..a4801ff707 100644 --- a/app/init.php +++ b/app/init.php @@ -935,22 +935,25 @@ App::setResource('clients', function ($request, $console, $project) { fn ($node) => $node['hostname'], \array_filter( $console->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname'])) + fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && !empty($node['hostname'])) ) ); - $clients = \array_unique( - \array_merge( - $clientsConsole, - \array_map( - fn ($node) => $node['hostname'], - \array_filter( - $project->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname'])) - ) - ) - ) - ); + $clients = $clientsConsole; + $platforms = $project->getAttribute('platforms', []); + + foreach ($platforms as $node) { + if ( + isset($node['type']) && + ($node['type'] === Origin::CLIENT_TYPE_WEB || + $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && + !empty($node['hostname']) + ) { + $clients[] = $node['hostname']; + } + } + + $clients = array_unique($clients); return $clients; }, ['request', 'console', 'project']); diff --git a/composer.lock b/composer.lock index 3f9bf551d2..191286b143 100644 --- a/composer.lock +++ b/composer.lock @@ -1910,12 +1910,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "b7bcc9b373242a9e494b0b7bbf78dfa54333727c" + "reference": "22f9009b06b9d9aa32ca71c76500eaa8fa3366b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/b7bcc9b373242a9e494b0b7bbf78dfa54333727c", - "reference": "b7bcc9b373242a9e494b0b7bbf78dfa54333727c", + "url": "https://api.github.com/repos/utopia-php/database/zipball/22f9009b06b9d9aa32ca71c76500eaa8fa3366b4", + "reference": "22f9009b06b9d9aa32ca71c76500eaa8fa3366b4", "shasum": "" }, "require": { @@ -1958,7 +1958,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/feat-isolation-mode" }, - "time": "2023-11-22T07:58:21+00:00" + "time": "2023-11-27T01:55:11+00:00" }, { "name": "utopia-php/domains", diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index 9d8af4482a..3104341139 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -372,7 +372,7 @@ class V15 extends Migration } } - $this->projectDB->deleteCachedCollection($table); + $this->projectDB->purgeCachedCollection($table); } /** @@ -479,7 +479,7 @@ class V15 extends Migration $this->createCollection('cache'); Console::log('Created new Collection "variables" collection'); $this->createCollection('variables'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'abuse': diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index c0e2498e7f..4bdae76621 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -48,7 +48,7 @@ class V17 extends Migration try { $this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'mimeType' from {$id}: {$th->getMessage()}"); } @@ -76,7 +76,7 @@ class V17 extends Migration * Create 'size' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'size'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'size' from {$id}: {$th->getMessage()}"); } @@ -88,7 +88,7 @@ class V17 extends Migration * Update 'mimeType' attribute size (127->255) */ $this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'mimeType' from {$id}: {$th->getMessage()}"); } @@ -98,7 +98,7 @@ class V17 extends Migration * Create 'bucketInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'bucketInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } @@ -110,7 +110,7 @@ class V17 extends Migration * Delete 'endTime' attribute (use startTime+duration if needed) */ $this->projectDB->deleteAttribute($id, 'endTime'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'endTime' from {$id}: {$th->getMessage()}"); } @@ -120,7 +120,7 @@ class V17 extends Migration * Rename 'outputPath' to 'path' */ $this->projectDB->renameAttribute($id, 'outputPath', 'path'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'path' from {$id}: {$th->getMessage()}"); } @@ -130,7 +130,7 @@ class V17 extends Migration * Create 'deploymentInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } @@ -142,7 +142,7 @@ class V17 extends Migration * Delete 'type' attribute */ $this->projectDB->deleteAttribute($id, 'type'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'type' from {$id}: {$th->getMessage()}"); } @@ -154,7 +154,7 @@ class V17 extends Migration * Create 'resourceInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'resourceInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}"); } @@ -166,7 +166,7 @@ class V17 extends Migration * Create 'deploymentInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } @@ -176,7 +176,7 @@ class V17 extends Migration * Create 'scheduleInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); } @@ -186,7 +186,7 @@ class V17 extends Migration * Delete 'scheduleUpdatedAt' attribute */ $this->projectDB->deleteAttribute($id, 'scheduleUpdatedAt'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'scheduleUpdatedAt' from {$id}: {$th->getMessage()}"); } @@ -198,7 +198,7 @@ class V17 extends Migration * Create 'resourceInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'resourceInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}"); } @@ -208,7 +208,7 @@ class V17 extends Migration * Create 'buildInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'buildInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'buildInternalId' from {$id}: {$th->getMessage()}"); } @@ -220,7 +220,7 @@ class V17 extends Migration * Create 'functionInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'functionInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'functionInternalId' from {$id}: {$th->getMessage()}"); } @@ -230,7 +230,7 @@ class V17 extends Migration * Create 'deploymentInternalId' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index 12d573e549..ac4093aaca 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -106,7 +106,7 @@ class V18 extends Migration * Create 'passwordHistory' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'passwordHistory'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'passwordHistory' from {$id}: {$th->getMessage()}"); } @@ -117,7 +117,7 @@ class V18 extends Migration * Create 'prefs' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'prefs'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'prefs' from {$id}: {$th->getMessage()}"); } @@ -128,7 +128,7 @@ class V18 extends Migration * Create 'options' attribute */ $this->createAttributeFromCollection($this->projectDB, $id, 'options'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'options' from {$id}: {$th->getMessage()}"); } diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index c04a3b03de..8083e36426 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -100,7 +100,7 @@ class V19 extends Migration try { $this->createAttributeFromCollection($this->projectDB, $id, 'bucketInternalId', 'files'); - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'bucketInternalId' from {$id}: {$th->getMessage()}"); } @@ -160,7 +160,7 @@ class V19 extends Migration Console::warning("'error' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'buckets': @@ -188,7 +188,7 @@ class V19 extends Migration } } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'builds': @@ -211,7 +211,7 @@ class V19 extends Migration Console::warning("'path' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'certificates': @@ -227,7 +227,7 @@ class V19 extends Migration Console::warning("'logs' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'databases': @@ -237,7 +237,7 @@ class V19 extends Migration Console::warning("'enabled' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'deployments': @@ -300,7 +300,7 @@ class V19 extends Migration } } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'executions': @@ -361,7 +361,7 @@ class V19 extends Migration Console::warning("'_key_responseStatusCode' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'files': @@ -388,7 +388,7 @@ class V19 extends Migration } } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'functions': @@ -450,7 +450,7 @@ class V19 extends Migration } } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'memberships': @@ -460,7 +460,7 @@ class V19 extends Migration Console::warning("'teamInternalId' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); // Intentional fall through to update memberships.userInternalId case 'sessions': @@ -471,7 +471,7 @@ class V19 extends Migration Console::warning("'userInternalId' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'domains': @@ -484,7 +484,7 @@ class V19 extends Migration Console::warning("'projectInternalId' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'projects': @@ -502,7 +502,7 @@ class V19 extends Migration } } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'stats': @@ -515,26 +515,26 @@ class V19 extends Migration // Holding off on these until a future release // try { // $this->projectDB->deleteAttribute($id, 'type'); - // $this->projectDB->deleteCachedCollection($id); + // $this->projectDB->purgeCachedCollection($id); // } catch (\Throwable $th) { // Console::warning("'type' from {$id}: {$th->getMessage()}"); // } // try { // $this->projectDB->deleteIndex($id, '_key_metric_period_time'); - // $this->projectDB->deleteCachedCollection($id); + // $this->projectDB->purgeCachedCollection($id); // } catch (\Throwable $th) { // Console::warning("'_key_metric_period_time' from {$id}: {$th->getMessage()}"); // } // try { // $this->createIndexFromCollection($this->projectDB, $id, '_key_metric_period_time'); - // $this->projectDB->deleteCachedCollection($id); + // $this->projectDB->purgeCachedCollection($id); // } catch (\Throwable $th) { // Console::warning("'_key_metric_period_time' from {$id}: {$th->getMessage()}"); // } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'users': @@ -562,7 +562,7 @@ class V19 extends Migration Console::warning("'_key_accessedAt' from {$id}: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; case 'variables': @@ -610,7 +610,7 @@ class V19 extends Migration } } - $this->projectDB->deleteCachedCollection($id); + $this->projectDB->purgeCachedCollection($id); break; default: @@ -753,7 +753,7 @@ class V19 extends Migration Console::warning("'domains' from projects: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection('projects'); + $this->projectDB->purgeCachedCollection('projects'); try { $this->projectDB->deleteAttribute('builds', 'stderr'); @@ -767,7 +767,7 @@ class V19 extends Migration Console::warning("'stdout' from builds: {$th->getMessage()}"); } - $this->projectDB->deleteCachedCollection('builds'); + $this->projectDB->purgeCachedCollection('builds'); } /** diff --git a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php index 5a04df04ba..860cc3a8a2 100644 --- a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php +++ b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php @@ -113,7 +113,7 @@ class DeleteOrphanedProjects extends Action foreach ($collections as $collection) { if ($commit) { $dbForProject->deleteCollection($collection->getId()); - $dbForConsole->deleteCachedCollection($collection->getId()); + $dbForConsole->purgeCachedCollection($collection->getId()); } Console::info('--Deleting collection (' . $collection->getId() . ') project no (' . $project->getInternalId() . ')'); } @@ -121,12 +121,12 @@ class DeleteOrphanedProjects extends Action if ($commit) { $dbForConsole->deleteDocument('projects', $project->getId()); - $dbForConsole->deleteCachedDocument('projects', $project->getId()); + $dbForConsole->purgeCachedDocument('projects', $project->getId()); if ($dbForProject->exists($dbForProject->getDatabase(), Database::METADATA)) { try { $dbForProject->deleteCollection(Database::METADATA); - $dbForProject->deleteCachedCollection(Database::METADATA); + $dbForProject->purgeCachedCollection(Database::METADATA); } catch (\Throwable $th) { Console::warning('Metadata collection does not exist'); } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index e0ec75e1d4..a90dd742e3 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -186,10 +186,10 @@ class Databases extends Action } if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } /** @@ -336,12 +336,12 @@ class Databases extends Action } } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } @@ -402,7 +402,7 @@ class Databases extends Action $this->trigger($database, $collection, $index, $project, $projectId, $events); } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } /** @@ -459,7 +459,7 @@ class Databases extends Action $this->trigger($database, $collection, $index, $project, $projectId, $events); } - $dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } /** @@ -514,8 +514,8 @@ class Databases extends Action } $relatedCollection = $dbForProject->getDocument('database_' . $databaseInternalId, $relationship['relatedCollection']); $dbForProject->deleteDocument('attributes', $databaseInternalId . '_' . $relatedCollection->getInternalId() . '_' . $relationship['twoWayKey']); - $dbForProject->deleteCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId()); } $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index b95a13a12e..ad3621c46e 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -311,8 +311,8 @@ class Deletes extends Action } $relatedCollection = $dbForProject->getDocument('database_' . $databaseInternalId, $relationship['relatedCollection']); $dbForProject->deleteDocument('attributes', $databaseInternalId . '_' . $relatedCollection->getInternalId() . '_' . $relationship['twoWayKey']); - $dbForProject->deleteCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId()); - $dbForProject->deleteCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId()); } $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); @@ -370,7 +370,7 @@ class Deletes extends Action $dbForProject, function (Document $membership) use ($dbForProject) { $userId = $membership->getAttribute('userId'); - $dbForProject->deleteCachedDocument('users', $userId); + $dbForProject->purgeCachedDocument('users', $userId); } ); } @@ -504,7 +504,7 @@ class Deletes extends Action Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); - $dbForProject->deleteCachedDocument('users', $userId); + $dbForProject->purgeCachedDocument('users', $userId); // Delete Memberships and decrement team membership counts $this->deleteByGroup('memberships', [ diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 31b0df59a3..0bbb3acc5f 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -220,7 +220,7 @@ class Migrations extends Action ]); $this->dbForConsole->createDocument('keys', $key); - $this->dbForConsole->deleteCachedDocument('projects', $project->getId()); + $this->dbForConsole->purgeCachedDocument('projects', $project->getId()); return $key; } From b9ac8e644dcc797e948e6597c0349298d8fece21 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:26:35 +1300 Subject: [PATCH 07/61] Set/reset tenant on init --- app/init.php | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/app/init.php b/app/init.php index a4801ff707..85c618e63c 100644 --- a/app/init.php +++ b/app/init.php @@ -953,9 +953,7 @@ App::setResource('clients', function ($request, $console, $project) { } } - $clients = array_unique($clients); - - return $clients; + return \array_unique($clients); }, ['request', 'console', 'project']); App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) { @@ -1127,22 +1125,26 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, $database = new Database($dbAdapter, $cache); $database - ->setNamespace('_' . $project->getInternalId()) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); if ($project->getAttribute('shareTables')) { $database - ->setNamespace('') ->setShareTables(true) - ->setTenant($project->getId()); + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); } return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); -App::setResource('dbForConsole', function (Group $pools, Cache $cache, Document $project) { +App::setResource('dbForConsole', function (Group $pools, Cache $cache) { $dbAdapter = $pools ->get('console') ->pop() @@ -1151,14 +1153,13 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache, Document $database = new Database($dbAdapter, $cache); $database - ->setTenant($project->getId()) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); return $database; -}, ['pools', 'cache', 'project']); +}, ['pools', 'cache']); App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools @@ -1172,16 +1173,20 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $configure = (function (Database $database) use ($project) { $database - ->setNamespace('_' . $project->getInternalId()) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); if ($project->getAttribute('shareTables')) { $database - ->setNamespace('') ->setShareTables(true) - ->setTenant($project->getId()); + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); } }); From 68548ebd478d2f8ef559c9d2845bf998555e5556 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:27:16 +1300 Subject: [PATCH 08/61] Fix worker tenant set/reset --- app/worker.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/worker.php b/app/worker.php index 98dc9e682e..b3382193f9 100644 --- a/app/worker.php +++ b/app/worker.php @@ -72,9 +72,12 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, if ($project->getAttribute('shareTables')) { $database ->setShareTables(true) - ->setTenant($project->getId()); + ->setTenant($project->getInternalId()) + ->setNamespace(''); } else { $database + ->setShareTables(false) + ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } @@ -94,14 +97,19 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; + if ($project->getAttribute('shareTables')) { $database ->setShareTables(true) - ->setTenant($project->getId()); + ->setTenant($project->getInternalId()) + ->setNamespace(''); } else { $database + ->setShareTables(false) + ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } + return $database; } @@ -117,9 +125,12 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if ($project->getAttribute('shareTables')) { $database ->setShareTables(true) - ->setTenant($project->getId()); + ->setTenant($project->getInternalId()) + ->setNamespace(''); } else { $database + ->setShareTables(false) + ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } @@ -228,7 +239,7 @@ try { * Any worker can be configured with the following env vars: * - _APP_WORKERS_NUM The total number of worker processes * - _APP_WORKER_PER_CORE The number of worker processes per core (ignored if _APP_WORKERS_NUM is set) - * - _APP_QUEUE_NAME The name of the queue to read for database events + * - _APP_QUEUE_NAME The name of the queue to read for database events */ if ($workerName === 'databases') { $queueName = App::getEnv('_APP_QUEUE_NAME', 'database_db_main'); From 9472bff8f9f3211c58ddfd345a53a1ee0c3bc7b2 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:27:41 +1300 Subject: [PATCH 09/61] Fix project create tenant set/reset --- app/controllers/api/projects.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 72af60b44a..994f842184 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -9,6 +9,7 @@ use Appwrite\Network\Validator\Origin; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\ProjectId; use Appwrite\Utopia\Database\Validator\Queries\Projects; +use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use PHPMailer\PHPMailer\PHPMailer; use Utopia\Abuse\Adapters\TimeLimit; @@ -71,11 +72,12 @@ App::post('/v1/projects') ->param('legalCity', '', new Text(256), 'Project legal City. Max length: 256 chars.', true) ->param('legalAddress', '', new Text(256), 'Project legal Address. Max length: 256 chars.', true) ->param('legalTaxId', '', new Text(256), 'Project legal Tax ID. Max length: 256 chars.', true) + ->inject('request') ->inject('response') ->inject('dbForConsole') ->inject('cache') ->inject('pools') - ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools) { + ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForConsole, Cache $cache, Group $pools) { $team = $dbForConsole->getDocument('teams', $teamId); @@ -98,8 +100,6 @@ App::post('/v1/projects') $projectId = ($projectId == 'unique()') ? ID::unique() : $projectId; - $dbForConsole->setTenant($projectId); - $backups['database_db_fra1_v14x_02'] = ['from' => '03:00', 'to' => '05:00']; $backups['database_db_fra1_v14x_03'] = ['from' => '00:00', 'to' => '02:00']; $backups['database_db_fra1_v14x_04'] = ['from' => '00:00', 'to' => '02:00']; @@ -141,8 +141,13 @@ App::post('/v1/projects') throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); } - static $counter = 0; - $shareTables = $counter++ % 2 === 0; + // One in 20 projects use shared tables + $shareTables = !\mt_rand(0, 19); + + // Allow overriding in development mode + if (App::isDevelopment()) { + $shareTables = (bool) $request->getHeader('x-appwrite-share-tables', false); + } try { $project = $dbForConsole->createDocument('projects', new Document([ @@ -187,10 +192,13 @@ App::post('/v1/projects') if ($shareTables) { $dbForProject ->setShareTables(true) - ->setTenant($project->getId()); + ->setTenant($project->getInternalId()) + ->setNamespace(''); } else { $dbForProject - ->setNamespace("_{$project->getInternalId()}"); + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); } $dbForProject->create(); From 0885f31dd72e8e466f6cd7f774514b4e6c3cfc3b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:29:23 +1300 Subject: [PATCH 10/61] Update database --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 191286b143..858fe2284c 100644 --- a/composer.lock +++ b/composer.lock @@ -1910,12 +1910,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "22f9009b06b9d9aa32ca71c76500eaa8fa3366b4" + "reference": "8756141bef49993643acea5120314b9390bfe30a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/22f9009b06b9d9aa32ca71c76500eaa8fa3366b4", - "reference": "22f9009b06b9d9aa32ca71c76500eaa8fa3366b4", + "url": "https://api.github.com/repos/utopia-php/database/zipball/8756141bef49993643acea5120314b9390bfe30a", + "reference": "8756141bef49993643acea5120314b9390bfe30a", "shasum": "" }, "require": { @@ -1958,7 +1958,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/feat-isolation-mode" }, - "time": "2023-11-27T01:55:11+00:00" + "time": "2023-11-27T07:58:37+00:00" }, { "name": "utopia-php/domains", From 82dfe5ddee4f82f47cb08fd450a859de5ed0208f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:30:02 +1300 Subject: [PATCH 11/61] Add tests --- app/controllers/general.php | 4 +- .../Projects/ProjectsConsoleClientTest.php | 470 ++++++++++++++++++ .../Projects/ProjectsCustomClientTest.php | 5 - .../Projects/ProjectsCustomServerTest.php | 5 - 4 files changed, 472 insertions(+), 12 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 8bf01f1123..eac637eeb3 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -427,7 +427,7 @@ App::init() ->addHeader('Server', 'Appwrite') ->addHeader('X-Content-Type-Options', 'nosniff') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') - ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma') + ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Share-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma') ->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $refDomain) ->addHeader('Access-Control-Allow-Credentials', 'true'); @@ -591,7 +591,7 @@ App::options() $response ->addHeader('Server', 'Appwrite') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') - ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Fallback-Cookies') + ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Share-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Fallback-Cookies') ->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $origin) ->addHeader('Access-Control-Allow-Credentials', 'true') diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index f90a04f290..b0172b9d2e 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; use Tests\E2E\Client; +use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; @@ -3294,4 +3295,473 @@ class ProjectsConsoleClientTest extends Scope return $data; } + + public function testTenantIsolation(): void + { + // Create a team and a project + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => ID::unique(), + 'name' => 'Amazing Team', + ]); + + $teamId = $team['body']['$id']; + + // Project-level isolation + $project1 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-share-tables' => false + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project', + 'teamId' => $teamId, + 'region' => 'default' + ]); + + // Application level isolation (shared tables) + $project2 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-share-tables' => true + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project', + 'teamId' => $teamId, + 'region' => 'default' + ]); + + // Project-level isolation + $project3 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-share-tables' => false + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project', + 'teamId' => $teamId, + 'region' => 'default' + ]); + + // Application level isolation (shared tables) + $project4 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-share-tables' => true + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project', + 'teamId' => $teamId, + 'region' => 'default' + ]); + + // Create and API key in each project + $key1 = $this->client->call(Client::METHOD_POST, '/projects/' . $project1['body']['$id'] . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + ]); + + $key2 = $this->client->call(Client::METHOD_POST, '/projects/' . $project2['body']['$id'] . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + ]); + + $key3 = $this->client->call(Client::METHOD_POST, '/projects/' . $project3['body']['$id'] . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + ]); + + $key4 = $this->client->call(Client::METHOD_POST, '/projects/' . $project4['body']['$id'] . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + ]); + + // Create a database in each project + $database1 = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Amazing Database', + ]); + + $database2 = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Amazing Database', + ]); + + $database3 = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Amazing Database', + ]); + + $database4 = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Amazing Database', + ]); + + // Create a collection in each project + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $database1['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ], [ + 'databaseId' => $database1['body']['$id'], + 'collectionId' => ID::unique(), + 'name' => 'Amazing Collection', + ]); + + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $database2['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ], [ + 'databaseId' => $database2['body']['$id'], + 'collectionId' => ID::unique(), + 'name' => 'Amazing Collection', + ]); + + $collection3 = $this->client->call(Client::METHOD_POST, '/databases/' . $database3['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ], [ + 'databaseId' => $database3['body']['$id'], + 'collectionId' => ID::unique(), + 'name' => 'Amazing Collection', + ]); + + $collection4 = $this->client->call(Client::METHOD_POST, '/databases/' . $database4['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ], [ + 'databaseId' => $database4['body']['$id'], + 'collectionId' => ID::unique(), + 'name' => 'Amazing Collection', + ]); + + // Create an attribute in each project + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $database1['body']['$id'] . '/collections/' . $collection1['body']['$id'] . '/attributes/string', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ], [ + 'databaseId' => $database1['body']['$id'], + 'collectionId' => $collection1['body']['$id'], + 'key' => ID::unique(), + 'size' => 255, + 'required' => true + ]); + + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $database2['body']['$id'] . '/collections/' . $collection2['body']['$id'] . '/attributes/string', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ], [ + 'databaseId' => $database2['body']['$id'], + 'collectionId' => $collection2['body']['$id'], + 'key' => ID::unique(), + 'size' => 255, + 'required' => true + ]); + + $attribute3 = $this->client->call(Client::METHOD_POST, '/databases/' . $database3['body']['$id'] . '/collections/' . $collection3['body']['$id'] . '/attributes/string', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ], [ + 'databaseId' => $database3['body']['$id'], + 'collectionId' => $collection3['body']['$id'], + 'key' => ID::unique(), + 'size' => 255, + 'required' => true + ]); + + $attribute4 = $this->client->call(Client::METHOD_POST, '/databases/' . $database4['body']['$id'] . '/collections/' . $collection4['body']['$id'] . '/attributes/string', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ], [ + 'databaseId' => $database4['body']['$id'], + 'collectionId' => $collection4['body']['$id'], + 'key' => ID::unique(), + 'size' => 255, + 'required' => true + ]); + + // Wait for attributes + \sleep(2); + + // Create an index in each project + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $database1['body']['$id'] . '/collections/' . $collection1['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ], [ + 'databaseId' => $database1['body']['$id'], + 'collectionId' => $collection1['body']['$id'], + 'key' => ID::unique(), + 'type' => Database::INDEX_KEY, + 'attributes' => [$attribute1['body']['key']], + ]); + + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $database2['body']['$id'] . '/collections/' . $collection2['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ], [ + 'databaseId' => $database2['body']['$id'], + 'collectionId' => $collection2['body']['$id'], + 'key' => ID::unique(), + 'type' => Database::INDEX_KEY, + 'attributes' => [$attribute2['body']['key']], + ]); + + $index3 = $this->client->call(Client::METHOD_POST, '/databases/' . $database3['body']['$id'] . '/collections/' . $collection3['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ], [ + 'databaseId' => $database3['body']['$id'], + 'collectionId' => $collection3['body']['$id'], + 'key' => ID::unique(), + 'type' => Database::INDEX_KEY, + 'attributes' => [$attribute3['body']['key']], + ]); + + $index4 = $this->client->call(Client::METHOD_POST, '/databases/' . $database4['body']['$id'] . '/collections/' . $collection4['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ], [ + 'databaseId' => $database4['body']['$id'], + 'collectionId' => $collection4['body']['$id'], + 'key' => ID::unique(), + 'type' => Database::INDEX_KEY, + 'attributes' => [$attribute4['body']['key']], + ]); + + // Wait for indexes + \sleep(2); + + // Assert that each project has only 1 database, 1 collection, 1 attribute and 1 index + $databasesProject1 = $this->client->call(Client::METHOD_GET, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ]); + + $this->assertEquals(1, $databasesProject1['body']['total']); + $this->assertEquals(1, \count($databasesProject1['body']['databases'])); + + $databasesProject2 = $this->client->call(Client::METHOD_GET, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ]); + + $this->assertEquals(1, $databasesProject2['body']['total']); + $this->assertEquals(1, \count($databasesProject2['body']['databases'])); + + $databasesProject3 = $this->client->call(Client::METHOD_GET, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ]); + + $this->assertEquals(1, $databasesProject3['body']['total']); + $this->assertEquals(1, \count($databasesProject3['body']['databases'])); + + $databasesProject4 = $this->client->call(Client::METHOD_GET, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ]); + + $this->assertEquals(1, $databasesProject4['body']['total']); + $this->assertEquals(1, \count($databasesProject4['body']['databases'])); + + $collectionsProject1 = $this->client->call(Client::METHOD_GET, '/databases/' . $database1['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ]); + + $this->assertEquals(1, $collectionsProject1['body']['total']); + $this->assertEquals(1, \count($collectionsProject1['body']['collections'])); + + $collectionsProject2 = $this->client->call(Client::METHOD_GET, '/databases/' . $database2['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ]); + + $this->assertEquals(1, $collectionsProject2['body']['total']); + $this->assertEquals(1, \count($collectionsProject2['body']['collections'])); + + $collectionsProject3 = $this->client->call(Client::METHOD_GET, '/databases/' . $database3['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ]); + + $this->assertEquals(1, $collectionsProject3['body']['total']); + $this->assertEquals(1, \count($collectionsProject3['body']['collections'])); + + $collectionsProject4 = $this->client->call(Client::METHOD_GET, '/databases/' . $database4['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ]); + + $this->assertEquals(1, $collectionsProject4['body']['total']); + $this->assertEquals(1, \count($collectionsProject4['body']['collections'])); + + $attributesProject1 = $this->client->call(Client::METHOD_GET, '/databases/' . $database1['body']['$id'] . '/collections/' . $collection1['body']['$id'] . '/attributes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ]); + + $this->assertEquals(1, $attributesProject1['body']['total']); + $this->assertEquals(1, \count($attributesProject1['body']['attributes'])); + + $attributesProject2 = $this->client->call(Client::METHOD_GET, '/databases/' . $database2['body']['$id'] . '/collections/' . $collection2['body']['$id'] . '/attributes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ]); + + $this->assertEquals(1, $attributesProject2['body']['total']); + $this->assertEquals(1, \count($attributesProject2['body']['attributes'])); + + $attributesProject3 = $this->client->call(Client::METHOD_GET, '/databases/' . $database3['body']['$id'] . '/collections/' . $collection3['body']['$id'] . '/attributes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ]); + + $this->assertEquals(1, $attributesProject3['body']['total']); + $this->assertEquals(1, \count($attributesProject3['body']['attributes'])); + + $attributesProject4 = $this->client->call(Client::METHOD_GET, '/databases/' . $database4['body']['$id'] . '/collections/' . $collection4['body']['$id'] . '/attributes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ]); + + $this->assertEquals(1, $attributesProject4['body']['total']); + $this->assertEquals(1, \count($attributesProject4['body']['attributes'])); + + $indexesProject1 = $this->client->call(Client::METHOD_GET, '/databases/' . $database1['body']['$id'] . '/collections/' . $collection1['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ]); + + $this->assertEquals(1, $indexesProject1['body']['total']); + $this->assertEquals(1, \count($indexesProject1['body']['indexes'])); + + $indexesProject2 = $this->client->call(Client::METHOD_GET, '/databases/' . $database2['body']['$id'] . '/collections/' . $collection2['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ]); + + $this->assertEquals(1, $indexesProject2['body']['total']); + $this->assertEquals(1, \count($indexesProject2['body']['indexes'])); + + $indexesProject3 = $this->client->call(Client::METHOD_GET, '/databases/' . $database3['body']['$id'] . '/collections/' . $collection3['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ]); + + $this->assertEquals(1, $indexesProject3['body']['total']); + $this->assertEquals(1, \count($indexesProject3['body']['indexes'])); + + $indexesProject4 = $this->client->call(Client::METHOD_GET, '/databases/' . $database4['body']['$id'] . '/collections/' . $collection4['body']['$id'] . '/indexes', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key4['body']['secret'] + ]); + + $this->assertEquals(1, $indexesProject4['body']['total']); + $this->assertEquals(1, \count($indexesProject4['body']['indexes'])); + + // Attempt to read cross-type resources + $collectionProject2WithProject1Key = $this->client->call(Client::METHOD_GET, '/databases/' . $database2['body']['$id'] . '/collections/' . $collection2['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ]); + + $this->assertEquals(404, $collectionProject2WithProject1Key['headers']['status-code']); + + $collectionProject1WithProject2Key = $this->client->call(Client::METHOD_GET, '/databases/' . $database1['body']['$id'] . '/collections/' . $collection1['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ]); + + $this->assertEquals(404, $collectionProject1WithProject2Key['headers']['status-code']); + + // Attempt to read cross-tenant resources + $collectionProject3WithProject1Key = $this->client->call(Client::METHOD_GET, '/databases/' . $database3['body']['$id'] . '/collections/' . $collection3['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ]); + + $this->assertEquals(404, $collectionProject3WithProject1Key['headers']['status-code']); + + $collectionProject1WithProject3Key = $this->client->call(Client::METHOD_GET, '/databases/' . $database1['body']['$id'] . '/collections/' . $collection1['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project3['body']['$id'], + 'x-appwrite-key' => $key3['body']['secret'] + ]); + + $this->assertEquals(404, $collectionProject1WithProject3Key['headers']['status-code']); + + // Assert that shared project resources can have the same ID as they're unique on tenant + ID not just ID + $collection5 = $this->client->call(Client::METHOD_POST, '/databases/' . $database2['body']['$id'] . '/collections', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ], [ + 'databaseId' => $database2['body']['$id'], + 'collectionId' => $collection4['body']['$id'], + 'name' => 'Amazing Collection', + ]); + + $this->assertEquals(201, $collection5['headers']['status-code']); + } } diff --git a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php index 9dfd48ce50..ddef681e61 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php @@ -11,9 +11,4 @@ class ProjectsCustomClientTest extends Scope { use ProjectCustom; use SideClient; - - public function testMock() - { - $this->assertEquals(true, true); - } } diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index 1c5b48f146..2d11896676 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -11,9 +11,4 @@ class ProjectsCustomServerTest extends Scope { use ProjectCustom; use SideServer; - - public function testMock() - { - $this->assertEquals(true, true); - } } From edee5400ba873df0bfefa3ceead352d837118171 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:43:21 +1300 Subject: [PATCH 12/61] Fix casing --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index 85c618e63c..ff797b5fbc 100644 --- a/app/init.php +++ b/app/init.php @@ -1264,7 +1264,7 @@ function getDevice($root): Device return match ($device) { Storage::DEVICE_S3 => new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl), - STORAGE::DEVICE_DO_SPACES => new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl), + Storage::DEVICE_DO_SPACES => new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl), Storage::DEVICE_BACKBLAZE => new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl), Storage::DEVICE_LINODE => new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl), Storage::DEVICE_WASABI => new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl), From 2e89113e6a4ff1f6bb9a2d05f3b00da15540e282 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 00:52:46 +1300 Subject: [PATCH 13/61] Self review --- .gitignore | 1 + app/worker.php | 1 - appwrite.json | 4 ---- 3 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 appwrite.json diff --git a/.gitignore b/.gitignore index 3151de5adb..15478fcfab 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ debug/ app/sdks dev/yasd_init.php .phpunit.result.cache +appwrite.json diff --git a/app/worker.php b/app/worker.php index b3382193f9..1ef1d340a6 100644 --- a/app/worker.php +++ b/app/worker.php @@ -81,7 +81,6 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getInternalId()); } - return $database; }, ['cache', 'register', 'message', 'dbForConsole']); diff --git a/appwrite.json b/appwrite.json deleted file mode 100644 index e3d948ed1a..0000000000 --- a/appwrite.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "projectId": "console", - "projectName": "" -} \ No newline at end of file From c4806e883edf3a13cbcfabda86e90bea3e5938b5 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 01:00:22 +1300 Subject: [PATCH 14/61] Update lock --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index a5d1fb327a..c61e497ab6 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": "2c23008af30193734b6717a41632aa54", + "content-hash": "75330561b68809c4c842c513ead64783", "packages": [ { "name": "adhocore/jwt", @@ -1910,12 +1910,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "8756141bef49993643acea5120314b9390bfe30a" + "reference": "ba6d104d2d0ac2de115bb426b01cdcbdc5143ce6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/8756141bef49993643acea5120314b9390bfe30a", - "reference": "8756141bef49993643acea5120314b9390bfe30a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/ba6d104d2d0ac2de115bb426b01cdcbdc5143ce6", + "reference": "ba6d104d2d0ac2de115bb426b01cdcbdc5143ce6", "shasum": "" }, "require": { @@ -1958,7 +1958,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/feat-isolation-mode" }, - "time": "2023-11-27T07:58:37+00:00" + "time": "2023-11-27T11:35:51+00:00" }, { "name": "utopia-php/domains", From c1f10b06a3db68df9e5c424715a597a44e2d3ce3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 01:34:29 +1300 Subject: [PATCH 15/61] Fix index limit test --- composer.lock | 8 ++++---- .../e2e/Services/Databases/DatabasesCustomServerTest.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index c61e497ab6..04d20d6fb5 100644 --- a/composer.lock +++ b/composer.lock @@ -1910,12 +1910,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "ba6d104d2d0ac2de115bb426b01cdcbdc5143ce6" + "reference": "c1341e2daa90aaa93511a98838cd48243aa2eae5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/ba6d104d2d0ac2de115bb426b01cdcbdc5143ce6", - "reference": "ba6d104d2d0ac2de115bb426b01cdcbdc5143ce6", + "url": "https://api.github.com/repos/utopia-php/database/zipball/c1341e2daa90aaa93511a98838cd48243aa2eae5", + "reference": "c1341e2daa90aaa93511a98838cd48243aa2eae5", "shasum": "" }, "require": { @@ -1958,7 +1958,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/feat-isolation-mode" }, - "time": "2023-11-27T11:35:51+00:00" + "time": "2023-11-27T12:29:12+00:00" }, { "name": "utopia-php/domains", diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 648a4de800..aa1d91dcdf 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1374,10 +1374,10 @@ class DatabasesCustomServerTest extends Scope } // Test indexLimit = 64 - // MariaDB, MySQL, and MongoDB create 5 indexes per new collection + // MariaDB, MySQL, and MongoDB create 6 indexes per new collection // Add up to the limit, then check if the next index throws IndexLimitException - for ($i = 0; $i < 59; $i++) { // $this->assertEquals(true, static::getDatabase()->createIndex('indexLimit', "index{$i}", Database::INDEX_KEY, ["test{$i}"], [16])); + for ($i = 0; $i < 58; $i++) { $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1405,7 +1405,7 @@ class DatabasesCustomServerTest extends Scope $this->assertIsArray($collection['body']['attributes']); $this->assertIsArray($collection['body']['indexes']); $this->assertCount(64, $collection['body']['attributes']); - $this->assertCount(59, $collection['body']['indexes']); + $this->assertCount(58, $collection['body']['indexes']); $tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', From 632c902e1c9bc88a2c712a34444220968cbbbc0d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 01:53:24 +1300 Subject: [PATCH 16/61] Remove debug trace --- app/controllers/general.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 441976f7fb..1880e3826d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -685,7 +685,6 @@ App::error() Console::error('[Error] Message: ' . $message); Console::error('[Error] File: ' . $file); Console::error('[Error] Line: ' . $line); - Console::error('[Error] Trace: ' . $error->getTraceAsString()); } /** Handle Utopia Errors */ From 7104f9e2c840e07284a154d816f2c1e5a9125208 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 28 Nov 2023 02:08:04 +1300 Subject: [PATCH 17/61] Add comments marking `shareTables` project attributes + header overrides as temporary --- app/config/collections.php | 1 + app/controllers/api/projects.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/config/collections.php b/app/config/collections.php index 60eeaf40a8..ed5e94eb65 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3269,6 +3269,7 @@ $consoleCollections = array_merge([ 'filters' => [], ], [ + // To be removed once all project are using shared tables '$id' => ID::custom('shareTables'), 'type' => Database::VAR_BOOLEAN, 'format' => '', diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 994f842184..330f89dffd 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -144,7 +144,7 @@ App::post('/v1/projects') // One in 20 projects use shared tables $shareTables = !\mt_rand(0, 19); - // Allow overriding in development mode + // Allow overriding in development mode, to be removed once all project are using shared tables if (App::isDevelopment()) { $shareTables = (bool) $request->getHeader('x-appwrite-share-tables', false); } From 4f539f1ed48a99fdec0f27be759d38d6192a1585 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 30 Nov 2023 16:04:15 +1300 Subject: [PATCH 18/61] Update switch to match --- app/init.php | 85 +++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/app/init.php b/app/init.php index f2063870ac..82e2baf804 100644 --- a/app/init.php +++ b/app/init.php @@ -1290,46 +1290,51 @@ function getDevice($root): Device default => new Local($root), }; } else { - switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) { - case Storage::DEVICE_LOCAL: - default: - return new Local($root); - case Storage::DEVICE_S3: - $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); - $s3SecretKey = App::getEnv('_APP_STORAGE_S3_SECRET', ''); - $s3Region = App::getEnv('_APP_STORAGE_S3_REGION', ''); - $s3Bucket = App::getEnv('_APP_STORAGE_S3_BUCKET', ''); - $s3Acl = 'private'; - return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); - case Storage::DEVICE_DO_SPACES: - $doSpacesAccessKey = App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); - $doSpacesSecretKey = App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); - $doSpacesRegion = App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); - $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); - $doSpacesAcl = 'private'; - return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); - case Storage::DEVICE_BACKBLAZE: - $backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); - $backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); - $backblazeRegion = App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); - $backblazeBucket = App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); - $backblazeAcl = 'private'; - return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); - case Storage::DEVICE_LINODE: - $linodeAccessKey = App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); - $linodeSecretKey = App::getEnv('_APP_STORAGE_LINODE_SECRET', ''); - $linodeRegion = App::getEnv('_APP_STORAGE_LINODE_REGION', ''); - $linodeBucket = App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); - $linodeAcl = 'private'; - return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); - case Storage::DEVICE_WASABI: - $wasabiAccessKey = App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); - $wasabiSecretKey = App::getEnv('_APP_STORAGE_WASABI_SECRET', ''); - $wasabiRegion = App::getEnv('_APP_STORAGE_WASABI_REGION', ''); - $wasabiBucket = App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); - $wasabiAcl = 'private'; - return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); - } + $device = strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? ''); + + return match ($device) { + Storage::DEVICE_S3 => new S3( + $root, + App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''), + App::getEnv('_APP_STORAGE_S3_SECRET', ''), + App::getEnv('_APP_STORAGE_S3_BUCKET', ''), + App::getEnv('_APP_STORAGE_S3_REGION', ''), + 'private' + ), + Storage::DEVICE_DO_SPACES => new DOSpaces( + $root, + App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''), + App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''), + App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''), + App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''), + 'private' + ), + Storage::DEVICE_BACKBLAZE => new Backblaze( + $root, + App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''), + App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''), + App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''), + App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''), + 'private' + ), + Storage::DEVICE_LINODE => new Linode( + $root, + App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''), + App::getEnv('_APP_STORAGE_LINODE_SECRET', ''), + App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''), + App::getEnv('_APP_STORAGE_LINODE_REGION', ''), + 'private' + ), + Storage::DEVICE_WASABI => new Wasabi( + $root, + App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''), + App::getEnv('_APP_STORAGE_WASABI_SECRET', ''), + App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''), + App::getEnv('_APP_STORAGE_WASABI_REGION', ''), + 'private' + ), + default => new Local($root), + }; } } From e109f1e0080a59b9c91e0533b0ce1ce846319c6e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 30 Nov 2023 16:06:49 +1300 Subject: [PATCH 19/61] Add metadata in worker dbs --- app/worker.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/worker.php b/app/worker.php index 1ef1d340a6..41c5a06a9d 100644 --- a/app/worker.php +++ b/app/worker.php @@ -69,6 +69,10 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database = new Database($adapter, $cache); + $database + ->setMetadata('host', \gethostname()) + ->setMetadata('project', $project->getId()); + if ($project->getAttribute('shareTables')) { $database ->setShareTables(true) From 7e12da5a2aaa81342a42f297dbb93c86023c42d0 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 30 Nov 2023 16:32:15 +1300 Subject: [PATCH 20/61] Use hard-coded DB name instead of project attribute --- app/controllers/api/projects.php | 13 +++++++------ app/init.php | 7 ++++--- app/worker.php | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 330f89dffd..9916ae67f2 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -129,7 +129,7 @@ App::post('/v1/projects') } } - $databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE', null); + $databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE'); $index = array_search($databaseOverride, $databases); if ($index !== false) { $database = $databases[$index]; @@ -142,11 +142,13 @@ App::post('/v1/projects') } // One in 20 projects use shared tables - $shareTables = !\mt_rand(0, 19); + if (!\mt_rand(0, 19)) { + $database = DATABASE_SHARED_TABLES; + } - // Allow overriding in development mode, to be removed once all project are using shared tables - if (App::isDevelopment()) { - $shareTables = (bool) $request->getHeader('x-appwrite-share-tables', false); + // Allow overriding in development mode, to be removed once all project are using shared tables. + if (App::isDevelopment() && $request->getHeader('x-appwrite-share-tables', false)) { + $database = DATABASE_SHARED_TABLES; } try { @@ -181,7 +183,6 @@ App::post('/v1/projects') 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), 'database' => $database, - 'shareTables' => $shareTables, ])); } catch (Duplicate) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); diff --git a/app/init.php b/app/init.php index 82e2baf804..214f91ae71 100644 --- a/app/init.php +++ b/app/init.php @@ -140,7 +140,8 @@ const APP_SOCIAL_DEV = 'https://dev.to/appwrite'; const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite'; const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1'; const APP_HOSTNAME_INTERNAL = 'appwrite'; -// Database Reconnect +// Database +const DATABASE_SHARED_TABLES = 'database_db_self_hosted_shared_tables'; const DATABASE_RECONNECT_SLEEP = 2; const DATABASE_RECONNECT_MAX_ATTEMPTS = 10; // Database Worker Types @@ -1148,7 +1149,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('shareTables')) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -1196,7 +1197,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('shareTables')) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/worker.php b/app/worker.php index 41c5a06a9d..71de280bfb 100644 --- a/app/worker.php +++ b/app/worker.php @@ -73,7 +73,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); - if ($project->getAttribute('shareTables')) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -101,7 +101,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('shareTables')) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -125,7 +125,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; - if ($project->getAttribute('shareTables')) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) From 6b0586eaf60129d1bb5ef481caf4e26a39f08cc9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 8 Dec 2023 18:06:53 +0100 Subject: [PATCH 21/61] Remove DB attribute --- app/config/collections.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index ed5e94eb65..db229ce87a 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3268,18 +3268,6 @@ $consoleCollections = array_merge([ 'array' => false, 'filters' => [], ], - [ - // To be removed once all project are using shared tables - '$id' => ID::custom('shareTables'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => ID::custom('logo'), 'type' => Database::VAR_STRING, From 4245c0b86e19cc812ca4c08da9d66c038c0de25d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 8 Dec 2023 18:07:38 +0100 Subject: [PATCH 22/61] Update dependencies --- composer.json | 6 ++--- composer.lock | 69 +++++++++++++++++---------------------------------- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/composer.json b/composer.json index 799f5b4987..3f24d9da74 100644 --- a/composer.json +++ b/composer.json @@ -43,13 +43,13 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.13.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "dev-feat-isolation-modes as 0.33.0", + "utopia-php/abuse": "0.34.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "dev-feat-isolation-modes as 0.35.0", + "utopia-php/audit": "0.36.*", "utopia-php/cache": "0.8.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-feat-isolation-mode as 0.45.2", + "utopia-php/database": "0.46.*", "utopia-php/domains": "0.3.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.31.0", diff --git a/composer.lock b/composer.lock index 04d20d6fb5..f591332dd0 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": "75330561b68809c4c842c513ead64783", + "content-hash": "4282a4b17ae483c99bb529c9b8cf7198", "packages": [ { "name": "adhocore/jwt", @@ -1615,23 +1615,23 @@ }, { "name": "utopia-php/abuse", - "version": "dev-feat-isolation-modes", + "version": "0.34.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "171eda04bfc53e5e24bdb36230ae84fe686ac2ee" + "reference": "49f84abc0f2317ba5b55af809cf6b411253c4855" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/171eda04bfc53e5e24bdb36230ae84fe686ac2ee", - "reference": "171eda04bfc53e5e24bdb36230ae84fe686ac2ee", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/49f84abc0f2317ba5b55af809cf6b411253c4855", + "reference": "49f84abc0f2317ba5b55af809cf6b411253c4855", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "dev-feat-isolation-mode as 0.45.0" + "utopia-php/database": "0.46.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1658,9 +1658,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/feat-isolation-modes" + "source": "https://github.com/utopia-php/abuse/tree/0.34.0" }, - "time": "2023-11-22T09:49:43+00:00" + "time": "2023-12-08T17:04:15+00:00" }, { "name": "utopia-php/analytics", @@ -1710,21 +1710,21 @@ }, { "name": "utopia-php/audit", - "version": "dev-feat-isolation-modes", + "version": "0.36.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "b561fa872c60e28afda02b4428ad5a2444099c44" + "reference": "b490f06d687fc1510d44ddce305afb81462ddd62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/b561fa872c60e28afda02b4428ad5a2444099c44", - "reference": "b561fa872c60e28afda02b4428ad5a2444099c44", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/b490f06d687fc1510d44ddce305afb81462ddd62", + "reference": "b490f06d687fc1510d44ddce305afb81462ddd62", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "dev-feat-isolation-mode as 0.45.0" + "utopia-php/database": "0.46.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1751,9 +1751,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/feat-isolation-modes" + "source": "https://github.com/utopia-php/audit/tree/0.36.0" }, - "time": "2023-11-22T09:49:57+00:00" + "time": "2023-12-08T17:04:53+00:00" }, { "name": "utopia-php/cache", @@ -1906,16 +1906,16 @@ }, { "name": "utopia-php/database", - "version": "dev-feat-isolation-mode", + "version": "0.46.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "c1341e2daa90aaa93511a98838cd48243aa2eae5" + "reference": "035e6b4a0005ad87aa73beca8714721925ea8f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/c1341e2daa90aaa93511a98838cd48243aa2eae5", - "reference": "c1341e2daa90aaa93511a98838cd48243aa2eae5", + "url": "https://api.github.com/repos/utopia-php/database/zipball/035e6b4a0005ad87aa73beca8714721925ea8f5e", + "reference": "035e6b4a0005ad87aa73beca8714721925ea8f5e", "shasum": "" }, "require": { @@ -1956,9 +1956,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/feat-isolation-mode" + "source": "https://github.com/utopia-php/database/tree/0.46.0" }, - "time": "2023-11-27T12:29:12+00:00" + "time": "2023-12-08T16:02:38+00:00" }, { "name": "utopia-php/domains", @@ -5796,32 +5796,9 @@ "time": "2023-08-28T11:09:02+00:00" } ], - "aliases": [ - { - "package": "utopia-php/abuse", - "version": "dev-feat-isolation-modes", - "alias": "0.33.0", - "alias_normalized": "0.33.0.0" - }, - { - "package": "utopia-php/audit", - "version": "dev-feat-isolation-modes", - "alias": "0.35.0", - "alias_normalized": "0.35.0.0" - }, - { - "package": "utopia-php/database", - "version": "dev-feat-isolation-mode", - "alias": "0.45.2", - "alias_normalized": "0.45.2.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/abuse": 20, - "utopia-php/audit": 20, - "utopia-php/database": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 4710310629326ba2aa7442de926a42ac003ad4e9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 8 Dec 2023 18:33:35 +0100 Subject: [PATCH 23/61] Check if self-hosted --- .env | 1 + app/controllers/api/projects.php | 17 ++++++--- app/init.php | 60 +++++++++++++------------------- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/.env b/.env index ad551e705a..cbd27c74bb 100644 --- a/.env +++ b/.env @@ -1,4 +1,5 @@ _APP_ENV=development +_APP_EDITION=self-hosted _APP_LOCALE=en _APP_WORKER_PER_CORE=6 _APP_CONSOLE_WHITELIST_ROOT=disabled diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 9916ae67f2..c21de5f83e 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -141,13 +141,20 @@ App::post('/v1/projects') throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); } - // One in 20 projects use shared tables - if (!\mt_rand(0, 19)) { + // TODO: One in 20 projects use shared tables. Temporary until all projects are using shared tables. + if ( + !\mt_rand(0, 19) + && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' + ) { $database = DATABASE_SHARED_TABLES; } - // Allow overriding in development mode, to be removed once all project are using shared tables. - if (App::isDevelopment() && $request->getHeader('x-appwrite-share-tables', false)) { + // TODO: Allow overriding in development mode. Temporary until all projects are using shared tables. + if ( + App::isDevelopment() + && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' + && $request->getHeader('x-appwrite-share-tables', false) + ) { $database = DATABASE_SHARED_TABLES; } @@ -190,7 +197,7 @@ App::post('/v1/projects') $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); - if ($shareTables) { + if ($database === DATABASE_SHARED_TABLES) { $dbForProject ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/init.php b/app/init.php index 515d9f884e..121ef327e2 100644 --- a/app/init.php +++ b/app/init.php @@ -684,47 +684,38 @@ $register->set('pools', function () { /** * Get Resource * - * Creation could be reused accross connection types like database, cache, queue, etc. + * Creation could be reused across connection types like database, cache, queue, etc. * * Resource assignment to an adapter will happen below. */ - switch ($dsnScheme) { - case 'mysql': - case 'mariadb': - $resource = function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array( - PDO::ATTR_TIMEOUT => 3, // Seconds - PDO::ATTR_PERSISTENT => true, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed - PDO::ATTR_EMULATE_PREPARES => true, - PDO::ATTR_STRINGIFY_FETCHES => true - )); - }); - }; - break; - case 'redis': - $resource = function () use ($dsnHost, $dsnPort, $dsnPass) { - $redis = new Redis(); - @$redis->pconnect($dsnHost, (int)$dsnPort); - if ($dsnPass) { - $redis->auth($dsnPass); - } - $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); + $resource = match ($dsnScheme) { + 'mysql', + 'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { + return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { + return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array( + PDO::ATTR_TIMEOUT => 3, // Seconds + PDO::ATTR_PERSISTENT => true, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => true, + PDO::ATTR_STRINGIFY_FETCHES => true + )); + }); + }, + 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { + $redis = new Redis(); + @$redis->pconnect($dsnHost, (int)$dsnPort); + if ($dsnPass) { + $redis->auth($dsnPass); + } + $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); - return $redis; - }; - break; - - default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"); - break; - } + return $redis; + }, + default => throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"), + }; $pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) { // Get Adapter - $adapter = null; switch ($type) { case 'database': $adapter = match ($dsn->getScheme()) { @@ -753,7 +744,6 @@ $register->set('pools', function () { default: throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); - break; } return $adapter; From 78e4c0611bb1237f09f6ac1ead3e391457bc5851 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 4 Mar 2024 20:02:45 +0100 Subject: [PATCH 24/61] Update deps --- composer.json | 4 +- composer.lock | 120 ++++++++++++++++++++++++++++---------------------- 2 files changed, 70 insertions(+), 54 deletions(-) diff --git a/composer.json b/composer.json index da5bee6dfb..90e8e7ec20 100644 --- a/composer.json +++ b/composer.json @@ -46,11 +46,11 @@ "appwrite/php-clamav": "2.0.*", "utopia-php/abuse": "0.34.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.35.*", + "utopia-php/audit": "0.36.*", "utopia-php/cache": "0.9.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.45.*", + "utopia-php/database": "dev-feat-0.45-isolation-modes as 0.46.0", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index c789878e99..3d511d9d0f 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": "f7a4173bb5adeea3518f949fa883a282", + "content-hash": "ea035b22fabb5e8518ee5fd6a6afbc3a", "packages": [ { "name": "adhocore/jwt", @@ -1187,16 +1187,16 @@ }, { "name": "utopia-php/database", - "version": "0.45.6", + "version": "dev-feat-0.45-isolation-modes", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "c7cc6d57683a4c13d9772dbeea343adb72c443fd" + "reference": "086c18e03d2bb3d1b12d1ccfc45d47da1473e05f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/c7cc6d57683a4c13d9772dbeea343adb72c443fd", - "reference": "c7cc6d57683a4c13d9772dbeea343adb72c443fd", + "url": "https://api.github.com/repos/utopia-php/database/zipball/086c18e03d2bb3d1b12d1ccfc45d47da1473e05f", + "reference": "086c18e03d2bb3d1b12d1ccfc45d47da1473e05f", "shasum": "" }, "require": { @@ -1204,7 +1204,7 @@ "ext-pdo": "*", "php": ">=8.0", "utopia-php/cache": "0.9.*", - "utopia-php/framework": "0.*.*", + "utopia-php/framework": "0.33.*", "utopia-php/mongo": "0.3.*" }, "require-dev": { @@ -1237,9 +1237,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.45.6" + "source": "https://github.com/utopia-php/database/tree/feat-0.45-isolation-modes" }, - "time": "2024-02-01T02:33:43+00:00" + "time": "2024-03-04T18:38:13+00:00" }, { "name": "utopia-php/domains", @@ -2822,20 +2822,21 @@ }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -2876,9 +2877,15 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -3217,16 +3224,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.30", + "version": "9.2.31", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", "shasum": "" }, "require": { @@ -3283,7 +3290,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" }, "funding": [ { @@ -3291,7 +3298,7 @@ "type": "github" } ], - "time": "2023-12-22T06:47:57+00:00" + "time": "2024-03-02T06:37:42+00:00" }, { "name": "phpunit/php-file-iterator", @@ -3689,16 +3696,16 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { @@ -3733,7 +3740,7 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" }, "funding": [ { @@ -3741,7 +3748,7 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { "name": "sebastian/code-unit", @@ -3987,16 +3994,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -4041,7 +4048,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -4049,7 +4056,7 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -4116,16 +4123,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { @@ -4181,7 +4188,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -4189,20 +4196,20 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { @@ -4245,7 +4252,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -4253,7 +4260,7 @@ "type": "github" } ], - "time": "2023-08-02T09:26:13+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { "name": "sebastian/lines-of-code", @@ -4973,16 +4980,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -5011,7 +5018,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -5019,7 +5026,7 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2024-03-03T12:36:25+00:00" }, { "name": "twig/twig", @@ -5094,9 +5101,18 @@ "time": "2023-11-21T18:54:41+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-feat-0.45-isolation-modes", + "alias": "0.46.0", + "alias_normalized": "0.46.0.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From fcc5a747d12a86863302f711f5ac9ec58db0fc7d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 4 Mar 2024 20:26:11 +0100 Subject: [PATCH 25/61] Fix test --- tests/e2e/General/HTTPTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index bf8f6de279..fd5cf7e925 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -31,7 +31,7 @@ class HTTPTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEquals('Appwrite', $response['headers']['server']); $this->assertEquals('GET, POST, PUT, PATCH, DELETE', $response['headers']['access-control-allow-methods']); - $this->assertEquals('Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Fallback-Cookies', $response['headers']['access-control-allow-headers']); + $this->assertEquals('Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Share-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Fallback-Cookies', $response['headers']['access-control-allow-headers']); $this->assertEquals('X-Fallback-Cookies', $response['headers']['access-control-expose-headers']); $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin']); $this->assertEquals('true', $response['headers']['access-control-allow-credentials']); From c768375e130f231dce8e24d0eaf5d19d1d4118b5 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 4 Mar 2024 20:54:35 +0100 Subject: [PATCH 26/61] Set tenant for CLI scope db --- app/cli.php | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/app/cli.php b/app/cli.php index e3f0ba72d7..c98cc62e7c 100644 --- a/app/cli.php +++ b/app/cli.php @@ -103,7 +103,19 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - $database->setNamespace('_' . $project->getInternalId()); + + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $database + ->setShareTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + return $database; } @@ -116,6 +128,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $database + ->setShareTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + $database ->setNamespace('_' . $project->getInternalId()) ->setMetadata('host', \gethostname()) From 7fc214afbef4a77ccd9819138c81349eb1d67d5c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 5 Mar 2024 11:55:29 +0100 Subject: [PATCH 27/61] Update libs --- composer.json | 2 +- composer.lock | 55 +++++++++++++++++++++------------------------------ 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/composer.json b/composer.json index 90e8e7ec20..33d3b158ec 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ "utopia-php/cache": "0.9.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-feat-0.45-isolation-modes as 0.46.0", + "utopia-php/database": "0.45.7", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 3d511d9d0f..c2150e47dc 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": "ea035b22fabb5e8518ee5fd6a6afbc3a", + "content-hash": "9ab28ccc7cde35e834aac175d331c346", "packages": [ { "name": "adhocore/jwt", @@ -895,23 +895,23 @@ }, { "name": "utopia-php/abuse", - "version": "0.34.0", + "version": "0.34.1", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "49f84abc0f2317ba5b55af809cf6b411253c4855" + "reference": "c8497650cd3ee0d04fe8a9e6391572262c1d89e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/49f84abc0f2317ba5b55af809cf6b411253c4855", - "reference": "49f84abc0f2317ba5b55af809cf6b411253c4855", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/c8497650cd3ee0d04fe8a9e6391572262c1d89e0", + "reference": "c8497650cd3ee0d04fe8a9e6391572262c1d89e0", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.46.*" + "utopia-php/database": "0.45.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -938,9 +938,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.34.0" + "source": "https://github.com/utopia-php/abuse/tree/0.34.1" }, - "time": "2023-12-08T17:04:15+00:00" + "time": "2024-03-05T10:43:41+00:00" }, { "name": "utopia-php/analytics", @@ -990,21 +990,21 @@ }, { "name": "utopia-php/audit", - "version": "0.36.0", + "version": "0.36.1", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "b490f06d687fc1510d44ddce305afb81462ddd62" + "reference": "9db48fed0558c33c9ddbb493fe2171844a3f0fd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/b490f06d687fc1510d44ddce305afb81462ddd62", - "reference": "b490f06d687fc1510d44ddce305afb81462ddd62", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/9db48fed0558c33c9ddbb493fe2171844a3f0fd4", + "reference": "9db48fed0558c33c9ddbb493fe2171844a3f0fd4", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.46.*" + "utopia-php/database": "0.45.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1031,9 +1031,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.36.0" + "source": "https://github.com/utopia-php/audit/tree/0.36.1" }, - "time": "2023-12-08T17:04:53+00:00" + "time": "2024-03-05T10:50:30+00:00" }, { "name": "utopia-php/cache", @@ -1187,16 +1187,16 @@ }, { "name": "utopia-php/database", - "version": "dev-feat-0.45-isolation-modes", + "version": "0.45.7", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "086c18e03d2bb3d1b12d1ccfc45d47da1473e05f" + "reference": "f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/086c18e03d2bb3d1b12d1ccfc45d47da1473e05f", - "reference": "086c18e03d2bb3d1b12d1ccfc45d47da1473e05f", + "url": "https://api.github.com/repos/utopia-php/database/zipball/f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03", + "reference": "f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03", "shasum": "" }, "require": { @@ -1237,9 +1237,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/feat-0.45-isolation-modes" + "source": "https://github.com/utopia-php/database/tree/0.45.7" }, - "time": "2024-03-04T18:38:13+00:00" + "time": "2024-03-05T10:28:02+00:00" }, { "name": "utopia-php/domains", @@ -5101,18 +5101,9 @@ "time": "2023-11-21T18:54:41+00:00" } ], - "aliases": [ - { - "package": "utopia-php/database", - "version": "dev-feat-0.45-isolation-modes", - "alias": "0.46.0", - "alias_normalized": "0.46.0.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 1b7ce8fc61af94f3bc24a86b50ceb3c775f7fc32 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 6 Mar 2024 10:59:05 +0100 Subject: [PATCH 28/61] Debug --- app/cli.php | 2 ++ app/controllers/api/projects.php | 3 +++ app/init.php | 2 ++ app/worker.php | 3 +++ 4 files changed, 10 insertions(+) diff --git a/app/cli.php b/app/cli.php index c98cc62e7c..324d1c948c 100644 --- a/app/cli.php +++ b/app/cli.php @@ -105,6 +105,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database = $databases[$databaseName]; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -129,6 +130,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 552c3f786b..06f219fb6f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -158,6 +158,8 @@ App::post('/v1/projects') $database = DATABASE_SHARED_TABLES; } + \var_dump('DATABASE: ' . $database); + try { $project = $dbForConsole->createDocument('projects', new Document([ '$id' => $projectId, @@ -198,6 +200,7 @@ App::post('/v1/projects') $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); if ($database === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $dbForProject ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/init.php b/app/init.php index 06d508e27a..705b8173e4 100644 --- a/app/init.php +++ b/app/init.php @@ -1136,6 +1136,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -1184,6 +1185,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/worker.php b/app/worker.php index 989f1223af..207762fef9 100644 --- a/app/worker.php +++ b/app/worker.php @@ -76,6 +76,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setMetadata('project', $project->getId()); if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -115,6 +116,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $database = $databases[$databaseName]; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -139,6 +141,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) From 3312ed1c5da4b60ce9721a636a02dab182e4ef8d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 6 Mar 2024 21:14:55 +0100 Subject: [PATCH 29/61] Debug --- app/cli.php | 2 - app/init.php | 16 +- app/worker.php | 3 - composer.lock | 12 +- names2.json | 1527 ++++++++++++++++++++++++++++++++++++++++++++++++ test.php | 0 6 files changed, 1540 insertions(+), 20 deletions(-) create mode 100644 names2.json create mode 100644 test.php diff --git a/app/cli.php b/app/cli.php index 324d1c948c..c98cc62e7c 100644 --- a/app/cli.php +++ b/app/cli.php @@ -105,7 +105,6 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database = $databases[$databaseName]; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -130,7 +129,6 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/init.php b/app/init.php index 705b8173e4..2493386390 100644 --- a/app/init.php +++ b/app/init.php @@ -1135,18 +1135,17 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); + //if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); @@ -1185,7 +1184,6 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/app/worker.php b/app/worker.php index 207762fef9..989f1223af 100644 --- a/app/worker.php +++ b/app/worker.php @@ -76,7 +76,6 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setMetadata('project', $project->getId()); if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -116,7 +115,6 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $database = $databases[$databaseName]; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) @@ -141,7 +139,6 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); $database ->setShareTables(true) ->setTenant($project->getInternalId()) diff --git a/composer.lock b/composer.lock index c2150e47dc..905abf7103 100644 --- a/composer.lock +++ b/composer.lock @@ -2764,16 +2764,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.1", + "version": "v5.0.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69" + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69", - "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", "shasum": "" }, "require": { @@ -2816,9 +2816,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" }, - "time": "2024-02-21T19:24:10+00:00" + "time": "2024-03-05T20:51:40+00:00" }, { "name": "phar-io/manifest", diff --git a/names2.json b/names2.json new file mode 100644 index 0000000000..a32b5ca8d5 --- /dev/null +++ b/names2.json @@ -0,0 +1,1527 @@ +{ + "album-database": 1, + "default": 7, + "Renew-Tech-DB": 1, + "posts": 7, + "vreddb": 1, + "test-db": 12, + "friendly-secret": 1, + "recipeDB": 2, + "TestDb": 2, + "first": 5, + "test": 96, + "Securelee": 1, + "cpldb": 1, + "SpeakingDB": 1, + "StoriesDB": 1, + "UserSignup": 1, + "WrittenDB": 1, + "db1": 17, + "CourcesDB": 1, + "Learnhub": 1, + "Users": 17, + "notes": 3, + "main": 28, + "Event planning ": 1, + "SupAut": 1, + "userTable": 1, + "coredb": 1, + "event-planner": 1, + "P01": 1, + "chatgpt-database": 1, + "JQQ Memes": 1, + "nocodb": 1, + "TaskList": 1, + "Retail": 1, + "Test": 30, + "Subscriptions": 1, + "Primary DB": 1, + "travelappdatabase": 1, + "DB": 7, + "back-end": 1, + "mydb": 5, + "Chats": 1, + "secrets": 1, + "pine": 1, + "MamaPut": 1, + "simpleApp": 1, + "gossip": 1, + "ecom_database": 1, + "edge-data": 1, + "vizualGitDb": 1, + "ticket": 1, + "toDo": 1, + "beacon": 1, + "hero": 1, + "users": 33, + "Twitter Test": 21, + "code-share": 1, + "DbName": 1, + "MyRecipePad": 1, + "twitter_clone": 3, + "event_db": 1, + "timers": 1, + "parsiukai": 1, + "AuthDatabase": 2, + "pfs_dev": 1, + "contratista": 1, + "support-local": 1, + "hey": 1, + "mindmemoDB": 1, + "E commerse": 1, + "my_basketball_club": 1, + "Amaad": 1, + "testdb": 21, + "twitter-clone": 7, + "srikalyanam": 1, + "todos": 27, + "Recipes": 2, + "todo": 18, + "demo": 12, + "confessus": 1, + "game": 3, + "primary": 2, + "dummy workout": 1, + "FitPulse": 1, + "vender": 1, + "workouts": 1, + "fresh": 1, + "hello": 3, + "auth": 1, + "domain": 1, + "Glitch": 1, + "Teste": 1, + "UsersData": 1, + "Linda": 1, + "supabse": 1, + "events": 4, + "dopecut-data": 1, + "lll": 1, + "FurrBuddiesDB": 1, + "VeterinarianDB": 1, + "test-sso-akhilesh": 1, + "cdv": 1, + "testing": 4, + "USDZ models": 1, + "book1": 1, + "Events": 4, + "cmpt-int-db": 1, + "yupio_db": 1, + "content": 3, + "test1": 2, + "okr db": 1, + "ckh-sport-equipment": 1, + "Twitter test": 1, + "Companies": 1, + "datas": 1, + "first-database": 1, + "tiger": 1, + "evo_db": 2, + "ProHacks": 1, + "cards": 1, + "projects": 3, + "app": 29, + "conversations": 2, + "Logging": 1, + "images": 2, + "podbase": 1, + "MYMATCH": 1, + "TestDB1": 2, + "m": 1, + "Tasks": 3, + "Recipes-Tracker": 1, + "db": 21, + "restaurants-details": 1, + "TEST": 2, + "first-db": 1, + "product-info-management": 1, + "demodb": 1, + "chats": 1, + "project-db": 2, + "logs_db": 1, + "users_db": 2, + "hustlehub-db": 1, + "profile": 1, + "jha": 1, + "photosharing": 1, + "mongi": 1, + "tupropiedad": 1, + "spotify database": 1, + "usersWatchlists": 1, + "watchlistsDB": 1, + "twitter_test": 1, + "chatDB": 1, + "development": 4, + "11": 1, + "vm": 1, + "manga mania db": 1, + "tutorialDB": 1, + "quizapp": 3, + "GitSafari": 1, + "lulucat": 1, + "testdatabase1101": 1, + "shops": 1, + "Salt-user-db": 1, + "insta_clone": 1, + "jobo": 1, + "vectors": 1, + "prueba": 2, + "Tech Blog": 1, + "socio_db": 1, + "Eventhub": 1, + "we-code": 1, + "jalauncodinghub": 1, + "beebeer_db": 1, + "recipes": 3, + "Twitter Clone dev": 1, + "testDb": 1, + "Rizq Sharing": 1, + "abc": 1, + "4_db": 1, + "dtdb": 1, + "clientUser": 1, + "asnad database": 1, + "ded": 1, + "yesusa_portal": 1, + "guidepilot-db": 1, + "hackathon_entries": 1, + "Dime": 1, + "blogs": 8, + "Genx": 1, + "SQD": 1, + "hippoDatabase": 1, + "Todo": 2, + "merchdjv_productdb": 1, + "sample": 2, + "datatest": 1, + "esp": 1, + "project": 2, + "letsdesign": 1, + "Studentpos": 1, + "movies": 2, + "quickstart": 1, + "Backup": 1, + "Default": 11, + "XXX": 4, + "vue_crud": 1, + "lessons": 1, + "test-database": 2, + "HellDB": 1, + "myDB": 1, + "products": 5, + "Straddle": 1, + "reketupa": 1, + "Restore": 1, + "Setup": 1, + "task-db": 1, + "money_manager": 1, + "3tee_databas": 1, + "jobs": 2, + "multi-resume": 1, + "my_db": 1, + "Trobia": 1, + "Movies": 5, + "foo": 2, + "Event Planner": 1, + "bleed": 1, + "DB1": 3, + "database": 9, + "fitadom": 1, + "hashnode": 1, + "stenodb": 1, + "nexus": 1, + "hosts": 1, + "space_launches_info": 1, + "dev": 9, + "testbase": 2, + "tinto": 1, + "test_db": 5, + "Data info": 1, + "demo db": 1, + "Studucatrial": 1, + "twitterClone": 2, + "Babu": 1, + "Cara": 1, + "booking": 2, + "Url Shortener": 1, + "votify": 1, + "lynaesh_dashboard": 1, + "URLShort": 1, + "SocialMedia": 1, + "appDatabase": 10, + "Database 1": 1, + "ps-innovation-day": 1, + "AppDatabase": 161, + "appdatabase": 1, + "svellodatabase": 1, + "user": 5, + "TrelloDatabase": 2, + "first_app": 1, + "boats": 1, + "intratec-tecnologia": 1, + "chat-app": 1, + "DnD database": 1, + "appwrite": 2, + "admin_users_database": 1, + "app database": 2, + "234234": 1, + "dusers": 1, + "trello-database": 4, + "TaskerDB": 1, + "meddb": 1, + "dsuite-db": 2, + "fleekytrendsProducts": 1, + "healthservices": 1, + "openchat": 1, + "Aurelia DB": 1, + "Locations": 1, + "AppDB": 3, + "VideoCall": 1, + "Development": 2, + "TrelloApp": 1, + "type-frenzy": 1, + "config": 1, + "FakeDB": 1, + "dev_01": 1, + "register": 1, + "gratitude_jar_db": 1, + "priceers": 1, + "Huntdb": 1, + "TrelloDb": 2, + "prasad": 1, + "brtbhrthtrhhtrhtrnh": 1, + "CodingFlux Database": 1, + "Flair Database": 1, + "FVB": 1, + "Admin": 2, + "emailusers": 1, + "ITrackemail": 1, + "notificationtoken": 1, + "orgcode": 1, + "schoolreq": 1, + "Triperbus": 1, + "vehicles": 1, + "ATWS Databases": 1, + "Buildrankers-Prod": 1, + "Discussion Forum": 1, + "CanbanDatabase": 1, + "chipIn MVP database": 1, + "jamshaidtaskifyDatabase": 1, + "school": 2, + "todo-db": 2, + "LearningApp": 1, + "twitter test": 2, + "TestDB": 9, + "appdata": 1, + "flutter_appwrite_col": 1, + "flutter_appwrite": 1, + "PromanageDatabase": 1, + "landing": 1, + "bank-data": 1, + "moni": 1, + "StuffDatabase": 1, + "alertapp-prod": 1, + "alertapp-qa": 1, + "Walldb": 1, + "role:on": 1, + "leaderboardlearn": 1, + "Taskify": 1, + "DB-PAYMENT-PAGE": 1, + "ggg": 2, + "TrelloCloneDB": 1, + "kanban-gpt-app": 1, + "awc-news": 1, + "data": 6, + "orders": 1, + "ding": 1, + "bisky_chat": 1, + "vaibgram-db": 1, + "trello-clone": 3, + "appdb": 3, + "trelo": 1, + "tpmt": 1, + "languageEx": 1, + "virtualBot": 1, + "Database test": 1, + "Main": 9, + "rnd": 1, + "trips": 1, + "ProductDatabase": 1, + "atesting": 1, + "cakebudget": 1, + "oya_db": 1, + "Raven": 1, + "TaskAppDatabase": 1, + "main_db": 1, + "exams": 1, + "Notes": 1, + "root": 2, + "Exercises": 1, + "estudos": 1, + "store": 2, + "trello-db": 1, + "ProdAmigoDB": 1, + "chikigram": 1, + "Viagens": 1, + "brainwars_db": 1, + "app-database": 1, + "Trello": 2, + "Admins": 1, + "wax": 1, + "undanganonline": 1, + "Sunarp": 1, + "recipto_db": 1, + "trello_clone_db": 1, + "dB": 2, + "Messages": 3, + "Dadabase": 1, + "SecurePass": 1, + "Registrations": 1, + "Sponsors": 1, + "Trello Database": 2, + "contact_form": 1, + "chat_db": 1, + "app_database": 1, + "watchlist": 1, + "myorg": 1, + "temir": 1, + "Todos": 4, + "Website Color CSS": 1, + "testonio": 1, + "teste": 3, + "trello-v2": 1, + "tikDb": 1, + "Queries": 1, + "shophub": 1, + "appDatabases": 1, + "trelloDatabase": 1, + "appDataBase": 1, + "mmm": 1, + "workdiary": 1, + "Specs99 DB": 1, + "App database": 1, + "Frank": 1, + "app_data": 1, + "app_pop_up_db": 1, + "express_pay_app_database": 1, + "nextcloudify_db_dev": 1, + "main database": 1, + "VitaPlate": 1, + "writepost": 1, + "trial": 1, + "BataapDB": 1, + "collectify_database": 1, + "pso2_items_database": 1, + "agis": 1, + "twitter": 4, + "HabitProDB": 1, + "TripArchitectDB": 1, + "airiedb": 1, + "purupdb": 1, + "flutter": 7, + "flutter_database": 12, + "geoteams": 1, + "Ecom": 1, + "Trabajadores": 1, + "HnosUceda": 1, + "etracker": 2, + "Reviews": 1, + "trello-clone-db": 1, + "AllPos": 1, + "liqlid-mvp-main": 1, + "db01": 2, + "Trello dev": 1, + "child": 1, + "shortcuts": 1, + "TrelloCloneAppDatabase": 1, + "leagueFusion": 1, + "activity_1000k": 1, + "activity_100k": 1, + "TaskManager-Projects": 1, + "SocialMediaAppDB": 1, + "devdactic": 2, + "dbtian": 1, + "BlogMd": 1, + "Trello_Clone_AppDatabase": 1, + "waste-collection": 1, + "user_details": 1, + "appwrite_hackathon": 1, + "new": 4, + "messages": 6, + "Render2023": 1, + "testinggg": 1, + "chatwrite": 3, + "Chatty": 1, + "information": 1, + "chattingDB": 1, + "NoteDb": 1, + "app-db": 3, + "123": 1, + "webook": 1, + "apt": 1, + "User": 6, + "hackerspace": 1, + "general": 5, + "ChatDB": 2, + "renderatl-2023": 1, + "General": 1, + "zoro": 1, + "testData": 1, + "ns-db": 1, + "tbUsuario": 1, + "trails": 1, + "GameRefill Shop": 1, + "fitdb": 1, + "cccmedia": 1, + "robodoradca": 1, + "astro": 1, + "369": 1, + "likakuDB": 1, + "clinick-db": 1, + "devices": 2, + "maindb": 1, + "notebooks": 1, + "chatting-application": 1, + "Storage": 1, + "CSE_DB": 1, + "AppTodo": 1, + "rideonparts": 1, + "appwritedb": 1, + "Testdb": 1, + "wisetally": 1, + "staging": 3, + "taskkify-db": 1, + "Ellume360": 1, + "EllumeLogin": 1, + "trell-app-database": 1, + "products database": 1, + "AInews": 1, + "Session": 1, + "riia-db": 1, + "backfillJobs": 1, + "Settings": 1, + "Log": 1, + "App": 2, + "Document": 1, + "oneDeal": 1, + "scan_and_go_db": 1, + "goraiya db": 1, + "CombiDataBase": 1, + "dcg": 1, + "todoData": 1, + "notestester": 1, + "recipe": 1, + "mqtt_auth": 1, + "pumprecord-db": 1, + "Slideshub": 1, + "Prescriptions ": 1, + "AppDataBase": 2, + "business_Aid": 1, + "trello_app": 1, + "slack-app-db": 1, + "taskapp": 1, + "trello-app": 1, + "SorageX": 1, + "superdb": 1, + "Osd": 1, + "trivia_project": 1, + "Emp": 1, + "userdetails": 1, + "HRIS": 1, + "Account": 1, + "tetris": 1, + "task-ai_database": 1, + "SheroDatabase": 1, + "UserData": 2, + "DashboardDb": 1, + "mydatabase": 1, + "event name, description, date, and location": 1, + "Payments": 1, + "Skarban": 1, + "VGPT": 1, + "WhatsappDatabase": 1, + "meetings": 1, + "Icicle_Statistics": 1, + "CRUX": 1, + "crud": 1, + "hosting": 1, + "Tt": 1, + "tables": 1, + "arbah": 1, + "globalbulls": 1, + "calligrapy": 1, + "instant_messenger": 1, + "Finance": 1, + "cook it up": 1, + "main-db": 1, + "IRA": 1, + "AppDtabase": 1, + "who fed the pet data": 1, + "agenda": 1, + "invoices": 2, + "notifications": 2, + "patient": 1, + "userSettings": 1, + "nmn": 1, + "upinvoice": 1, + "base64": 1, + "swingfire-app": 1, + "photos": 3, + "meetify": 1, + "gptmanaDB": 1, + "pos": 2, + "school_council": 1, + "62d985ab68e0e4b60293": 1, + "62dd7c6bbe54693b8a32": 1, + "secure-chat": 1, + "android-test": 1, + "commpcs_pro": 1, + "TEST DATABASE": 1, + "TaskWalletDB": 1, + "Contracts": 1, + "sampleDB": 1, + "telegram_bot": 1, + "AZED": 1, + "Hapix-db": 1, + "prod": 4, + "App-db": 1, + "quotes": 1, + "Dummy data": 1, + "User appointments": 1, + "chrono": 1, + "VarsityWorldDevelopment": 1, + "ServiceProviders": 1, + "r": 1, + "Murad": 1, + "ScheduleHero": 4, + "testindb": 1, + "flutter_db": 1, + "defaultDb": 1, + "History": 1, + "Distributors-Labels": 1, + "LoggingDB": 1, + "reservas": 1, + "SurveyDatabase": 1, + "no-bullshit-recipes-database": 1, + "lvr_db": 1, + "db1234": 1, + "myClass": 1, + "trello": 2, + "mrElayaDb": 1, + "memos": 1, + "Accounts": 1, + "Commissions": 1, + "lines": 1, + "BKB": 2, + "Elements": 2, + "design_resources": 1, + "public_data": 1, + "users_data": 1, + "X-connect": 1, + "inventory": 1, + "OrganizerDB": 1, + "AppDatabasexxxx": 1, + "animals": 1, + "transport": 1, + "markly": 1, + "db_app": 1, + "board": 2, + "ahaporn": 1, + "subscribers": 1, + "databases": 1, + "message": 1, + "vote": 1, + "portfolio": 2, + "chat": 12, + "QuestList": 1, + "Personal Life Assistant DB": 1, + "C Programming Club": 1, + "groupevents-db": 1, + "resumix": 1, + ",": 1, + "Negotiations": 1, + "Basedate": 4, + "twitterdb": 1, + "STO": 1, + "ai-generator-db-v1": 1, + "e-commerce": 1, + "MADG7": 1, + "TrelloAppDatabase": 1, + "firstdb": 1, + "Items": 1, + "digitalsign": 1, + "e-commerce-app": 1, + "appDb": 2, + "anycasts": 1, + "food": 2, + "noodles-db": 1, + "properly": 1, + "repulse": 1, + "geolocation1_db": 1, + "Updated Database": 9, + "db_kharcha_aamdani": 1, + "Jajanan Lobet": 1, + "NodeToDo": 1, + "mutual_funds": 1, + "nextjs": 1, + "bybit": 1, + "medlogs": 1, + "life-loop": 1, + "ll": 1, + "client": 1, + "AllThumbs": 1, + "Test DB": 2, + "todoApp": 1, + "t.db1": 1, + "dog_sitting": 1, + "todosss": 1, + "doovu": 1, + "tasks": 4, + "tasks_list": 7, + "cagnotte": 1, + "6482f68757302733e335": 1, + "64d7c796b08f76ec51f6": 1, + "db_demo": 1, + "bus": 1, + "election-app": 1, + "a": 2, + "employees": 2, + "database_name_m001": 1, + "resume": 2, + "ImmerseToDo": 1, + "[PROD] krello db": 1, + "myMlmDb": 1, + "ct": 1, + "RacketScoreDB": 1, + "khataApp": 1, + "luna": 1, + "Abc": 1, + "TestDatabase1": 1, + "dev12": 1, + "taskies main database": 1, + "SO-SKILLED": 1, + "hp01": 17, + "iku": 1, + "items": 2, + "mi-tunes-db": 1, + "TaskifyDatabase": 1, + "Ttatar": 1, + "myDatabase": 2, + "TaskBro": 1, + "appslause_trello_db": 1, + "blogposts": 18, + "trundling": 1, + "base_database": 1, + "bookListTest": 1, + "PU-Chd": 1, + "Pu-Chd": 1, + "postapi": 1, + "FamProDB": 1, + "photoshare": 1, + "Blog": 4, + "W.Task-AppDatabase": 1, + "TrelloAppDataBase": 1, + "fleet": 1, + "reservation": 1, + "drb": 1, + "DemoDatabase": 1, + "storage alpha": 1, + "contentus": 1, + "contentus-shadow-db": 1, + "whatsapp": 1, + "explore-aw-db": 1, + "phone auth demo": 1, + "readlits-db": 1, + "facemodel": 1, + "categories": 1, + "pms": 1, + "mohali-id": 1, + "UserDatabase": 1, + "collabverse": 1, + "gratitude-db": 1, + "my-digital-manager-database": 1, + "budget": 1, + "jmdb": 1, + "okaki-sensoren": 1, + "Personality": 1, + "UserDB": 1, + "ghgh": 1, + "JinjaCovers": 1, + "Blogs": 1, + "ihmtransact": 1, + "MoodMapDB": 1, + "pruebaadz": 1, + "cv": 1, + "fff": 1, + "monedaDB": 1, + "Main Database": 1, + "thenonpp_dev": 1, + "product": 3, + "ecommerce": 1, + "TASKS": 1, + "portals": 1, + "twitterTest": 1, + "sample_data": 1, + "Phalam": 1, + "journalDB": 1, + "LeaveFormStore": 1, + "Event DB": 1, + "Employees": 1, + "transactions_db": 1, + "melange": 1, + "myskoolDb": 1, + "blood_bank_db": 1, + "blood_chat_db": 1, + "bracket_assets_db": 1, + "bracket_db": 1, + "bracket_invitations_db": 1, + "chats_db": 1, + "counselling_appointments_db": 1, + "counselling_db": 1, + "discussion_assets_db": 1, + "discussion_db": 1, + "discussion_talks_db": 1, + "discussion_user_stats": 1, + "events_db": 1, + "members_db": 1, + "user_notification_db": 1, + "seats": 1, + "A": 2, + "Marks": 1, + "d1": 1, + "Diary Dev": 1, + "Load Test": 1, + "wer": 1, + "Products": 3, + "medical": 1, + "xanwas": 1, + "committable-backend": 1, + "Food": 1, + "Management": 1, + "chef_mani": 1, + "DB Billetterie": 1, + "Appwrite DB": 1, + "mio-admin": 1, + "User Data": 2, + "News DB": 1, + "info_Sossis": 1, + "DB_AULAS": 1, + "todo-final": 1, + "Evd": 1, + "players": 1, + "HungerZero": 1, + "Twitter db": 1, + "connectkoreaair": 1, + "s": 1, + "xpenzave_db": 1, + "students": 1, + "chatBlog": 1, + "newChatBlog": 1, + "TEAMING PORTAL CHAT ": 1, + "rss_db": 1, + "stella": 1, + "Database": 3, + "Twitter": 2, + "TrelloDB": 2, + "lorgger": 1, + "mindly_db": 1, + "Testdatabase": 1, + "soundboard": 1, + "GroupChatDB": 1, + "one": 2, + "Heatank": 1, + "bucket_data": 1, + "user_data": 1, + "primary_db": 1, + "Project": 1, + "tripbot": 1, + "sell_smart_main": 1, + "mainDB": 1, + "hackathon": 1, + "AppDatabse": 1, + "MyApp": 2, + "bookstore": 1, + "devverse-db": 1, + "expense-care-db": 1, + "pins": 1, + "expensasaurus": 1, + "Ireland Made": 1, + "sac": 1, + "WriterBlog": 1, + "snippad-main": 1, + "Trello-data": 1, + "silai": 1, + "codecollab": 1, + "Transactions": 1, + "Local Log": 1, + "AppDatabases": 1, + "FirstTestDB": 1, + "SignalClone": 1, + "FileStore": 1, + "21yards": 1, + "todo-app": 2, + "Insudash": 1, + "zokoboss": 1, + "Karte": 2, + "Rel-TEST": 1, + "olimpodb": 1, + "zinduo flashcard": 1, + "newDB": 1, + "EventScape": 1, + "Konsulting": 1, + "Demo": 1, + "redmatters": 1, + "essai_db": 1, + "my-stirixis-database": 1, + "MyBlogs": 1, + "blogpost": 3, + "zlist_db": 1, + "movieData": 1, + "Players": 1, + "mindful-me": 1, + "lolo": 1, + "sharebitedb": 1, + "master": 1, + "sf": 1, + "noteenc": 1, + "blogposts ": 1, + "Blog-Posts": 1, + "db-1": 1, + "testDB": 2, + "641f01fb3f6a1bc22c7e": 1, + "mysql": 1, + "HabitDB": 1, + "agents": 1, + "Tam Duc Apparel DB": 1, + "blog-post": 1, + "stores": 1, + "department": 1, + "sop": 1, + "Distributa": 3, + "rnxcode_db": 1, + "netflix_clone": 1, + "guizapp": 1, + "BlogPosts": 1, + "Chat": 2, + "Bedevelopers-Database": 1, + "likumbi": 1, + "OptionSuperManDB": 1, + "article": 1, + "NewDB": 1, + "MyGameStudio": 1, + "default_db": 1, + "userdata": 2, + "Main DB": 1, + "travfddb": 1, + "expenses": 1, + "incomes": 1, + "consultations_database": 1, + "doctors_database": 1, + "patients_database": 1, + "dealfuel": 1, + "Zenivote": 1, + "Portfolio Details": 1, + "Abhidhan Rajendra Kosh": 1, + "common": 1, + "AppUser": 1, + "studygang": 1, + "Peakfit.Db": 1, + "Credentials": 1, + "destinations": 1, + "fun2print_cc": 1, + "billing1": 1, + "studygangdb": 1, + "autana_ide": 1, + "betadev": 1, + "Vibey": 1, + "Slam Book": 1, + "TeleGPT": 1, + "Clips": 1, + "Quizmaster": 1, + "Office Hours DB": 1, + "canva order": 1, + "VideoWatching": 1, + "DataBase": 1, + "sharif-invoice": 1, + "Hack Questions": 1, + "er": 1, + "course": 1, + "Almost Netflix Project": 1, + "Database_sree": 1, + "Quizapp": 1, + "UNIT": 1, + "Public": 2, + "SalesT": 1, + "ZIC": 1, + "Employee": 1, + "Pets": 1, + "twitter-database": 2, + "dev-db": 1, + "track-db": 1, + "demo-db": 2, + "test db": 2, + "teste_db": 1, + "db_lumes": 1, + "SuperWalk": 1, + "rbac2": 1, + "Animesh": 1, + "Bereal": 1, + "PdfTest": 1, + "colonium-users": 1, + "dbMyPrice": 1, + "Production": 2, + "admin_db": 1, + "report-feelings": 1, + "browser": 1, + "protasker": 1, + "shop": 1, + "trigger-tech": 1, + "user data": 1, + "online_env": 1, + "DC3Mobi": 1, + "webappdb": 1, + "synapp": 1, + "pages": 1, + "collective-tales-dev": 1, + "Bildwurf DB": 1, + "Cards": 1, + "ok": 1, + "tmp": 1, + "StandUp": 1, + "Web Database": 1, + "TodoDB": 1, + "Prueba": 1, + "pafunn": 1, + "profiles": 2, + "nice-support": 1, + "pulse": 1, + "jargonjar": 1, + "xsx": 1, + "event-lly": 1, + "Sprittie": 1, + "test_database": 1, + "StroyOko": 1, + "Sparkle": 1, + "Coworkers": 1, + "Canva Templates": 1, + "production": 5, + "home-management": 1, + "dt": 1, + "vodo_db": 1, + "MyTestDB": 1, + "LinkedIn DB": 1, + "blog": 15, + "Example Database": 1, + "companion_db": 1, + "uni_sort": 1, + "rfg_app": 1, + "twitter-clone-project": 1, + "Restaurant_profiles": 1, + "trytowin": 1, + "db_test": 2, + "gallery": 1, + "usersData": 1, + "core": 1, + "IM": 1, + "TechBase": 1, + "ANDON": 1, + "awtest-db": 1, + "Widgets": 1, + "ember": 1, + "asdasdasd": 1, + "courrierflex": 1, + "TunezStream": 1, + "PmanDatabase": 1, + "weintegral": 1, + "TrelloData": 1, + "Test db": 1, + "bandom": 1, + "rezoom-eh-db": 1, + "WordJournalDB": 1, + "99": 1, + "T": 1, + "dop_exams": 1, + "database1": 3, + "asx": 1, + "myilsc": 1, + "Student Base": 1, + "shortify": 1, + "Cheelz Database": 1, + "TESLA Web Database": 1, + "Shorely Ibiza": 1, + "test-server": 1, + "Local_Gems": 1, + "articles": 1, + "AppwriteDb": 1, + "Auction": 1, + "lol": 1, + "todowrite-db": 1, + "BooksDB": 1, + "LoanDB": 2, + "dali": 1, + "JCI app": 1, + "OMS": 1, + "PIM": 1, + "RFx": 1, + "Data": 6, + "acctg1": 1, + "hris1": 1, + "hris2": 1, + "JobTitle": 2, + "CRUD database": 1, + "Foodtracker": 1, + "typical_food": 1, + "demoDB": 1, + "base1": 1, + "trello database": 1, + "demo-db-2": 1, + "Hypertrophy": 1, + "Dojo database": 1, + "skinvasai": 1, + "sgveti": 1, + "medicademy-db": 1, + "habbit": 1, + "Task": 1, + "Data ": 1, + "mvp": 1, + "wwwg": 1, + "public-system": 1, + "student_data": 1, + "chatting": 1, + "Kharidoit": 1, + "kj": 1, + "local": 1, + "wallpaper": 1, + "workspace": 1, + "sarcom-admin": 1, + "tickets": 1, + "ifiye-db": 1, + "Dev": 1, + "Prod": 2, + "TooodooosDB": 1, + "Climast database ": 1, + "My Provisioned DB": 1, + "logs": 2, + "Ascended": 1, + "avx": 1, + "geoloyaltydb": 1, + "yulidb": 1, + "public": 2, + "cms": 1, + "shop together": 1, + "UsersPosts": 1, + "tetst1": 1, + "blogdatabase": 1, + "Twitter test db": 1, + "vhhfdh": 1, + "baket": 1, + "i2e_sw_account": 1, + "New": 1, + "appwrite-test": 1, + "example database": 1, + "storyTable": 1, + "Clothing": 1, + "SV dataflow": 1, + "hgfdjd": 1, + "CoorfyDB": 1, + "purchased": 1, + "Countdown": 1, + "moe": 1, + "rawabialkharef": 1, + "123database": 1, + "shareamDB": 1, + "twitter_db": 1, + "fluttiyomi": 1, + "trends": 1, + "servers": 1, + "Oblongata": 1, + "Cygnus": 1, + "appwriteLearningDb": 1, + "Product": 1, + "PedroDB": 1, + "opos": 1, + "top-team-opos": 1, + "trainings": 1, + "converstations": 1, + "Modern Deals": 1, + "WebStorage": 1, + "apiTestOnline": 1, + "rajmade": 1, + "Profile image url": 1, + "Demo 1": 1, + "Akordi": 1, + "syncms": 1, + "pranav": 1, + "Oracle ": 1, + "dashboard": 1, + "deti": 1, + "exms": 1, + "rm-test": 1, + "test2": 1, + "Grids": 1, + "ProductionDatabase": 1, + "TestDatabase": 1, + "Yukt": 1, + "z": 1, + "CMS": 1, + "Entries": 1, + "books": 1, + "ewoerp": 1, + "AVImark Reports": 1, + "customtabs": 1, + "Database-1": 1, + "sampledatabase": 1, + "Deptos": 1, + "Sugam's Database": 1, + "Test-DB": 2, + "sms": 1, + "skyone-todo": 1, + "tiktok-clone": 1, + "YouTube Videos": 1, + "automata": 1, + "radium": 1, + "TestDb1": 1, + "etherdb": 1, + "global_db": 1, + "near.db": 1, + "Yggdrasil": 1, + "comentarios_db": 1, + "photo_fusion": 1, + "seashipfinder": 1, + "issues": 1, + "DojoDB": 1, + "jkjk": 1, + "dms": 1, + "online_blood_and_organ_donation_system": 1, + "reminders": 1, + "some-database": 1, + "socialPixer": 1, + "home-cafe": 1, + "betrendz-dev": 1, + "snapgram": 3, + "donation-retriever": 1, + "storeDB": 1, + "befree-users": 1, + "Chemistry stuff": 1, + "Core Database": 1, + "instaFaceGram": 1, + "theUiratec": 1, + "blendr": 1, + "occulo": 1, + "nextdb": 1, + "routes": 1, + "user-data": 1, + "JDB": 1, + "shorelyIbizaProduction": 1, + "socialApp": 1, + "SimplGram": 1, + "Snapgram_Data": 1, + "snapcy": 1, + "Image_DB": 1, + "hello_world": 1, + "download": 1, + "Mydb": 2, + "trip": 1, + "oral": 1, + "dddd": 1, + "shopping-list": 1, + "omnibrain": 1, + "basic": 1, + "unity": 1, + "xerox_bot": 1, + "first_db": 1, + "SIEL DB": 1, + "db-preprod": 1, + "testme": 2, + "dreamdb": 1, + "anochat-database": 1, + "anochat-db": 2, + "anochat-dn": 1, + "sovo_db": 1, + "pumpkin": 1, + "marketplace-test": 1, + "PG": 1, + "user list": 1, + "userdb": 1, + "amri": 1, + "members": 1, + "daily-match": 1, + "gdt-members": 1, + "Systems": 1, + "swiftform": 1, + "fanaka": 1, + "dbDev": 1, + "my-first-db": 1, + "Vehicles": 1, + "Kennels": 1, + "calendula": 1, + "asdasd": 1, + "tsproject": 1, + "mallas": 1, + "variedades": 1, + "qs": 1, + "asd": 1, + "mdc_magazine": 1, + "mdc_store": 1, + "School Me DB": 1, + "jczd": 1, + "kupczyk": 1, + "Testing": 1, + "sprintcap": 1, + "CloudShared": 1, + "urls": 1, + "willy": 1, + "My first database": 1, + "Links": 1, + "Twitter Clone": 1, + "functions": 1, + "viewCollections": 1, + "stagging": 1, + "Payment Records": 1, + "AED307Group14": 1, + "rubrica": 1, + "histronia": 1, + "td": 1, + "doctor": 1, + "features": 1, + "park": 1, + "College Cutoff": 1, + "like": 1, + "todos-db": 1, + "TESTDB": 1, + "1": 2, + "BetterChatGPT": 1, + "FIrst db": 1, + "bot_database_test": 1, + "cloud-maturity": 1, + "vendas": 1, + "swirly test": 1, + "Terst": 1, + "CC_db": 1, + "pos db": 1, + "Groups": 1, + "testdatabase": 1, + "kaze": 1, + "Connect": 1, + "NUV-AzTechs-Database": 1, + "Payment Gateway": 1, + "testdata": 2, + "tradeassistant": 1, + "mediation_database": 1, + "dbTest": 1, + "basketball": 1, + "belanja_db": 1, + "Fun": 1, + "mytest": 1, + "FirstDatabase": 1, + "administration": 1, + "consumers": 1, + "mregistryDatabase": 1, + "Twst": 1, + "blogdb": 1, + "search_me": 1, + "aide": 1, + "plantebyt": 1, + "kittens": 1, + "waters": 1, + "aaaaa": 1, + "altrec_db": 1, + "atai": 1, + "Home": 1, + "swifty": 1, + "schedule": 1, + "andimar": 1, + "Manlou": 1, + "cuitanDB": 1, + "smartbcard": 1, + "afe": 1, + "Openstartup": 1, + "Stock": 1, + "drivers": 1, + "sample_order": 1, + "5870": 1, + "kjhg": 1, + "xva": 1, + "MyTemplates": 1, + "Fiesta Data": 1, + "patients": 1, + "animated_dev": 1, + "classapp-db": 1, + "dbb": 1, + "twilio": 1, + "ads": 1, + "Saved Images": 1, + "Name": 1, + "MyDB": 2, + "RipplesCode": 1, + "LeaguesWorld": 1, + "outlet": 1, + "scorer": 1, + "itistime": 1, + "Manuk Biru DB": 1, + "guests": 1, + "questions": 1, + "AI Poker": 1, + "nash_app": 1, + "cars": 1, + "ccc": 1, + "Bookings": 1, + "proj": 1, + "Twitter Clone Database": 1, + "quantasip": 1, + "navigation": 1, + "check": 1, + "testovacka_db": 1, + "base": 1, + "Testbase": 1, + "CoDeveloper Database": 1, + "sample_db": 1, + "dg_1142_dbstore": 1, + "todo-fawp-db": 1, + "project_database": 1, + "Issues": 1, + "cinehousedb": 1, + "foodItems": 1, + "Snowcamp": 1, + "codeApi": 1, + "debify": 1, + "Ymir": 1, + "NetflixDB": 1, + "Database2": 1, + "brainTeaser": 1, + "Fableit Dev": 1, + "Twitter Database": 1, + "Users ": 1, + "portal": 1, + "svelte-test": 1, + "TatiaDb": 1, + "FirstDB": 1, + "galaxies": 1, + "cf_db": 1, + "formData": 1, + "Letter of Credit DB": 1, + "Attribute": 1, + "Inventar": 1, + "banco": 1, + "Announce": 1, + "Maintenance": 1, + "aptkr": 1, + "streamlinks": 1, + "maze1": 1, + "Macellpower": 1, + "Student": 1, + "Forms": 1, + "company-management": 1, + "DBDFM1": 1, + "skool": 1, + "foods": 1, + "Harsh": 1, + "loginator-db": 1, + "Blubbidb": 1, + "Parchin_DB": 1, + "Fitness_App": 1, + "Books": 1, + "usersDB": 1, + "yum": 1, + "yumShares": 12, + "bottledrive": 1, + "website": 1, + "ampPanda": 1, + "TestData": 1, + "oppenheimer": 1, + "sampleDatabase": 1, + "ims_db": 1, + "dingleberry": 1, + "shopaholic-db": 1, + "Sample Database": 1, + "delta-co": 1, + "myLabDB": 1, + "posts database": 1, + "Newsletter": 1, + "order_management": 1, + "psn-kadi-svelte": 1, + "PeetFeederDb": 1, + "yyui": 1, + "taskninja": 1, + "hmnz-core": 1, + "payroll": 1, + "Demo_DB": 1, + "reco-teams-alpha": 1, + "foodly": 1, + "set": 1, + "tst": 1, + "HuntPile": 1, + "-": 1, + "Images": 1, + "money": 1, + "relax": 1, + "todo2": 1, + "vmfk": 1, + "ident": 1, + "recommend": 1, + "Cinemagix ": 1, + "picoLens": 1, + "Organizations": 1, + "safescan": 1, + "first db": 1, + "Photos": 1, + "nn": 1, + "todo's": 1, + "db_news": 1, + "listings": 1, + "to-do-list": 1, + "event-manager": 1, + "iconinstallation": 1, + "charshow_db": 1, + "snipdb": 1, + "socio-flare": 1, + "venicedb": 1, + "drip": 1, + "playground": 1, + "shelters-db": 1, + "kudoscrate": 1, + "Task_management_app": 1, + "ptp": 2, + "workout-history": 1, + "Muslim": 1, + "asklocaldb": 1, + "databiatch": 1, + "QuizProDB": 1, + "discussions": 1, + "ics": 1, + "UsersDetails": 1, + "my-chat": 1, + "easy-prompt-test": 1, + "cmt4": 1, + "cmt5": 1, + "cmt6": 1, + "atglancecronconfig": 1, + "atglancenewsdb": 1, + "mainbase": 1, + "quiz": 2, + "Let's Connect": 1, + "Bill Pecker": 1, + "Database1": 1, + "prompt-store": 1, + "DB-test-1": 1, + "SevyController": 1, + "buzz2xdb": 1, + "recipeYardDatabase": 1, + "quickd": 1, + "Chat Database": 1, + "mods": 1, + "opslog": 1, + "live_feedback": 1, + "stoker_database": 1, + "Education": 1, + "No Signal": 1, + "Appwrite CMS": 1, + "firstDatabase": 1, + "LinkedIn": 1, + "neptune_blindbox": 1, + "Msgs": 1, + "table": 1, + "post": 1, + "rareBeauty": 1, + "formsDB": 1 +} \ No newline at end of file diff --git a/test.php b/test.php new file mode 100644 index 0000000000..e69de29bb2 From 2bed17de35bcd3a7f2ea3e958b8b67dd32f89079 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 6 Mar 2024 21:50:31 +0100 Subject: [PATCH 30/61] Debug --- app/cli.php | 28 ++++++++++++++-------------- app/init.php | 14 +++++++------- app/worker.php | 42 +++++++++++++++++++++--------------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/app/cli.php b/app/cli.php index c98cc62e7c..76e15e2ff9 100644 --- a/app/cli.php +++ b/app/cli.php @@ -104,17 +104,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } return $database; } @@ -128,17 +128,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } $database ->setNamespace('_' . $project->getInternalId()) diff --git a/app/init.php b/app/init.php index 2493386390..26ebdab7a9 100644 --- a/app/init.php +++ b/app/init.php @@ -1183,17 +1183,17 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } }); if (isset($databases[$databaseName])) { diff --git a/app/worker.php b/app/worker.php index 989f1223af..a3ff06f9a5 100644 --- a/app/worker.php +++ b/app/worker.php @@ -75,17 +75,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } return $database; }, ['cache', 'register', 'message', 'dbForConsole']); @@ -114,17 +114,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } return $database; } @@ -138,17 +138,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $database - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } return $database; }; From 1ffb80f2f79e511718b62518b3715e7f34d16664 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 10:37:57 +0100 Subject: [PATCH 31/61] Fix realtime db --- app/realtime.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index f7fc7070a4..4f0ba634e7 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -78,10 +78,17 @@ function getProjectDB(Document $project): Database $database = new Database($dbAdapter, getCache()); - $database - ->setNamespace('_' . $project->getInternalId()) - ->setMetadata('host', \gethostname()) - ->setMetadata('project', $project->getId()); +// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $database + ->setShareTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace(''); +// } else { +// $database +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } return $database; } From 1db9d8b9aba110286d3151f149ab0c44a3424d3c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 10:40:03 +0100 Subject: [PATCH 32/61] Fix method refs --- app/cli.php | 1 - app/controllers/api/projects.php | 15 +++++++-------- src/Appwrite/Platform/Tasks/GetMigrationStats.php | 2 +- src/Appwrite/Platform/Workers/Hamster.php | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/app/cli.php b/app/cli.php index 76e15e2ff9..0780ee5e5a 100644 --- a/app/cli.php +++ b/app/cli.php @@ -141,7 +141,6 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, // } $database - ->setNamespace('_' . $project->getInternalId()) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 06f219fb6f..20f8f16c11 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -199,18 +199,17 @@ App::post('/v1/projects') $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); - if ($database === DATABASE_SHARED_TABLES) { - \var_dump('Using shared tables'); +// if ($database === DATABASE_SHARED_TABLES) { $dbForProject ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); - } else { - $dbForProject - ->setShareTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } +// } else { +// $dbForProject +// ->setShareTables(false) +// ->setTenant(null) +// ->setNamespace('_' . $project->getInternalId()); +// } $dbForProject->create(); diff --git a/src/Appwrite/Platform/Tasks/GetMigrationStats.php b/src/Appwrite/Platform/Tasks/GetMigrationStats.php index b76e0428d7..a8d88e1459 100644 --- a/src/Appwrite/Platform/Tasks/GetMigrationStats.php +++ b/src/Appwrite/Platform/Tasks/GetMigrationStats.php @@ -102,7 +102,7 @@ class GetMigrationStats extends Action ->getResource(); $dbForProject = new Database($adapter, $cache); - $dbForProject->setDefaultDatabase('appwrite'); + $dbForProject->setDatabase('appwrite'); $dbForProject->setNamespace('_' . $project->getInternalId()); /** Get Project ID */ diff --git a/src/Appwrite/Platform/Workers/Hamster.php b/src/Appwrite/Platform/Workers/Hamster.php index 0fb705d0f7..98bc56ee14 100644 --- a/src/Appwrite/Platform/Workers/Hamster.php +++ b/src/Appwrite/Platform/Workers/Hamster.php @@ -122,7 +122,7 @@ class Hamster extends Action ->getResource(); $dbForProject = new Database($adapter, $cache); - $dbForProject->setDefaultDatabase('appwrite'); + $dbForProject->setDatabase('appwrite'); $dbForProject->setNamespace('_' . $project->getInternalId()); $statsPerProject = []; From 503fb2ca82290e6ce8e01c44ad687212e411c162 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 12:49:54 +0100 Subject: [PATCH 33/61] Debug --- app/init.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/init.php b/app/init.php index 26ebdab7a9..a20598397d 100644 --- a/app/init.php +++ b/app/init.php @@ -1146,8 +1146,8 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, // ->setTenant(null) // ->setNamespace('_' . $project->getInternalId()); // } - - return $database; + return null; +// return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); App::setResource('dbForConsole', function (Group $pools, Cache $cache) { From b857fa3cdc690112e52d87bf3d3fa1ccdf74d363 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 14:06:33 +0100 Subject: [PATCH 34/61] Debug --- app/init.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index a20598397d..b5ebd4bb9f 100644 --- a/app/init.php +++ b/app/init.php @@ -1210,7 +1210,8 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database = new Database($dbAdapter, $cache); $databases[$databaseName] = $database; $configure($database); - return $database; + return null; +// return $database; }; }, ['pools', 'dbForConsole', 'cache']); From 8a73203635f781599361984a34b28c5fd2823679 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 14:52:13 +0100 Subject: [PATCH 35/61] Revert debugs --- app/cli.php | 28 ++++++------- app/controllers/api/projects.php | 16 +++---- app/init.php | 36 ++++++++-------- app/realtime.php | 14 +++---- app/worker.php | 42 +++++++++---------- .../Platform/Tasks/DeleteOrphanedProjects.php | 17 ++++++-- .../Platform/Tasks/GetMigrationStats.php | 17 ++++++-- src/Appwrite/Platform/Workers/Hamster.php | 17 ++++++-- 8 files changed, 110 insertions(+), 77 deletions(-) diff --git a/app/cli.php b/app/cli.php index 0780ee5e5a..e246101e1c 100644 --- a/app/cli.php +++ b/app/cli.php @@ -104,17 +104,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } return $database; } @@ -128,17 +128,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } $database ->setMetadata('host', \gethostname()) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 20f8f16c11..89ca9e15fe 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -130,7 +130,7 @@ App::post('/v1/projects') } $databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE'); - $index = array_search($databaseOverride, $databases); + $index = \array_search($databaseOverride, $databases); if ($index !== false) { $database = $databases[$index]; } else { @@ -199,17 +199,17 @@ App::post('/v1/projects') $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); -// if ($database === DATABASE_SHARED_TABLES) { + if ($database === DATABASE_SHARED_TABLES) { $dbForProject ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $dbForProject -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $dbForProject + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } $dbForProject->create(); diff --git a/app/init.php b/app/init.php index b5ebd4bb9f..a7ffcc5154 100644 --- a/app/init.php +++ b/app/init.php @@ -1135,19 +1135,19 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - //if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } - return null; -// return $database; + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + + return $database; }, ['pools', 'dbForConsole', 'cache', 'project']); App::setResource('dbForConsole', function (Group $pools, Cache $cache) { @@ -1183,17 +1183,17 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } }); if (isset($databases[$databaseName])) { @@ -1210,8 +1210,8 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database = new Database($dbAdapter, $cache); $databases[$databaseName] = $database; $configure($database); - return null; -// return $database; + + return $database; }; }, ['pools', 'dbForConsole', 'cache']); diff --git a/app/realtime.php b/app/realtime.php index 4f0ba634e7..80c5a4fbaf 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -78,17 +78,17 @@ function getProjectDB(Document $project): Database $database = new Database($dbAdapter, getCache()); -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } return $database; } diff --git a/app/worker.php b/app/worker.php index a3ff06f9a5..989f1223af 100644 --- a/app/worker.php +++ b/app/worker.php @@ -75,17 +75,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } return $database; }, ['cache', 'register', 'message', 'dbForConsole']); @@ -114,17 +114,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } return $database; } @@ -138,17 +138,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; -// if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database ->setShareTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); -// } else { -// $database -// ->setShareTables(false) -// ->setTenant(null) -// ->setNamespace('_' . $project->getInternalId()); -// } + } else { + $database + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } return $database; }; diff --git a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php index 860cc3a8a2..5fe4b10472 100644 --- a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php +++ b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php @@ -83,15 +83,26 @@ class DeleteOrphanedProjects extends Action } try { - $db = $project->getAttribute('database'); + $database = $project->getAttribute('database'); $adapter = $pools - ->get($db) + ->get($database) ->pop() ->getResource(); $dbForProject = new Database($adapter, $cache); $dbForProject->setDatabase('appwrite'); - $dbForProject->setNamespace('_' . $project->getInternalId()); + + if ($database === DATABASE_SHARED_TABLES) { + $dbForProject + ->setShareTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $dbForProject + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } $collectionsCreated = 0; $cnt++; diff --git a/src/Appwrite/Platform/Tasks/GetMigrationStats.php b/src/Appwrite/Platform/Tasks/GetMigrationStats.php index a8d88e1459..fa47c27c6d 100644 --- a/src/Appwrite/Platform/Tasks/GetMigrationStats.php +++ b/src/Appwrite/Platform/Tasks/GetMigrationStats.php @@ -95,15 +95,26 @@ class GetMigrationStats extends Action Console::info("Getting stats for {$project->getId()}"); try { - $db = $project->getAttribute('database'); + $database = $project->getAttribute('database'); $adapter = $pools - ->get($db) + ->get($database) ->pop() ->getResource(); $dbForProject = new Database($adapter, $cache); $dbForProject->setDatabase('appwrite'); - $dbForProject->setNamespace('_' . $project->getInternalId()); + + if ($database === DATABASE_SHARED_TABLES) { + $dbForProject + ->setShareTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $dbForProject + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } /** Get Project ID */ $stats['Project ID'] = $project->getId(); diff --git a/src/Appwrite/Platform/Workers/Hamster.php b/src/Appwrite/Platform/Workers/Hamster.php index 98bc56ee14..167e4d7fe7 100644 --- a/src/Appwrite/Platform/Workers/Hamster.php +++ b/src/Appwrite/Platform/Workers/Hamster.php @@ -115,15 +115,26 @@ class Hamster extends Action Console::log("Getting stats for Project {$project->getId()}"); try { - $db = $project->getAttribute('database'); + $database = $project->getAttribute('database'); $adapter = $pools - ->get($db) + ->get($database) ->pop() ->getResource(); $dbForProject = new Database($adapter, $cache); $dbForProject->setDatabase('appwrite'); - $dbForProject->setNamespace('_' . $project->getInternalId()); + + if ($database === DATABASE_SHARED_TABLES) { + $dbForProject + ->setShareTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace(''); + } else { + $dbForProject + ->setShareTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } $statsPerProject = []; From f166a1c20114c891d42f2f519f5e00bc63e26099 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 17:43:44 +0100 Subject: [PATCH 36/61] Update db --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 33d3b158ec..e5aef1ef6d 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ "utopia-php/cache": "0.9.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.45.7", + "utopia-php/database": "0.45.8", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index 905abf7103..b0046320f9 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": "9ab28ccc7cde35e834aac175d331c346", + "content-hash": "767fe773a75b04ff6c22eac8b2c1498b", "packages": [ { "name": "adhocore/jwt", @@ -1187,16 +1187,16 @@ }, { "name": "utopia-php/database", - "version": "0.45.7", + "version": "0.45.8", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03" + "reference": "8c68f04f073e50c5199bc2df22c5bf9e3be512e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03", - "reference": "f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03", + "url": "https://api.github.com/repos/utopia-php/database/zipball/8c68f04f073e50c5199bc2df22c5bf9e3be512e4", + "reference": "8c68f04f073e50c5199bc2df22c5bf9e3be512e4", "shasum": "" }, "require": { @@ -1237,9 +1237,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.45.7" + "source": "https://github.com/utopia-php/database/tree/0.45.8" }, - "time": "2024-03-05T10:28:02+00:00" + "time": "2024-03-07T16:36:43+00:00" }, { "name": "utopia-php/domains", From 664df69a5f944b83c99f2367d8386e2aeff8067d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Mar 2024 17:49:59 +0100 Subject: [PATCH 37/61] Fix method refs --- app/cli.php | 8 ++++---- app/controllers/api/projects.php | 4 ++-- app/init.php | 8 ++++---- app/realtime.php | 4 ++-- app/worker.php | 12 ++++++------ .../Platform/Tasks/DeleteOrphanedProjects.php | 4 ++-- src/Appwrite/Platform/Tasks/GetMigrationStats.php | 4 ++-- src/Appwrite/Platform/Workers/Hamster.php | 4 ++-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/app/cli.php b/app/cli.php index e246101e1c..f03be2cb33 100644 --- a/app/cli.php +++ b/app/cli.php @@ -106,12 +106,12 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } @@ -130,12 +130,12 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 89ca9e15fe..19f8f33a3d 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -201,12 +201,12 @@ App::post('/v1/projects') if ($database === DATABASE_SHARED_TABLES) { $dbForProject - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $dbForProject - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/app/init.php b/app/init.php index a7ffcc5154..cbfe1bfc5c 100644 --- a/app/init.php +++ b/app/init.php @@ -1137,12 +1137,12 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } @@ -1185,12 +1185,12 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/app/realtime.php b/app/realtime.php index 80c5a4fbaf..0e31df50f8 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -80,12 +80,12 @@ function getProjectDB(Document $project): Database if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/app/worker.php b/app/worker.php index 989f1223af..d732cb5ee0 100644 --- a/app/worker.php +++ b/app/worker.php @@ -77,12 +77,12 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } @@ -116,12 +116,12 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } @@ -140,12 +140,12 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { $database - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $database - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php index 5fe4b10472..0bb15830fc 100644 --- a/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php +++ b/src/Appwrite/Platform/Tasks/DeleteOrphanedProjects.php @@ -94,12 +94,12 @@ class DeleteOrphanedProjects extends Action if ($database === DATABASE_SHARED_TABLES) { $dbForProject - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $dbForProject - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/src/Appwrite/Platform/Tasks/GetMigrationStats.php b/src/Appwrite/Platform/Tasks/GetMigrationStats.php index fa47c27c6d..a88b8a4c97 100644 --- a/src/Appwrite/Platform/Tasks/GetMigrationStats.php +++ b/src/Appwrite/Platform/Tasks/GetMigrationStats.php @@ -106,12 +106,12 @@ class GetMigrationStats extends Action if ($database === DATABASE_SHARED_TABLES) { $dbForProject - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $dbForProject - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } diff --git a/src/Appwrite/Platform/Workers/Hamster.php b/src/Appwrite/Platform/Workers/Hamster.php index 167e4d7fe7..aeb243117e 100644 --- a/src/Appwrite/Platform/Workers/Hamster.php +++ b/src/Appwrite/Platform/Workers/Hamster.php @@ -126,12 +126,12 @@ class Hamster extends Action if ($database === DATABASE_SHARED_TABLES) { $dbForProject - ->setShareTables(true) + ->setSharedTables(true) ->setTenant($project->getInternalId()) ->setNamespace(''); } else { $dbForProject - ->setShareTables(false) + ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getInternalId()); } From 9ca1375af332299f5f283931e3b1f676768e59ec Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 9 Mar 2024 22:56:20 +0100 Subject: [PATCH 38/61] Fix index lengths given tenant is added --- app/config/collections.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index e2f3c11be7..9693b19bf7 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -313,7 +313,7 @@ $commonCollections = [ '$id' => ID::custom('_key_email'), 'type' => Database::INDEX_UNIQUE, 'attributes' => ['email'], - 'lengths' => [320], + 'lengths' => [256], 'orders' => [Database::ORDER_ASC], ], [ @@ -733,7 +733,7 @@ $commonCollections = [ '$id' => ID::custom('_key_provider_providerUid'), 'type' => Database::INDEX_KEY, 'attributes' => ['provider', 'providerUid'], - 'lengths' => [100, 100], + 'lengths' => [128, 128], 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], ], [ @@ -857,14 +857,14 @@ $commonCollections = [ '$id' => ID::custom('_key_userInternalId_provider_providerUid'), 'type' => Database::INDEX_UNIQUE, 'attributes' => ['userInternalId', 'provider', 'providerUid'], - 'lengths' => [Database::LENGTH_KEY, 100, 385], + 'lengths' => [11, 128, 128], 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], ], [ '$id' => ID::custom('_key_provider_providerUid'), 'type' => Database::INDEX_UNIQUE, 'attributes' => ['provider', 'providerUid'], - 'lengths' => [100, 640], + 'lengths' => [128, 128], 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], ], [ @@ -885,7 +885,7 @@ $commonCollections = [ '$id' => ID::custom('_key_provider'), 'type' => Database::INDEX_KEY, 'attributes' => ['provider'], - 'lengths' => [100], + 'lengths' => [128], 'orders' => [Database::ORDER_ASC], ], [ @@ -2113,7 +2113,7 @@ $projectCollections = array_merge([ '$id' => ID::custom('_key_name'), 'type' => Database::INDEX_KEY, 'attributes' => ['name'], - 'lengths' => [768], + 'lengths' => [256], 'orders' => [Database::ORDER_ASC], ], [ @@ -2162,7 +2162,7 @@ $projectCollections = array_merge([ '$id' => ID::custom('_key_runtime'), 'type' => Database::INDEX_KEY, 'attributes' => ['runtime'], - 'lengths' => [768], + 'lengths' => [64], 'orders' => [Database::ORDER_ASC], ], [ @@ -2902,14 +2902,14 @@ $projectCollections = array_merge([ '$id' => ID::custom('_key_trigger'), 'type' => Database::INDEX_KEY, 'attributes' => ['trigger'], - 'lengths' => [128], + 'lengths' => [32], 'orders' => [Database::ORDER_ASC], ], [ '$id' => ID::custom('_key_status'), 'type' => Database::INDEX_KEY, 'attributes' => ['status'], - 'lengths' => [128], + 'lengths' => [32], 'orders' => [Database::ORDER_ASC], ], [ @@ -4834,14 +4834,14 @@ $bucketCollections = [ '$id' => ID::custom('_key_name'), 'type' => Database::INDEX_KEY, 'attributes' => ['name'], - 'lengths' => [768], + 'lengths' => [256], 'orders' => [Database::ORDER_ASC], ], [ '$id' => ID::custom('_key_signature'), 'type' => Database::INDEX_KEY, 'attributes' => ['signature'], - 'lengths' => [768], + 'lengths' => [256], 'orders' => [Database::ORDER_ASC], ], [ From 65c21a34c0383359856dacc0710983eb2966de26 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sun, 10 Mar 2024 12:50:51 +0100 Subject: [PATCH 39/61] Update database --- composer.json | 2 +- composer.lock | 52 +++++++++++++++++++++++++-------------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/composer.json b/composer.json index e5aef1ef6d..afa8520cfb 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ "utopia-php/cache": "0.9.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.45.8", + "utopia-php/database": "0.45.*", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index b0046320f9..8fa95ff28f 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": "767fe773a75b04ff6c22eac8b2c1498b", + "content-hash": "d9a7df9d8d4ed11e157accbd2d73bf7b", "packages": [ { "name": "adhocore/jwt", @@ -404,16 +404,16 @@ }, { "name": "jean85/pretty-package-versions", - "version": "2.0.5", + "version": "2.0.6", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af" + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af", - "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", "shasum": "" }, "require": { @@ -421,9 +421,9 @@ "php": "^7.1|^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.17", + "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^0.12.66", + "phpstan/phpstan": "^1.4", "phpunit/phpunit": "^7.5|^8.5|^9.4", "vimeo/psalm": "^4.3" }, @@ -457,9 +457,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" }, - "time": "2021-10-08T21:21:46+00:00" + "time": "2024-03-08T09:58:59+00:00" }, { "name": "league/csv", @@ -1187,16 +1187,16 @@ }, { "name": "utopia-php/database", - "version": "0.45.8", + "version": "0.45.9", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "8c68f04f073e50c5199bc2df22c5bf9e3be512e4" + "reference": "f28a3f5b5276d3459694669f01a382b3e35b2006" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/8c68f04f073e50c5199bc2df22c5bf9e3be512e4", - "reference": "8c68f04f073e50c5199bc2df22c5bf9e3be512e4", + "url": "https://api.github.com/repos/utopia-php/database/zipball/f28a3f5b5276d3459694669f01a382b3e35b2006", + "reference": "f28a3f5b5276d3459694669f01a382b3e35b2006", "shasum": "" }, "require": { @@ -1237,9 +1237,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.45.8" + "source": "https://github.com/utopia-php/database/tree/0.45.9" }, - "time": "2024-03-07T16:36:43+00:00" + "time": "2024-03-10T11:46:14+00:00" }, { "name": "utopia-php/domains", @@ -2413,30 +2413,30 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.36.4", + "version": "0.36.7", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "8d932098009d62d37dda73cfe4ebc11f83e21405" + "reference": "c9c07e8d96b80f62507bbb5ef90fa0769e560621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8d932098009d62d37dda73cfe4ebc11f83e21405", - "reference": "8d932098009d62d37dda73cfe4ebc11f83e21405", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/c9c07e8d96b80f62507bbb5ef90fa0769e560621", + "reference": "c9c07e8d96b80f62507bbb5ef90fa0769e560621", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "matthiasmullie/minify": "^1.3.68", + "matthiasmullie/minify": "1.3.*", "php": ">=8.0", - "twig/twig": "^3.4.1" + "twig/twig": "v3.8.*" }, "require-dev": { - "brianium/paratest": "^6.4", - "phpunit/phpunit": "^9.5.21", - "squizlabs/php_codesniffer": "^3.6" + "brianium/paratest": "v7.4.*", + "phpunit/phpunit": "10.5.*", + "squizlabs/php_codesniffer": "3.9.*" }, "type": "library", "autoload": { @@ -2458,9 +2458,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.36.4" + "source": "https://github.com/appwrite/sdk-generator/tree/0.36.7" }, - "time": "2024-02-20T16:36:15+00:00" + "time": "2024-03-09T16:57:18+00:00" }, { "name": "doctrine/deprecations", From 7fc990a56d7cc2f86c8854e9279e1635b72764bf Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sun, 10 Mar 2024 18:45:50 +0100 Subject: [PATCH 40/61] Debug --- app/controllers/shared/api.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index a5f5af764e..8454e41b50 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -523,7 +523,9 @@ App::shutdown() $queueForDeletes->trigger(); } + \var_dump('About to trigger database event'); if (!empty($queueForDatabase->getType())) { + \var_dump('Triggering database event'); $queueForDatabase->trigger(); } From 7e1894feb57a561cfeee263aaecc315734614b05 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 11 Mar 2024 14:14:32 +0100 Subject: [PATCH 41/61] Debug --- app/controllers/shared/api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 8454e41b50..9e69ae4ced 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -523,10 +523,10 @@ App::shutdown() $queueForDeletes->trigger(); } - \var_dump('About to trigger database event'); if (!empty($queueForDatabase->getType())) { - \var_dump('Triggering database event'); + \var_dump('Before triggering database event'); $queueForDatabase->trigger(); + \var_dump('After triggering database event'); } /** From cfc69b0f9212eb950afc7849b502bfed3775083a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 12 Mar 2024 16:54:06 +0100 Subject: [PATCH 42/61] Debug --- src/Appwrite/Event/Database.php | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index 442cbe4bbc..c2a36577c4 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -111,14 +111,23 @@ class Database extends Event $client = new Client($this->queue, $this->connection); - return $client->enqueue([ - 'project' => $this->project, - 'user' => $this->user, - 'type' => $this->type, - 'collection' => $this->collection, - 'document' => $this->document, - 'database' => $this->database, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); + try { + $result = $client->enqueue([ + 'project' => $this->project, + 'user' => $this->user, + 'type' => $this->type, + 'collection' => $this->collection, + 'document' => $this->document, + 'database' => $this->database, + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + ]); + \var_dump('Enqueued event'); + \var_dump($result); + return $result; + } catch (\Throwable $th) { + \var_dump('Enqueue event failed'); + \var_dump($th); + return false; + } } } From c7bf9bb3ec3d8c28bfaa978000894afd78b1df01 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 12 Mar 2024 17:09:09 +0100 Subject: [PATCH 43/61] Debug --- src/Appwrite/Event/Database.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index c2a36577c4..ace846d8b4 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -111,6 +111,8 @@ class Database extends Event $client = new Client($this->queue, $this->connection); + \var_dump('Event queue name is: ' . $this->queue); + try { $result = $client->enqueue([ 'project' => $this->project, From 0112fd9b841690cab9020c19046aca8b0d82d002 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 1 May 2024 16:17:02 +1200 Subject: [PATCH 44/61] Add unique email test --- .../Projects/ProjectsConsoleClientTest.php | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 2308c0d6a3..7db5415d65 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3929,6 +3929,31 @@ class ProjectsConsoleClientTest extends Scope 'name' => 'Amazing Collection', ]); - $this->assertEquals(201, $collection5['headers']['status-code']); + // Assert that users across projects on shared tables can have the same email as they're unique on tenant + email not just email + $user1 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2['body']['$id'], + 'x-appwrite-key' => $key1['body']['secret'] + ], [ + 'userId' => 'user', + 'email' => 'test@localhost', + 'password' => 'password', + 'name' => 'Test User', + ]); + + $this->assertEquals(201, $user1['headers']['status-code']); + + $user2 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project4['body']['$id'], + 'x-appwrite-key' => $key2['body']['secret'] + ], [ + 'userId' => 'user', + 'email' => 'test@localhost', + 'password' => 'password', + 'name' => 'Test User', + ]); + + $this->assertEquals(201, $user2['headers']['status-code']); } } From d4254b34e22c8324b2b1785096ae62abbc8bb2df Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 2 May 2024 18:28:03 +1200 Subject: [PATCH 45/61] Update db name --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index 4b3115caf8..2fb06200a9 100644 --- a/app/init.php +++ b/app/init.php @@ -144,7 +144,7 @@ const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation= const APP_HOSTNAME_INTERNAL = 'appwrite'; // Databases -const DATABASE_SHARED_TABLES = 'database_db_self_hosted_shared_tables'; +const DATABASE_SHARED_TABLES = 'database_db_fra1_self_hosted_16_0'; // Database Reconnect const DATABASE_RECONNECT_SLEEP = 2; From c4deb0ba93c409c6c0edf697324ed17089c9ac91 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 3 May 2024 21:30:38 +1200 Subject: [PATCH 46/61] Allow shared tables namespace override --- app/cli.php | 5 +++-- app/controllers/api/projects.php | 2 +- app/init.php | 4 ++-- app/realtime.php | 2 +- app/worker.php | 7 ++++--- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/cli.php b/app/cli.php index 01c67895ba..11ab6598d9 100644 --- a/app/cli.php +++ b/app/cli.php @@ -7,6 +7,7 @@ use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Appwrite\Event\Func; use Appwrite\Platform\Appwrite; +use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\CLI; @@ -107,7 +108,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) @@ -131,7 +132,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 778749522b..d3d09f4adf 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -211,7 +211,7 @@ App::post('/v1/projects') $dbForProject ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $dbForProject ->setSharedTables(false) diff --git a/app/init.php b/app/init.php index 2fb06200a9..2e9af63d5d 100644 --- a/app/init.php +++ b/app/init.php @@ -1318,7 +1318,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) @@ -1366,7 +1366,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) diff --git a/app/realtime.php b/app/realtime.php index 09a58c5a10..c58a32ded7 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -89,7 +89,7 @@ if (!function_exists("getProjectDB")) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) diff --git a/app/worker.php b/app/worker.php index 2336e3be3a..8167289e4a 100644 --- a/app/worker.php +++ b/app/worker.php @@ -16,6 +16,7 @@ use Appwrite\Event\Usage; use Appwrite\Event\UsageDump; use Appwrite\Platform\Appwrite; use Swoole\Runtime; +use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; @@ -82,7 +83,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) @@ -110,7 +111,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) @@ -134,7 +135,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(''); + ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); } else { $database ->setSharedTables(false) From db940701628217463ec8523ccbb6b2889968b803 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 6 May 2024 17:33:36 +1200 Subject: [PATCH 47/61] Use DSN for project database --- app/cli.php | 13 ++++++----- app/controllers/api/projects.php | 37 +++++++++++++++++++++++--------- app/init.php | 15 +++++++------ app/realtime.php | 17 +++++++++------ app/worker.php | 18 ++++++++++------ composer.json | 2 +- composer.lock | 18 +++++++++------- docker-compose.yml | 3 +-- 8 files changed, 77 insertions(+), 46 deletions(-) diff --git a/app/cli.php b/app/cli.php index 11ab6598d9..73da58bcbf 100644 --- a/app/cli.php +++ b/app/cli.php @@ -16,6 +16,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Service; use Utopia\Pools\Group; @@ -99,16 +100,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + $dsn = new DSN($project->getAttribute('database')); + + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -128,11 +131,11 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index d3d09f4adf..0770723f96 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -30,6 +30,7 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Domains\Validator\PublicDomain; +use Utopia\DSN\DSN; use Utopia\Locale\Locale; use Utopia\Pools\Group; use Utopia\System\System; @@ -142,9 +143,9 @@ App::post('/v1/projects') $databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE'); $index = \array_search($databaseOverride, $databases); if ($index !== false) { - $database = $databases[$index]; + $dsn = $databases[$index]; } else { - $database = $databases[array_rand($databases)]; + $dsn = $databases[array_rand($databases)]; } if ($projectId === 'console') { @@ -156,7 +157,14 @@ App::post('/v1/projects') !\mt_rand(0, 19) && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' ) { - $database = DATABASE_SHARED_TABLES; + $schema = 'appwrite'; + $database = 'appwrite'; + $namespace = App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); + $dsn = $schema . '://' . DATABASE_SHARED_TABLES . '?database=' . $database; + + if (!empty($namespace)) { + $dsn .= '&namespace=' . $namespace; + } } // TODO: Allow overriding in development mode. Temporary until all projects are using shared tables. @@ -165,7 +173,14 @@ App::post('/v1/projects') && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' && $request->getHeader('x-appwrite-share-tables', false) ) { - $database = DATABASE_SHARED_TABLES; + $schema = 'appwrite'; + $database = 'appwrite'; + $namespace = App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); + $dsn = $schema . '://' . DATABASE_SHARED_TABLES . '?database=' . $database; + + if (!empty($namespace)) { + $dsn .= '&namespace=' . $namespace; + } } try { @@ -199,19 +214,21 @@ App::post('/v1/projects') 'keys' => null, 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), - 'database' => $database, + 'database' => $dsn, ])); } catch (Duplicate) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); } - $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); + $dsn = new DSN($dsn); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + $dbForProject = new Database($pools->get($databaseName)->pop()->getResource(), $cache); - if ($database === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $dbForProject ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $dbForProject ->setSharedTables(false) @@ -224,8 +241,8 @@ App::post('/v1/projects') $audit = new Audit($dbForProject); $audit->setup(); - $adapter = new TimeLimit('', 0, 1, $dbForProject); - $adapter->setup(); + $abuse = new TimeLimit('', 0, 1, $dbForProject); + $abuse->setup(); /** @var array $collections */ $collections = Config::getParam('collections', [])['projects'] ?? []; diff --git a/app/init.php b/app/init.php index 2e9af63d5d..0412052294 100644 --- a/app/init.php +++ b/app/init.php @@ -1314,11 +1314,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $dsn = new DSN($project->getAttribute('database')); + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -1354,19 +1356,20 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + $dsn = new DSN($project->getAttribute('database')); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); - $configure = (function (Database $database) use ($project) { + $configure = (function (Database $database) use ($project, $dsn) { $database ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/app/realtime.php b/app/realtime.php index c58a32ded7..489d0d9642 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -26,6 +26,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\System\System; use Utopia\WebSocket\Adapter; @@ -77,19 +78,21 @@ if (!function_exists("getProjectDB")) { return getConsoleDB(); } - $dbAdapter = $pools - ->get($project->getAttribute('database')) + $dsn = new DSN($project->getAttribute('database')); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + + $adapter = $pools + ->get($databaseName) ->pop() - ->getResource() - ; + ->getResource(); - $database = new Database($dbAdapter, getCache()); + $database = new Database($adapter, getCache()); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/app/worker.php b/app/worker.php index 8167289e4a..9ab41bacb5 100644 --- a/app/worker.php +++ b/app/worker.php @@ -25,6 +25,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; @@ -79,11 +80,13 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database = new Database($adapter, $cache); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $dsn = new DSN($project->getAttribute('database')); + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -102,16 +105,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + $dsn = new DSN($project->getAttribute('database')); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -131,11 +135,11 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/composer.json b/composer.json index df004e6b44..5ce9a0a138 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "utopia-php/config": "0.2.*", "utopia-php/database": "0.49.*", "utopia-php/domains": "0.5.*", - "utopia-php/dsn": "0.2.*", + "utopia-php/dsn": "dev-feat-allow-nullable-scheme", "utopia-php/framework": "0.33.*", "utopia-php/fetch": "0.2.*", "utopia-php/image": "0.6.*", diff --git a/composer.lock b/composer.lock index 9d4300f0a4..cd47546770 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": "28ecd4705def24ce61eee0f6676439d6", + "content-hash": "7276ce4fa8a3c75f95f952153fdca69f", "packages": [ { "name": "adhocore/jwt", @@ -1672,16 +1672,16 @@ }, { "name": "utopia-php/dsn", - "version": "0.2.0", + "version": "dev-feat-allow-nullable-scheme", "source": { "type": "git", "url": "https://github.com/utopia-php/dsn.git", - "reference": "c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7" + "reference": "09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dsn/zipball/c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7", - "reference": "c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7", + "url": "https://api.github.com/repos/utopia-php/dsn/zipball/09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c", + "reference": "09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c", "shasum": "" }, "require": { @@ -1713,9 +1713,9 @@ ], "support": { "issues": "https://github.com/utopia-php/dsn/issues", - "source": "https://github.com/utopia-php/dsn/tree/0.2.0" + "source": "https://github.com/utopia-php/dsn/tree/feat-allow-nullable-scheme" }, - "time": "2023-11-02T12:01:43+00:00" + "time": "2024-05-06T05:15:19+00:00" }, { "name": "utopia-php/fetch", @@ -5505,7 +5505,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/dsn": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docker-compose.yml b/docker-compose.yml index 0f78f08d36..82c38ba269 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,8 +10,6 @@ x-logging: &x-logging max-file: "5" max-size: "10m" -version: "3" - services: traefik: image: traefik:2.11 @@ -94,6 +92,7 @@ services: - app/http.php environment: - _APP_ENV + - _APP_EDITION - _APP_WORKER_PER_CORE - _APP_LOCALE - _APP_CONSOLE_WHITELIST_ROOT From ec2878b505a186505457dcdbef89fed07d943063 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 6 May 2024 17:34:17 +1200 Subject: [PATCH 48/61] Lint --- app/cli.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/cli.php b/app/cli.php index 73da58bcbf..cd60a0f5bf 100644 --- a/app/cli.php +++ b/app/cli.php @@ -7,7 +7,6 @@ use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Appwrite\Event\Func; use Appwrite\Platform\Appwrite; -use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\CLI; From 52c52fa5199551c5879c269c686594201e31c222 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 6 May 2024 18:13:41 +1200 Subject: [PATCH 49/61] Add scheme to DSN on fail --- app/cli.php | 16 +++++++++------- app/controllers/api/projects.php | 11 ++++++++--- app/init.php | 21 ++++++++++++++------- app/realtime.php | 9 ++++++--- app/worker.php | 21 ++++++++++++++------- 5 files changed, 51 insertions(+), 27 deletions(-) diff --git a/app/cli.php b/app/cli.php index cd60a0f5bf..655ea68a4c 100644 --- a/app/cli.php +++ b/app/cli.php @@ -99,12 +99,14 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $dbForConsole; } - $dsn = new DSN($project->getAttribute('database')); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } - $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); - - if (isset($databases[$databaseName])) { - $database = $databases[$databaseName]; + if (isset($databases[$dsn->getHost()])) { + $database = $databases[$dsn->getHost()]; if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database @@ -122,13 +124,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, } $dbAdapter = $pools - ->get($databaseName) + ->get($dsn->getHost()) ->pop() ->getResource(); $database = new Database($dbAdapter, $cache); - $databases[$databaseName] = $database; + $databases[$dsn->getHost()] = $database; if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 0770723f96..532a6d5b28 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -220,9 +220,14 @@ App::post('/v1/projects') throw new Exception(Exception::PROJECT_ALREADY_EXISTS); } - $dsn = new DSN($dsn); - $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); - $dbForProject = new Database($pools->get($databaseName)->pop()->getResource(), $cache); + try { + $dsn = new DSN($dsn); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $dsn); + } + + $adapter = $pools->get($dsn->getHost())->pop()->getResource(); + $dbForProject = new Database($adapter, $cache); if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $dbForProject diff --git a/app/init.php b/app/init.php index 0412052294..84c29f9613 100644 --- a/app/init.php +++ b/app/init.php @@ -1314,7 +1314,11 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - $dsn = new DSN($project->getAttribute('database')); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database @@ -1356,8 +1360,11 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $dbForConsole; } - $dsn = new DSN($project->getAttribute('database')); - $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } $configure = (function (Database $database) use ($project, $dsn) { $database @@ -1378,19 +1385,19 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, } }); - if (isset($databases[$databaseName])) { - $database = $databases[$databaseName]; + if (isset($databases[$dsn->getHost()])) { + $database = $databases[$dsn->getHost()]; $configure($database); return $database; } $dbAdapter = $pools - ->get($databaseName) + ->get($dsn->getHost()) ->pop() ->getResource(); $database = new Database($dbAdapter, $cache); - $databases[$databaseName] = $database; + $databases[$dsn->getHost()] = $database; $configure($database); return $database; diff --git a/app/realtime.php b/app/realtime.php index 489d0d9642..dd22ef8165 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -78,11 +78,14 @@ if (!function_exists("getProjectDB")) { return getConsoleDB(); } - $dsn = new DSN($project->getAttribute('database')); - $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } $adapter = $pools - ->get($databaseName) + ->get($dsn->getHost()) ->pop() ->getResource(); diff --git a/app/worker.php b/app/worker.php index 9ab41bacb5..599d126f95 100644 --- a/app/worker.php +++ b/app/worker.php @@ -80,7 +80,11 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database = new Database($adapter, $cache); - $dsn = new DSN($project->getAttribute('database')); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database @@ -105,11 +109,14 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso return $dbForConsole; } - $dsn = new DSN($project->getAttribute('database')); - $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } - if (isset($databases[$databaseName])) { - $database = $databases[$databaseName]; + if (isset($databases[$dsn->getHost()])) { + $database = $databases[$dsn->getHost()]; if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database @@ -127,13 +134,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso } $dbAdapter = $pools - ->get($databaseName) + ->get($dsn->getHost()) ->pop() ->getResource(); $database = new Database($dbAdapter, $cache); - $databases[$databaseName] = $database; + $databases[$dsn->getHost()] = $database; if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database From 5e62007c8f4f3d88966145c5d631aa8e46c620e9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 6 May 2024 21:19:19 +1200 Subject: [PATCH 50/61] Fix dbForProject resources --- app/init.php | 8 +++++++- app/worker.php | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/init.php b/app/init.php index 84c29f9613..4bb2d5fc67 100644 --- a/app/init.php +++ b/app/init.php @@ -1302,8 +1302,14 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, return $dbForConsole; } + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } + $dbAdapter = $pools - ->get($project->getAttribute('database')) + ->get($dsn->getHost()) ->pop() ->getResource(); diff --git a/app/worker.php b/app/worker.php index 599d126f95..edb8480d00 100644 --- a/app/worker.php +++ b/app/worker.php @@ -73,8 +73,14 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $pools = $register->get('pools'); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } + $adapter = $pools - ->get($project->getAttribute('database')) + ->get($dsn->getHost()) ->pop() ->getResource(); From 35365e067a8440a601fb690acb5ab4b91efa0333 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 6 May 2024 21:19:56 +1200 Subject: [PATCH 51/61] Update IDE helper --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5ce9a0a138..245777d35f 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,7 @@ "ext-fileinfo": "*", "appwrite/sdk-generator": "0.38.*", "phpunit/phpunit": "9.5.20", - "swoole/ide-helper": "5.0.2", + "swoole/ide-helper": "5.1.2", "textalk/websocket": "1.5.7", "laravel/pint": "^1.14" }, From bfc4c98600e246d563e8aa34ca07067d4ac48e69 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 14:03:06 +1200 Subject: [PATCH 52/61] Update to DSN release --- composer.json | 2 +- composer.lock | 30 ++++++++++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 245777d35f..8865a32d91 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "utopia-php/config": "0.2.*", "utopia-php/database": "0.49.*", "utopia-php/domains": "0.5.*", - "utopia-php/dsn": "dev-feat-allow-nullable-scheme", + "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", "utopia-php/fetch": "0.2.*", "utopia-php/image": "0.6.*", diff --git a/composer.lock b/composer.lock index cd47546770..72bead0f5c 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": "7276ce4fa8a3c75f95f952153fdca69f", + "content-hash": "6ce62f5b54254e5023c5ace349a0ced7", "packages": [ { "name": "adhocore/jwt", @@ -1672,16 +1672,16 @@ }, { "name": "utopia-php/dsn", - "version": "dev-feat-allow-nullable-scheme", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/utopia-php/dsn.git", - "reference": "09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c" + "reference": "42ee37a3d1785100b2f69091c9d4affadb6846eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dsn/zipball/09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c", - "reference": "09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c", + "url": "https://api.github.com/repos/utopia-php/dsn/zipball/42ee37a3d1785100b2f69091c9d4affadb6846eb", + "reference": "42ee37a3d1785100b2f69091c9d4affadb6846eb", "shasum": "" }, "require": { @@ -1713,9 +1713,9 @@ ], "support": { "issues": "https://github.com/utopia-php/dsn/issues", - "source": "https://github.com/utopia-php/dsn/tree/feat-allow-nullable-scheme" + "source": "https://github.com/utopia-php/dsn/tree/0.2.1" }, - "time": "2024-05-06T05:15:19+00:00" + "time": "2024-05-07T02:01:25+00:00" }, { "name": "utopia-php/fetch", @@ -5142,16 +5142,16 @@ }, { "name": "swoole/ide-helper", - "version": "5.0.2", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/swoole/ide-helper.git", - "reference": "16cfee44a6ec92254228c39bcab2fb8ae74cc2ea" + "reference": "33ec7af9111b76d06a70dd31191cc74793551112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swoole/ide-helper/zipball/16cfee44a6ec92254228c39bcab2fb8ae74cc2ea", - "reference": "16cfee44a6ec92254228c39bcab2fb8ae74cc2ea", + "url": "https://api.github.com/repos/swoole/ide-helper/zipball/33ec7af9111b76d06a70dd31191cc74793551112", + "reference": "33ec7af9111b76d06a70dd31191cc74793551112", "shasum": "" }, "type": "library", @@ -5168,9 +5168,9 @@ "description": "IDE help files for Swoole.", "support": { "issues": "https://github.com/swoole/ide-helper/issues", - "source": "https://github.com/swoole/ide-helper/tree/5.0.2" + "source": "https://github.com/swoole/ide-helper/tree/5.1.2" }, - "time": "2023-03-20T06:05:55+00:00" + "time": "2024-02-01T22:28:11+00:00" }, { "name": "symfony/polyfill-ctype", @@ -5505,9 +5505,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/dsn": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 912e3b01dccaa90aa4e25a2a92c5d212c30a283f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 14:07:04 +1200 Subject: [PATCH 53/61] Add clarifying comments --- app/cli.php | 1 + app/controllers/api/projects.php | 1 + app/init.php | 3 +++ app/realtime.php | 1 + app/worker.php | 3 +++ 5 files changed, 9 insertions(+) diff --git a/app/cli.php b/app/cli.php index 655ea68a4c..da7d23c18d 100644 --- a/app/cli.php +++ b/app/cli.php @@ -102,6 +102,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 532a6d5b28..896d6b8ce6 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -223,6 +223,7 @@ App::post('/v1/projects') try { $dsn = new DSN($dsn); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $dsn); } diff --git a/app/init.php b/app/init.php index 4bb2d5fc67..847c67bebc 100644 --- a/app/init.php +++ b/app/init.php @@ -1305,6 +1305,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } @@ -1323,6 +1324,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } @@ -1369,6 +1371,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } diff --git a/app/realtime.php b/app/realtime.php index dd22ef8165..edf83a5694 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -81,6 +81,7 @@ if (!function_exists("getProjectDB")) { try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } diff --git a/app/worker.php b/app/worker.php index edb8480d00..d698a824ac 100644 --- a/app/worker.php +++ b/app/worker.php @@ -76,6 +76,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } @@ -89,6 +90,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } @@ -118,6 +120,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso try { $dsn = new DSN($project->getAttribute('database')); } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables $dsn = new DSN('mysql://' . $project->getAttribute('database')); } From 0e9838d2907342bc5395ff64d89552cb8e478e27 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 15:48:20 +1200 Subject: [PATCH 54/61] Remove logging and test files --- app/controllers/shared/api.php | 2 - names2.json | 1527 ----------------- src/Appwrite/Event/Database.php | 6 - test.php | 0 .../Databases/DatabasesCustomServerTest.php | 2 - 5 files changed, 1537 deletions(-) delete mode 100644 names2.json delete mode 100644 test.php diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 16d816dfd1..1afd6b652e 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -637,9 +637,7 @@ App::shutdown() } if (!empty($queueForDatabase->getType())) { - \var_dump('Before triggering database event'); $queueForDatabase->trigger(); - \var_dump('After triggering database event'); } if (!empty($queueForBuilds->getType())) { diff --git a/names2.json b/names2.json deleted file mode 100644 index a32b5ca8d5..0000000000 --- a/names2.json +++ /dev/null @@ -1,1527 +0,0 @@ -{ - "album-database": 1, - "default": 7, - "Renew-Tech-DB": 1, - "posts": 7, - "vreddb": 1, - "test-db": 12, - "friendly-secret": 1, - "recipeDB": 2, - "TestDb": 2, - "first": 5, - "test": 96, - "Securelee": 1, - "cpldb": 1, - "SpeakingDB": 1, - "StoriesDB": 1, - "UserSignup": 1, - "WrittenDB": 1, - "db1": 17, - "CourcesDB": 1, - "Learnhub": 1, - "Users": 17, - "notes": 3, - "main": 28, - "Event planning ": 1, - "SupAut": 1, - "userTable": 1, - "coredb": 1, - "event-planner": 1, - "P01": 1, - "chatgpt-database": 1, - "JQQ Memes": 1, - "nocodb": 1, - "TaskList": 1, - "Retail": 1, - "Test": 30, - "Subscriptions": 1, - "Primary DB": 1, - "travelappdatabase": 1, - "DB": 7, - "back-end": 1, - "mydb": 5, - "Chats": 1, - "secrets": 1, - "pine": 1, - "MamaPut": 1, - "simpleApp": 1, - "gossip": 1, - "ecom_database": 1, - "edge-data": 1, - "vizualGitDb": 1, - "ticket": 1, - "toDo": 1, - "beacon": 1, - "hero": 1, - "users": 33, - "Twitter Test": 21, - "code-share": 1, - "DbName": 1, - "MyRecipePad": 1, - "twitter_clone": 3, - "event_db": 1, - "timers": 1, - "parsiukai": 1, - "AuthDatabase": 2, - "pfs_dev": 1, - "contratista": 1, - "support-local": 1, - "hey": 1, - "mindmemoDB": 1, - "E commerse": 1, - "my_basketball_club": 1, - "Amaad": 1, - "testdb": 21, - "twitter-clone": 7, - "srikalyanam": 1, - "todos": 27, - "Recipes": 2, - "todo": 18, - "demo": 12, - "confessus": 1, - "game": 3, - "primary": 2, - "dummy workout": 1, - "FitPulse": 1, - "vender": 1, - "workouts": 1, - "fresh": 1, - "hello": 3, - "auth": 1, - "domain": 1, - "Glitch": 1, - "Teste": 1, - "UsersData": 1, - "Linda": 1, - "supabse": 1, - "events": 4, - "dopecut-data": 1, - "lll": 1, - "FurrBuddiesDB": 1, - "VeterinarianDB": 1, - "test-sso-akhilesh": 1, - "cdv": 1, - "testing": 4, - "USDZ models": 1, - "book1": 1, - "Events": 4, - "cmpt-int-db": 1, - "yupio_db": 1, - "content": 3, - "test1": 2, - "okr db": 1, - "ckh-sport-equipment": 1, - "Twitter test": 1, - "Companies": 1, - "datas": 1, - "first-database": 1, - "tiger": 1, - "evo_db": 2, - "ProHacks": 1, - "cards": 1, - "projects": 3, - "app": 29, - "conversations": 2, - "Logging": 1, - "images": 2, - "podbase": 1, - "MYMATCH": 1, - "TestDB1": 2, - "m": 1, - "Tasks": 3, - "Recipes-Tracker": 1, - "db": 21, - "restaurants-details": 1, - "TEST": 2, - "first-db": 1, - "product-info-management": 1, - "demodb": 1, - "chats": 1, - "project-db": 2, - "logs_db": 1, - "users_db": 2, - "hustlehub-db": 1, - "profile": 1, - "jha": 1, - "photosharing": 1, - "mongi": 1, - "tupropiedad": 1, - "spotify database": 1, - "usersWatchlists": 1, - "watchlistsDB": 1, - "twitter_test": 1, - "chatDB": 1, - "development": 4, - "11": 1, - "vm": 1, - "manga mania db": 1, - "tutorialDB": 1, - "quizapp": 3, - "GitSafari": 1, - "lulucat": 1, - "testdatabase1101": 1, - "shops": 1, - "Salt-user-db": 1, - "insta_clone": 1, - "jobo": 1, - "vectors": 1, - "prueba": 2, - "Tech Blog": 1, - "socio_db": 1, - "Eventhub": 1, - "we-code": 1, - "jalauncodinghub": 1, - "beebeer_db": 1, - "recipes": 3, - "Twitter Clone dev": 1, - "testDb": 1, - "Rizq Sharing": 1, - "abc": 1, - "4_db": 1, - "dtdb": 1, - "clientUser": 1, - "asnad database": 1, - "ded": 1, - "yesusa_portal": 1, - "guidepilot-db": 1, - "hackathon_entries": 1, - "Dime": 1, - "blogs": 8, - "Genx": 1, - "SQD": 1, - "hippoDatabase": 1, - "Todo": 2, - "merchdjv_productdb": 1, - "sample": 2, - "datatest": 1, - "esp": 1, - "project": 2, - "letsdesign": 1, - "Studentpos": 1, - "movies": 2, - "quickstart": 1, - "Backup": 1, - "Default": 11, - "XXX": 4, - "vue_crud": 1, - "lessons": 1, - "test-database": 2, - "HellDB": 1, - "myDB": 1, - "products": 5, - "Straddle": 1, - "reketupa": 1, - "Restore": 1, - "Setup": 1, - "task-db": 1, - "money_manager": 1, - "3tee_databas": 1, - "jobs": 2, - "multi-resume": 1, - "my_db": 1, - "Trobia": 1, - "Movies": 5, - "foo": 2, - "Event Planner": 1, - "bleed": 1, - "DB1": 3, - "database": 9, - "fitadom": 1, - "hashnode": 1, - "stenodb": 1, - "nexus": 1, - "hosts": 1, - "space_launches_info": 1, - "dev": 9, - "testbase": 2, - "tinto": 1, - "test_db": 5, - "Data info": 1, - "demo db": 1, - "Studucatrial": 1, - "twitterClone": 2, - "Babu": 1, - "Cara": 1, - "booking": 2, - "Url Shortener": 1, - "votify": 1, - "lynaesh_dashboard": 1, - "URLShort": 1, - "SocialMedia": 1, - "appDatabase": 10, - "Database 1": 1, - "ps-innovation-day": 1, - "AppDatabase": 161, - "appdatabase": 1, - "svellodatabase": 1, - "user": 5, - "TrelloDatabase": 2, - "first_app": 1, - "boats": 1, - "intratec-tecnologia": 1, - "chat-app": 1, - "DnD database": 1, - "appwrite": 2, - "admin_users_database": 1, - "app database": 2, - "234234": 1, - "dusers": 1, - "trello-database": 4, - "TaskerDB": 1, - "meddb": 1, - "dsuite-db": 2, - "fleekytrendsProducts": 1, - "healthservices": 1, - "openchat": 1, - "Aurelia DB": 1, - "Locations": 1, - "AppDB": 3, - "VideoCall": 1, - "Development": 2, - "TrelloApp": 1, - "type-frenzy": 1, - "config": 1, - "FakeDB": 1, - "dev_01": 1, - "register": 1, - "gratitude_jar_db": 1, - "priceers": 1, - "Huntdb": 1, - "TrelloDb": 2, - "prasad": 1, - "brtbhrthtrhhtrhtrnh": 1, - "CodingFlux Database": 1, - "Flair Database": 1, - "FVB": 1, - "Admin": 2, - "emailusers": 1, - "ITrackemail": 1, - "notificationtoken": 1, - "orgcode": 1, - "schoolreq": 1, - "Triperbus": 1, - "vehicles": 1, - "ATWS Databases": 1, - "Buildrankers-Prod": 1, - "Discussion Forum": 1, - "CanbanDatabase": 1, - "chipIn MVP database": 1, - "jamshaidtaskifyDatabase": 1, - "school": 2, - "todo-db": 2, - "LearningApp": 1, - "twitter test": 2, - "TestDB": 9, - "appdata": 1, - "flutter_appwrite_col": 1, - "flutter_appwrite": 1, - "PromanageDatabase": 1, - "landing": 1, - "bank-data": 1, - "moni": 1, - "StuffDatabase": 1, - "alertapp-prod": 1, - "alertapp-qa": 1, - "Walldb": 1, - "role:on": 1, - "leaderboardlearn": 1, - "Taskify": 1, - "DB-PAYMENT-PAGE": 1, - "ggg": 2, - "TrelloCloneDB": 1, - "kanban-gpt-app": 1, - "awc-news": 1, - "data": 6, - "orders": 1, - "ding": 1, - "bisky_chat": 1, - "vaibgram-db": 1, - "trello-clone": 3, - "appdb": 3, - "trelo": 1, - "tpmt": 1, - "languageEx": 1, - "virtualBot": 1, - "Database test": 1, - "Main": 9, - "rnd": 1, - "trips": 1, - "ProductDatabase": 1, - "atesting": 1, - "cakebudget": 1, - "oya_db": 1, - "Raven": 1, - "TaskAppDatabase": 1, - "main_db": 1, - "exams": 1, - "Notes": 1, - "root": 2, - "Exercises": 1, - "estudos": 1, - "store": 2, - "trello-db": 1, - "ProdAmigoDB": 1, - "chikigram": 1, - "Viagens": 1, - "brainwars_db": 1, - "app-database": 1, - "Trello": 2, - "Admins": 1, - "wax": 1, - "undanganonline": 1, - "Sunarp": 1, - "recipto_db": 1, - "trello_clone_db": 1, - "dB": 2, - "Messages": 3, - "Dadabase": 1, - "SecurePass": 1, - "Registrations": 1, - "Sponsors": 1, - "Trello Database": 2, - "contact_form": 1, - "chat_db": 1, - "app_database": 1, - "watchlist": 1, - "myorg": 1, - "temir": 1, - "Todos": 4, - "Website Color CSS": 1, - "testonio": 1, - "teste": 3, - "trello-v2": 1, - "tikDb": 1, - "Queries": 1, - "shophub": 1, - "appDatabases": 1, - "trelloDatabase": 1, - "appDataBase": 1, - "mmm": 1, - "workdiary": 1, - "Specs99 DB": 1, - "App database": 1, - "Frank": 1, - "app_data": 1, - "app_pop_up_db": 1, - "express_pay_app_database": 1, - "nextcloudify_db_dev": 1, - "main database": 1, - "VitaPlate": 1, - "writepost": 1, - "trial": 1, - "BataapDB": 1, - "collectify_database": 1, - "pso2_items_database": 1, - "agis": 1, - "twitter": 4, - "HabitProDB": 1, - "TripArchitectDB": 1, - "airiedb": 1, - "purupdb": 1, - "flutter": 7, - "flutter_database": 12, - "geoteams": 1, - "Ecom": 1, - "Trabajadores": 1, - "HnosUceda": 1, - "etracker": 2, - "Reviews": 1, - "trello-clone-db": 1, - "AllPos": 1, - "liqlid-mvp-main": 1, - "db01": 2, - "Trello dev": 1, - "child": 1, - "shortcuts": 1, - "TrelloCloneAppDatabase": 1, - "leagueFusion": 1, - "activity_1000k": 1, - "activity_100k": 1, - "TaskManager-Projects": 1, - "SocialMediaAppDB": 1, - "devdactic": 2, - "dbtian": 1, - "BlogMd": 1, - "Trello_Clone_AppDatabase": 1, - "waste-collection": 1, - "user_details": 1, - "appwrite_hackathon": 1, - "new": 4, - "messages": 6, - "Render2023": 1, - "testinggg": 1, - "chatwrite": 3, - "Chatty": 1, - "information": 1, - "chattingDB": 1, - "NoteDb": 1, - "app-db": 3, - "123": 1, - "webook": 1, - "apt": 1, - "User": 6, - "hackerspace": 1, - "general": 5, - "ChatDB": 2, - "renderatl-2023": 1, - "General": 1, - "zoro": 1, - "testData": 1, - "ns-db": 1, - "tbUsuario": 1, - "trails": 1, - "GameRefill Shop": 1, - "fitdb": 1, - "cccmedia": 1, - "robodoradca": 1, - "astro": 1, - "369": 1, - "likakuDB": 1, - "clinick-db": 1, - "devices": 2, - "maindb": 1, - "notebooks": 1, - "chatting-application": 1, - "Storage": 1, - "CSE_DB": 1, - "AppTodo": 1, - "rideonparts": 1, - "appwritedb": 1, - "Testdb": 1, - "wisetally": 1, - "staging": 3, - "taskkify-db": 1, - "Ellume360": 1, - "EllumeLogin": 1, - "trell-app-database": 1, - "products database": 1, - "AInews": 1, - "Session": 1, - "riia-db": 1, - "backfillJobs": 1, - "Settings": 1, - "Log": 1, - "App": 2, - "Document": 1, - "oneDeal": 1, - "scan_and_go_db": 1, - "goraiya db": 1, - "CombiDataBase": 1, - "dcg": 1, - "todoData": 1, - "notestester": 1, - "recipe": 1, - "mqtt_auth": 1, - "pumprecord-db": 1, - "Slideshub": 1, - "Prescriptions ": 1, - "AppDataBase": 2, - "business_Aid": 1, - "trello_app": 1, - "slack-app-db": 1, - "taskapp": 1, - "trello-app": 1, - "SorageX": 1, - "superdb": 1, - "Osd": 1, - "trivia_project": 1, - "Emp": 1, - "userdetails": 1, - "HRIS": 1, - "Account": 1, - "tetris": 1, - "task-ai_database": 1, - "SheroDatabase": 1, - "UserData": 2, - "DashboardDb": 1, - "mydatabase": 1, - "event name, description, date, and location": 1, - "Payments": 1, - "Skarban": 1, - "VGPT": 1, - "WhatsappDatabase": 1, - "meetings": 1, - "Icicle_Statistics": 1, - "CRUX": 1, - "crud": 1, - "hosting": 1, - "Tt": 1, - "tables": 1, - "arbah": 1, - "globalbulls": 1, - "calligrapy": 1, - "instant_messenger": 1, - "Finance": 1, - "cook it up": 1, - "main-db": 1, - "IRA": 1, - "AppDtabase": 1, - "who fed the pet data": 1, - "agenda": 1, - "invoices": 2, - "notifications": 2, - "patient": 1, - "userSettings": 1, - "nmn": 1, - "upinvoice": 1, - "base64": 1, - "swingfire-app": 1, - "photos": 3, - "meetify": 1, - "gptmanaDB": 1, - "pos": 2, - "school_council": 1, - "62d985ab68e0e4b60293": 1, - "62dd7c6bbe54693b8a32": 1, - "secure-chat": 1, - "android-test": 1, - "commpcs_pro": 1, - "TEST DATABASE": 1, - "TaskWalletDB": 1, - "Contracts": 1, - "sampleDB": 1, - "telegram_bot": 1, - "AZED": 1, - "Hapix-db": 1, - "prod": 4, - "App-db": 1, - "quotes": 1, - "Dummy data": 1, - "User appointments": 1, - "chrono": 1, - "VarsityWorldDevelopment": 1, - "ServiceProviders": 1, - "r": 1, - "Murad": 1, - "ScheduleHero": 4, - "testindb": 1, - "flutter_db": 1, - "defaultDb": 1, - "History": 1, - "Distributors-Labels": 1, - "LoggingDB": 1, - "reservas": 1, - "SurveyDatabase": 1, - "no-bullshit-recipes-database": 1, - "lvr_db": 1, - "db1234": 1, - "myClass": 1, - "trello": 2, - "mrElayaDb": 1, - "memos": 1, - "Accounts": 1, - "Commissions": 1, - "lines": 1, - "BKB": 2, - "Elements": 2, - "design_resources": 1, - "public_data": 1, - "users_data": 1, - "X-connect": 1, - "inventory": 1, - "OrganizerDB": 1, - "AppDatabasexxxx": 1, - "animals": 1, - "transport": 1, - "markly": 1, - "db_app": 1, - "board": 2, - "ahaporn": 1, - "subscribers": 1, - "databases": 1, - "message": 1, - "vote": 1, - "portfolio": 2, - "chat": 12, - "QuestList": 1, - "Personal Life Assistant DB": 1, - "C Programming Club": 1, - "groupevents-db": 1, - "resumix": 1, - ",": 1, - "Negotiations": 1, - "Basedate": 4, - "twitterdb": 1, - "STO": 1, - "ai-generator-db-v1": 1, - "e-commerce": 1, - "MADG7": 1, - "TrelloAppDatabase": 1, - "firstdb": 1, - "Items": 1, - "digitalsign": 1, - "e-commerce-app": 1, - "appDb": 2, - "anycasts": 1, - "food": 2, - "noodles-db": 1, - "properly": 1, - "repulse": 1, - "geolocation1_db": 1, - "Updated Database": 9, - "db_kharcha_aamdani": 1, - "Jajanan Lobet": 1, - "NodeToDo": 1, - "mutual_funds": 1, - "nextjs": 1, - "bybit": 1, - "medlogs": 1, - "life-loop": 1, - "ll": 1, - "client": 1, - "AllThumbs": 1, - "Test DB": 2, - "todoApp": 1, - "t.db1": 1, - "dog_sitting": 1, - "todosss": 1, - "doovu": 1, - "tasks": 4, - "tasks_list": 7, - "cagnotte": 1, - "6482f68757302733e335": 1, - "64d7c796b08f76ec51f6": 1, - "db_demo": 1, - "bus": 1, - "election-app": 1, - "a": 2, - "employees": 2, - "database_name_m001": 1, - "resume": 2, - "ImmerseToDo": 1, - "[PROD] krello db": 1, - "myMlmDb": 1, - "ct": 1, - "RacketScoreDB": 1, - "khataApp": 1, - "luna": 1, - "Abc": 1, - "TestDatabase1": 1, - "dev12": 1, - "taskies main database": 1, - "SO-SKILLED": 1, - "hp01": 17, - "iku": 1, - "items": 2, - "mi-tunes-db": 1, - "TaskifyDatabase": 1, - "Ttatar": 1, - "myDatabase": 2, - "TaskBro": 1, - "appslause_trello_db": 1, - "blogposts": 18, - "trundling": 1, - "base_database": 1, - "bookListTest": 1, - "PU-Chd": 1, - "Pu-Chd": 1, - "postapi": 1, - "FamProDB": 1, - "photoshare": 1, - "Blog": 4, - "W.Task-AppDatabase": 1, - "TrelloAppDataBase": 1, - "fleet": 1, - "reservation": 1, - "drb": 1, - "DemoDatabase": 1, - "storage alpha": 1, - "contentus": 1, - "contentus-shadow-db": 1, - "whatsapp": 1, - "explore-aw-db": 1, - "phone auth demo": 1, - "readlits-db": 1, - "facemodel": 1, - "categories": 1, - "pms": 1, - "mohali-id": 1, - "UserDatabase": 1, - "collabverse": 1, - "gratitude-db": 1, - "my-digital-manager-database": 1, - "budget": 1, - "jmdb": 1, - "okaki-sensoren": 1, - "Personality": 1, - "UserDB": 1, - "ghgh": 1, - "JinjaCovers": 1, - "Blogs": 1, - "ihmtransact": 1, - "MoodMapDB": 1, - "pruebaadz": 1, - "cv": 1, - "fff": 1, - "monedaDB": 1, - "Main Database": 1, - "thenonpp_dev": 1, - "product": 3, - "ecommerce": 1, - "TASKS": 1, - "portals": 1, - "twitterTest": 1, - "sample_data": 1, - "Phalam": 1, - "journalDB": 1, - "LeaveFormStore": 1, - "Event DB": 1, - "Employees": 1, - "transactions_db": 1, - "melange": 1, - "myskoolDb": 1, - "blood_bank_db": 1, - "blood_chat_db": 1, - "bracket_assets_db": 1, - "bracket_db": 1, - "bracket_invitations_db": 1, - "chats_db": 1, - "counselling_appointments_db": 1, - "counselling_db": 1, - "discussion_assets_db": 1, - "discussion_db": 1, - "discussion_talks_db": 1, - "discussion_user_stats": 1, - "events_db": 1, - "members_db": 1, - "user_notification_db": 1, - "seats": 1, - "A": 2, - "Marks": 1, - "d1": 1, - "Diary Dev": 1, - "Load Test": 1, - "wer": 1, - "Products": 3, - "medical": 1, - "xanwas": 1, - "committable-backend": 1, - "Food": 1, - "Management": 1, - "chef_mani": 1, - "DB Billetterie": 1, - "Appwrite DB": 1, - "mio-admin": 1, - "User Data": 2, - "News DB": 1, - "info_Sossis": 1, - "DB_AULAS": 1, - "todo-final": 1, - "Evd": 1, - "players": 1, - "HungerZero": 1, - "Twitter db": 1, - "connectkoreaair": 1, - "s": 1, - "xpenzave_db": 1, - "students": 1, - "chatBlog": 1, - "newChatBlog": 1, - "TEAMING PORTAL CHAT ": 1, - "rss_db": 1, - "stella": 1, - "Database": 3, - "Twitter": 2, - "TrelloDB": 2, - "lorgger": 1, - "mindly_db": 1, - "Testdatabase": 1, - "soundboard": 1, - "GroupChatDB": 1, - "one": 2, - "Heatank": 1, - "bucket_data": 1, - "user_data": 1, - "primary_db": 1, - "Project": 1, - "tripbot": 1, - "sell_smart_main": 1, - "mainDB": 1, - "hackathon": 1, - "AppDatabse": 1, - "MyApp": 2, - "bookstore": 1, - "devverse-db": 1, - "expense-care-db": 1, - "pins": 1, - "expensasaurus": 1, - "Ireland Made": 1, - "sac": 1, - "WriterBlog": 1, - "snippad-main": 1, - "Trello-data": 1, - "silai": 1, - "codecollab": 1, - "Transactions": 1, - "Local Log": 1, - "AppDatabases": 1, - "FirstTestDB": 1, - "SignalClone": 1, - "FileStore": 1, - "21yards": 1, - "todo-app": 2, - "Insudash": 1, - "zokoboss": 1, - "Karte": 2, - "Rel-TEST": 1, - "olimpodb": 1, - "zinduo flashcard": 1, - "newDB": 1, - "EventScape": 1, - "Konsulting": 1, - "Demo": 1, - "redmatters": 1, - "essai_db": 1, - "my-stirixis-database": 1, - "MyBlogs": 1, - "blogpost": 3, - "zlist_db": 1, - "movieData": 1, - "Players": 1, - "mindful-me": 1, - "lolo": 1, - "sharebitedb": 1, - "master": 1, - "sf": 1, - "noteenc": 1, - "blogposts ": 1, - "Blog-Posts": 1, - "db-1": 1, - "testDB": 2, - "641f01fb3f6a1bc22c7e": 1, - "mysql": 1, - "HabitDB": 1, - "agents": 1, - "Tam Duc Apparel DB": 1, - "blog-post": 1, - "stores": 1, - "department": 1, - "sop": 1, - "Distributa": 3, - "rnxcode_db": 1, - "netflix_clone": 1, - "guizapp": 1, - "BlogPosts": 1, - "Chat": 2, - "Bedevelopers-Database": 1, - "likumbi": 1, - "OptionSuperManDB": 1, - "article": 1, - "NewDB": 1, - "MyGameStudio": 1, - "default_db": 1, - "userdata": 2, - "Main DB": 1, - "travfddb": 1, - "expenses": 1, - "incomes": 1, - "consultations_database": 1, - "doctors_database": 1, - "patients_database": 1, - "dealfuel": 1, - "Zenivote": 1, - "Portfolio Details": 1, - "Abhidhan Rajendra Kosh": 1, - "common": 1, - "AppUser": 1, - "studygang": 1, - "Peakfit.Db": 1, - "Credentials": 1, - "destinations": 1, - "fun2print_cc": 1, - "billing1": 1, - "studygangdb": 1, - "autana_ide": 1, - "betadev": 1, - "Vibey": 1, - "Slam Book": 1, - "TeleGPT": 1, - "Clips": 1, - "Quizmaster": 1, - "Office Hours DB": 1, - "canva order": 1, - "VideoWatching": 1, - "DataBase": 1, - "sharif-invoice": 1, - "Hack Questions": 1, - "er": 1, - "course": 1, - "Almost Netflix Project": 1, - "Database_sree": 1, - "Quizapp": 1, - "UNIT": 1, - "Public": 2, - "SalesT": 1, - "ZIC": 1, - "Employee": 1, - "Pets": 1, - "twitter-database": 2, - "dev-db": 1, - "track-db": 1, - "demo-db": 2, - "test db": 2, - "teste_db": 1, - "db_lumes": 1, - "SuperWalk": 1, - "rbac2": 1, - "Animesh": 1, - "Bereal": 1, - "PdfTest": 1, - "colonium-users": 1, - "dbMyPrice": 1, - "Production": 2, - "admin_db": 1, - "report-feelings": 1, - "browser": 1, - "protasker": 1, - "shop": 1, - "trigger-tech": 1, - "user data": 1, - "online_env": 1, - "DC3Mobi": 1, - "webappdb": 1, - "synapp": 1, - "pages": 1, - "collective-tales-dev": 1, - "Bildwurf DB": 1, - "Cards": 1, - "ok": 1, - "tmp": 1, - "StandUp": 1, - "Web Database": 1, - "TodoDB": 1, - "Prueba": 1, - "pafunn": 1, - "profiles": 2, - "nice-support": 1, - "pulse": 1, - "jargonjar": 1, - "xsx": 1, - "event-lly": 1, - "Sprittie": 1, - "test_database": 1, - "StroyOko": 1, - "Sparkle": 1, - "Coworkers": 1, - "Canva Templates": 1, - "production": 5, - "home-management": 1, - "dt": 1, - "vodo_db": 1, - "MyTestDB": 1, - "LinkedIn DB": 1, - "blog": 15, - "Example Database": 1, - "companion_db": 1, - "uni_sort": 1, - "rfg_app": 1, - "twitter-clone-project": 1, - "Restaurant_profiles": 1, - "trytowin": 1, - "db_test": 2, - "gallery": 1, - "usersData": 1, - "core": 1, - "IM": 1, - "TechBase": 1, - "ANDON": 1, - "awtest-db": 1, - "Widgets": 1, - "ember": 1, - "asdasdasd": 1, - "courrierflex": 1, - "TunezStream": 1, - "PmanDatabase": 1, - "weintegral": 1, - "TrelloData": 1, - "Test db": 1, - "bandom": 1, - "rezoom-eh-db": 1, - "WordJournalDB": 1, - "99": 1, - "T": 1, - "dop_exams": 1, - "database1": 3, - "asx": 1, - "myilsc": 1, - "Student Base": 1, - "shortify": 1, - "Cheelz Database": 1, - "TESLA Web Database": 1, - "Shorely Ibiza": 1, - "test-server": 1, - "Local_Gems": 1, - "articles": 1, - "AppwriteDb": 1, - "Auction": 1, - "lol": 1, - "todowrite-db": 1, - "BooksDB": 1, - "LoanDB": 2, - "dali": 1, - "JCI app": 1, - "OMS": 1, - "PIM": 1, - "RFx": 1, - "Data": 6, - "acctg1": 1, - "hris1": 1, - "hris2": 1, - "JobTitle": 2, - "CRUD database": 1, - "Foodtracker": 1, - "typical_food": 1, - "demoDB": 1, - "base1": 1, - "trello database": 1, - "demo-db-2": 1, - "Hypertrophy": 1, - "Dojo database": 1, - "skinvasai": 1, - "sgveti": 1, - "medicademy-db": 1, - "habbit": 1, - "Task": 1, - "Data ": 1, - "mvp": 1, - "wwwg": 1, - "public-system": 1, - "student_data": 1, - "chatting": 1, - "Kharidoit": 1, - "kj": 1, - "local": 1, - "wallpaper": 1, - "workspace": 1, - "sarcom-admin": 1, - "tickets": 1, - "ifiye-db": 1, - "Dev": 1, - "Prod": 2, - "TooodooosDB": 1, - "Climast database ": 1, - "My Provisioned DB": 1, - "logs": 2, - "Ascended": 1, - "avx": 1, - "geoloyaltydb": 1, - "yulidb": 1, - "public": 2, - "cms": 1, - "shop together": 1, - "UsersPosts": 1, - "tetst1": 1, - "blogdatabase": 1, - "Twitter test db": 1, - "vhhfdh": 1, - "baket": 1, - "i2e_sw_account": 1, - "New": 1, - "appwrite-test": 1, - "example database": 1, - "storyTable": 1, - "Clothing": 1, - "SV dataflow": 1, - "hgfdjd": 1, - "CoorfyDB": 1, - "purchased": 1, - "Countdown": 1, - "moe": 1, - "rawabialkharef": 1, - "123database": 1, - "shareamDB": 1, - "twitter_db": 1, - "fluttiyomi": 1, - "trends": 1, - "servers": 1, - "Oblongata": 1, - "Cygnus": 1, - "appwriteLearningDb": 1, - "Product": 1, - "PedroDB": 1, - "opos": 1, - "top-team-opos": 1, - "trainings": 1, - "converstations": 1, - "Modern Deals": 1, - "WebStorage": 1, - "apiTestOnline": 1, - "rajmade": 1, - "Profile image url": 1, - "Demo 1": 1, - "Akordi": 1, - "syncms": 1, - "pranav": 1, - "Oracle ": 1, - "dashboard": 1, - "deti": 1, - "exms": 1, - "rm-test": 1, - "test2": 1, - "Grids": 1, - "ProductionDatabase": 1, - "TestDatabase": 1, - "Yukt": 1, - "z": 1, - "CMS": 1, - "Entries": 1, - "books": 1, - "ewoerp": 1, - "AVImark Reports": 1, - "customtabs": 1, - "Database-1": 1, - "sampledatabase": 1, - "Deptos": 1, - "Sugam's Database": 1, - "Test-DB": 2, - "sms": 1, - "skyone-todo": 1, - "tiktok-clone": 1, - "YouTube Videos": 1, - "automata": 1, - "radium": 1, - "TestDb1": 1, - "etherdb": 1, - "global_db": 1, - "near.db": 1, - "Yggdrasil": 1, - "comentarios_db": 1, - "photo_fusion": 1, - "seashipfinder": 1, - "issues": 1, - "DojoDB": 1, - "jkjk": 1, - "dms": 1, - "online_blood_and_organ_donation_system": 1, - "reminders": 1, - "some-database": 1, - "socialPixer": 1, - "home-cafe": 1, - "betrendz-dev": 1, - "snapgram": 3, - "donation-retriever": 1, - "storeDB": 1, - "befree-users": 1, - "Chemistry stuff": 1, - "Core Database": 1, - "instaFaceGram": 1, - "theUiratec": 1, - "blendr": 1, - "occulo": 1, - "nextdb": 1, - "routes": 1, - "user-data": 1, - "JDB": 1, - "shorelyIbizaProduction": 1, - "socialApp": 1, - "SimplGram": 1, - "Snapgram_Data": 1, - "snapcy": 1, - "Image_DB": 1, - "hello_world": 1, - "download": 1, - "Mydb": 2, - "trip": 1, - "oral": 1, - "dddd": 1, - "shopping-list": 1, - "omnibrain": 1, - "basic": 1, - "unity": 1, - "xerox_bot": 1, - "first_db": 1, - "SIEL DB": 1, - "db-preprod": 1, - "testme": 2, - "dreamdb": 1, - "anochat-database": 1, - "anochat-db": 2, - "anochat-dn": 1, - "sovo_db": 1, - "pumpkin": 1, - "marketplace-test": 1, - "PG": 1, - "user list": 1, - "userdb": 1, - "amri": 1, - "members": 1, - "daily-match": 1, - "gdt-members": 1, - "Systems": 1, - "swiftform": 1, - "fanaka": 1, - "dbDev": 1, - "my-first-db": 1, - "Vehicles": 1, - "Kennels": 1, - "calendula": 1, - "asdasd": 1, - "tsproject": 1, - "mallas": 1, - "variedades": 1, - "qs": 1, - "asd": 1, - "mdc_magazine": 1, - "mdc_store": 1, - "School Me DB": 1, - "jczd": 1, - "kupczyk": 1, - "Testing": 1, - "sprintcap": 1, - "CloudShared": 1, - "urls": 1, - "willy": 1, - "My first database": 1, - "Links": 1, - "Twitter Clone": 1, - "functions": 1, - "viewCollections": 1, - "stagging": 1, - "Payment Records": 1, - "AED307Group14": 1, - "rubrica": 1, - "histronia": 1, - "td": 1, - "doctor": 1, - "features": 1, - "park": 1, - "College Cutoff": 1, - "like": 1, - "todos-db": 1, - "TESTDB": 1, - "1": 2, - "BetterChatGPT": 1, - "FIrst db": 1, - "bot_database_test": 1, - "cloud-maturity": 1, - "vendas": 1, - "swirly test": 1, - "Terst": 1, - "CC_db": 1, - "pos db": 1, - "Groups": 1, - "testdatabase": 1, - "kaze": 1, - "Connect": 1, - "NUV-AzTechs-Database": 1, - "Payment Gateway": 1, - "testdata": 2, - "tradeassistant": 1, - "mediation_database": 1, - "dbTest": 1, - "basketball": 1, - "belanja_db": 1, - "Fun": 1, - "mytest": 1, - "FirstDatabase": 1, - "administration": 1, - "consumers": 1, - "mregistryDatabase": 1, - "Twst": 1, - "blogdb": 1, - "search_me": 1, - "aide": 1, - "plantebyt": 1, - "kittens": 1, - "waters": 1, - "aaaaa": 1, - "altrec_db": 1, - "atai": 1, - "Home": 1, - "swifty": 1, - "schedule": 1, - "andimar": 1, - "Manlou": 1, - "cuitanDB": 1, - "smartbcard": 1, - "afe": 1, - "Openstartup": 1, - "Stock": 1, - "drivers": 1, - "sample_order": 1, - "5870": 1, - "kjhg": 1, - "xva": 1, - "MyTemplates": 1, - "Fiesta Data": 1, - "patients": 1, - "animated_dev": 1, - "classapp-db": 1, - "dbb": 1, - "twilio": 1, - "ads": 1, - "Saved Images": 1, - "Name": 1, - "MyDB": 2, - "RipplesCode": 1, - "LeaguesWorld": 1, - "outlet": 1, - "scorer": 1, - "itistime": 1, - "Manuk Biru DB": 1, - "guests": 1, - "questions": 1, - "AI Poker": 1, - "nash_app": 1, - "cars": 1, - "ccc": 1, - "Bookings": 1, - "proj": 1, - "Twitter Clone Database": 1, - "quantasip": 1, - "navigation": 1, - "check": 1, - "testovacka_db": 1, - "base": 1, - "Testbase": 1, - "CoDeveloper Database": 1, - "sample_db": 1, - "dg_1142_dbstore": 1, - "todo-fawp-db": 1, - "project_database": 1, - "Issues": 1, - "cinehousedb": 1, - "foodItems": 1, - "Snowcamp": 1, - "codeApi": 1, - "debify": 1, - "Ymir": 1, - "NetflixDB": 1, - "Database2": 1, - "brainTeaser": 1, - "Fableit Dev": 1, - "Twitter Database": 1, - "Users ": 1, - "portal": 1, - "svelte-test": 1, - "TatiaDb": 1, - "FirstDB": 1, - "galaxies": 1, - "cf_db": 1, - "formData": 1, - "Letter of Credit DB": 1, - "Attribute": 1, - "Inventar": 1, - "banco": 1, - "Announce": 1, - "Maintenance": 1, - "aptkr": 1, - "streamlinks": 1, - "maze1": 1, - "Macellpower": 1, - "Student": 1, - "Forms": 1, - "company-management": 1, - "DBDFM1": 1, - "skool": 1, - "foods": 1, - "Harsh": 1, - "loginator-db": 1, - "Blubbidb": 1, - "Parchin_DB": 1, - "Fitness_App": 1, - "Books": 1, - "usersDB": 1, - "yum": 1, - "yumShares": 12, - "bottledrive": 1, - "website": 1, - "ampPanda": 1, - "TestData": 1, - "oppenheimer": 1, - "sampleDatabase": 1, - "ims_db": 1, - "dingleberry": 1, - "shopaholic-db": 1, - "Sample Database": 1, - "delta-co": 1, - "myLabDB": 1, - "posts database": 1, - "Newsletter": 1, - "order_management": 1, - "psn-kadi-svelte": 1, - "PeetFeederDb": 1, - "yyui": 1, - "taskninja": 1, - "hmnz-core": 1, - "payroll": 1, - "Demo_DB": 1, - "reco-teams-alpha": 1, - "foodly": 1, - "set": 1, - "tst": 1, - "HuntPile": 1, - "-": 1, - "Images": 1, - "money": 1, - "relax": 1, - "todo2": 1, - "vmfk": 1, - "ident": 1, - "recommend": 1, - "Cinemagix ": 1, - "picoLens": 1, - "Organizations": 1, - "safescan": 1, - "first db": 1, - "Photos": 1, - "nn": 1, - "todo's": 1, - "db_news": 1, - "listings": 1, - "to-do-list": 1, - "event-manager": 1, - "iconinstallation": 1, - "charshow_db": 1, - "snipdb": 1, - "socio-flare": 1, - "venicedb": 1, - "drip": 1, - "playground": 1, - "shelters-db": 1, - "kudoscrate": 1, - "Task_management_app": 1, - "ptp": 2, - "workout-history": 1, - "Muslim": 1, - "asklocaldb": 1, - "databiatch": 1, - "QuizProDB": 1, - "discussions": 1, - "ics": 1, - "UsersDetails": 1, - "my-chat": 1, - "easy-prompt-test": 1, - "cmt4": 1, - "cmt5": 1, - "cmt6": 1, - "atglancecronconfig": 1, - "atglancenewsdb": 1, - "mainbase": 1, - "quiz": 2, - "Let's Connect": 1, - "Bill Pecker": 1, - "Database1": 1, - "prompt-store": 1, - "DB-test-1": 1, - "SevyController": 1, - "buzz2xdb": 1, - "recipeYardDatabase": 1, - "quickd": 1, - "Chat Database": 1, - "mods": 1, - "opslog": 1, - "live_feedback": 1, - "stoker_database": 1, - "Education": 1, - "No Signal": 1, - "Appwrite CMS": 1, - "firstDatabase": 1, - "LinkedIn": 1, - "neptune_blindbox": 1, - "Msgs": 1, - "table": 1, - "post": 1, - "rareBeauty": 1, - "formsDB": 1 -} \ No newline at end of file diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index ace846d8b4..c0c5ef2f43 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -111,8 +111,6 @@ class Database extends Event $client = new Client($this->queue, $this->connection); - \var_dump('Event queue name is: ' . $this->queue); - try { $result = $client->enqueue([ 'project' => $this->project, @@ -123,12 +121,8 @@ class Database extends Event 'database' => $this->database, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); - \var_dump('Enqueued event'); - \var_dump($result); return $result; } catch (\Throwable $th) { - \var_dump('Enqueue event failed'); - \var_dump($th); return false; } } diff --git a/test.php b/test.php deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index b3d3ae4d10..085d3ca01b 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1296,8 +1296,6 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $this->getHeaders())); - \var_dump($attributes['body']); - $this->assertEquals(0, $attributes['body']['total']); } From 356d155df20b012bd86a1751a65a7ea5df347474 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 17:29:12 +1200 Subject: [PATCH 55/61] Add shared tables enabled flag for quick toggle --- app/controllers/api/projects.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 896d6b8ce6..9e5e1ff364 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -155,6 +155,7 @@ App::post('/v1/projects') // TODO: One in 20 projects use shared tables. Temporary until all projects are using shared tables. if ( !\mt_rand(0, 19) + && App::getEnv('_APP_DATABASE_SHARED_TABLES', 'enabled') === 'enabled' && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' ) { $schema = 'appwrite'; From e9bac08de02aa8e44a99f2d85267c715e77fa54a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 17:59:24 +1200 Subject: [PATCH 56/61] Fix header test --- app/controllers/api/projects.php | 2 +- app/controllers/general.php | 4 ++-- tests/e2e/General/HTTPTest.php | 2 +- tests/e2e/Services/Projects/ProjectsConsoleClientTest.php | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 9e5e1ff364..f7a39b9d2d 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -172,7 +172,7 @@ App::post('/v1/projects') if ( App::isDevelopment() && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' - && $request->getHeader('x-appwrite-share-tables', false) + && $request->getHeader('x-appwrited-share-tables', false) ) { $schema = 'appwrite'; $database = 'appwrite'; diff --git a/app/controllers/general.php b/app/controllers/general.php index 3a3b52579e..dd9484bb0e 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -574,7 +574,7 @@ App::init() ->addHeader('Server', 'Appwrite') ->addHeader('X-Content-Type-Options', 'nosniff') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') - ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Share-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent') + ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Shared-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $refDomain) ->addHeader('Access-Control-Allow-Credentials', 'true'); @@ -625,7 +625,7 @@ App::options() $response ->addHeader('Server', 'Appwrite') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') - ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Share-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent') + ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Shared-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $origin) ->addHeader('Access-Control-Allow-Credentials', 'true') diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 8692dea34e..0bb5ca4650 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -31,7 +31,7 @@ class HTTPTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEquals('Appwrite', $response['headers']['server']); $this->assertEquals('GET, POST, PUT, PATCH, DELETE', $response['headers']['access-control-allow-methods']); - $this->assertEquals('Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Share-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent', $response['headers']['access-control-allow-headers']); + $this->assertEquals('Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-Appwrite-Shared-Tables, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent', $response['headers']['access-control-allow-headers']); $this->assertEquals('X-Appwrite-Session, X-Fallback-Cookies', $response['headers']['access-control-expose-headers']); $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin']); $this->assertEquals('true', $response['headers']['access-control-allow-credentials']); diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 7db5415d65..12db8c814c 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3480,7 +3480,7 @@ class ProjectsConsoleClientTest extends Scope $project1 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-share-tables' => false + 'x-appwrite-shared-tables' => false ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Amazing Project', @@ -3492,7 +3492,7 @@ class ProjectsConsoleClientTest extends Scope $project2 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-share-tables' => true + 'x-appwrite-shared-tables' => true ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Amazing Project', @@ -3504,7 +3504,7 @@ class ProjectsConsoleClientTest extends Scope $project3 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-share-tables' => false + 'x-appwrite-shared-tables' => false ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Amazing Project', @@ -3516,7 +3516,7 @@ class ProjectsConsoleClientTest extends Scope $project4 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-share-tables' => true + 'x-appwrite-shared-tables' => true ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Amazing Project', From e69862bd6fad09b4cc792729bf636e2548f6a343 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 18:11:15 +1200 Subject: [PATCH 57/61] Fix google issuer change --- tests/e2e/Services/Health/HealthCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 5fd7ab96da..335e44be1b 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -455,7 +455,7 @@ class HealthCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('/CN=www.google.com', $response['body']['name']); $this->assertEquals('www.google.com', $response['body']['subjectSN']); - $this->assertEquals('Google Trust Services LLC', $response['body']['issuerOrganisation']); + $this->assertEquals('Google Trust Services', $response['body']['issuerOrganisation']); $this->assertIsInt($response['body']['validFrom']); $this->assertIsInt($response['body']['validTo']); From 82dfbbd6148f47086d5626081ab538eb4e05c51c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 18:11:30 +1200 Subject: [PATCH 58/61] Fix isolation user test --- .../Projects/ProjectsConsoleClientTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 12db8c814c..0d2cc9b301 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3530,7 +3530,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Key Test', - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write', 'users.read', 'users.write'], ]); $key2 = $this->client->call(Client::METHOD_POST, '/projects/' . $project2['body']['$id'] . '/keys', array_merge([ @@ -3538,7 +3538,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Key Test', - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write', 'users.read', 'users.write'], ]); $key3 = $this->client->call(Client::METHOD_POST, '/projects/' . $project3['body']['$id'] . '/keys', array_merge([ @@ -3546,7 +3546,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Key Test', - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write', 'users.read', 'users.write'], ]); $key4 = $this->client->call(Client::METHOD_POST, '/projects/' . $project4['body']['$id'] . '/keys', array_merge([ @@ -3554,7 +3554,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Key Test', - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write'], + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.read', 'attributes.write', 'indexes.read', 'indexes.write', 'documents.read', 'documents.write', 'users.read', 'users.write'], ]); // Create a database in each project @@ -3933,10 +3933,10 @@ class ProjectsConsoleClientTest extends Scope $user1 = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', 'x-appwrite-project' => $project2['body']['$id'], - 'x-appwrite-key' => $key1['body']['secret'] + 'x-appwrite-key' => $key2['body']['secret'] ], [ 'userId' => 'user', - 'email' => 'test@localhost', + 'email' => 'test@appwrite.io', 'password' => 'password', 'name' => 'Test User', ]); @@ -3946,10 +3946,10 @@ class ProjectsConsoleClientTest extends Scope $user2 = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', 'x-appwrite-project' => $project4['body']['$id'], - 'x-appwrite-key' => $key2['body']['secret'] + 'x-appwrite-key' => $key4['body']['secret'] ], [ 'userId' => 'user', - 'email' => 'test@localhost', + 'email' => 'test@appwrite.io', 'password' => 'password', 'name' => 'Test User', ]); From 7023cdfb9e40d7585d76964ec4a0088cc14c7704 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 18:23:54 +1200 Subject: [PATCH 59/61] Revert "Fix google issuer change" This reverts commit e69862bd6fad09b4cc792729bf636e2548f6a343. --- tests/e2e/Services/Health/HealthCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 335e44be1b..5fd7ab96da 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -455,7 +455,7 @@ class HealthCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('/CN=www.google.com', $response['body']['name']); $this->assertEquals('www.google.com', $response['body']['subjectSN']); - $this->assertEquals('Google Trust Services', $response['body']['issuerOrganisation']); + $this->assertEquals('Google Trust Services LLC', $response['body']['issuerOrganisation']); $this->assertIsInt($response['body']['validFrom']); $this->assertIsInt($response['body']['validTo']); From 5f9c192d728940e68e6f11c0b1202d20d1abec7a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 19:53:20 +1200 Subject: [PATCH 60/61] Add assertion --- tests/e2e/Services/Projects/ProjectsConsoleClientTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 0d2cc9b301..39264386df 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3929,6 +3929,8 @@ class ProjectsConsoleClientTest extends Scope 'name' => 'Amazing Collection', ]); + $this->assertEquals(201, $collection5['headers']['status-code']); + // Assert that users across projects on shared tables can have the same email as they're unique on tenant + email not just email $user1 = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', From 921eb2b9006c9f7d2b4de2c1103936c09ec9eb66 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 7 May 2024 22:08:00 +1200 Subject: [PATCH 61/61] App::getEnv -> System::getEnv --- app/controllers/api/avatars.php | 5 +++-- app/controllers/api/projects.php | 12 ++++++------ app/controllers/api/storage.php | 2 +- app/controllers/general.php | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 23d62826da..337ba8fd9e 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -16,6 +16,7 @@ use Utopia\Domains\Domain; use Utopia\Fetch\Client; use Utopia\Image\Image; use Utopia\Logger\Logger; +use Utopia\System\System; use Utopia\Validator\Boolean; use Utopia\Validator\HexColor; use Utopia\Validator\Range; @@ -319,8 +320,8 @@ App::get('/v1/avatars/favicon') ->setAllowRedirects(false) ->setUserAgent(\sprintf( APP_USERAGENT, - App::getEnv('_APP_VERSION', 'UNKNOWN'), - App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) + System::getEnv('_APP_VERSION', 'UNKNOWN'), + System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) )) ->fetch($url); } catch (\Throwable) { diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index f7a39b9d2d..c1ffd6466f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -140,7 +140,7 @@ App::post('/v1/projects') } } - $databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE'); + $databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE'); $index = \array_search($databaseOverride, $databases); if ($index !== false) { $dsn = $databases[$index]; @@ -155,12 +155,12 @@ App::post('/v1/projects') // TODO: One in 20 projects use shared tables. Temporary until all projects are using shared tables. if ( !\mt_rand(0, 19) - && App::getEnv('_APP_DATABASE_SHARED_TABLES', 'enabled') === 'enabled' - && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' + && System::getEnv('_APP_DATABASE_SHARED_TABLES', 'enabled') === 'enabled' + && System::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' ) { $schema = 'appwrite'; $database = 'appwrite'; - $namespace = App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); + $namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); $dsn = $schema . '://' . DATABASE_SHARED_TABLES . '?database=' . $database; if (!empty($namespace)) { @@ -171,12 +171,12 @@ App::post('/v1/projects') // TODO: Allow overriding in development mode. Temporary until all projects are using shared tables. if ( App::isDevelopment() - && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' + && System::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' && $request->getHeader('x-appwrited-share-tables', false) ) { $schema = 'appwrite'; $database = 'appwrite'; - $namespace = App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); + $namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); $dsn = $schema . '://' . DATABASE_SHARED_TABLES . '?database=' . $database; if (!empty($namespace)) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 37c5c032e1..9215d99345 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -63,7 +63,7 @@ App::post('/v1/storage/buckets') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) - ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) App::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) App::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) + ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) diff --git a/app/controllers/general.php b/app/controllers/general.php index dd9484bb0e..bcdf0fecb3 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -713,8 +713,8 @@ App::error() if ($error->getCode() >= 400 && $error->getCode() < 500) { // Register error logger - $providerName = App::getEnv('_APP_EXPERIMENT_LOGGING_PROVIDER', ''); - $providerConfig = App::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', ''); + $providerName = System::getEnv('_APP_EXPERIMENT_LOGGING_PROVIDER', ''); + $providerConfig = System::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', ''); if (!(empty($providerName) || empty($providerConfig))) { if (!Logger::hasProvider($providerName)) {