From 982373c915c32c9294d86cb9499d5e1bbde456d5 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 10 Jul 2023 08:04:27 +0000 Subject: [PATCH 01/15] feat: update error in Exception constructor --- app/controllers/api/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index dce493b024..651efbfbeb 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -414,7 +414,7 @@ App::get('/v1/users/:userId') $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { - throw new Exception('User not found', 404, Exception::USER_NOT_FOUND); + throw new Exception(Exception::USER_NOT_FOUND); } $response->dynamic($user, Response::MODEL_USER); From bf9219e811d8d85b98fb059ad26b86388e7b16c3 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 11 Jul 2023 01:20:24 +0400 Subject: [PATCH 02/15] fix: cloud redirect --- app/controllers/web/console.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index 571049d9ef..72379d3629 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -9,6 +9,7 @@ App::get('/console/*') ->alias('auth/*') ->alias('/invite') ->alias('/login') + ->alias('/card/*') ->alias('/recover') ->alias('/register/*') ->groups(['web']) From b4ce4c7837175fe0c9066d4eb7cb192c54535f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 15 Jul 2023 17:26:57 +0200 Subject: [PATCH 03/15] Update console --- app/console | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/console b/app/console index b981302dee..104c82a0ab 160000 --- a/app/console +++ b/app/console @@ -1 +1 @@ -Subproject commit b981302dee30eab33e155af79f0088822b29a2b6 +Subproject commit 104c82a0abc9baf661ffb59759fcae5e05a73c5f From fce230dca8b998f3810d051f3a878aa4761d1711 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 17 Jul 2023 16:42:46 -0700 Subject: [PATCH 04/15] Fix team delete Ensure all memberships are deleted and the cached users are invalidated so that the nested memberships will refresh. --- app/controllers/api/teams.php | 12 ------------ app/workers/deletes.php | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 572b6f02a8..664e9a658b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -255,18 +255,6 @@ App::delete('/v1/teams/:teamId') throw new Exception(Exception::TEAM_NOT_FOUND); } - $memberships = $dbForProject->find('memberships', [ - Query::equal('teamId', [$teamId]), - Query::limit(2000), // TODO fix members limit - ]); - - // TODO delete all members individually from the user object - foreach ($memberships as $membership) { - if (!$dbForProject->deleteDocument('memberships', $membership->getId())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership for team from DB'); - } - } - if (!$dbForProject->deleteDocument('teams', $teamId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove team from DB'); } diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 6eed3a8a40..840e77f9f8 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -8,7 +8,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; use Appwrite\Resque\Worker; -use Executor\Executor; use Utopia\Storage\Device\Local; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; @@ -296,12 +295,21 @@ class DeletesV1 extends Worker */ protected function deleteMemberships(Document $document, Document $project): void { - $teamId = $document->getAttribute('teamId', ''); + $dbForProject = $this->getProjectDB($project); + $teamInternalId = $document->getInternalId(); // Delete Memberships - $this->deleteByGroup('memberships', [ - Query::equal('teamId', [$teamId]) - ], $this->getProjectDB($project)); + $this->deleteByGroup( + 'memberships', + [ + Query::equal('teamInternalId', [$teamInternalId]) + ], + $dbForProject, + function (Document $membership) use ($dbForProject) { + $userId = $membership->getAttribute('userId'); + $dbForProject->deleteCachedDocument('users', $userId); + } + ); } /** From 308c92f203c329d38e67db79204b6ecfcc87a45d Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 17 Jul 2023 17:07:37 -0700 Subject: [PATCH 05/15] Ensure resources are deleted using their internal Id This is necessary because a resource can be re-created with the same id. If we don't use the internal id, the newer recreated resource can be deleted. --- app/workers/deletes.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 840e77f9f8..6b2522812f 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -254,6 +254,7 @@ class DeletesV1 extends Worker protected function deleteCollection(Document $document, Document $project): void { $collectionId = $document->getId(); + $collectionInternalId = $document->getInternalId(); $databaseId = $document->getAttribute('databaseId'); $databaseInternalId = $document->getAttribute('databaseInternalId'); @@ -262,13 +263,13 @@ class DeletesV1 extends Worker $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); $this->deleteByGroup('attributes', [ - Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$collectionId]) + Query::equal('databaseInternalId', [$databaseInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) ], $dbForProject); $this->deleteByGroup('indexes', [ - Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$collectionId]) + Query::equal('databaseInternalId', [$databaseInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) ], $dbForProject); $this->deleteAuditLogsByResource('database/' . $databaseId . '/collection/' . $collectionId, $project); @@ -337,19 +338,20 @@ class DeletesV1 extends Worker protected function deleteUser(Document $document, Document $project): void { $userId = $document->getId(); + $userInternalId = $document->getInternalId(); $dbForProject = $this->getProjectDB($project); // Delete all sessions of this user from the sessions table and update the sessions field of the user record $this->deleteByGroup('sessions', [ - Query::equal('userId', [$userId]) + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); $dbForProject->deleteCachedDocument('users', $userId); // Delete Memberships and decrement team membership counts $this->deleteByGroup('memberships', [ - Query::equal('userId', [$userId]) + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject, function (Document $document) use ($dbForProject) { if ($document->getAttribute('confirm')) { // Count only confirmed members $teamId = $document->getAttribute('teamId'); @@ -359,7 +361,7 @@ class DeletesV1 extends Worker 'teams', $teamId, // Ensure that total >= 0 - $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)) + $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)) ); } } @@ -367,7 +369,7 @@ class DeletesV1 extends Worker // Delete tokens $this->deleteByGroup('tokens', [ - Query::equal('userId', [$userId]) + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); } @@ -482,13 +484,14 @@ class DeletesV1 extends Worker $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); $functionId = $document->getId(); + $functionInternalId = $document->getInternalId(); /** * Delete Variables */ Console::info("Deleting variables for function " . $functionId); $this->deleteByGroup('variables', [ - Query::equal('functionId', [$functionId]) + Query::equal('functionInternalId', [$functionInternalId]) ], $dbForProject); /** From 05f314e88ce089937ab59ecf69d6873019370653 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 18 Jul 2023 10:10:56 +0000 Subject: [PATCH 06/15] fix: delete schedule document if project is deleted as well --- app/workers/deletes.php | 5 +++-- composer.lock | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 6eed3a8a40..1e31fc270f 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -147,7 +147,8 @@ class DeletesV1 extends Worker $project = $this->getConsoleDB()->getDocument('projects', $document->getAttribute('projectId')); if ($project->isEmpty()) { - Console::warning('Unable to delete schedule for function ' . $document->getAttribute('resourceId')); + $this->getConsoleDB()->deleteDocument('schedules', $document->getId()); + Console::success('Deleted schedule for deleted project ' . $document->getAttribute('projectId')); return; } @@ -155,7 +156,7 @@ class DeletesV1 extends Worker if ($function->isEmpty()) { $this->getConsoleDB()->deleteDocument('schedules', $document->getId()); - Console::success('Deleting schedule for function ' . $document->getAttribute('resourceId')); + Console::success('Deleted schedule for function ' . $document->getAttribute('resourceId')); } } ); diff --git a/composer.lock b/composer.lock index aed1b97dd5..05a58d7ad4 100644 --- a/composer.lock +++ b/composer.lock @@ -3253,16 +3253,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -3303,9 +3303,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "phar-io/manifest", @@ -3656,16 +3656,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.22.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "ec58baf7b3c7f1c81b3b00617c953249fb8cf30c" + "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/ec58baf7b3c7f1c81b3b00617c953249fb8cf30c", - "reference": "ec58baf7b3c7f1c81b3b00617c953249fb8cf30c", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/65c39594fbd8c67abfc68bb323f86447bab79cc0", + "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0", "shasum": "" }, "require": { @@ -3697,9 +3697,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.22.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.22.1" }, - "time": "2023-06-01T12:35:21+00:00" + "time": "2023-06-29T20:46:06+00:00" }, { "name": "phpunit/php-code-coverage", From c7492ee35ed1da7cb7d4aded63f95877c0428541 Mon Sep 17 00:00:00 2001 From: Steven <1477010+stnguyen90@users.noreply.github.com> Date: Wed, 19 Jul 2023 01:32:11 +0000 Subject: [PATCH 07/15] Fix a bug where the delete worker wasn't iterating over schedules --- app/workers/deletes.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 1e31fc270f..3efe9910a5 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -679,16 +679,26 @@ class DeletesV1 extends Worker $limit = 50; $results = []; $sum = $limit; + $cursor = null; $executionStart = \microtime(true); while ($sum === $limit) { $chunk++; - $results = $database->find($collection, \array_merge([Query::limit($limit)], $queries)); + $mergedQueries = \array_merge([Query::limit($limit)], $queries); + if ($cursor instanceof Document) { + $mergedQueries[] = Query::cursorAfter($cursor); + } + + $results = $database->find($collection, $mergedQueries); $sum = count($results); + if ($sum > 0) { + $cursor = $results[$sum - 1]; + } + foreach ($results as $document) { if (is_callable($callback)) { $callback($document); From f164676b4427c5ae605666f38afffb0474000b65 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:15:31 -0700 Subject: [PATCH 08/15] Fix install template paths --- src/Appwrite/Platform/Tasks/Install.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index 219a03129d..c15dddeccd 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -198,8 +198,8 @@ class Install extends Action } } - $templateForCompose = new View(__DIR__ . '/../views/install/compose.phtml'); - $templateForEnv = new View(__DIR__ . '/../views/install/env.phtml'); + $templateForCompose = new View(__DIR__ . '/../../../../app/views/install/compose.phtml'); + $templateForEnv = new View(__DIR__ . '/../../../../app/views/install/env.phtml'); $templateForCompose ->setParam('httpPort', $httpPort) From 1989ff873ec80dc2b7de05fc2bc1ad541b7be99f Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:16:36 -0700 Subject: [PATCH 09/15] Fix install analytics --- src/Appwrite/Platform/Tasks/Install.php | 27 ++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index c15dddeccd..4af3cc9d4f 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -6,7 +6,8 @@ use Appwrite\Auth\Auth; use Appwrite\Docker\Compose; use Appwrite\Docker\Env; use Appwrite\Utopia\View; -use Utopia\Analytics\GoogleAnalytics; +use Utopia\Analytics\Adapter\GoogleAnalytics; +use Utopia\Analytics\Event; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Validator\Text; @@ -215,14 +216,22 @@ class Install extends Action if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::error($message); Console::exit(1); } if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::error($message); Console::exit(1); } @@ -243,13 +252,21 @@ class Install extends Action if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::error($message); Console::error($stderr); Console::exit($exit); } else { $message = 'Appwrite installed successfully'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::success($message); } } From c32f8e49e265fb69455045fbc8977061b506ed5e Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:21:34 -0700 Subject: [PATCH 10/15] Make the install path a class property This makes it so the property can be used by subclasses. --- src/Appwrite/Platform/Tasks/Install.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index 4af3cc9d4f..f8509799b9 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -15,6 +15,8 @@ use Utopia\Platform\Action; class Install extends Action { + protected string $path = '/usr/src/code/appwrite'; + public static function getName(): string { return 'install'; @@ -51,7 +53,6 @@ class Install extends Action * 6. Run data migration */ $config = Config::getParam('variables'); - $path = '/usr/src/code/appwrite'; $defaultHTTPPort = '80'; $defaultHTTPSPort = '443'; $vars = []; @@ -71,19 +72,19 @@ class Install extends Action Console::success('Starting Appwrite installation...'); // Create directory with write permissions - if (null !== $path && !\file_exists(\dirname($path))) { - if (!@\mkdir(\dirname($path), 0755, true)) { - Console::error('Can\'t create directory ' . \dirname($path)); + if (null !== $this->path && !\file_exists(\dirname($this->path))) { + if (!@\mkdir(\dirname($this->path), 0755, true)) { + Console::error('Can\'t create directory ' . \dirname($this->path)); Console::exit(1); } } - $data = @file_get_contents($path . '/docker-compose.yml'); + $data = @file_get_contents($this->path . '/docker-compose.yml'); if ($data !== false) { $time = \time(); Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); - file_put_contents($path . '/docker-compose.yml.' . $time . '.backup', $data); + file_put_contents($this->path . '/docker-compose.yml.' . $time . '.backup', $data); $compose = new Compose($data); $appwrite = $compose->getService('appwrite'); $oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null; @@ -117,11 +118,11 @@ class Install extends Action } } - $data = @file_get_contents($path . '/.env'); + $data = @file_get_contents($this->path . '/.env'); if ($data !== false) { // Fetch all env vars from previous .env file Console::info('Env file found, creating backup: .env.' . $time . '.backup'); - file_put_contents($path . '/.env.' . $time . '.backup', $data); + file_put_contents($this->path . '/.env.' . $time . '.backup', $data); $env = new Env($data); foreach ($env->list() as $key => $value) { @@ -214,7 +215,7 @@ class Install extends Action ->setParam('vars', $input) ; - if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { + if (!file_put_contents($this->path . '/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; $event = new Event(); $event->setName(APP_VERSION_STABLE . ' - ' . $message) @@ -225,7 +226,7 @@ class Install extends Action Console::exit(1); } - if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { + if (!file_put_contents($this->path . '/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; $event = new Event(); $event->setName(APP_VERSION_STABLE . ' - ' . $message) @@ -246,9 +247,9 @@ class Install extends Action } } - Console::log("Running \"docker compose -f {$path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes\""); + Console::log("Running \"docker compose -f {$this->path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes\""); - $exit = Console::execute("${env} docker compose -f {$path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr); + $exit = Console::execute("${env} docker compose -f {$this->path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr); if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; From d8ea72b49eb865ef5ded9a6c17655ea8bc9d6783 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:34:04 -0700 Subject: [PATCH 11/15] Create a dedicated upgrade task Before, we used the same command for both installation and upgrades. This lead to problems because developers would try to upgrade in the wrong folder and end up creating a new installation. This new upgrade command validates the existence of an existing installation before proceeding with the upgrade to ensure no new installation is created when upgrading. --- bin/upgrade | 3 ++ src/Appwrite/Platform/Services/Tasks.php | 2 ++ src/Appwrite/Platform/Tasks/Upgrade.php | 42 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100755 bin/upgrade create mode 100644 src/Appwrite/Platform/Tasks/Upgrade.php diff --git a/bin/upgrade b/bin/upgrade new file mode 100755 index 0000000000..ce32b9ca30 --- /dev/null +++ b/bin/upgrade @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/cli.php upgrade $@ \ No newline at end of file diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index 10c573da42..bc8d1bbc72 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -22,6 +22,7 @@ use Appwrite\Platform\Tasks\VolumeSync; use Appwrite\Platform\Tasks\CalcUsersStats; use Appwrite\Platform\Tasks\CalcTierStats; use Appwrite\Platform\Tasks\PatchDeleteProjectCollections; +use Appwrite\Platform\Tasks\Upgrade; class Tasks extends Service { @@ -36,6 +37,7 @@ class Tasks extends Service ->addAction(Hamster::getName(), new Hamster()) ->addAction(Doctor::getName(), new Doctor()) ->addAction(Install::getName(), new Install()) + ->addAction(Upgrade::getName(), new Upgrade()) ->addAction(Maintenance::getName(), new Maintenance()) ->addAction(PatchCreateMissingSchedules::getName(), new PatchCreateMissingSchedules()) ->addAction(ClearCardCache::getName(), new ClearCardCache()) diff --git a/src/Appwrite/Platform/Tasks/Upgrade.php b/src/Appwrite/Platform/Tasks/Upgrade.php new file mode 100644 index 0000000000..e3f0458394 --- /dev/null +++ b/src/Appwrite/Platform/Tasks/Upgrade.php @@ -0,0 +1,42 @@ +desc('Upgrade Appwrite') + ->param('httpPort', '', new Text(4), 'Server HTTP port', true) + ->param('httpsPort', '', new Text(4), 'Server HTTPS port', true) + ->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true) + ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) + ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) + ->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive)); + } + + public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive): void + { + // Check for previous installation + $data = @file_get_contents($this->path . '/docker-compose.yml'); + if (empty($data)) { + Console::error('Appwrite installation not found.'); + Console::log('The command was not run in the parent folder of your appwrite installation.'); + Console::log('Please navigate to the parent directory of the Appwrite installation and try again.'); + Console::log(' parent_directory <= you run the command in this directory'); + Console::log(' └── appwrite'); + Console::log(' └── docker-compose.yml'); + Console::exit(1); + } + parent::action($httpPort, $httpsPort, $organization, $image, $interactive); + } +} From 128b9d1b1bbc2b2fd3b7f71f4b43236fa5d46357 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 25 Jul 2023 13:50:43 -0700 Subject: [PATCH 12/15] Prompt developer to confirm installing over existing install --- src/Appwrite/Platform/Tasks/Install.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index f8509799b9..051d512ec4 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -82,6 +82,15 @@ class Install extends Action $data = @file_get_contents($this->path . '/docker-compose.yml'); if ($data !== false) { + if ($interactive == 'Y' && Console::isInteractive()) { + $answer = Console::confirm('Previous installation found, do you want to overwrite it? (Y/n)'); + + if ($answer !== 'Y') { + Console::info('No action taken.'); + return; + } + } + $time = \time(); Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); file_put_contents($this->path . '/docker-compose.yml.' . $time . '.backup', $data); From 30ef106406f3c2f32c0cad3b1133bc2498ffbf84 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 2 Aug 2023 11:36:50 -0700 Subject: [PATCH 13/15] Bump console to fix missing active deployment bug --- app/console | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/console b/app/console index 104c82a0ab..59d6ebe70e 160000 --- a/app/console +++ b/app/console @@ -1 +1 @@ -Subproject commit 104c82a0abc9baf661ffb59759fcae5e05a73c5f +Subproject commit 59d6ebe70e80f1914f2f44ee31bdd318ba6e35ee From 01f55445f1efe6c9971a0f2c68c9885f8eb8cbfa Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 3 Aug 2023 19:29:01 +0400 Subject: [PATCH 14/15] feat: add new database cluster --- app/controllers/api/projects.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 4892e7418e..ec3032be4b 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -95,6 +95,7 @@ App::post('/v1/projects') $backups['database_db_fra1_03'] = ['from' => '10:30', 'to' => '11:15']; $backups['database_db_fra1_04'] = ['from' => '13:30', 'to' => '14:15']; $backups['database_db_fra1_05'] = ['from' => '4:30', 'to' => '5:15']; + $backups['database_db_fra1_06'] = ['from' => '16:30', 'to' => '17:15']; $databases = Config::getParam('pools-database', []); @@ -118,7 +119,7 @@ App::post('/v1/projects') } } - if ($index = array_search('database_db_fra1_05', $databases)) { + if ($index = array_search('database_db_fra1_06', $databases)) { $database = $databases[$index]; } else { $database = $databases[array_rand($databases)]; From 9499cbf9f7fc7be9b624ccbcfe5e8251bf853875 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Sun, 6 Aug 2023 13:59:28 +0400 Subject: [PATCH 15/15] feat: udpate console branch name --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 4a4bf6aef7..273ff83846 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "app/console"] path = app/console url = https://github.com/appwrite/console - branch = cloud-cards + branch = cloud-1.1.x