From a6768bdc32f60323b56c1248cfd1aad389fcb533 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 31 May 2023 14:41:56 +0300 Subject: [PATCH 01/99] saving file output to cache instead of decoding data to json --- app/config/collections.php | 22 ++++++++++++++++++++++ app/controllers/api/storage.php | 4 ++-- app/controllers/shared/api.php | 31 ++++++++++++------------------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 85a279faa5..e8a317697d 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3206,6 +3206,28 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => 'accessedAt', 'type' => Database::VAR_DATETIME, diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index d59d950d93..82cba1ab48 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -945,6 +945,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $data = $image->output($output, $quality); + unset($image); + $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; $response @@ -952,8 +954,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->setContentType($contentType) ->file($data) ; - - unset($image); }); App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 289fbca8f4..56fc02bbbf 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -195,28 +195,25 @@ App::init() $database->setProject($project); $dbForProject->on(Database::EVENT_DOCUMENT_CREATE, fn ($event, Document $document) => $databaseListener($event, $document, $usage)); - $dbForProject->on(Database::EVENT_DOCUMENT_DELETE, fn ($event, Document $document) => $databaseListener($event, $document, $usage)); $useCache = $route->getLabel('cache', false); - if ($useCache) { $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; + $cacheLog = $dbForProject->getDocument('cache', $key); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); $timestamp = 60 * 60 * 24 * 30; $data = $cache->load($key, $timestamp); - if (!empty($data)) { - $data = json_decode($data, true); - $parts = explode('/', $data['resourceType']); + if (!empty($data) && !empty($cacheLog)) { + $parts = explode('/', $cacheLog->getAttribute('resourceType')); $type = $parts[0] ?? null; if ($type === 'bucket') { $bucketId = $parts[1] ?? null; - - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -225,11 +222,12 @@ App::init() $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); + if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $parts = explode('/', $data['resource']); + $parts = explode('/', $cacheLog->getAttribute('resource')); $fileId = $parts[1] ?? null; if ($fileSecurity && !$valid) { @@ -246,8 +244,8 @@ App::init() $response ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT') ->addHeader('X-Appwrite-Cache', 'hit') - ->setContentType($data['contentType']) - ->send(base64_decode($data['payload'])) + ->setContentType($cacheLog->getAttribute('mimeType')) + ->send($data) ; $route->setIsActive(false); @@ -475,7 +473,6 @@ App::shutdown() if ($useCache) { $resource = $resourceType = null; $data = $response->getPayload(); - if (!empty($data['payload'])) { $pattern = $route->getLabel('cache.resource', null); if (!empty($pattern)) { @@ -488,14 +485,8 @@ App::shutdown() } $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; - $data = json_encode([ - 'resourceType' => $resourceType, - 'resource' => $resource, - 'contentType' => $response->getContentType(), - 'payload' => base64_encode($data['payload']), - ]) ; - $signature = md5($data); + $signature = md5($data['payload']); $cacheLog = $dbForProject->getDocument('cache', $key); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); $now = DateTime::now(); @@ -503,6 +494,8 @@ App::shutdown() Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, + 'resourceType' => $resourceType, + 'mimeType' => $response->getContentType(), 'accessedAt' => $now, 'signature' => $signature, ]))); @@ -515,7 +508,7 @@ App::shutdown() $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); - $cache->save($key, $data); + $cache->save($key, $data['payload']); } } } From e9fda6168c21c0db9dd2ade5a30c3f662460d2cc Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 31 May 2023 15:50:19 +0300 Subject: [PATCH 02/99] saving file output to cache instead of decoding data to json --- app/controllers/shared/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 56fc02bbbf..2e5f5f7a84 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -207,7 +207,7 @@ App::init() $timestamp = 60 * 60 * 24 * 30; $data = $cache->load($key, $timestamp); - if (!empty($data) && !empty($cacheLog)) { + if (!empty($data) && !$cacheLog->isEmpty()) { $parts = explode('/', $cacheLog->getAttribute('resourceType')); $type = $parts[0] ?? null; From 9562b952857833e758b7fcf9fcecadec4cc37e3b Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 31 May 2023 19:34:12 +0300 Subject: [PATCH 03/99] saving file output to cache instead of decoding data to json --- 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 2e5f5f7a84..e85fdeda95 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -200,7 +200,7 @@ App::init() $useCache = $route->getLabel('cache', false); if ($useCache) { $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; - $cacheLog = $dbForProject->getDocument('cache', $key); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -487,7 +487,7 @@ App::shutdown() $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; $signature = md5($data['payload']); - $cacheLog = $dbForProject->getDocument('cache', $key); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); $now = DateTime::now(); if ($cacheLog->isEmpty()) { From bed88baa6c9d565a873bf65feaab9b1bf578932d Mon Sep 17 00:00:00 2001 From: shimon Date: Sat, 22 Jul 2023 17:08:28 +0300 Subject: [PATCH 04/99] added bucketId to cache::deleteByResource --- app/controllers/api/storage.php | 9 +--- app/controllers/shared/api.php | 5 +-- app/init.php | 2 +- app/workers/deletes.php | 76 ++++++++++++++++++++++++++++----- src/Appwrite/Event/Delete.php | 14 ++++++ 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 82cba1ab48..4225b862b5 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -359,8 +359,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ->inject('mode') ->inject('deviceFiles') ->inject('deviceLocal') - ->inject('deletes') - ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal, Delete $deletes) { + ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); @@ -654,11 +653,6 @@ App::post('/v1/storage/buckets/:bucketId/files') ->setContext('bucket', $bucket) ; - $deletes - ->setType(DELETE_TYPE_CACHE_BY_RESOURCE) - ->setResource('file/' . $file->getId()) - ; - $metadata = null; // was causing leaks as it was passed by reference $response @@ -1416,6 +1410,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') if ($deviceDeleted) { $deletes ->setType(DELETE_TYPE_CACHE_BY_RESOURCE) + ->setResourceType('bucket/' . $bucket->getId()) ->setResource('file/' . $fileId) ; diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index e85fdeda95..aaae656457 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -199,7 +199,7 @@ App::init() $useCache = $route->getLabel('cache', false); if ($useCache) { - $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; + $key = md5($request->getURI() . '*' . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) @@ -484,8 +484,7 @@ App::shutdown() $resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user); } - $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; - + $key = md5($request->getURI() . '*' . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; $signature = md5($data['payload']); $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); diff --git a/app/init.php b/app/init.php index d959cf24b5..9d3ceb5fcb 100644 --- a/app/init.php +++ b/app/init.php @@ -100,7 +100,7 @@ const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate pe const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours -const APP_CACHE_BUSTER = 504; +const APP_CACHE_BUSTER = 505; const APP_VERSION_STABLE = '1.3.5'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; diff --git a/app/workers/deletes.php b/app/workers/deletes.php index f27bc4feb9..72c56ba73a 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -114,10 +114,10 @@ class DeletesV1 extends Worker break; case DELETE_TYPE_CACHE_BY_RESOURCE: - $this->deleteCacheByResource($project->getId()); + $this->deleteCacheByResource($project, $this->args['resource'], $this->args['resourceType']); break; case DELETE_TYPE_CACHE_BY_TIMESTAMP: - $this->deleteCacheByDate(); + $this->deleteCacheByDate($this->args['datetime']); break; default: Console::error('No delete operation for type: ' . $type); @@ -130,22 +130,76 @@ class DeletesV1 extends Worker } /** - * @param string $projectId + * @param Document $project + * @param string $resource + * @param string|null $resourceType + * @throws Exception */ - protected function deleteCacheByResource(string $projectId): void + protected function deleteCacheByResource(Document $project, string $resource, string $resourceType = null): void { - $this->deleteCacheFiles([ - Query::equal('resource', [$this->args['resource']]), - ]); + $projectId = $project->getId(); + $dbForProject = $this->getProjectDB($projectId); + + $cache = new Cache( + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) + ); + + $query[] = Query::equal('resource', [$resource]); + if (!empty($resourceType)) { + $query[] = Query::equal('resourceType', [$resourceType]); + } + + $this->deleteByGroup( + 'cache', + $query, + $dbForProject, + function (Document $document) use ($cache, $projectId) { + $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); + + if ($cache->purge($document->getId())) { + Console::success('Deleting cache file: ' . $path); + } else { + Console::error('Failed to delete cache file: ' . $path); + } + } + ); } - protected function deleteCacheByDate(): void + /** + * @param string $datetime + * @throws Exception + */ + protected function deleteCacheByDate(string $datetime): void { - $this->deleteCacheFiles([ - Query::lessThan('accessedAt', $this->args['datetime']), - ]); + $this->deleteForProjectIds(function (string $projectId) use ($datetime) { + + $dbForProject = $this->getProjectDB($projectId); + $cache = new Cache( + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) + ); + + $query = [ + Query::lessThan('accessedAt', $datetime), + ]; + + $this->deleteByGroup( + 'cache', + $query, + $dbForProject, + function (Document $document) use ($cache, $projectId) { + $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); + + if ($cache->purge($document->getId())) { + Console::success('Deleting cache file: ' . $path); + } else { + Console::error('Failed to delete cache file: ' . $path); + } + } + ); + }); } + protected function deleteCacheFiles($query): void { $this->deleteForProjectIds(function (string $projectId) use ($query) { diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index d1519121a6..448c27f622 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -9,6 +9,7 @@ class Delete extends Event { protected string $type = ''; protected ?Document $document = null; + protected ?string $resourceType = null; protected ?string $resource = null; protected ?string $datetime = null; protected ?string $hourlyUsageRetentionDatetime = null; @@ -102,6 +103,19 @@ class Delete extends Event return $this; } + /** + * Sets the resource type for the delete event. + * + * @param string $resourceType + * @return self + */ + public function setResourceType(string $resourceType): self + { + $this->resourceType = $resourceType; + + return $this; + } + /** * Returns the set document for the delete event. * From 2f7b0c9938e55cae647ac72651d2f91574843342 Mon Sep 17 00:00:00 2001 From: shimon Date: Sat, 22 Jul 2023 17:31:33 +0300 Subject: [PATCH 05/99] added bucketId to cache::deleteByResource --- src/Appwrite/Event/Delete.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index 448c27f622..cca38d29db 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -140,6 +140,7 @@ class Delete extends Event 'type' => $this->type, 'document' => $this->document, 'resource' => $this->resource, + 'resourceType' => $this->resourceType, 'datetime' => $this->datetime, 'hourlyUsageRetentionDatetime' => $this->hourlyUsageRetentionDatetime, ]); From 45f16e560c2916dbb1586187d3c1efd6054c36eb Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 5 Sep 2023 21:17:54 +0300 Subject: [PATCH 06/99] sync against master --- app/config/collections.php | 4 +- app/controllers/api/storage.php | 4 +- app/controllers/shared/api.php | 2 - app/workers/deletes.php | 41 +------- composer.lock | 165 ++++++++++---------------------- 5 files changed, 56 insertions(+), 160 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 5273edac1f..483d8247e5 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -4504,8 +4504,8 @@ $consoleCollections = array_merge([ 'filters' => [], ], [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index b0f7fc0277..c42c85c11d 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -970,8 +970,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $data = $image->output($output, $quality); - unset($image); - $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; $response @@ -979,6 +977,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->setContentType($contentType) ->file($data) ; + + unset($image); }); App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 1c809c78ea..030faf95b0 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -253,8 +253,6 @@ App::init() ->setContentType($cacheLog->getAttribute('mimeType')) ->send($data) ; - - $route->setIsActive(false); } else { $response->addHeader('X-Appwrite-Cache', 'miss'); } diff --git a/app/workers/deletes.php b/app/workers/deletes.php index cdd39128bf..c0b2e5eada 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -123,6 +123,9 @@ class DeletesV1 extends Worker case DELETE_TYPE_CACHE_BY_TIMESTAMP: $this->deleteCacheByDate($this->args['datetime']); break; + case DELETE_TYPE_SCHEDULES: + $this->deleteSchedules($this->args['datetime']); + break; default: Console::error('No delete operation for type: ' . $type); break; @@ -175,7 +178,7 @@ class DeletesV1 extends Worker protected function deleteCacheByResource(Document $project, string $resource, string $resourceType = null): void { $projectId = $project->getId(); - $dbForProject = $this->getProjectDB($projectId); + $dbForProject = $this->getProjectDB($project); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) @@ -202,41 +205,6 @@ class DeletesV1 extends Worker ); } - /** - * @param string $datetime - * @throws Exception - */ - protected function deleteCacheByDate(string $datetime): void - { - $this->deleteForProjectIds(function (string $projectId) use ($datetime) { - - $dbForProject = $this->getProjectDB($projectId); - $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) - ); - - $query = [ - Query::lessThan('accessedAt', $datetime), - ]; - - $this->deleteByGroup( - 'cache', - $query, - $dbForProject, - function (Document $document) use ($cache, $projectId) { - $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); - - if ($cache->purge($document->getId())) { - Console::success('Deleting cache file: ' . $path); - } else { - Console::error('Failed to delete cache file: ' . $path); - } - } - ); - }); - } - - /** * @param string $datetime * @throws Exception @@ -271,7 +239,6 @@ class DeletesV1 extends Worker }); } - /** * @param Document $document database document * @param Document $project diff --git a/composer.lock b/composer.lock index 8a3bf6d014..2989168afe 100644 --- a/composer.lock +++ b/composer.lock @@ -386,79 +386,6 @@ }, "time": "2023-04-18T15:34:23+00:00" }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, { "name": "dragonmantank/cron-expression", "version": "v3.3.2", @@ -914,24 +841,28 @@ }, { "name": "jean85/pretty-package-versions", - "version": "1.6.0", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "1e0104b46f045868f11942aea058cd7186d6c303" + "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/1e0104b46f045868f11942aea058cd7186d6c303", - "reference": "1e0104b46f045868f11942aea058cd7186d6c303", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af", "shasum": "" }, "require": { - "composer/package-versions-deprecated": "^1.8.0", - "php": "^7.0|^8.0" + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.0|^8.5|^9.2" + "friendsofphp/php-cs-fixer": "^2.17", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^0.12.66", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" }, "type": "library", "extra": { @@ -954,7 +885,7 @@ "email": "alessandro.lai85@gmail.com" } ], - "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "description": "A library to get pretty versions strings of installed dependencies", "keywords": [ "composer", "package", @@ -963,9 +894,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/1.6.0" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" }, - "time": "2021-02-04T16:20:16+00:00" + "time": "2021-10-08T21:21:46+00:00" }, { "name": "laravel/pint", @@ -1188,34 +1119,35 @@ }, { "name": "mongodb/mongodb", - "version": "1.8.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/mongodb/mongo-php-library.git", - "reference": "953dbc19443aa9314c44b7217a16873347e6840d" + "reference": "b0bbd657f84219212487d01a8ffe93a789e1e488" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/953dbc19443aa9314c44b7217a16873347e6840d", - "reference": "953dbc19443aa9314c44b7217a16873347e6840d", + "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/b0bbd657f84219212487d01a8ffe93a789e1e488", + "reference": "b0bbd657f84219212487d01a8ffe93a789e1e488", "shasum": "" }, "require": { "ext-hash": "*", "ext-json": "*", - "ext-mongodb": "^1.8.1", - "jean85/pretty-package-versions": "^1.2", - "php": "^7.0 || ^8.0", + "ext-mongodb": "^1.11.0", + "jean85/pretty-package-versions": "^1.2 || ^2.0.1", + "php": "^7.1 || ^8.0", "symfony/polyfill-php80": "^1.19" }, "require-dev": { - "squizlabs/php_codesniffer": "^3.5, <3.5.5", - "symfony/phpunit-bridge": "5.x-dev" + "doctrine/coding-standard": "^9.0", + "squizlabs/php_codesniffer": "^3.6", + "symfony/phpunit-bridge": "^5.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { @@ -1250,9 +1182,9 @@ ], "support": { "issues": "https://github.com/mongodb/mongo-php-library/issues", - "source": "https://github.com/mongodb/mongo-php-library/tree/1.8.0" + "source": "https://github.com/mongodb/mongo-php-library/tree/1.10.0" }, - "time": "2020-11-25T12:26:02+00:00" + "time": "2021-10-20T22:22:37+00:00" }, { "name": "mustangostang/spyc", @@ -2220,16 +2152,16 @@ }, { "name": "utopia-php/database", - "version": "0.43.0", + "version": "0.43.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "fb96fc6c94d5efcd43913c34bece62daba76a5e9" + "reference": "cc0247f4f0c402b39f663bf9f77b29d69b95f9d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/fb96fc6c94d5efcd43913c34bece62daba76a5e9", - "reference": "fb96fc6c94d5efcd43913c34bece62daba76a5e9", + "url": "https://api.github.com/repos/utopia-php/database/zipball/cc0247f4f0c402b39f663bf9f77b29d69b95f9d6", + "reference": "cc0247f4f0c402b39f663bf9f77b29d69b95f9d6", "shasum": "" }, "require": { @@ -2238,12 +2170,11 @@ "php": ">=8.0", "utopia-php/cache": "0.8.*", "utopia-php/framework": "0.*.*", - "utopia-php/mongo": "0.2.*" + "utopia-php/mongo": "0.3.*" }, "require-dev": { "fakerphp/faker": "^1.14", "laravel/pint": "1.4.*", - "mongodb/mongodb": "1.8.0", "pcov/clobber": "^2.0", "phpstan/phpstan": "1.10.*", "phpunit/phpunit": "^9.4", @@ -2271,9 +2202,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.43.0" + "source": "https://github.com/utopia-php/database/tree/0.43.1" }, - "time": "2023-08-29T10:18:39+00:00" + "time": "2023-09-01T20:38:36+00:00" }, { "name": "utopia-php/domains", @@ -2691,21 +2622,21 @@ }, { "name": "utopia-php/mongo", - "version": "0.2.0", + "version": "0.3.1", "source": { "type": "git", "url": "https://github.com/utopia-php/mongo.git", - "reference": "b6dfb31b93c07c59b8bbd62a3b52e3b97a407c09" + "reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/mongo/zipball/b6dfb31b93c07c59b8bbd62a3b52e3b97a407c09", - "reference": "b6dfb31b93c07c59b8bbd62a3b52e3b97a407c09", + "url": "https://api.github.com/repos/utopia-php/mongo/zipball/52326a9a43e2d27ff0c15c48ba746dacbe9a7aee", + "reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee", "shasum": "" }, "require": { "ext-mongodb": "*", - "mongodb/mongodb": "1.8.0", + "mongodb/mongodb": "1.10.0", "php": ">=8.0" }, "require-dev": { @@ -2745,9 +2676,9 @@ ], "support": { "issues": "https://github.com/utopia-php/mongo/issues", - "source": "https://github.com/utopia-php/mongo/tree/0.2.0" + "source": "https://github.com/utopia-php/mongo/tree/0.3.1" }, - "time": "2023-03-22T10:44:29+00:00" + "time": "2023-09-01T17:25:28+00:00" }, { "name": "utopia-php/orchestration", @@ -3460,16 +3391,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.34.1", + "version": "0.34.2", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "81538d10abacd81350c265b516c72ef315116013" + "reference": "06ea25aace27790e42d57fdbc7ccf97e0b31a6ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/81538d10abacd81350c265b516c72ef315116013", - "reference": "81538d10abacd81350c265b516c72ef315116013", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/06ea25aace27790e42d57fdbc7ccf97e0b31a6ba", + "reference": "06ea25aace27790e42d57fdbc7ccf97e0b31a6ba", "shasum": "" }, "require": { @@ -3505,9 +3436,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.34.1" + "source": "https://github.com/appwrite/sdk-generator/tree/0.34.2" }, - "time": "2023-08-30T07:57:31+00:00" + "time": "2023-08-31T14:10:33+00:00" }, { "name": "doctrine/deprecations", @@ -6096,5 +6027,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } From 93fa7496b180f56a82d58d7230c3c46214795e51 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Fri, 6 Oct 2023 18:10:24 +0530 Subject: [PATCH 07/99] Update GETTING_STARTED.md Fixed the issue mentioned in sdk-for-python repository Issue - 62. Issue link - https://github.com/appwrite/sdk-for-python/issues/62 --- docs/sdks/python/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/python/GETTING_STARTED.md b/docs/sdks/python/GETTING_STARTED.md index 9f693b65c6..86d1bdf1dc 100644 --- a/docs/sdks/python/GETTING_STARTED.md +++ b/docs/sdks/python/GETTING_STARTED.md @@ -23,7 +23,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```python users = Users(client) -result = users.create('[USER_ID]', 'email@example.com', 'password') +result = users.create(ID.unique(), email = 'email1@example.com', phone = '+123456789', password = 'password', name = 'user1') ``` ### Full Example @@ -43,7 +43,7 @@ client = Client() users = Users(client) -result = users.create(ID.unique(), 'email@example.com', 'password') +result = users.create(ID.unique(), email = 'email1@example.com', phone = '+123456789', password = 'password', name = 'user1') ``` ### Error Handling @@ -52,7 +52,7 @@ The Appwrite Python SDK raises `AppwriteException` object with `message`, `code` ```python users = Users(client) try: - result = users.create(ID.unique(), 'email@example.com', 'password') + result = users.create(ID.unique(), email = 'email1@example.com', phone = '+123456789', password = 'password', name = 'user1') except AppwriteException as e: print(e.message) ``` From 9ccaa5a883ebc1b0fb1ac0f0a836a8b97c16f502 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Wed, 11 Oct 2023 18:14:12 +0530 Subject: [PATCH 08/99] Update GETTING_STARTED.md Changed user1 name and (email1 -> email). --- docs/sdks/python/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/python/GETTING_STARTED.md b/docs/sdks/python/GETTING_STARTED.md index 86d1bdf1dc..eed858e3ef 100644 --- a/docs/sdks/python/GETTING_STARTED.md +++ b/docs/sdks/python/GETTING_STARTED.md @@ -23,7 +23,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```python users = Users(client) -result = users.create(ID.unique(), email = 'email1@example.com', phone = '+123456789', password = 'password', name = 'user1') +result = users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") ``` ### Full Example @@ -43,7 +43,7 @@ client = Client() users = Users(client) -result = users.create(ID.unique(), email = 'email1@example.com', phone = '+123456789', password = 'password', name = 'user1') +result = users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") ``` ### Error Handling @@ -52,7 +52,7 @@ The Appwrite Python SDK raises `AppwriteException` object with `message`, `code` ```python users = Users(client) try: - result = users.create(ID.unique(), email = 'email1@example.com', phone = '+123456789', password = 'password', name = 'user1') + result = users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") except AppwriteException as e: print(e.message) ``` From 8cc1c0d6dc84b447107126e829141b18326eff58 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:07:53 +0530 Subject: [PATCH 09/99] Update android GETTING_STARTED.md --- docs/sdks/android/GETTING_STARTED.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/sdks/android/GETTING_STARTED.md b/docs/sdks/android/GETTING_STARTED.md index 684f98e0f6..04139817ba 100644 --- a/docs/sdks/android/GETTING_STARTED.md +++ b/docs/sdks/android/GETTING_STARTED.md @@ -52,8 +52,10 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos val account = Account(client) val response = account.create( ID.unique(), - "email@example.com", - "password" + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) ``` @@ -72,8 +74,10 @@ val client = Client(context) val account = Account(client) val user = account.create( ID.unique(), - "email@example.com", - "password" + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) ``` @@ -82,7 +86,7 @@ The Appwrite Android SDK raises an `AppwriteException` object with `message`, `c ```kotlin try { - var user = account.create(ID.unique(), "email@example.com", "password") + var user = account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") Log.d("Appwrite user", user.toMap()) } catch(e : AppwriteException) { e.printStackTrace() @@ -94,4 +98,4 @@ You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-android) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) -- 🚂 [Appwrite Android Playground](https://github.com/appwrite/playground-for-android) \ No newline at end of file +- 🚂 [Appwrite Android Playground](https://github.com/appwrite/playground-for-android) From 4be8be13533d52498e8597935c8635a08be4fc37 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:14:26 +0530 Subject: [PATCH 10/99] Update apple GETTING_STARTED.md --- docs/sdks/apple/GETTING_STARTED.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/sdks/apple/GETTING_STARTED.md b/docs/sdks/apple/GETTING_STARTED.md index e62f1ce3fa..e90e539646 100644 --- a/docs/sdks/apple/GETTING_STARTED.md +++ b/docs/sdks/apple/GETTING_STARTED.md @@ -75,9 +75,11 @@ let account = Account(client) do { let user = try await account.create( - userId: ID.unique(), - email: "email@example.com", - password: "password" + ID.unique(), + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) print(String(describing: user.toMap())) } catch { @@ -100,9 +102,11 @@ func main() { do { let user = try await account.create( - userId: ID.unique(), - email: "email@example.com", - password: "password" + ID.unique(), + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) print(String(describing: account.toMap())) } catch { From 777c8dd587902b22b5655653a604dd1e3e15aa20 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:18:01 +0530 Subject: [PATCH 11/99] Update dart GETTING_STARTED.md --- docs/sdks/dart/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/dart/GETTING_STARTED.md b/docs/sdks/dart/GETTING_STARTED.md index 559c0894a3..be58c77e82 100644 --- a/docs/sdks/dart/GETTING_STARTED.md +++ b/docs/sdks/dart/GETTING_STARTED.md @@ -16,7 +16,7 @@ void main() async { Users users = Users(client); try { - final user = await users.create(userId: ID.unique(), email: ‘email@example.com’,password: ‘password’, name: ‘name’); + final user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { print(e.message); @@ -31,7 +31,7 @@ The Appwrite Dart SDK raises `AppwriteException` object with `message`, `code` a Users users = Users(client); try { - final user = await users.create(userId: ID.unique(), email: ‘email@example.com’,password: ‘password’, name: ‘name’); + final user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From b334f2e3459bd68136d6e534da468f481588b9c3 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:19:54 +0530 Subject: [PATCH 12/99] Update deno GETTING_STARTED.md --- docs/sdks/deno/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/deno/GETTING_STARTED.md b/docs/sdks/deno/GETTING_STARTED.md index 6546719a61..a660f871e1 100644 --- a/docs/sdks/deno/GETTING_STARTED.md +++ b/docs/sdks/deno/GETTING_STARTED.md @@ -21,7 +21,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```typescript let users = new sdk.Users(client); -let user = await users.create(ID.unique(), 'email@example.com', 'password'); +let user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); console.log(user); ``` @@ -39,7 +39,7 @@ client .setSelfSigned() // Use only on dev mode with a self-signed SSL cert ; -let user = await users.create(ID.unique(), 'email@example.com', 'password'); +let user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); console.log(user); ``` @@ -50,7 +50,7 @@ The Appwrite Deno SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let user = await users.create(ID.unique(), 'email@example.com', 'password'); + let user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); } catch(e) { console.log(e.message); } From 0587aec6430d71ba4d4d197e20b2e3a7b74caab5 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:22:16 +0530 Subject: [PATCH 13/99] Update dotnet GETTING_STARTED.md --- docs/sdks/dotnet/GETTING_STARTED.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/sdks/dotnet/GETTING_STARTED.md b/docs/sdks/dotnet/GETTING_STARTED.md index 08d7742dd0..85dbfd8d28 100644 --- a/docs/sdks/dotnet/GETTING_STARTED.md +++ b/docs/sdks/dotnet/GETTING_STARTED.md @@ -16,10 +16,11 @@ var client = new Client() var users = new Users(client); var user = await users.Create( - userId: ID.Unique(), - email: "email@example.com", - password: "password", - name: "name"); + ID.unique(), + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien"); Console.WriteLine(user.ToMap()); ``` @@ -33,10 +34,11 @@ var users = new Users(client); try { var user = await users.Create( - userId: ID.Unique(), - email: "email@example.com", - password: "password", - name: "name"); + ID.unique(), + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien"); } catch (AppwriteException e) { From 613a7331692f99710f3444fa93854ea2fa49b49e Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:25:54 +0530 Subject: [PATCH 14/99] Update dart EXAMPLES.md --- docs/sdks/dart/EXAMPLES.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/sdks/dart/EXAMPLES.md b/docs/sdks/dart/EXAMPLES.md index 208cc7f782..e062b8dc32 100644 --- a/docs/sdks/dart/EXAMPLES.md +++ b/docs/sdks/dart/EXAMPLES.md @@ -18,9 +18,11 @@ Create a new user: Users users = Users(client); User result = await users.create( - userId: '[USER_ID]', - email: 'email@example.com', - password: 'password', + ID.unique(), + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ); ``` @@ -57,4 +59,4 @@ storage.createFile( }); ``` -All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs) \ No newline at end of file +All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs) From 2c3b860e63c8b048fbfd2fad39fccd59102825f4 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:28:09 +0530 Subject: [PATCH 15/99] Update flutter-dev EXAMPLES.md --- docs/sdks/flutter-dev/EXAMPLES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/flutter-dev/EXAMPLES.md b/docs/sdks/flutter-dev/EXAMPLES.md index 23b631900f..57f6e88873 100644 --- a/docs/sdks/flutter-dev/EXAMPLES.md +++ b/docs/sdks/flutter-dev/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(userId: '[USER_ID]', email: 'me@appwrite.io', password: 'password', name: 'My Name'); +final user = await account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); @@ -60,4 +60,4 @@ storage.createFile( }); ``` -All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs) \ No newline at end of file +All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs) From 006d4237f546786f74d1ccb0e547f236d59ef685 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:30:16 +0530 Subject: [PATCH 16/99] Update flutter GETTING_STARTED.md --- docs/sdks/flutter/GETTING_STARTED.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 110ee3eb4a..70d8db58a5 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -105,10 +105,7 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos Account account = Account(client); final user = await account .create( - userId: ID.unique(), - email: 'me@appwrite.io', - password: 'password', - name: 'My Name' + ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" ); ``` @@ -133,10 +130,7 @@ void main() { final user = await account .create( - userId: ID.unique(), - email: 'me@appwrite.io', - password: 'password', - name: 'My Name' + ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" ); } ``` @@ -148,7 +142,7 @@ The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `type Account account = Account(client); try { - final user = await account.create(userId: ID.unique(), email: ‘email@example.com’,password: ‘password’, name: ‘name’); + final user = await account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From 0d314df5612294b21f8de6d1d9858696cbf7e9e1 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:31:20 +0530 Subject: [PATCH 17/99] Update flutter EXAMPLES.md --- docs/sdks/flutter/EXAMPLES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/flutter/EXAMPLES.md b/docs/sdks/flutter/EXAMPLES.md index 23b631900f..57f6e88873 100644 --- a/docs/sdks/flutter/EXAMPLES.md +++ b/docs/sdks/flutter/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(userId: '[USER_ID]', email: 'me@appwrite.io', password: 'password', name: 'My Name'); +final user = await account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); @@ -60,4 +60,4 @@ storage.createFile( }); ``` -All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs) \ No newline at end of file +All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs) From 7d2b4503e3274dfd934e10a280836fbac101826c Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:34:32 +0530 Subject: [PATCH 18/99] Update kotlin GETTING_STARTED.md --- docs/sdks/kotlin/GETTING_STARTED.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/sdks/kotlin/GETTING_STARTED.md b/docs/sdks/kotlin/GETTING_STARTED.md index 99d5e719af..ab449e088a 100644 --- a/docs/sdks/kotlin/GETTING_STARTED.md +++ b/docs/sdks/kotlin/GETTING_STARTED.md @@ -25,8 +25,10 @@ Once your SDK object is set, create any of the Appwrite service objects and choo val users = Users(client) val user = users.create( user = ID.unique(), - email = "email@example.com", - password = "password", + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) ``` @@ -47,8 +49,10 @@ suspend fun main() { val users = Users(client) val user = users.create( user = ID.unique(), - email = "email@example.com", - password = "password", + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) } ``` @@ -67,8 +71,10 @@ suspend fun main() { try { val user = users.create( user = ID.unique(), - email = "email@example.com", - password = "password", + email = 'email@example.com', + phone = '+123456789', + password = 'password', + name = "Walter O'Brien" ) } catch (e: AppwriteException) { e.printStackTrace() From e93681afc0113abe94105ee50c56234a8b84a907 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:36:49 +0530 Subject: [PATCH 19/99] Update nodejs GETTING_STARTED.md --- docs/sdks/nodejs/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/nodejs/GETTING_STARTED.md b/docs/sdks/nodejs/GETTING_STARTED.md index 985648d3fd..93b8482bc6 100644 --- a/docs/sdks/nodejs/GETTING_STARTED.md +++ b/docs/sdks/nodejs/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```js let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), 'email@example.com', undefined, 'password', 'Jane Doe'); +let promise = users.create(sdk.ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -45,7 +45,7 @@ client ; let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), 'email@example.com', undefined, 'password', 'Jane Doe'); +let promise = users.create(sdk.ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -61,7 +61,7 @@ The Appwrite Node SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let res = await users.create(sdk.ID.unique(), 'email@example.com', 'password'); + let res = await users.create(sdk.ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); } catch(e) { console.log(e.message); } From 086116d0f0821fd792a1f46f3a67c3fcbc8b68ee Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:43:09 +0530 Subject: [PATCH 20/99] Update php GETTING_STARTED.md --- docs/sdks/php/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/php/GETTING_STARTED.md b/docs/sdks/php/GETTING_STARTED.md index faa3dcf654..dc3bcfe059 100644 --- a/docs/sdks/php/GETTING_STARTED.md +++ b/docs/sdks/php/GETTING_STARTED.md @@ -20,7 +20,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```php $users = new Users($client); -$user = $users->create(ID::unique(), 'email@example.com', 'password'); +$user = $users->create(ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); ``` ### Full Example @@ -40,7 +40,7 @@ $client $users = new Users($client); -$user = $users->create(ID::unique(), 'email@example.com', 'password'); +$user = $users->create(ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); ``` ### Error Handling @@ -49,7 +49,7 @@ The Appwrite PHP SDK raises `AppwriteException` object with `message`, `code` an ```php $users = new Users($client); try { - $user = $users->create(ID::unique(), 'email@example.com', 'password'); + $user = $users->create(ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); } catch(AppwriteException $error) { echo $error->message; } From acc408f5ab8167c8f06dfc13915f6a332bebecb8 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:45:54 +0530 Subject: [PATCH 21/99] Update ruby GETTING_STARTED.md --- docs/sdks/ruby/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/ruby/GETTING_STARTED.md b/docs/sdks/ruby/GETTING_STARTED.md index da10e1aebc..3c9596148c 100644 --- a/docs/sdks/ruby/GETTING_STARTED.md +++ b/docs/sdks/ruby/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```ruby users = Appwrite::Users.new(client); -user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', password: 'password'); +user = users.create(userId: Appwrite::ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); ``` ### Full Example @@ -40,7 +40,7 @@ client users = Appwrite::Users.new(client); -user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', password: 'password'); +user = users.create(userId: Appwrite::ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); ``` ### Error Handling @@ -50,7 +50,7 @@ The Appwrite Ruby SDK raises `Appwrite::Exception` object with `message`, `code` users = Appwrite::Users.new(client); begin - user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', password: 'password'); + user = users.create(userId: Appwrite::ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); rescue Appwrite::Exception => error puts error.message end From 303212fba8af4ab40221373d6108779befe1ff90 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:47:43 +0530 Subject: [PATCH 22/99] Update swift GETTING_STARTED.md --- docs/sdks/swift/GETTING_STARTED.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/sdks/swift/GETTING_STARTED.md b/docs/sdks/swift/GETTING_STARTED.md index e0fb45dd7d..69174c22d6 100644 --- a/docs/sdks/swift/GETTING_STARTED.md +++ b/docs/sdks/swift/GETTING_STARTED.md @@ -25,9 +25,7 @@ let users = Users(client) do { let user = try await users.create( - userId: ID.unique(), - email: "email@example.com", - password: "password" + userId = ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" ) print(String(describing: user.toMap())) } catch { @@ -51,9 +49,7 @@ func main() { do { let user = try await users.create( - userId: ID.unique(), - email: "email@example.com", - password: "password" + userId = ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" ) print(String(describing: user.toMap())) } catch { From bb9dd4423d696d6c232cb6b64f04336a70a76827 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:49:47 +0530 Subject: [PATCH 23/99] Update web GETTING_STARTED.md --- docs/sdks/web/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/web/GETTING_STARTED.md b/docs/sdks/web/GETTING_STARTED.md index 445a362c05..26c73ed50b 100644 --- a/docs/sdks/web/GETTING_STARTED.md +++ b/docs/sdks/web/GETTING_STARTED.md @@ -25,7 +25,7 @@ Once your SDK object is set, access any of the Appwrite services and choose any const account = new Account(client); // Register User -account.create(ID.unique(), 'me@example.com', 'password', 'Jane Doe') +account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { @@ -47,7 +47,7 @@ client const account = new Account(client); // Register User -account.create(ID.unique(), 'me@example.com', 'password', 'Jane Doe') +account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { From 4b7c13d3e25b0ced809889ddf9fa9331a340a283 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:02:37 +0530 Subject: [PATCH 24/99] changes made android GETTING_STARTED.md --- docs/sdks/android/GETTING_STARTED.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/sdks/android/GETTING_STARTED.md b/docs/sdks/android/GETTING_STARTED.md index 04139817ba..d324ca2d89 100644 --- a/docs/sdks/android/GETTING_STARTED.md +++ b/docs/sdks/android/GETTING_STARTED.md @@ -52,10 +52,10 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos val account = Account(client) val response = account.create( ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien" + 'email@example.com', + '+123456789', + 'password', + "Walter O'Brien" ) ``` @@ -74,10 +74,10 @@ val client = Client(context) val account = Account(client) val user = account.create( ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien" + 'email@example.com', + '+123456789', + 'password', + "Walter O'Brien" ) ``` @@ -86,7 +86,7 @@ The Appwrite Android SDK raises an `AppwriteException` object with `message`, `c ```kotlin try { - var user = account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") + var user = account.create(ID.unique(),'email@example.com','+123456789','password',"Walter O'Brien") Log.d("Appwrite user", user.toMap()) } catch(e : AppwriteException) { e.printStackTrace() From af87c24cfd355709c4964e7de1726bba26cc3b38 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:06:43 +0530 Subject: [PATCH 25/99] changes made apple GETTING_STARTED.md --- docs/sdks/apple/GETTING_STARTED.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/sdks/apple/GETTING_STARTED.md b/docs/sdks/apple/GETTING_STARTED.md index e90e539646..7c8b5b9d6f 100644 --- a/docs/sdks/apple/GETTING_STARTED.md +++ b/docs/sdks/apple/GETTING_STARTED.md @@ -75,11 +75,11 @@ let account = Account(client) do { let user = try await account.create( - ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien" + userId: ID.unique(), + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien" ) print(String(describing: user.toMap())) } catch { @@ -102,11 +102,11 @@ func main() { do { let user = try await account.create( - ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien" + userId: ID.unique(), + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien" ) print(String(describing: account.toMap())) } catch { From 7721f29d0e8a0879c5fa844f0b77d9701237a99a Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:09:33 +0530 Subject: [PATCH 26/99] changes made dart GETTING_STARTED.md --- docs/sdks/dart/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/dart/GETTING_STARTED.md b/docs/sdks/dart/GETTING_STARTED.md index be58c77e82..83f1f9e8ff 100644 --- a/docs/sdks/dart/GETTING_STARTED.md +++ b/docs/sdks/dart/GETTING_STARTED.md @@ -16,7 +16,7 @@ void main() async { Users users = Users(client); try { - final user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + final user = await users.create(userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { print(e.message); @@ -31,7 +31,7 @@ The Appwrite Dart SDK raises `AppwriteException` object with `message`, `code` a Users users = Users(client); try { - final user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + final user = await users.create(userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From 2d123f60e1f08bd45b3f3cc69253e180abf5d91a Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:12:29 +0530 Subject: [PATCH 27/99] changes made dart EXAMPLES.md --- docs/sdks/dart/EXAMPLES.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/sdks/dart/EXAMPLES.md b/docs/sdks/dart/EXAMPLES.md index e062b8dc32..10150f3ca2 100644 --- a/docs/sdks/dart/EXAMPLES.md +++ b/docs/sdks/dart/EXAMPLES.md @@ -18,11 +18,11 @@ Create a new user: Users users = Users(client); User result = await users.create( - ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien" + userId: '[USER_ID]', + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien" ); ``` From ec17284bfd1af505e44795b8f195b5dff08105f4 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:15:42 +0530 Subject: [PATCH 28/99] changes made deno GETTING_STARTED.md --- docs/sdks/deno/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/deno/GETTING_STARTED.md b/docs/sdks/deno/GETTING_STARTED.md index a660f871e1..fb56f493f3 100644 --- a/docs/sdks/deno/GETTING_STARTED.md +++ b/docs/sdks/deno/GETTING_STARTED.md @@ -21,7 +21,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```typescript let users = new sdk.Users(client); -let user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +let user = await users.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); console.log(user); ``` @@ -39,7 +39,7 @@ client .setSelfSigned() // Use only on dev mode with a self-signed SSL cert ; -let user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +let user = await users.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); console.log(user); ``` @@ -50,7 +50,7 @@ The Appwrite Deno SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let user = await users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + let user = await users.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); } catch(e) { console.log(e.message); } From 8ac7aca2a4394d786b8c10de59fdb76498d1d6af Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:19:02 +0530 Subject: [PATCH 29/99] changes made dotnet GETTING_STARTED.md --- docs/sdks/dotnet/GETTING_STARTED.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/sdks/dotnet/GETTING_STARTED.md b/docs/sdks/dotnet/GETTING_STARTED.md index 85dbfd8d28..b46e6294fe 100644 --- a/docs/sdks/dotnet/GETTING_STARTED.md +++ b/docs/sdks/dotnet/GETTING_STARTED.md @@ -16,11 +16,11 @@ var client = new Client() var users = new Users(client); var user = await users.Create( - ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien"); + userId: ID.unique(), + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien"); Console.WriteLine(user.ToMap()); ``` @@ -34,11 +34,11 @@ var users = new Users(client); try { var user = await users.Create( - ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', - name = "Walter O'Brien"); + userId: ID.unique(), + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien"); } catch (AppwriteException e) { From e920c1f8b466471b8b2d7518c2a67e64fb870efb Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:21:19 +0530 Subject: [PATCH 30/99] changes made flutter-dev EXAMPLES.md --- docs/sdks/flutter-dev/EXAMPLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdks/flutter-dev/EXAMPLES.md b/docs/sdks/flutter-dev/EXAMPLES.md index 57f6e88873..ce3ab6a169 100644 --- a/docs/sdks/flutter-dev/EXAMPLES.md +++ b/docs/sdks/flutter-dev/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +final user = await account.create(userId: '[USER_ID]', email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); From ba8cafbd4529f573821a6c4dcfd0e7276abed781 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:25:00 +0530 Subject: [PATCH 31/99] changes made flutter GETTING_STARTED.md --- docs/sdks/flutter/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 70d8db58a5..49767d9951 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -105,7 +105,7 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos Account account = Account(client); final user = await account .create( - ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" + userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien" ); ``` @@ -130,7 +130,7 @@ void main() { final user = await account .create( - ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" + userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien" ); } ``` @@ -142,7 +142,7 @@ The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `type Account account = Account(client); try { - final user = await account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + final user = await account.create(userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From e6b0d22e07c41d392ec91a566ca0170823f1cfae Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:26:57 +0530 Subject: [PATCH 32/99] changes made flutter EXAMPLES.md --- docs/sdks/flutter/EXAMPLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdks/flutter/EXAMPLES.md b/docs/sdks/flutter/EXAMPLES.md index 57f6e88873..ce3ab6a169 100644 --- a/docs/sdks/flutter/EXAMPLES.md +++ b/docs/sdks/flutter/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +final user = await account.create(userId: '[USER_ID]', email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); From 2cce14418c1a7c73d6349aa5f362590c222755fe Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:37:53 +0530 Subject: [PATCH 33/99] changes made nodejs GETTING_STARTED.md --- docs/sdks/nodejs/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/nodejs/GETTING_STARTED.md b/docs/sdks/nodejs/GETTING_STARTED.md index 93b8482bc6..6bfeb5511d 100644 --- a/docs/sdks/nodejs/GETTING_STARTED.md +++ b/docs/sdks/nodejs/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```js let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +let promise = users.create(sdk.ID.unique(), 'email@example.com', undefined, '+123456789', 'password', "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -45,7 +45,7 @@ client ; let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +let promise = users.create(sdk.ID.unique(), 'email@example.com', undefined, '+123456789', 'password', "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -61,7 +61,7 @@ The Appwrite Node SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let res = await users.create(sdk.ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + let res = await users.create(sdk.ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); } catch(e) { console.log(e.message); } From d37bfa0a5ee6e0651eda098ea0e7a550593fc39c Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:41:10 +0530 Subject: [PATCH 34/99] changes made php GETTING_STARTED.md --- docs/sdks/php/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/php/GETTING_STARTED.md b/docs/sdks/php/GETTING_STARTED.md index dc3bcfe059..ddd34ff4fa 100644 --- a/docs/sdks/php/GETTING_STARTED.md +++ b/docs/sdks/php/GETTING_STARTED.md @@ -20,7 +20,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```php $users = new Users($client); -$user = $users->create(ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +$user = $users->create(ID::unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); ``` ### Full Example @@ -40,7 +40,7 @@ $client $users = new Users($client); -$user = $users->create(ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +$user = $users->create(ID::unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); ``` ### Error Handling @@ -49,7 +49,7 @@ The Appwrite PHP SDK raises `AppwriteException` object with `message`, `code` an ```php $users = new Users($client); try { - $user = $users->create(ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + $user = $users->create(ID::unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); } catch(AppwriteException $error) { echo $error->message; } From 5138d4c0f9001033b0bb31fa2fa5d156bf50f48e Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:45:24 +0530 Subject: [PATCH 35/99] changes made ruby GETTING_STARTED.md --- docs/sdks/ruby/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/ruby/GETTING_STARTED.md b/docs/sdks/ruby/GETTING_STARTED.md index 3c9596148c..e41b691a53 100644 --- a/docs/sdks/ruby/GETTING_STARTED.md +++ b/docs/sdks/ruby/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```ruby users = Appwrite::Users.new(client); -user = users.create(userId: Appwrite::ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); ``` ### Full Example @@ -40,7 +40,7 @@ client users = Appwrite::Users.new(client); -user = users.create(userId: Appwrite::ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); +user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); ``` ### Error Handling @@ -50,7 +50,7 @@ The Appwrite Ruby SDK raises `Appwrite::Exception` object with `message`, `code` users = Appwrite::Users.new(client); begin - user = users.create(userId: Appwrite::ID::unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien"); + user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); rescue Appwrite::Exception => error puts error.message end From 569d54bee3ce4100abbf05814f4e614a349eb38b Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:49:51 +0530 Subject: [PATCH 36/99] changes made swift GETTING_STARTED.md --- docs/sdks/swift/GETTING_STARTED.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/sdks/swift/GETTING_STARTED.md b/docs/sdks/swift/GETTING_STARTED.md index 69174c22d6..a5c851ef8f 100644 --- a/docs/sdks/swift/GETTING_STARTED.md +++ b/docs/sdks/swift/GETTING_STARTED.md @@ -25,7 +25,11 @@ let users = Users(client) do { let user = try await users.create( - userId = ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" + userId: ID.unique(), + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien" ) print(String(describing: user.toMap())) } catch { @@ -49,7 +53,11 @@ func main() { do { let user = try await users.create( - userId = ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien" + userId: ID.unique(), + email: 'email@example.com', + phone: '+123456789', + password: 'password', + name: "Walter O'Brien" ) print(String(describing: user.toMap())) } catch { From 8d7ab130ffc607c4d0ce3f8bc10657b4314a9fd1 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:52:28 +0530 Subject: [PATCH 37/99] changes made web GETTING_STARTED.md --- docs/sdks/web/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/web/GETTING_STARTED.md b/docs/sdks/web/GETTING_STARTED.md index 26c73ed50b..82c50e733a 100644 --- a/docs/sdks/web/GETTING_STARTED.md +++ b/docs/sdks/web/GETTING_STARTED.md @@ -25,7 +25,7 @@ Once your SDK object is set, access any of the Appwrite services and choose any const account = new Account(client); // Register User -account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") +account.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { @@ -47,7 +47,7 @@ client const account = new Account(client); // Register User -account.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") +account.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { From a66fc13ebc050605e4f1ebd57a4d92b830276aa5 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:40:09 +0530 Subject: [PATCH 38/99] Update android GETTING_STARTED.md --- docs/sdks/android/GETTING_STARTED.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/sdks/android/GETTING_STARTED.md b/docs/sdks/android/GETTING_STARTED.md index d324ca2d89..0fa056373c 100644 --- a/docs/sdks/android/GETTING_STARTED.md +++ b/docs/sdks/android/GETTING_STARTED.md @@ -52,9 +52,9 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos val account = Account(client) val response = account.create( ID.unique(), - 'email@example.com', - '+123456789', - 'password', + "email@example.com", + "+123456789", + "password", "Walter O'Brien" ) ``` @@ -74,9 +74,9 @@ val client = Client(context) val account = Account(client) val user = account.create( ID.unique(), - 'email@example.com', - '+123456789', - 'password', + "email@example.com", + "+123456789", + "password", "Walter O'Brien" ) ``` @@ -86,7 +86,7 @@ The Appwrite Android SDK raises an `AppwriteException` object with `message`, `c ```kotlin try { - var user = account.create(ID.unique(),'email@example.com','+123456789','password',"Walter O'Brien") + var user = account.create(ID.unique(),"email@example.com","+123456789","password","Walter O'Brien") Log.d("Appwrite user", user.toMap()) } catch(e : AppwriteException) { e.printStackTrace() From 8fed930b7d3d6667c95a823c2521753866124c36 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:43:47 +0530 Subject: [PATCH 39/99] Update apple GETTING_STARTED.md --- docs/sdks/apple/GETTING_STARTED.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/sdks/apple/GETTING_STARTED.md b/docs/sdks/apple/GETTING_STARTED.md index 7c8b5b9d6f..e1de510afc 100644 --- a/docs/sdks/apple/GETTING_STARTED.md +++ b/docs/sdks/apple/GETTING_STARTED.md @@ -76,9 +76,9 @@ let account = Account(client) do { let user = try await account.create( userId: ID.unique(), - email: 'email@example.com', - phone: '+123456789', - password: 'password', + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien" ) print(String(describing: user.toMap())) @@ -103,9 +103,9 @@ func main() { do { let user = try await account.create( userId: ID.unique(), - email: 'email@example.com', - phone: '+123456789', - password: 'password', + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien" ) print(String(describing: account.toMap())) From ea282a17614d176d2d58621ac6c1388a29f78e31 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:51:10 +0530 Subject: [PATCH 40/99] Update dart GETTING_STARTED.md --- docs/sdks/dart/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/dart/GETTING_STARTED.md b/docs/sdks/dart/GETTING_STARTED.md index 83f1f9e8ff..a1dd4b5c4e 100644 --- a/docs/sdks/dart/GETTING_STARTED.md +++ b/docs/sdks/dart/GETTING_STARTED.md @@ -16,7 +16,7 @@ void main() async { Users users = Users(client); try { - final user = await users.create(userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); + final user = await users.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { print(e.message); @@ -31,7 +31,7 @@ The Appwrite Dart SDK raises `AppwriteException` object with `message`, `code` a Users users = Users(client); try { - final user = await users.create(userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); + final user = await users.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From 6c4983f65f97c9da332b1fe570f5dbe0af4b18be Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:52:39 +0530 Subject: [PATCH 41/99] Update dart EXAMPLES.md --- docs/sdks/dart/EXAMPLES.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sdks/dart/EXAMPLES.md b/docs/sdks/dart/EXAMPLES.md index 10150f3ca2..fc2c6d0996 100644 --- a/docs/sdks/dart/EXAMPLES.md +++ b/docs/sdks/dart/EXAMPLES.md @@ -18,10 +18,10 @@ Create a new user: Users users = Users(client); User result = await users.create( - userId: '[USER_ID]', - email: 'email@example.com', - phone: '+123456789', - password: 'password', + userId: ID.unique(), + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien" ); ``` From 618c14524dad6b7643b294e18e6e0260f45bce49 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:55:24 +0530 Subject: [PATCH 42/99] Update deno GETTING_STARTED.md --- docs/sdks/deno/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/deno/GETTING_STARTED.md b/docs/sdks/deno/GETTING_STARTED.md index fb56f493f3..22ea80aa84 100644 --- a/docs/sdks/deno/GETTING_STARTED.md +++ b/docs/sdks/deno/GETTING_STARTED.md @@ -21,7 +21,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```typescript let users = new sdk.Users(client); -let user = await users.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); +let user = await users.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); console.log(user); ``` @@ -39,7 +39,7 @@ client .setSelfSigned() // Use only on dev mode with a self-signed SSL cert ; -let user = await users.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); +let user = await users.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); console.log(user); ``` @@ -50,7 +50,7 @@ The Appwrite Deno SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let user = await users.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); + let user = await users.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); } catch(e) { console.log(e.message); } From 15863c2886392648487546b8619c36a82e1827a6 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:57:12 +0530 Subject: [PATCH 43/99] Update dotnet GETTING_STARTED.md --- docs/sdks/dotnet/GETTING_STARTED.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/sdks/dotnet/GETTING_STARTED.md b/docs/sdks/dotnet/GETTING_STARTED.md index b46e6294fe..ce3386f9d6 100644 --- a/docs/sdks/dotnet/GETTING_STARTED.md +++ b/docs/sdks/dotnet/GETTING_STARTED.md @@ -17,9 +17,9 @@ var users = new Users(client); var user = await users.Create( userId: ID.unique(), - email: 'email@example.com', - phone: '+123456789', - password: 'password', + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien"); Console.WriteLine(user.ToMap()); @@ -35,9 +35,9 @@ try { var user = await users.Create( userId: ID.unique(), - email: 'email@example.com', - phone: '+123456789', - password: 'password', + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien"); } catch (AppwriteException e) From 0c2374e66a7f0851c9e01a37c50fa97fdb9888d2 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:02:17 +0530 Subject: [PATCH 44/99] Update flutter-dev EXAMPLES.md --- docs/sdks/flutter-dev/EXAMPLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdks/flutter-dev/EXAMPLES.md b/docs/sdks/flutter-dev/EXAMPLES.md index ce3ab6a169..19eeb6b531 100644 --- a/docs/sdks/flutter-dev/EXAMPLES.md +++ b/docs/sdks/flutter-dev/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(userId: '[USER_ID]', email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); +final user = await account.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); From 154e9722173bc42c159f4dd553cc0844acdf3da4 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:04:32 +0530 Subject: [PATCH 45/99] Update flutter GETTING_STARTED.md --- docs/sdks/flutter/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 49767d9951..7ee30477fb 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -105,7 +105,7 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos Account account = Account(client); final user = await account .create( - userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien" + userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien" ); ``` @@ -130,7 +130,7 @@ void main() { final user = await account .create( - userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien" + userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien" ); } ``` @@ -142,7 +142,7 @@ The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `type Account account = Account(client); try { - final user = await account.create(userId: ID.unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); + final user = await account.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From f6281158a2a65085e6bbd9475ca47da0aefdb2dc Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:05:43 +0530 Subject: [PATCH 46/99] Update flutter EXAMPLES.md --- docs/sdks/flutter/EXAMPLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdks/flutter/EXAMPLES.md b/docs/sdks/flutter/EXAMPLES.md index ce3ab6a169..19eeb6b531 100644 --- a/docs/sdks/flutter/EXAMPLES.md +++ b/docs/sdks/flutter/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(userId: '[USER_ID]', email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); +final user = await account.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); From 902f20f20ccb5cfda692388a7dcf9988e2a7aab0 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:08:06 +0530 Subject: [PATCH 47/99] Update kotlin GETTING_STARTED.md --- docs/sdks/kotlin/GETTING_STARTED.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/sdks/kotlin/GETTING_STARTED.md b/docs/sdks/kotlin/GETTING_STARTED.md index ab449e088a..5b5ee5f050 100644 --- a/docs/sdks/kotlin/GETTING_STARTED.md +++ b/docs/sdks/kotlin/GETTING_STARTED.md @@ -25,9 +25,9 @@ Once your SDK object is set, create any of the Appwrite service objects and choo val users = Users(client) val user = users.create( user = ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', + email = "email@example.com", + phone = "+123456789", + password = "password", name = "Walter O'Brien" ) ``` @@ -49,9 +49,9 @@ suspend fun main() { val users = Users(client) val user = users.create( user = ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', + email = "email@example.com", + phone = "+123456789", + password = "password", name = "Walter O'Brien" ) } @@ -71,9 +71,9 @@ suspend fun main() { try { val user = users.create( user = ID.unique(), - email = 'email@example.com', - phone = '+123456789', - password = 'password', + email = "email@example.com", + phone = "+123456789", + password = "password", name = "Walter O'Brien" ) } catch (e: AppwriteException) { From 88efb36eadd85714fbe9d86e4402295c9e3513a7 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:10:28 +0530 Subject: [PATCH 48/99] Update nodejs GETTING_STARTED.md --- docs/sdks/nodejs/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/nodejs/GETTING_STARTED.md b/docs/sdks/nodejs/GETTING_STARTED.md index 6bfeb5511d..63dd185dd8 100644 --- a/docs/sdks/nodejs/GETTING_STARTED.md +++ b/docs/sdks/nodejs/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```js let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), 'email@example.com', undefined, '+123456789', 'password', "Walter O'Brien"); +let promise = users.create(sdk.ID.unique(), "email@example.com", undefined, "+123456789", "password", "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -45,7 +45,7 @@ client ; let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), 'email@example.com', undefined, '+123456789', 'password', "Walter O'Brien"); +let promise = users.create(sdk.ID.unique(), "email@example.com", undefined, "+123456789", "password", "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -61,7 +61,7 @@ The Appwrite Node SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let res = await users.create(sdk.ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); + let res = await users.create(sdk.ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); } catch(e) { console.log(e.message); } From a5ea32c237bc38a1266ff12be00ea435cf934dff Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:12:31 +0530 Subject: [PATCH 49/99] Update php GETTING_STARTED.md --- docs/sdks/php/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/php/GETTING_STARTED.md b/docs/sdks/php/GETTING_STARTED.md index ddd34ff4fa..acbd06c8a4 100644 --- a/docs/sdks/php/GETTING_STARTED.md +++ b/docs/sdks/php/GETTING_STARTED.md @@ -20,7 +20,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```php $users = new Users($client); -$user = $users->create(ID::unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); +$user = $users->create(ID::unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); ``` ### Full Example @@ -40,7 +40,7 @@ $client $users = new Users($client); -$user = $users->create(ID::unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); +$user = $users->create(ID::unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); ``` ### Error Handling @@ -49,7 +49,7 @@ The Appwrite PHP SDK raises `AppwriteException` object with `message`, `code` an ```php $users = new Users($client); try { - $user = $users->create(ID::unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien"); + $user = $users->create(ID::unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); } catch(AppwriteException $error) { echo $error->message; } From d3b91b5ec54ac7ffa4354689adfd60873b2a6aec Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:14:58 +0530 Subject: [PATCH 50/99] Update python GETTING_STARTED.md --- docs/sdks/python/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/python/GETTING_STARTED.md b/docs/sdks/python/GETTING_STARTED.md index eed858e3ef..2732ef8483 100644 --- a/docs/sdks/python/GETTING_STARTED.md +++ b/docs/sdks/python/GETTING_STARTED.md @@ -23,7 +23,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```python users = Users(client) -result = users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") +result = users.create(ID.unique(), email = "email@example.com", phone = "+123456789", password = "password", name = "Walter O'Brien") ``` ### Full Example @@ -43,7 +43,7 @@ client = Client() users = Users(client) -result = users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") +result = users.create(ID.unique(), email = "email@example.com", phone = "+123456789", password = "password", name = "Walter O'Brien") ``` ### Error Handling @@ -52,7 +52,7 @@ The Appwrite Python SDK raises `AppwriteException` object with `message`, `code` ```python users = Users(client) try: - result = users.create(ID.unique(), email = 'email@example.com', phone = '+123456789', password = 'password', name = "Walter O'Brien") + result = users.create(ID.unique(), email = "email@example.com", phone = "+123456789", password = "password", name = "Walter O'Brien") except AppwriteException as e: print(e.message) ``` From a26c9214cbe8166cbf6fb4f1775dc42e181e3e21 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:17:18 +0530 Subject: [PATCH 51/99] Update ruby GETTING_STARTED.md --- docs/sdks/ruby/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/ruby/GETTING_STARTED.md b/docs/sdks/ruby/GETTING_STARTED.md index e41b691a53..5d7d7ee370 100644 --- a/docs/sdks/ruby/GETTING_STARTED.md +++ b/docs/sdks/ruby/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```ruby users = Appwrite::Users.new(client); -user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); +user = users.create(userId: Appwrite::ID::unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); ``` ### Full Example @@ -40,7 +40,7 @@ client users = Appwrite::Users.new(client); -user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); +user = users.create(userId: Appwrite::ID::unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); ``` ### Error Handling @@ -50,7 +50,7 @@ The Appwrite Ruby SDK raises `Appwrite::Exception` object with `message`, `code` users = Appwrite::Users.new(client); begin - user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', phone: '+123456789', password: 'password', name: "Walter O'Brien"); + user = users.create(userId: Appwrite::ID::unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); rescue Appwrite::Exception => error puts error.message end From b2e4513af3e16109329805f57c57eb30b27eaa4c Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:19:07 +0530 Subject: [PATCH 52/99] Update swift GETTING_STARTED.md --- docs/sdks/swift/GETTING_STARTED.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/sdks/swift/GETTING_STARTED.md b/docs/sdks/swift/GETTING_STARTED.md index a5c851ef8f..49aa51e9b2 100644 --- a/docs/sdks/swift/GETTING_STARTED.md +++ b/docs/sdks/swift/GETTING_STARTED.md @@ -26,9 +26,9 @@ let users = Users(client) do { let user = try await users.create( userId: ID.unique(), - email: 'email@example.com', - phone: '+123456789', - password: 'password', + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien" ) print(String(describing: user.toMap())) @@ -54,9 +54,9 @@ func main() { do { let user = try await users.create( userId: ID.unique(), - email: 'email@example.com', - phone: '+123456789', - password: 'password', + email: "email@example.com", + phone: "+123456789", + password: "password", name: "Walter O'Brien" ) print(String(describing: user.toMap())) From 0853de0760aea6feb40e311be1cd4156a2cc484e Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:21:22 +0530 Subject: [PATCH 53/99] Update web GETTING_STARTED.md --- docs/sdks/web/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/web/GETTING_STARTED.md b/docs/sdks/web/GETTING_STARTED.md index 82c50e733a..1219cb8958 100644 --- a/docs/sdks/web/GETTING_STARTED.md +++ b/docs/sdks/web/GETTING_STARTED.md @@ -25,7 +25,7 @@ Once your SDK object is set, access any of the Appwrite services and choose any const account = new Account(client); // Register User -account.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien") +account.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { @@ -47,7 +47,7 @@ client const account = new Account(client); // Register User -account.create(ID.unique(), 'email@example.com', '+123456789', 'password', "Walter O'Brien") +account.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { From 7d23b0af5f331d97b9589e3a0759acdfc5547e30 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:08:47 +0530 Subject: [PATCH 54/99] Update dotnet GETTING_STARTED.md --- docs/sdks/dotnet/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/dotnet/GETTING_STARTED.md b/docs/sdks/dotnet/GETTING_STARTED.md index ce3386f9d6..ae1f692e0c 100644 --- a/docs/sdks/dotnet/GETTING_STARTED.md +++ b/docs/sdks/dotnet/GETTING_STARTED.md @@ -16,7 +16,7 @@ var client = new Client() var users = new Users(client); var user = await users.Create( - userId: ID.unique(), + userId: ID.Unique(), email: "email@example.com", phone: "+123456789", password: "password", @@ -34,7 +34,7 @@ var users = new Users(client); try { var user = await users.Create( - userId: ID.unique(), + userId: ID.Unique(), email: "email@example.com", phone: "+123456789", password: "password", From c2c645188d5de2fc87fa6c9bc8d20d38faf4712e Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:10:08 +0530 Subject: [PATCH 55/99] Update nodejs GETTING_STARTED.md --- docs/sdks/nodejs/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/nodejs/GETTING_STARTED.md b/docs/sdks/nodejs/GETTING_STARTED.md index 63dd185dd8..e98400f846 100644 --- a/docs/sdks/nodejs/GETTING_STARTED.md +++ b/docs/sdks/nodejs/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```js let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), "email@example.com", undefined, "+123456789", "password", "Walter O'Brien"); +let promise = users.create(sdk.ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); promise.then(function (response) { console.log(response); @@ -45,7 +45,7 @@ client ; let users = new sdk.Users(client); -let promise = users.create(sdk.ID.unique(), "email@example.com", undefined, "+123456789", "password", "Walter O'Brien"); +let promise = users.create(sdk.ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien"); promise.then(function (response) { console.log(response); From da504ba46c40959628bc76cb51c88b883e64b90a Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 24 Oct 2023 08:59:36 +0530 Subject: [PATCH 56/99] Rectified android GETTING_STARTED.md removed phone number from account.create() function as it does not accept it. --- docs/sdks/android/GETTING_STARTED.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/sdks/android/GETTING_STARTED.md b/docs/sdks/android/GETTING_STARTED.md index 0fa056373c..de16f2cc57 100644 --- a/docs/sdks/android/GETTING_STARTED.md +++ b/docs/sdks/android/GETTING_STARTED.md @@ -53,7 +53,6 @@ val account = Account(client) val response = account.create( ID.unique(), "email@example.com", - "+123456789", "password", "Walter O'Brien" ) @@ -75,7 +74,6 @@ val account = Account(client) val user = account.create( ID.unique(), "email@example.com", - "+123456789", "password", "Walter O'Brien" ) @@ -86,7 +84,7 @@ The Appwrite Android SDK raises an `AppwriteException` object with `message`, `c ```kotlin try { - var user = account.create(ID.unique(),"email@example.com","+123456789","password","Walter O'Brien") + var user = account.create(ID.unique(),"email@example.com","password","Walter O'Brien") Log.d("Appwrite user", user.toMap()) } catch(e : AppwriteException) { e.printStackTrace() From 9eea574df520f5e91a2ec45aecbabf11644a7765 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:01:28 +0530 Subject: [PATCH 57/99] Rectified apple GETTING_STARTED.md Removed phone number from account.create() function as it does not accept it. --- docs/sdks/apple/GETTING_STARTED.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/sdks/apple/GETTING_STARTED.md b/docs/sdks/apple/GETTING_STARTED.md index e1de510afc..6defbc5f00 100644 --- a/docs/sdks/apple/GETTING_STARTED.md +++ b/docs/sdks/apple/GETTING_STARTED.md @@ -77,7 +77,6 @@ do { let user = try await account.create( userId: ID.unique(), email: "email@example.com", - phone: "+123456789", password: "password", name: "Walter O'Brien" ) @@ -104,7 +103,6 @@ func main() { let user = try await account.create( userId: ID.unique(), email: "email@example.com", - phone: "+123456789", password: "password", name: "Walter O'Brien" ) From c2ce7d0aa1398b7f870c00bdb40bd2791163a6a8 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:04:48 +0530 Subject: [PATCH 58/99] Rectified flutter-dev EXAMPLES.md Removed phone number from account.create() function as it does not accept it. --- docs/sdks/flutter-dev/EXAMPLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdks/flutter-dev/EXAMPLES.md b/docs/sdks/flutter-dev/EXAMPLES.md index 19eeb6b531..d0cb0c2b2a 100644 --- a/docs/sdks/flutter-dev/EXAMPLES.md +++ b/docs/sdks/flutter-dev/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); +final user = await account.create(userId: ID.unique(), email: "email@example.com", password: "password", name: "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); From daec743e8cb771f9aa8376d7146848deacbadb0f Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:07:04 +0530 Subject: [PATCH 59/99] Rectified flutter GETTING_STARTED.md Removed phone number from account.create() function as it does not accept it. --- docs/sdks/flutter/GETTING_STARTED.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 7ee30477fb..8d239402b3 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -105,7 +105,7 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos Account account = Account(client); final user = await account .create( - userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien" + userId: ID.unique(), email: "email@example.com", password: "password", name: "Walter O'Brien" ); ``` @@ -130,7 +130,7 @@ void main() { final user = await account .create( - userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien" + userId: ID.unique(), email: "email@example.com", password: "password", name: "Walter O'Brien" ); } ``` @@ -142,7 +142,7 @@ The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `type Account account = Account(client); try { - final user = await account.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); + final user = await account.create(userId: ID.unique(), email: "email@example.com", password: "password", name: "Walter O'Brien"); print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required From 7791cdc20170959c4d67772c23130a203f5b5966 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:09:18 +0530 Subject: [PATCH 60/99] Rectified flutter EXAMPLES.md Removed phone number from account.create() function as it does not accept it. --- docs/sdks/flutter/EXAMPLES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdks/flutter/EXAMPLES.md b/docs/sdks/flutter/EXAMPLES.md index 19eeb6b531..d0cb0c2b2a 100644 --- a/docs/sdks/flutter/EXAMPLES.md +++ b/docs/sdks/flutter/EXAMPLES.md @@ -17,7 +17,7 @@ Create a new user and session: ```dart Account account = Account(client); -final user = await account.create(userId: ID.unique(), email: "email@example.com", phone: "+123456789", password: "password", name: "Walter O'Brien"); +final user = await account.create(userId: ID.unique(), email: "email@example.com", password: "password", name: "Walter O'Brien"); final session = await account.createEmailSession(email: 'me@appwrite.io', password: 'password'); From eefbc68f6bab9218a0a5ae4ec998d2c34ed25400 Mon Sep 17 00:00:00 2001 From: Pratik Gupta <91310568+GuptaPratik02@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:12:13 +0530 Subject: [PATCH 61/99] Update web GETTING_STARTED.md Removed phone number from account.create() function as it does not accept it. --- docs/sdks/web/GETTING_STARTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdks/web/GETTING_STARTED.md b/docs/sdks/web/GETTING_STARTED.md index 1219cb8958..26aa9470bd 100644 --- a/docs/sdks/web/GETTING_STARTED.md +++ b/docs/sdks/web/GETTING_STARTED.md @@ -25,7 +25,7 @@ Once your SDK object is set, access any of the Appwrite services and choose any const account = new Account(client); // Register User -account.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien") +account.create(ID.unique(), "email@example.com", "password", "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { @@ -47,7 +47,7 @@ client const account = new Account(client); // Register User -account.create(ID.unique(), "email@example.com", "+123456789", "password", "Walter O'Brien") +account.create(ID.unique(), "email@example.com", "password", "Walter O'Brien") .then(function (response) { console.log(response); }, function (error) { From 5a3fd99a28a397f5bc1b3d6edf4f347a82a50a65 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 14 Nov 2023 20:05:59 +0200 Subject: [PATCH 62/99] remove deleteCollection() and deleteDatabase() from deletes worker --- src/Appwrite/Platform/Workers/Deletes.php | 76 ----------------------- 1 file changed, 76 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 6bb8636695..a1d0925e74 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -70,12 +70,6 @@ class Deletes extends Action switch (strval($type)) { case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { - case DELETE_TYPE_DATABASES: - $this->deleteDatabase($getProjectDB, $document, $project); - break; - case DELETE_TYPE_COLLECTIONS: - $this->deleteCollection($getProjectDB, $document, $project); - break; case DELETE_TYPE_PROJECTS: $this->deleteProject($dbForConsole, $getProjectDB, $getFilesDevice, $getFunctionsDevice, $getBuildsDevice, $getCacheDevice, $document); break; @@ -104,10 +98,6 @@ class Deletes extends Action $this->deleteRule($dbForConsole, $document); break; default: - if (\str_starts_with($document->getCollection(), 'database_')) { - $this->deleteCollection($getProjectDB, $document, $project); - break; - } Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); break; } @@ -264,72 +254,6 @@ class Deletes extends Action ); } - /** - * @param callable $getProjectDB - * @param Document $document - * @param Document $project - * @return void - * @throws Exception - */ - private function deleteDatabase(callable $getProjectDB, Document $document, Document $project): void - { - $databaseId = $document->getId(); - $dbForProject = $getProjectDB($project); - - $this->deleteByGroup('database_' . $document->getInternalId(), [], $dbForProject, function ($document) use ($getProjectDB, $project) { - $this->deleteCollection($getProjectDB, $document, $project); - }); - - $dbForProject->deleteCollection('database_' . $document->getInternalId()); - $this->deleteAuditLogsByResource($getProjectDB, 'database/' . $databaseId, $project); - } - - /** - * @param callable $getProjectDB - * @param Document $document teams document - * @param Document $project - * @return void - * @throws Exception - */ - private function deleteCollection(callable $getProjectDB, Document $document, Document $project): void - { - $collectionId = $document->getId(); - $collectionInternalId = $document->getInternalId(); - $databaseId = $document->getAttribute('databaseId'); - $databaseInternalId = $document->getAttribute('databaseInternalId'); - - $dbForProject = $getProjectDB($project); - - $relationships = \array_filter( - $document->getAttribute('attributes'), - fn ($attribute) => $attribute['type'] === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - if (!$relationship['twoWay']) { - continue; - } - $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->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); - - $this->deleteByGroup('attributes', [ - Query::equal('databaseInternalId', [$databaseInternalId]), - Query::equal('collectionInternalId', [$collectionInternalId]) - ], $dbForProject); - - $this->deleteByGroup('indexes', [ - Query::equal('databaseInternalId', [$databaseInternalId]), - Query::equal('collectionInternalId', [$collectionInternalId]) - ], $dbForProject); - - $this->deleteAuditLogsByResource($getProjectDB, 'database/' . $databaseId . '/collection/' . $collectionId, $project); - } - /** * @param Database $dbForConsole * @param callable $getProjectDB From 9960912bb13e932baeb17b8f415e3fb68c8e72d9 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 26 Nov 2023 18:52:02 +0200 Subject: [PATCH 63/99] sync against main --- app/config/collections.php | 169 +++++++++++++++------------------ app/controllers/shared/api.php | 5 +- 2 files changed, 80 insertions(+), 94 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 1596748815..a6e59ad744 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1366,6 +1366,85 @@ $commonCollections = [ ], ], ], + + 'cache' => [ + '$collection' => Database::METADATA, + '$id' => 'cache', + 'name' => 'Cache', + 'attributes' => [ + [ + '$id' => 'resource', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => 'signature', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_resource', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resource'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], ]; $projectCollections = array_merge([ @@ -1944,17 +2023,6 @@ $projectCollections = array_merge([ 'array' => false, 'filters' => ['subQueryVariables'], ], - [ - '$id' => ID::custom('varsProject'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryProjectVariables'], - ], [ '$id' => ID::custom('events'), 'type' => Database::VAR_STRING, @@ -2883,85 +2951,6 @@ $projectCollections = array_merge([ ], ], - 'cache' => [ - '$collection' => Database::METADATA, - '$id' => 'cache', - 'name' => 'Cache', - 'attributes' => [ - [ - '$id' => 'resource', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'resourceType', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => 'signature', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_resource', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resource'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - 'variables' => [ '$collection' => Database::METADATA, '$id' => 'variables', diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 22f5047a20..9839cf8961 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -203,7 +203,6 @@ App::init() $useCache = $route->getLabel('cache', false); if ($useCache) { $key = md5($request->getURI() . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER); - $key = md5($request->getURI() . '*' . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) @@ -367,9 +366,7 @@ App::shutdown() ->inject('queueForDatabase') ->inject('dbForProject') ->inject('queueForFunctions') - ->inject('mode') - ->inject('dbForConsole') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Stats $usage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Database $dbForProject, Func $queueForFunctions, string $mode, Database $dbForConsole) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Stats $usage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Database $dbForProject, Func $queueForFunctions) use ($parseLabel) { $responsePayload = $response->getPayload(); From 671b1624d5fdca7d4789f1c46b34433dfc92272e Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:20:20 +0530 Subject: [PATCH 64/99] Update exception for github session not found --- app/controllers/api/avatars.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index e0d967eb00..5f2ea4c2da 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -76,7 +76,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro } if (empty($gitHubSession)) { - throw new Exception(Exception::GENERAL_UNKNOWN, 'GitHub session not found.'); + throw new Exception(Exception::USER_SESSION_NOT_FOUND, 'GitHub session not found.'); } $provider = $gitHubSession->getAttribute('provider', ''); From 90cf28389c3216b0bde33a28ef9638a2e1d05b8f Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 18 Jan 2024 14:10:57 +0200 Subject: [PATCH 65/99] sync config::collections against main --- app/config/collections.php | 164 ++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 86 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index a6e59ad744..e1bd10728f 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1367,84 +1367,6 @@ $commonCollections = [ ], ], - 'cache' => [ - '$collection' => Database::METADATA, - '$id' => 'cache', - 'name' => 'Cache', - 'attributes' => [ - [ - '$id' => 'resource', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'resourceType', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => 'signature', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_resource', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resource'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], ]; $projectCollections = array_merge([ @@ -1502,7 +1424,6 @@ $projectCollections = array_merge([ ], ], ], - 'attributes' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('attributes'), @@ -1700,7 +1621,6 @@ $projectCollections = array_merge([ ], ], ], - 'indexes' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('indexes'), @@ -1838,7 +1758,6 @@ $projectCollections = array_merge([ ], ], ], - 'functions' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('functions'), @@ -2196,7 +2115,6 @@ $projectCollections = array_merge([ ] ], ], - 'deployments' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('deployments'), @@ -2584,7 +2502,6 @@ $projectCollections = array_merge([ ], ], ], - 'builds' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('builds'), @@ -2733,7 +2650,6 @@ $projectCollections = array_merge([ ] ], ], - 'executions' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('executions'), @@ -2950,7 +2866,6 @@ $projectCollections = array_merge([ ], ], ], - 'variables' => [ '$collection' => Database::METADATA, '$id' => 'variables', @@ -3068,7 +2983,84 @@ $projectCollections = array_merge([ ], ], ], - + 'cache' => [ + '$collection' => Database::METADATA, + '$id' => 'cache', + 'name' => 'Cache', + 'attributes' => [ + [ + '$id' => 'resource', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => 'signature', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_resource', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resource'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], 'migrations' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('migrations'), From b08e3d4e7b7c39b6eab546eccb7e7df4d9c859ba Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 18 Jan 2024 14:12:00 +0200 Subject: [PATCH 66/99] sync config::collections against main --- app/config/collections.php | 156 ++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index e1bd10728f..21e20d09c4 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -2866,6 +2866,84 @@ $projectCollections = array_merge([ ], ], ], + 'cache' => [ + '$collection' => Database::METADATA, + '$id' => 'cache', + 'name' => 'Cache', + 'attributes' => [ + [ + '$id' => 'resource', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => 'signature', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_resource', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resource'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], 'variables' => [ '$collection' => Database::METADATA, '$id' => 'variables', @@ -2983,84 +3061,6 @@ $projectCollections = array_merge([ ], ], ], - 'cache' => [ - '$collection' => Database::METADATA, - '$id' => 'cache', - 'name' => 'Cache', - 'attributes' => [ - [ - '$id' => 'resource', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'resourceType', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => 'signature', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_resource', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resource'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], 'migrations' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('migrations'), From 554bc89cb55efb8f2e81467b4fe947b0e8e408c1 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 18 Jan 2024 14:14:24 +0200 Subject: [PATCH 67/99] sync config::collections against main --- app/config/collections.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/app/config/collections.php b/app/config/collections.php index 21e20d09c4..1596748815 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1366,7 +1366,6 @@ $commonCollections = [ ], ], ], - ]; $projectCollections = array_merge([ @@ -1424,6 +1423,7 @@ $projectCollections = array_merge([ ], ], ], + 'attributes' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('attributes'), @@ -1621,6 +1621,7 @@ $projectCollections = array_merge([ ], ], ], + 'indexes' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('indexes'), @@ -1758,6 +1759,7 @@ $projectCollections = array_merge([ ], ], ], + 'functions' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('functions'), @@ -1942,6 +1944,17 @@ $projectCollections = array_merge([ 'array' => false, 'filters' => ['subQueryVariables'], ], + [ + '$id' => ID::custom('varsProject'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryProjectVariables'], + ], [ '$id' => ID::custom('events'), 'type' => Database::VAR_STRING, @@ -2115,6 +2128,7 @@ $projectCollections = array_merge([ ] ], ], + 'deployments' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('deployments'), @@ -2502,6 +2516,7 @@ $projectCollections = array_merge([ ], ], ], + 'builds' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('builds'), @@ -2650,6 +2665,7 @@ $projectCollections = array_merge([ ] ], ], + 'executions' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('executions'), @@ -2866,6 +2882,7 @@ $projectCollections = array_merge([ ], ], ], + 'cache' => [ '$collection' => Database::METADATA, '$id' => 'cache', @@ -2944,6 +2961,7 @@ $projectCollections = array_merge([ ], ], ], + 'variables' => [ '$collection' => Database::METADATA, '$id' => 'variables', @@ -3061,6 +3079,7 @@ $projectCollections = array_merge([ ], ], ], + 'migrations' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('migrations'), From 370704fafdaa963d4b7e38bf9ee223c7aeeb5425 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 21 Jan 2024 10:47:00 +0200 Subject: [PATCH 68/99] moved cache collection to $commonCollections collection config --- app/config/collections.php | 79 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/app/config/collections.php b/app/config/collections.php index 1596748815..57608274bf 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -18,6 +18,85 @@ $auth = Config::getParam('auth', []); */ $commonCollections = [ + 'cache' => [ + '$collection' => Database::METADATA, + '$id' => 'cache', + 'name' => 'Cache', + 'attributes' => [ + [ + '$id' => 'resource', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => 'signature', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_resource', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resource'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + 'users' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('users'), From e7ace61273b547de7f04b71a7d8404969f7712ae Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 12 Feb 2024 11:10:52 +0200 Subject: [PATCH 69/99] Sync against main --- app/config/collections.php | 6 ++--- app/controllers/api/databases.php | 12 +++++----- app/controllers/api/functions.php | 8 +++---- app/controllers/api/project.php | 8 +++---- app/controllers/api/storage.php | 8 +++---- app/controllers/api/users.php | 4 ++-- src/Appwrite/Platform/Tasks/CalcTierStats.php | 2 +- .../Platform/Tasks/CreateInfMetric.php | 6 ++--- src/Appwrite/Platform/Workers/Deletes.php | 2 +- src/Appwrite/Platform/Workers/Hamster.php | 2 +- src/Appwrite/Platform/Workers/Usage.php | 24 +++++++++---------- src/Appwrite/Platform/Workers/UsageHook.php | 6 ++--- 12 files changed, 44 insertions(+), 44 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 6f509260cc..3bc58eff56 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1349,10 +1349,10 @@ $commonCollections = [ ] ], - 'stats_v2' => [ + 'stats' => [ '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('stats_v2'), - 'name' => 'stats_v2', + '$id' => ID::custom('stats'), + 'name' => 'stats', 'attributes' => [ [ '$id' => ID::custom('metric'), diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 8684a7fae8..5fdb2edb2f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3563,7 +3563,7 @@ App::get('/v1/databases/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -3571,7 +3571,7 @@ App::get('/v1/databases/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -3647,7 +3647,7 @@ App::get('/v1/databases/:databaseId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -3655,7 +3655,7 @@ App::get('/v1/databases/:databaseId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -3733,7 +3733,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -3741,7 +3741,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d3913d180d..45df54b709 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -484,7 +484,7 @@ App::get('/v1/functions/:functionId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -492,7 +492,7 @@ App::get('/v1/functions/:functionId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -576,7 +576,7 @@ App::get('/v1/functions/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -584,7 +584,7 @@ App::get('/v1/functions/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 2269cb81c7..8dd6f8b82e 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -73,7 +73,7 @@ App::get('/v1/project/usage') Authorization::skip(function () use ($dbForProject, $firstDay, $lastDay, $period, $metrics, &$total, &$stats) { foreach ($metrics['total'] as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -81,7 +81,7 @@ App::get('/v1/project/usage') } foreach ($metrics['period'] as $metric) { - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::greaterThanEqual('time', $firstDay), @@ -116,7 +116,7 @@ App::get('/v1/project/usage') $id = $function->getId(); $name = $function->getAttribute('name'); $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS); - $value = $dbForProject->findOne('stats_v2', [ + $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -132,7 +132,7 @@ App::get('/v1/project/usage') $id = $bucket->getId(); $name = $bucket->getAttribute('name'); $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); - $value = $dbForProject->findOne('stats_v2', [ + $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 4f59410014..e4798fb51e 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1525,7 +1525,7 @@ App::get('/v1/storage/usage') $total = []; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1533,7 +1533,7 @@ App::get('/v1/storage/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -1610,7 +1610,7 @@ App::get('/v1/storage/:bucketId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1618,7 +1618,7 @@ App::get('/v1/storage/:bucketId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 38d65fba7e..06b446a110 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1263,7 +1263,7 @@ App::get('/v1/users/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { - $result = $dbForProject->findOne('stats_v2', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1271,7 +1271,7 @@ App::get('/v1/users/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats_v2', [ + $results = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/src/Appwrite/Platform/Tasks/CalcTierStats.php b/src/Appwrite/Platform/Tasks/CalcTierStats.php index 2c904973a9..05a28b418a 100644 --- a/src/Appwrite/Platform/Tasks/CalcTierStats.php +++ b/src/Appwrite/Platform/Tasks/CalcTierStats.php @@ -270,7 +270,7 @@ class CalcTierStats extends Action $limit = $periods[$range]['limit']; $period = $periods[$range]['period']; - $requestDocs = $dbForProject->find('stats_v2', [ + $requestDocs = $dbForProject->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/src/Appwrite/Platform/Tasks/CreateInfMetric.php b/src/Appwrite/Platform/Tasks/CreateInfMetric.php index 49b852ff6f..4b3f0e89fb 100644 --- a/src/Appwrite/Platform/Tasks/CreateInfMetric.php +++ b/src/Appwrite/Platform/Tasks/CreateInfMetric.php @@ -167,8 +167,8 @@ class CreateInfMetric extends Action try { $id = \md5("_inf_{$metric}"); - $dbForProject->deleteDocument('stats_v2', $id); - $dbForProject->createDocument('stats_v2', new Document([ + $dbForProject->deleteDocument('stats', $id); + $dbForProject->createDocument('stats', new Document([ '$id' => $id, 'metric' => $metric, 'period' => 'inf', @@ -190,7 +190,7 @@ class CreateInfMetric extends Action protected function getFromMetric(database $dbForProject, string $metric): int|float { - return $dbForProject->sum('stats_v2', 'value', [ + return $dbForProject->sum('stats', 'value', [ Query::equal('metric', [ $metric, ]), diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 4f5b9f5f96..eabc4fd707 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -351,7 +351,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); // Delete Usage stats - $this->deleteByGroup('stats_v2', [ + $this->deleteByGroup('stats', [ Query::lessThan('time', $hourlyUsageRetentionDatetime), Query::equal('period', ['1h']), ], $dbForProject); diff --git a/src/Appwrite/Platform/Workers/Hamster.php b/src/Appwrite/Platform/Workers/Hamster.php index 0fb705d0f7..6239f842e0 100644 --- a/src/Appwrite/Platform/Workers/Hamster.php +++ b/src/Appwrite/Platform/Workers/Hamster.php @@ -286,7 +286,7 @@ class Hamster extends Action $limit = $periodValue['limit']; $period = $periodValue['period']; - $requestDocs = $dbForProject->find('stats_v2', [ + $requestDocs = $dbForProject->find('stats', [ Query::equal('period', [$period]), Query::equal('metric', [$metric]), Query::limit($limit), diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 2097f101bd..13c5a8bff0 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -105,8 +105,8 @@ class Usage extends Action } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); + $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); if (!empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, @@ -124,7 +124,7 @@ class Usage extends Action case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; - $documents = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); + $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); if (!empty($documents['value'])) { $metrics[] = [ @@ -139,8 +139,8 @@ class Usage extends Action break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -158,13 +158,13 @@ class Usage extends Action break; case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ diff --git a/src/Appwrite/Platform/Workers/UsageHook.php b/src/Appwrite/Platform/Workers/UsageHook.php index 4781b1e892..8343b26355 100644 --- a/src/Appwrite/Platform/Workers/UsageHook.php +++ b/src/Appwrite/Platform/Workers/UsageHook.php @@ -67,7 +67,7 @@ class UsageHook extends Usage $id = \md5("{$time}_{$period}_{$key}"); try { - $dbForProject->createDocument('stats_v2', new Document([ + $dbForProject->createDocument('stats', new Document([ '$id' => $id, 'period' => $period, 'time' => $time, @@ -78,14 +78,14 @@ class UsageHook extends Usage } catch (Duplicate $th) { if ($value < 0) { $dbForProject->decreaseDocumentAttribute( - 'stats_v2', + 'stats', $id, 'value', abs($value) ); } else { $dbForProject->increaseDocumentAttribute( - 'stats_v2', + 'stats', $id, 'value', $value From 70effd1e99a418494f49ffb792758e1ad3636d68 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 12 Feb 2024 11:14:26 +0200 Subject: [PATCH 70/99] Sync against main --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index 80c3670eec..f27da88d24 100644 --- a/app/init.php +++ b/app/init.php @@ -112,7 +112,7 @@ const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours -const APP_CACHE_BUSTER = 329; +const APP_CACHE_BUSTER = 330; const APP_VERSION_STABLE = '1.4.13'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; From 3476ab26270099ab553bb0a9eb5474a99563896e Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 13 Feb 2024 12:26:02 +0000 Subject: [PATCH 71/99] dev: introduce redis insights --- docker-compose.yml | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index de71e3937a..ed912dc8e2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -928,6 +928,7 @@ services: # - appwrite # volumes: # - appwrite-uploads:/storage/uploads + # Dev Tools Start ------------------------------------------------------------------------------------------ # # The Appwrite Team uses the following tools to help debug, monitor and diagnose the Appwrite stack @@ -936,8 +937,9 @@ services: # # MailCatcher - An SMTP server. Catches all system emails and displays them in a nice UI. # RequestCatcher - An HTTP server. Catches all system https calls and displays them using a simple HTTP API. Used to debug & tests webhooks and HTTP tasks - # RedisCommander - A nice UI for exploring Redis data - # Webgrind - A nice UI for exploring and debugging code-level stuff + # Redis Insight - A nice UI for exploring Redis data + # Adminer - A nice UI for exploring MariaDB data + # GraphQl Explorer - A nice UI for exploring GraphQL API maildev: # used mainly for dev tests image: appwrite/mailcatcher:1.0.0 @@ -967,21 +969,15 @@ services: networks: - appwrite - # redis-commander: - # image: rediscommander/redis-commander:latest - # restart: unless-stopped - # networks: - # - appwrite - # environment: - # - REDIS_HOSTS=redis - # ports: - # - "8081:8081" - # webgrind: - # image: 'jokkedk/webgrind:latest' - # volumes: - # - './debug:/tmp' - # ports: - # - '3001:80' + redis-insight: + image: redis/redisinsight:latest + restart: unless-stopped + networks: + - appwrite + environment: + - REDIS_HOSTS=redis + ports: + - "8081:5540" graphql-explorer: container_name: appwrite-graphql-explorer From 459db9b43e710f0c592226a33d649011f67c681d Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 14 Feb 2024 07:34:12 +0200 Subject: [PATCH 72/99] usage updates --- .env | 2 +- src/Appwrite/Platform/Workers/UsageDump.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.env b/.env index b915f91516..2373b618c2 100644 --- a/.env +++ b/.env @@ -78,7 +78,7 @@ _APP_MAINTENANCE_RETENTION_CACHE=2592000 _APP_MAINTENANCE_RETENTION_EXECUTION=1209600 _APP_MAINTENANCE_RETENTION_ABUSE=86400 _APP_MAINTENANCE_RETENTION_AUDIT=1209600 -_APP_USAGE_AGGREGATION_INTERVAL=20 +_APP_USAGE_AGGREGATION_INTERVAL=30 _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000 _APP_MAINTENANCE_RETENTION_SCHEDULES=86400 _APP_USAGE_STATS=enabled diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index f563578984..4d0ec6f6b0 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -78,7 +78,7 @@ class UsageDump extends Action $id = \md5("{$time}_{$period}_{$key}"); try { - $dbForProject->createDocument('stats_v2', new Document([ + $dbForProject->createDocument('stats', new Document([ '$id' => $id, 'period' => $period, 'time' => $time, @@ -89,14 +89,14 @@ class UsageDump extends Action } catch (Duplicate $th) { if ($value < 0) { $dbForProject->decreaseDocumentAttribute( - 'stats_v2', + 'stats', $id, 'value', abs($value) ); } else { $dbForProject->increaseDocumentAttribute( - 'stats_v2', + 'stats', $id, 'value', $value From 00db19257d0d0b49745d31102f1240f6810ea214 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:57:24 +0530 Subject: [PATCH 73/99] Add health storage check --- app/controllers/api/health.php | 37 +++++++++++++++++++ docs/references/health/get-storage.md | 1 + .../Health/HealthCustomServerTest.php | 18 +++++++++ 3 files changed, 56 insertions(+) create mode 100644 docs/references/health/get-storage.md diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index a85f9da321..2f637be424 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -702,6 +702,43 @@ App::get('/v1/health/storage/local') $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); }); +App::get('/v1/health/storage') + ->desc('Get storage') + ->groups(['api', 'health']) + ->label('scope', 'health.read') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'health') + ->label('sdk.method', 'getStorage') + ->label('sdk.description', '/docs/references/health/get-storage.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->inject('response') + ->inject('deviceFiles') + ->action(function (Response $response, Device $deviceFiles) { + + $checkStart = \microtime(true); + + if (!$deviceFiles->write($deviceFiles->getPath('health.txt'), 'test', '')) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file'); + } + + if ($deviceFiles->read($deviceFiles->getPath('health.txt')) !== 'test') { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file'); + } + + if (!$deviceFiles->delete($deviceFiles->getPath('health.txt'))) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file'); + } + + $output = [ + 'status' => 'pass', + 'ping' => \round((\microtime(true) - $checkStart) / 1000) + ]; + + $response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS); + }); + App::get('/v1/health/anti-virus') ->desc('Get antivirus') ->groups(['api', 'health']) diff --git a/docs/references/health/get-storage.md b/docs/references/health/get-storage.md new file mode 100644 index 0000000000..ea73e88027 --- /dev/null +++ b/docs/references/health/get-storage.md @@ -0,0 +1 @@ +Check the Appwrite storage device is up and connection is successful. \ No newline at end of file diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index c817222c48..dde89a6a71 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -407,6 +407,24 @@ class HealthCustomServerTest extends Scope return []; } + public function testStorageSuccess(): array + { + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/health/storage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('pass', $response['body']['status']); + $this->assertIsInt($response['body']['ping']); + $this->assertLessThan(100, $response['body']['ping']); + + return []; + } + public function testStorageAntiVirusSuccess(): array { /** From 3b1233eaa9d7e4ba705e6073697c21d6e747dffe Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Sun, 18 Feb 2024 18:28:41 +0530 Subject: [PATCH 74/99] Add deviceFunctions and deviceBuilds as well --- app/controllers/api/health.php | 36 ++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 2f637be424..2cbf8add33 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -21,6 +21,20 @@ use Utopia\Validator\Multiple; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; +$checkStorageHealth = function (Device $device) { + if (!$device->write($device->getPath('health.txt'), 'test', '')) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); + } + + if ($device->read($device->getPath('health.txt')) !== 'test') { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot()); + } + + if (!$device->delete($device->getPath('health.txt'))) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot()); + } +}; + App::get('/v1/health') ->desc('Get HTTP') ->groups(['api', 'health']) @@ -715,20 +729,18 @@ App::get('/v1/health/storage') ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) ->inject('response') ->inject('deviceFiles') - ->action(function (Response $response, Device $deviceFiles) { - + ->inject('deviceFunctions') + ->inject('deviceBuilds') + ->action(function (Response $response, Device $deviceFiles, Device $deviceFunctions, Device $deviceBuilds) use ($checkStorageHealth) { + $devices = [$deviceFiles, $deviceFunctions, $deviceBuilds]; $checkStart = \microtime(true); - if (!$deviceFiles->write($deviceFiles->getPath('health.txt'), 'test', '')) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file'); - } - - if ($deviceFiles->read($deviceFiles->getPath('health.txt')) !== 'test') { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file'); - } - - if (!$deviceFiles->delete($deviceFiles->getPath('health.txt'))) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file'); + try { + foreach ($devices as $device) { + $checkStorageHealth($device); + } + } catch (Exception $e) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, $e->getMessage()); } $output = [ From e4a86d9777db3542f5b5de11da2772ac8975c7c1 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:19:54 +0530 Subject: [PATCH 75/99] Remove global function --- app/controllers/api/health.php | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 2cbf8add33..c007d629b6 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -21,20 +21,6 @@ use Utopia\Validator\Multiple; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -$checkStorageHealth = function (Device $device) { - if (!$device->write($device->getPath('health.txt'), 'test', '')) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); - } - - if ($device->read($device->getPath('health.txt')) !== 'test') { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot()); - } - - if (!$device->delete($device->getPath('health.txt'))) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot()); - } -}; - App::get('/v1/health') ->desc('Get HTTP') ->groups(['api', 'health']) @@ -731,16 +717,22 @@ App::get('/v1/health/storage') ->inject('deviceFiles') ->inject('deviceFunctions') ->inject('deviceBuilds') - ->action(function (Response $response, Device $deviceFiles, Device $deviceFunctions, Device $deviceBuilds) use ($checkStorageHealth) { + ->action(function (Response $response, Device $deviceFiles, Device $deviceFunctions, Device $deviceBuilds) { $devices = [$deviceFiles, $deviceFunctions, $deviceBuilds]; $checkStart = \microtime(true); - try { - foreach ($devices as $device) { - $checkStorageHealth($device); + foreach ($devices as $device) { + if (!$device->write($device->getPath('health.txt'), 'test', '')) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); + } + + if ($device->read($device->getPath('health.txt')) !== 'test') { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot()); + } + + if (!$device->delete($device->getPath('health.txt'))) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot()); } - } catch (Exception $e) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, $e->getMessage()); } $output = [ From 928ae74ffe2a49d199e7d99d1331c4c6925770c4 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 19 Feb 2024 06:04:29 +0000 Subject: [PATCH 76/99] fix project network usage --- app/controllers/api/project.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 8dd6f8b82e..a067c45588 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -144,9 +144,30 @@ App::get('/v1/project/usage') ]; }, $dbForProject->find('buckets')); + // merge network inbound + outbound + $projectBandwidth = []; + foreach ($usage[METRIC_NETWORK_INBOUND] as $item) { + $projectBandwidth[$item['date']] ??= 0; + $projectBandwidth[$item['date']] += $item['value']; + } + + foreach ($usage[METRIC_NETWORK_OUTBOUND] as $item) { + $projectBandwidth[$item['date']] ??= 0; + $projectBandwidth[$item['date']] += $item['value']; + } + + + $network = []; + foreach ($projectBandwidth as $date => $value) { + $network[] = [ + 'date' => $date, + 'value' => $value + ]; + } + $response->dynamic(new Document([ 'requests' => ($usage[METRIC_NETWORK_REQUESTS]), - 'network' => ($usage[METRIC_NETWORK_INBOUND] + $usage[METRIC_NETWORK_OUTBOUND]), + 'network' => $network, 'users' => ($usage[METRIC_USERS]), 'executions' => ($usage[METRIC_EXECUTIONS]), 'executionsTotal' => $total[METRIC_EXECUTIONS], From 1577be91721ce6d04a6a8a33b3607f407868632a Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 19 Feb 2024 21:36:14 +0200 Subject: [PATCH 77/99] usage/usage-dump queue health endpoints --- app/controllers/api/health.php | 55 +++++++++++++++++++ .../references/health/get-queue-usage-dump.md | 1 + docs/references/health/get-queue-usage.md | 1 + .../Health/HealthCustomServerTest.php | 48 ++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 docs/references/health/get-queue-usage-dump.md create mode 100644 docs/references/health/get-queue-usage.md diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index a85f9da321..f727492d3a 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -659,6 +659,60 @@ App::get('/v1/health/queue/functions') $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); +App::get('/v1/health/queue/usage') + ->desc('Get usage queue') + ->groups(['api', 'health']) + ->label('scope', 'health.read') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'health') + ->label('sdk.method', 'getQueueUsage') + ->label('sdk.description', '/docs/references/health/get-queue-usage.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) + ->inject('queue') + ->inject('response') + ->action(function (int|string $threshold, Connection $queue, Response $response) { + $threshold = \intval($threshold); + + $client = new Client(Event::USAGE_QUEUE_NAME, $queue); + $size = $client->getQueueSize(); + + if ($size >= $threshold) { + throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); + } + + $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); + }); + +App::get('/v1/health/queue/usage-dump') + ->desc('Get usage dump queue') + ->groups(['api', 'health']) + ->label('scope', 'health.read') + ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) + ->label('sdk.namespace', 'health') + ->label('sdk.method', 'getQueueUsage') + ->label('sdk.description', '/docs/references/health/get-queue-usage-dump.md') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) + ->inject('queue') + ->inject('response') + ->action(function (int|string $threshold, Connection $queue, Response $response) { + $threshold = \intval($threshold); + + $client = new Client(Event::USAGE_DUMP_QUEUE_NAME, $queue); + $size = $client->getQueueSize(); + + if ($size >= $threshold) { + throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); + } + + $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); + }); + App::get('/v1/health/storage/local') ->desc('Get local storage') ->groups(['api', 'health']) @@ -755,6 +809,7 @@ App::get('/v1/health/queue/failed/:name') Event::MAILS_QUEUE_NAME, Event::FUNCTIONS_QUEUE_NAME, Event::USAGE_QUEUE_NAME, + Event::USAGE_DUMP_QUEUE_NAME, Event::WEBHOOK_CLASS_NAME, Event::CERTIFICATES_QUEUE_NAME, Event::BUILDS_QUEUE_NAME, diff --git a/docs/references/health/get-queue-usage-dump.md b/docs/references/health/get-queue-usage-dump.md new file mode 100644 index 0000000000..3c95da1b8a --- /dev/null +++ b/docs/references/health/get-queue-usage-dump.md @@ -0,0 +1 @@ +Get the number of projects containing metrics that are waiting to be processed in the Appwrite internal queue server. \ No newline at end of file diff --git a/docs/references/health/get-queue-usage.md b/docs/references/health/get-queue-usage.md new file mode 100644 index 0000000000..8e5b64e642 --- /dev/null +++ b/docs/references/health/get-queue-usage.md @@ -0,0 +1 @@ +Get the number of metrics that are waiting to be processed in the Appwrite internal queue server. \ No newline at end of file diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index c817222c48..1ea0020e3d 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -494,4 +494,52 @@ class HealthCustomServerTest extends Scope return []; } + + public function testUsageSuccess() + { + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['size']); + $this->assertLessThan(100, $response['body']['size']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage?threshold=0', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + $this->assertEquals(503, $response['headers']['status-code']); + } + + public function testUsageDumpSuccess() + { + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage-dump', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['size']); + $this->assertLessThan(100, $response['body']['size']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage-dump?threshold=0', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + $this->assertEquals(503, $response['headers']['status-code']); + } } From c2ae330888571ed91ce00eef0f8bcb13121a4a6d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 20 Feb 2024 09:14:48 +0545 Subject: [PATCH 78/99] fix bandwidth usage --- app/controllers/api/project.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 2269cb81c7..47b94d3093 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -144,9 +144,30 @@ App::get('/v1/project/usage') ]; }, $dbForProject->find('buckets')); + // merge network inbound + outbound + $projectBandwidth = []; + foreach ($usage[METRIC_NETWORK_INBOUND] as $item) { + $projectBandwidth[$item['date']] ??= 0; + $projectBandwidth[$item['date']] += $item['value']; + } + + foreach ($usage[METRIC_NETWORK_OUTBOUND] as $item) { + $projectBandwidth[$item['date']] ??= 0; + $projectBandwidth[$item['date']] += $item['value']; + } + + + $network = []; + foreach ($projectBandwidth as $date => $value) { + $network[] = [ + 'date' => $date, + 'value' => $value + ]; + } + $response->dynamic(new Document([ 'requests' => ($usage[METRIC_NETWORK_REQUESTS]), - 'network' => ($usage[METRIC_NETWORK_INBOUND] + $usage[METRIC_NETWORK_OUTBOUND]), + 'network' => $network, 'users' => ($usage[METRIC_USERS]), 'executions' => ($usage[METRIC_EXECUTIONS]), 'executionsTotal' => $total[METRIC_EXECUTIONS], From d60e7c641f4c714b3a4fb9536c1aa5dc85b1cdc5 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 20 Feb 2024 15:56:25 +0000 Subject: [PATCH 79/99] Add ARM64 to docker publish --- .github/workflows/publish.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0fc3fc2df3..195eefebcd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,6 +17,9 @@ jobs: fetch-depth: 2 submodules: recursive + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Login to Docker Hub uses: docker/login-action@v2 with: @@ -35,11 +38,11 @@ jobs: uses: docker/build-push-action@v4 with: context: . - platforms: linux/amd64 + platforms: linux/amd64,linux/arm64 build-args: | VERSION=${{ steps.meta.outputs.version }} VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1 VITE_GA_PROJECT=G-L7G2B6PLDS VITE_CONSOLE_MODE=cloud push: true - tags: ${{ steps.meta.outputs.tags }} \ No newline at end of file + tags: ${{ steps.meta.outputs.tags }} From cc8705253e8ba6c95dc85059dd63624fb5de388e Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 21 Feb 2024 10:12:20 +0000 Subject: [PATCH 80/99] Add Docker Buildx for multiplatform --- .github/workflows/publish.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 195eefebcd..f914e662d3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,6 +20,9 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub uses: docker/login-action@v2 with: From 0dd2889de517c0a76b3b7c762ff3dacaef30bae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 21 Feb 2024 14:51:21 +0000 Subject: [PATCH 81/99] Fix double router curl --- app/controllers/general.php | 263 ++++++++++++++++++++++++++++++------ 1 file changed, 221 insertions(+), 42 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index bfec8b46be..e54d6c21e9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -12,6 +12,7 @@ use Swoole\Http\Request as SwooleRequest; use Utopia\Cache\Cache; use Utopia\Pools\Group; use Appwrite\Utopia\Request; +use MaxMind\Db\Reader; use Appwrite\Utopia\Response; use Appwrite\Utopia\View; use Appwrite\Extend\Exception as AppwriteException; @@ -19,6 +20,9 @@ use Utopia\Config\Config; use Utopia\Domains\Domain; use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; +use Appwrite\Event\Event; +use Appwrite\Event\Usage; +use Appwrite\ID; use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Response\Filters\V11 as ResponseV11; use Appwrite\Utopia\Response\Filters\V12 as ResponseV12; @@ -38,6 +42,7 @@ use Appwrite\Utopia\Request\Filters\V13 as RequestV13; use Appwrite\Utopia\Request\Filters\V14 as RequestV14; use Appwrite\Utopia\Request\Filters\V15 as RequestV15; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; +use Executor\Executor; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; @@ -45,7 +50,11 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleRequest, Request $request, Response $response) + +->inject('geodb') +Reader $geodb + +function router(App $utopia, Database $dbForConsole, Database $dbForProject, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); @@ -117,59 +126,214 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques $path .= '?' . $query; } + + $body = $swooleRequest->getContent() ?? ''; + $method = $swooleRequest->server['request_method']; + $requestHeaders = $request->getHeaders(); - $body = \json_encode([ - 'async' => false, - 'body' => $swooleRequest->getContent() ?? '', - 'method' => $swooleRequest->server['request_method'], - 'path' => $path, - 'headers' => $requestHeaders + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + + if ($function->isEmpty() || !$function->getAttribute('enabled')) { + throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND); + } + + $version = $function->getAttribute('version', 'v2'); + $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); + + $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; + + if (\is_null($runtime)) { + throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + } + + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); + + if ($deployment->getAttribute('resourceId') !== $function->getId()) { + throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + } + + if ($deployment->isEmpty()) { + throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + } + + /** Check if build has completed */ + $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); + if ($build->isEmpty()) { + throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND); + } + + if ($build->getAttribute('status') !== 'ready') { + throw new AppwriteException(AppwriteException::BUILD_NOT_READY); + } + + $permissions = $function->getAttribute('execute'); + + if (!(\in_array('any', $permissions)) && (\in_array('guests', $permissions))) { + throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"'); + } + + $headers = \array_merge([], $requestHeaders); + $headers['x-appwrite-trigger'] = 'http'; + $headers['x-appwrite-user-id'] = ''; + $headers['x-appwrite-user-jwt'] = ''; + $headers['x-appwrite-country-code'] = ''; + $headers['x-appwrite-continent-code'] = ''; + $headers['x-appwrite-continent-eu'] = 'false'; + + $ip = $headers['x-real-ip'] ?? ''; + if (!empty($ip)) { + $record = $geodb->get($ip); + + if ($record) { + $eu = Config::getParam('locale-eu'); + + $headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? ''; + $headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? ''; + $headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false'; + } + } + + $headersFiltered = []; + foreach ($headers as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } + } + + $executionId = ID::unique(); + + $execution = new Document([ + '$id' => $executionId, + '$permissions' => [], + 'functionInternalId' => $function->getInternalId(), + 'functionId' => $function->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentId' => $deployment->getId(), + 'trigger' => 'http', // http / schedule / event + 'status' => 'processing', // waiting / processing / completed / failed + 'responseStatusCode' => 0, + 'responseHeaders' => [], + 'requestPath' => $path, + 'requestMethod' => $method, + 'requestHeaders' => $headersFiltered, + 'errors' => '', + 'logs' => '', + 'duration' => 0.0, + 'search' => implode(' ', [$functionId, $executionId]), ]); - $headers = [ - 'Content-Type: application/json', - 'Content-Length: ' . \strlen($body), - 'X-Appwrite-Project: ' . $projectId - ]; + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('executionId', $execution->getId()) + ->setContext('function', $function); - $ch = \curl_init(); - \curl_setopt($ch, CURLOPT_URL, "http://localhost/v1/functions/{$functionId}/executions"); - \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); - \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - // \curl_setopt($ch, CURLOPT_HEADER, true); - \curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); - \curl_setopt($ch, CURLOPT_TIMEOUT, 30); + $durationStart = \microtime(true); - $executionResponse = \curl_exec($ch); - $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE); - $error = \curl_error($ch); - $errNo = \curl_errno($ch); + $vars = []; - \curl_close($ch); - - if ($errNo !== 0) { - throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Internal error: " . $error); + // V2 vars + if ($version === 'v2') { + $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '', + 'APPWRITE_FUNCTION_DATA' => $body ?? '', + 'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '', + 'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? '' + ]); } - if ($statusCode >= 400) { - $error = \json_decode($executionResponse, true)['message']; - throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Execution error: " . $error); + // Shared vars + foreach ($function->getAttribute('varsProject', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); } - $execution = \json_decode($executionResponse, true); + // Function vars + foreach ($function->getAttribute('vars', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + } - $contentType = 'text/plain'; - foreach ($execution['responseHeaders'] as $header) { - if (\strtolower($header['name']) === 'content-type') { - $contentType = $header['value']; + // Appwrite vars + $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_ID' => $functionId, + 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), + 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), + 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), + 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', + 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', + ]); + + /** Execute function */ + $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); + try { + $version = $function->getAttribute('version', 'v2'); + $command = $runtime['startCommand']; + $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; + $executionResponse = $executor->createExecution( + projectId: $project->getId(), + deploymentId: $deployment->getId(), + body: \strlen($body) > 0 ? $body : null, + variables: $vars, + timeout: $function->getAttribute('timeout', 0), + image: $runtime['image'], + source: $build->getAttribute('path', ''), + entrypoint: $deployment->getAttribute('entrypoint', ''), + version: $version, + path: $path, + method: $method, + headers: $headers, + runtimeEntrypoint: $command, + requestTimeout: 30 + ); + + $headersFiltered = []; + foreach ($executionResponse['headers'] as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } } - $response->setHeader($header['name'], $header['value']); + /** Update execution status */ + $status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed'; + $execution->setAttribute('status', $status); + $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); + $execution->setAttribute('responseHeaders', $headersFiltered); + $execution->setAttribute('logs', $executionResponse['logs']); + $execution->setAttribute('errors', $executionResponse['errors']); + $execution->setAttribute('duration', $executionResponse['duration']); + } catch (\Throwable $th) { + $durationEnd = \microtime(true); + + $execution + ->setAttribute('duration', $durationEnd - $durationStart) + ->setAttribute('status', 'failed') + ->setAttribute('responseStatusCode', 500) + ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); + Console::error($th->getMessage()); + } finally { + $queueForUsage + ->addMetric(METRIC_EXECUTIONS, 1) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ; } + if ($function->getAttribute('logging')) { + /** @var Document $execution */ + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + } + + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); + + $headers = []; + foreach (($executionResponse['headers'] ?? []) as $key => $value) { + $headers[] = ['name' => $key, 'value' => $value]; + } + + $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); + $execution->setAttribute('responseHeaders', $headers); + $body = $execution['responseBody'] ?? ''; $encodingKey = \array_search('x-open-runtimes-encoding', \array_column($execution['responseHeaders'], 'name')); @@ -179,6 +343,15 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques } } + $contentType = 'text/plain'; + foreach ($execution['responseHeaders'] as $header) { + if (\strtolower($header['name']) === 'content-type') { + $contentType = $header['value']; + } + + $response->setHeader($header['name'], $header['value']); + } + $response ->setContentType($contentType) ->setStatusCode($execution['responseStatusCode'] ?? 200) @@ -205,13 +378,16 @@ App::init() ->inject('console') ->inject('project') ->inject('dbForConsole') + ->inject('dbForProject') ->inject('user') ->inject('locale') ->inject('localeCodes') ->inject('clients') ->inject('servers') ->inject('queueForCertificates') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates) { + ->inject('queueForEvents') + ->inject('queueForUsage') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Database $dbForProject, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage) { /* * Appwrite Router */ @@ -220,7 +396,7 @@ App::init() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) { + if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage)) { return; } } @@ -571,7 +747,10 @@ App::options() ->inject('request') ->inject('response') ->inject('dbForConsole') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole) { + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForUsage') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage) { /* * Appwrite Router */ @@ -579,7 +758,7 @@ App::options() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) { + if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage)) { return; } } From e3c261b9e49076787b9b08112d6a51a3466a085a Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:24:55 +0000 Subject: [PATCH 82/99] fix: msg91 --- composer.json | 2 +- composer.lock | 48 ++++++++++----------- src/Appwrite/Platform/Workers/Messaging.php | 31 +++++++++---- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/composer.json b/composer.json index 41baf29d9a..795fb4ad30 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "utopia-php/image": "0.5.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.3.*", - "utopia-php/messaging": "0.2.*", + "utopia-php/messaging": "0.3.*", "utopia-php/migration": "0.3.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.5.*", diff --git a/composer.lock b/composer.lock index ca39c7d084..d30ad5f44b 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": "fd03f97115d752d1a94b533ccf570109", + "content-hash": "a8c299cb631eb98bbcf0a58a815f74ac", "packages": [ { "name": "adhocore/jwt", @@ -1551,16 +1551,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.2.0", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "2d0f474a106bb1da285f85e105c29b46085d3a43" + "reference": "d488223876f88f97bb76fd6681fed0df80558f62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/2d0f474a106bb1da285f85e105c29b46085d3a43", - "reference": "2d0f474a106bb1da285f85e105c29b46085d3a43", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/d488223876f88f97bb76fd6681fed0df80558f62", + "reference": "d488223876f88f97bb76fd6681fed0df80558f62", "shasum": "" }, "require": { @@ -1593,9 +1593,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.2.0" + "source": "https://github.com/utopia-php/messaging/tree/0.3.0" }, - "time": "2023-09-14T20:48:42+00:00" + "time": "2023-11-14T21:02:37+00:00" }, { "name": "utopia-php/migration", @@ -2417,16 +2417,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.36.2", + "version": "0.36.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "0aa67479d75f0e0cb7b60454031534d7f0abaece" + "reference": "8d932098009d62d37dda73cfe4ebc11f83e21405" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0aa67479d75f0e0cb7b60454031534d7f0abaece", - "reference": "0aa67479d75f0e0cb7b60454031534d7f0abaece", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8d932098009d62d37dda73cfe4ebc11f83e21405", + "reference": "8d932098009d62d37dda73cfe4ebc11f83e21405", "shasum": "" }, "require": { @@ -2462,9 +2462,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.2" + "source": "https://github.com/appwrite/sdk-generator/tree/0.36.4" }, - "time": "2024-01-19T01:04:35+00:00" + "time": "2024-02-20T16:36:15+00:00" }, { "name": "doctrine/deprecations", @@ -3047,16 +3047,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc" + "reference": "bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fad452781b3d774e3337b0c0b245dd8e5a4455fc", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353", + "reference": "bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353", "shasum": "" }, "require": { @@ -3099,9 +3099,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.1" }, - "time": "2024-01-11T11:49:22+00:00" + "time": "2024-01-18T19:15:27+00:00" }, { "name": "phpspec/prophecy", @@ -4657,16 +4657,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.8.1", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "14f5fff1e64118595db5408e946f3a22c75807f7" + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7", - "reference": "14f5fff1e64118595db5408e946f3a22c75807f7", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b", + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b", "shasum": "" }, "require": { @@ -4733,7 +4733,7 @@ "type": "open_collective" } ], - "time": "2024-01-11T20:47:48+00:00" + "time": "2024-02-16T15:06:51+00:00" }, { "name": "swoole/ide-helper", diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 1f3e29c8d5..7414148981 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -88,14 +88,29 @@ class Messaging extends Action return; } - $sms = match ($this->dsn->getHost()) { - 'mock' => new Mock($this->user, $this->secret), // used for tests - 'twilio' => new Twilio($this->user, $this->secret), - 'text-magic' => new TextMagic($this->user, $this->secret), - 'telesign' => new Telesign($this->user, $this->secret), - 'msg91' => new Msg91($this->user, $this->secret), - 'vonage' => new Vonage($this->user, $this->secret), - default => null + + switch ($this->dsn->getHost()) { + case 'mock': + $sms = new Mock($this->user, $this->secret); // used for tests + break; + case 'twilio': + $sms = new Twilio($this->user, $this->secret); + break; + case 'text-magic': + $sms = new TextMagic($this->user, $this->secret); + break; + case 'telesign': + $sms = new Telesign($this->user, $this->secret); + break; + case 'msg91': + $sms = new Msg91($this->user, $this->secret); + $sms->setTemplate($this->dsn->getParam('template')); + break; + case 'vonage': + $sms = new Vonage($this->user, $this->secret); + break; + default: + $sms = null; }; if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { From b2e1c162d25addd2bd7b3a4b97e5b96877fb6471 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:27:37 +0000 Subject: [PATCH 83/99] chore: fmt --- src/Appwrite/Platform/Workers/Messaging.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 7414148981..89d028b1a6 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -88,14 +88,14 @@ class Messaging extends Action return; } - + switch ($this->dsn->getHost()) { case 'mock': $sms = new Mock($this->user, $this->secret); // used for tests - break; + break; case 'twilio': $sms = new Twilio($this->user, $this->secret); - break; + break; case 'text-magic': $sms = new TextMagic($this->user, $this->secret); break; From 6567cff5dc2550ab279c8511219a9740cd3eb13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 21 Feb 2024 17:03:48 +0000 Subject: [PATCH 84/99] Fix missing todo --- app/controllers/general.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index e54d6c21e9..4486aa6d67 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -9,8 +9,6 @@ use Utopia\Logger\Logger; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Swoole\Http\Request as SwooleRequest; -use Utopia\Cache\Cache; -use Utopia\Pools\Group; use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use Appwrite\Utopia\Response; @@ -50,11 +48,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); - -->inject('geodb') -Reader $geodb - -function router(App $utopia, Database $dbForConsole, Database $dbForProject, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage) +function router(App $utopia, Database $dbForConsole, Database $dbForProject, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); @@ -387,7 +381,8 @@ App::init() ->inject('queueForCertificates') ->inject('queueForEvents') ->inject('queueForUsage') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Database $dbForProject, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage) { + ->inject('geodb') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Database $dbForProject, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { /* * Appwrite Router */ @@ -396,7 +391,7 @@ App::init() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage)) { + if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { return; } } @@ -750,7 +745,8 @@ App::options() ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForUsage') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage) { + ->inject('geodb') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { /* * Appwrite Router */ @@ -758,7 +754,7 @@ App::options() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage)) { + if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { return; } } From b03783c588f042805800886ad524962f265b0c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 21 Feb 2024 18:14:24 +0100 Subject: [PATCH 85/99] Fix bigs until works --- app/controllers/general.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 4486aa6d67..d9f6e5f280 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -48,7 +48,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, Database $dbForProject, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) +function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); @@ -126,6 +126,10 @@ function router(App $utopia, Database $dbForConsole, Database $dbForProject, Swo $requestHeaders = $request->getHeaders(); + $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + + $dbForProject = $getProjectDB($project); + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); if ($function->isEmpty() || !$function->getAttribute('enabled')) { @@ -372,7 +376,7 @@ App::init() ->inject('console') ->inject('project') ->inject('dbForConsole') - ->inject('dbForProject') + ->inject('getProjectDB') ->inject('user') ->inject('locale') ->inject('localeCodes') @@ -382,7 +386,7 @@ App::init() ->inject('queueForEvents') ->inject('queueForUsage') ->inject('geodb') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Database $dbForProject, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { /* * Appwrite Router */ @@ -391,7 +395,7 @@ App::init() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { return; } } @@ -742,11 +746,11 @@ App::options() ->inject('request') ->inject('response') ->inject('dbForConsole') - ->inject('dbForProject') + ->inject('getProjectDB') ->inject('queueForEvents') ->inject('queueForUsage') ->inject('geodb') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { /* * Appwrite Router */ @@ -754,7 +758,7 @@ App::options() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $dbForProject, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { return; } } From a8098831a366532b61eef591602555774b6a30ef Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 22 Feb 2024 12:21:48 +0530 Subject: [PATCH 86/99] Revert "usage/usage-dump queue health endpoints" --- .env | 2 +- app/config/collections.php | 28 +--- app/controllers/api/account.php | 2 +- app/controllers/api/avatars.php | 2 +- app/controllers/api/databases.php | 12 +- app/controllers/api/functions.php | 8 +- app/controllers/api/health.php | 55 -------- app/controllers/api/project.php | 8 +- app/controllers/api/storage.php | 9 +- app/controllers/api/users.php | 9 +- app/controllers/shared/api.php | 35 +++-- app/init.php | 2 +- docker-compose.yml | 30 +++-- .../references/health/get-queue-usage-dump.md | 1 - docs/references/health/get-queue-usage.md | 1 - src/Appwrite/Event/Delete.php | 15 --- src/Appwrite/Platform/Tasks/CalcTierStats.php | 2 +- .../Platform/Tasks/CreateInfMetric.php | 6 +- src/Appwrite/Platform/Workers/Deletes.php | 122 ++++++++++++++---- src/Appwrite/Platform/Workers/Hamster.php | 2 +- src/Appwrite/Platform/Workers/Usage.php | 24 ++-- src/Appwrite/Platform/Workers/UsageDump.php | 6 +- .../Specification/Format/OpenAPI3.php | 6 +- .../Specification/Format/Swagger2.php | 6 +- .../Health/HealthCustomServerTest.php | 48 ------- 25 files changed, 188 insertions(+), 253 deletions(-) delete mode 100644 docs/references/health/get-queue-usage-dump.md delete mode 100644 docs/references/health/get-queue-usage.md diff --git a/.env b/.env index 2373b618c2..b915f91516 100644 --- a/.env +++ b/.env @@ -78,7 +78,7 @@ _APP_MAINTENANCE_RETENTION_CACHE=2592000 _APP_MAINTENANCE_RETENTION_EXECUTION=1209600 _APP_MAINTENANCE_RETENTION_ABUSE=86400 _APP_MAINTENANCE_RETENTION_AUDIT=1209600 -_APP_USAGE_AGGREGATION_INTERVAL=30 +_APP_USAGE_AGGREGATION_INTERVAL=20 _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000 _APP_MAINTENANCE_RETENTION_SCHEDULES=86400 _APP_USAGE_STATS=enabled diff --git a/app/config/collections.php b/app/config/collections.php index 3bc58eff56..e2f3c11be7 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -34,28 +34,6 @@ $commonCollections = [ 'array' => false, 'filters' => [], ], - [ - '$id' => 'resourceType', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => 'accessedAt', 'type' => Database::VAR_DATETIME, @@ -1349,10 +1327,10 @@ $commonCollections = [ ] ], - 'stats' => [ + 'stats_v2' => [ '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('stats'), - 'name' => 'stats', + '$id' => ID::custom('stats_v2'), + 'name' => 'stats_v2', 'attributes' => [ [ '$id' => ID::custom('metric'), diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 17b2984471..68d2a544d8 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1791,7 +1791,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId()), + 'total' => $audit->countLogsByUser($user->getId()), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 5f2ea4c2da..e0d967eb00 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -76,7 +76,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro } if (empty($gitHubSession)) { - throw new Exception(Exception::USER_SESSION_NOT_FOUND, 'GitHub session not found.'); + throw new Exception(Exception::GENERAL_UNKNOWN, 'GitHub session not found.'); } $provider = $gitHubSession->getAttribute('provider', ''); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5fdb2edb2f..8684a7fae8 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3563,7 +3563,7 @@ App::get('/v1/databases/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -3571,7 +3571,7 @@ App::get('/v1/databases/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -3647,7 +3647,7 @@ App::get('/v1/databases/:databaseId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -3655,7 +3655,7 @@ App::get('/v1/databases/:databaseId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -3733,7 +3733,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -3741,7 +3741,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 45df54b709..d3913d180d 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -484,7 +484,7 @@ App::get('/v1/functions/:functionId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -492,7 +492,7 @@ App::get('/v1/functions/:functionId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -576,7 +576,7 @@ App::get('/v1/functions/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -584,7 +584,7 @@ App::get('/v1/functions/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index f7fea04fee..c007d629b6 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -659,60 +659,6 @@ App::get('/v1/health/queue/functions') $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); -App::get('/v1/health/queue/usage') - ->desc('Get usage queue') - ->groups(['api', 'health']) - ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueUsage') - ->label('sdk.description', '/docs/references/health/get-queue-usage.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) - ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') - ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { - $threshold = \intval($threshold); - - $client = new Client(Event::USAGE_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); - - if ($size >= $threshold) { - throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); - } - - $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }); - -App::get('/v1/health/queue/usage-dump') - ->desc('Get usage dump queue') - ->groups(['api', 'health']) - ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueUsage') - ->label('sdk.description', '/docs/references/health/get-queue-usage-dump.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) - ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') - ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { - $threshold = \intval($threshold); - - $client = new Client(Event::USAGE_DUMP_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); - - if ($size >= $threshold) { - throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); - } - - $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }); - App::get('/v1/health/storage/local') ->desc('Get local storage') ->groups(['api', 'health']) @@ -850,7 +796,6 @@ App::get('/v1/health/queue/failed/:name') Event::MAILS_QUEUE_NAME, Event::FUNCTIONS_QUEUE_NAME, Event::USAGE_QUEUE_NAME, - Event::USAGE_DUMP_QUEUE_NAME, Event::WEBHOOK_CLASS_NAME, Event::CERTIFICATES_QUEUE_NAME, Event::BUILDS_QUEUE_NAME, diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index a067c45588..47b94d3093 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -73,7 +73,7 @@ App::get('/v1/project/usage') Authorization::skip(function () use ($dbForProject, $firstDay, $lastDay, $period, $metrics, &$total, &$stats) { foreach ($metrics['total'] as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -81,7 +81,7 @@ App::get('/v1/project/usage') } foreach ($metrics['period'] as $metric) { - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::greaterThanEqual('time', $firstDay), @@ -116,7 +116,7 @@ App::get('/v1/project/usage') $id = $function->getId(); $name = $function->getAttribute('name'); $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS); - $value = $dbForProject->findOne('stats', [ + $value = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -132,7 +132,7 @@ App::get('/v1/project/usage') $id = $bucket->getId(); $name = $bucket->getAttribute('name'); $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); - $value = $dbForProject->findOne('stats', [ + $value = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index e4798fb51e..efe2515468 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1467,7 +1467,6 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') if ($deviceDeleted) { $queueForDeletes ->setType(DELETE_TYPE_CACHE_BY_RESOURCE) - ->setResourceType('bucket/' . $bucket->getId()) ->setResource('file/' . $fileId) ; @@ -1525,7 +1524,7 @@ App::get('/v1/storage/usage') $total = []; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1533,7 +1532,7 @@ App::get('/v1/storage/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -1610,7 +1609,7 @@ App::get('/v1/storage/:bucketId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1618,7 +1617,7 @@ App::get('/v1/storage/:bucketId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bbeef96f14..5ce2263f47 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -615,9 +615,6 @@ App::get('/v1/users/:userId/logs') $output[$i] = new Document([ 'event' => $log['event'], - 'userId' => ID::custom($log['data']['userId']), - 'userEmail' => $log['data']['userEmail'] ?? null, - 'userName' => $log['data']['userName'] ?? null, 'ip' => $log['ip'], 'time' => $log['time'], 'osCode' => $os['osCode'], @@ -646,7 +643,7 @@ App::get('/v1/users/:userId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId()), + 'total' => $audit->countLogsByUser($user->getId()), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -1266,7 +1263,7 @@ App::get('/v1/users/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $count => $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1274,7 +1271,7 @@ App::get('/v1/users/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 0423741e6d..df6ec002cb 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -252,22 +252,24 @@ App::init() ; $useCache = $route->getLabel('cache', false); + if ($useCache) { $key = md5($request->getURI() . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); $timestamp = 60 * 60 * 24 * 30; $data = $cache->load($key, $timestamp); - if (!empty($data) && !$cacheLog->isEmpty()) { - $parts = explode('/', $cacheLog->getAttribute('resourceType')); + if (!empty($data)) { + $data = json_decode($data, true); + $parts = explode('/', $data['resourceType']); $type = $parts[0] ?? null; if ($type === 'bucket') { $bucketId = $parts[1] ?? null; - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -279,12 +281,11 @@ App::init() $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); - if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $parts = explode('/', $cacheLog->getAttribute('resource')); + $parts = explode('/', $data['resource']); $fileId = $parts[1] ?? null; if ($fileSecurity && !$valid) { @@ -301,8 +302,8 @@ App::init() $response ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT') ->addHeader('X-Appwrite-Cache', 'hit') - ->setContentType($cacheLog->getAttribute('mimeType')) - ->send($data) + ->setContentType($data['contentType']) + ->send(base64_decode($data['payload'])) ; } else { $response->addHeader('X-Appwrite-Cache', 'miss'); @@ -533,6 +534,7 @@ App::shutdown() if ($useCache) { $resource = $resourceType = null; $data = $response->getPayload(); + if (!empty($data['payload'])) { $pattern = $route->getLabel('cache.resource', null); if (!empty($pattern)) { @@ -544,17 +546,22 @@ App::shutdown() $resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user); } - $key = md5($request->getURI() . '*' . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER; - $signature = md5($data['payload']); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $key = md5($request->getURI() . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER); + $data = json_encode([ + 'resourceType' => $resourceType, + 'resource' => $resource, + 'contentType' => $response->getContentType(), + 'payload' => base64_encode($data['payload']), + ]) ; + + $signature = md5($data); + $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); $now = DateTime::now(); if ($cacheLog->isEmpty()) { Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, - 'resourceType' => $resourceType, - 'mimeType' => $response->getContentType(), 'accessedAt' => $now, 'signature' => $signature, ]))); @@ -567,7 +574,7 @@ App::shutdown() $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); - $cache->save($key, $data['payload']); + $cache->save($key, $data); } } } diff --git a/app/init.php b/app/init.php index f27da88d24..80c3670eec 100644 --- a/app/init.php +++ b/app/init.php @@ -112,7 +112,7 @@ const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours -const APP_CACHE_BUSTER = 330; +const APP_CACHE_BUSTER = 329; const APP_VERSION_STABLE = '1.4.13'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; diff --git a/docker-compose.yml b/docker-compose.yml index ed912dc8e2..de71e3937a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -928,7 +928,6 @@ services: # - appwrite # volumes: # - appwrite-uploads:/storage/uploads - # Dev Tools Start ------------------------------------------------------------------------------------------ # # The Appwrite Team uses the following tools to help debug, monitor and diagnose the Appwrite stack @@ -937,9 +936,8 @@ services: # # MailCatcher - An SMTP server. Catches all system emails and displays them in a nice UI. # RequestCatcher - An HTTP server. Catches all system https calls and displays them using a simple HTTP API. Used to debug & tests webhooks and HTTP tasks - # Redis Insight - A nice UI for exploring Redis data - # Adminer - A nice UI for exploring MariaDB data - # GraphQl Explorer - A nice UI for exploring GraphQL API + # RedisCommander - A nice UI for exploring Redis data + # Webgrind - A nice UI for exploring and debugging code-level stuff maildev: # used mainly for dev tests image: appwrite/mailcatcher:1.0.0 @@ -969,15 +967,21 @@ services: networks: - appwrite - redis-insight: - image: redis/redisinsight:latest - restart: unless-stopped - networks: - - appwrite - environment: - - REDIS_HOSTS=redis - ports: - - "8081:5540" + # redis-commander: + # image: rediscommander/redis-commander:latest + # restart: unless-stopped + # networks: + # - appwrite + # environment: + # - REDIS_HOSTS=redis + # ports: + # - "8081:8081" + # webgrind: + # image: 'jokkedk/webgrind:latest' + # volumes: + # - './debug:/tmp' + # ports: + # - '3001:80' graphql-explorer: container_name: appwrite-graphql-explorer diff --git a/docs/references/health/get-queue-usage-dump.md b/docs/references/health/get-queue-usage-dump.md deleted file mode 100644 index 3c95da1b8a..0000000000 --- a/docs/references/health/get-queue-usage-dump.md +++ /dev/null @@ -1 +0,0 @@ -Get the number of projects containing metrics that are waiting to be processed in the Appwrite internal queue server. \ No newline at end of file diff --git a/docs/references/health/get-queue-usage.md b/docs/references/health/get-queue-usage.md deleted file mode 100644 index 8e5b64e642..0000000000 --- a/docs/references/health/get-queue-usage.md +++ /dev/null @@ -1 +0,0 @@ -Get the number of metrics that are waiting to be processed in the Appwrite internal queue server. \ No newline at end of file diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index 064fbcefa9..57300feb72 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -10,7 +10,6 @@ class Delete extends Event { protected string $type = ''; protected ?Document $document = null; - protected ?string $resourceType = null; protected ?string $resource = null; protected ?string $datetime = null; protected ?string $hourlyUsageRetentionDatetime = null; @@ -108,19 +107,6 @@ class Delete extends Event return $this; } - /** - * Sets the resource type for the delete event. - * - * @param string $resourceType - * @return self - */ - public function setResourceType(string $resourceType): self - { - $this->resourceType = $resourceType; - - return $this; - } - /** * Returns the set document for the delete event. * @@ -147,7 +133,6 @@ class Delete extends Event 'type' => $this->type, 'document' => $this->document, 'resource' => $this->resource, - 'resourceType' => $this->resourceType, 'datetime' => $this->datetime, 'hourlyUsageRetentionDatetime' => $this->hourlyUsageRetentionDatetime ]); diff --git a/src/Appwrite/Platform/Tasks/CalcTierStats.php b/src/Appwrite/Platform/Tasks/CalcTierStats.php index 05a28b418a..2c904973a9 100644 --- a/src/Appwrite/Platform/Tasks/CalcTierStats.php +++ b/src/Appwrite/Platform/Tasks/CalcTierStats.php @@ -270,7 +270,7 @@ class CalcTierStats extends Action $limit = $periods[$range]['limit']; $period = $periods[$range]['period']; - $requestDocs = $dbForProject->find('stats', [ + $requestDocs = $dbForProject->find('stats_v2', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), diff --git a/src/Appwrite/Platform/Tasks/CreateInfMetric.php b/src/Appwrite/Platform/Tasks/CreateInfMetric.php index 4b3f0e89fb..49b852ff6f 100644 --- a/src/Appwrite/Platform/Tasks/CreateInfMetric.php +++ b/src/Appwrite/Platform/Tasks/CreateInfMetric.php @@ -167,8 +167,8 @@ class CreateInfMetric extends Action try { $id = \md5("_inf_{$metric}"); - $dbForProject->deleteDocument('stats', $id); - $dbForProject->createDocument('stats', new Document([ + $dbForProject->deleteDocument('stats_v2', $id); + $dbForProject->createDocument('stats_v2', new Document([ '$id' => $id, 'metric' => $metric, 'period' => 'inf', @@ -190,7 +190,7 @@ class CreateInfMetric extends Action protected function getFromMetric(database $dbForProject, string $metric): int|float { - return $dbForProject->sum('stats', 'value', [ + return $dbForProject->sum('stats_v2', 'value', [ Query::equal('metric', [ $metric, ]), diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 37975979ce..96cb2d80cf 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -68,13 +68,18 @@ class Deletes extends Action $datetime = $payload['datetime'] ?? null; $hourlyUsageRetentionDatetime = $payload['hourlyUsageRetentionDatetime'] ?? null; $resource = $payload['resource'] ?? null; - $resourceType = $payload['resourceType'] ?? null; $document = new Document($payload['document'] ?? []); $project = new Document($payload['project'] ?? []); switch (strval($type)) { case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { + case DELETE_TYPE_DATABASES: + $this->deleteDatabase($getProjectDB, $document, $project); + break; + case DELETE_TYPE_COLLECTIONS: + $this->deleteCollection($getProjectDB, $document, $project); + break; case DELETE_TYPE_PROJECTS: $this->deleteProject($dbForConsole, $getProjectDB, $getFilesDevice, $getFunctionsDevice, $getBuildsDevice, $getCacheDevice, $document); break; @@ -103,6 +108,10 @@ class Deletes extends Action $this->deleteRule($dbForConsole, $document); break; default: + if (\str_starts_with($document->getCollection(), 'database_')) { + $this->deleteCollection($getProjectDB, $document, $project); + break; + } Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); break; } @@ -136,7 +145,7 @@ class Deletes extends Action $this->deleteUsageStats($project, $getProjectDB, $hourlyUsageRetentionDatetime); break; case DELETE_TYPE_CACHE_BY_RESOURCE: - $this->deleteCacheByResource($project, $getProjectDB, $resource, $resourceType); + $this->deleteCacheByResource($project, $getProjectDB, $resource); break; case DELETE_TYPE_CACHE_BY_TIMESTAMP: $this->deleteCacheByDate($project, $getProjectDB, $datetime); @@ -194,37 +203,32 @@ class Deletes extends Action * @param string $resource * @return void * @throws Authorization - * @param string|null $resourceType - * @throws Exception */ - private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, string $resourceType = null): void + private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource): void { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); + $document = $dbForProject->findOne('cache', [Query::equal('resource', [$resource])]); - $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) - ); + if ($document) { + $cache = new Cache( + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) + ); - $query[] = Query::equal('resource', [$resource]); - if (!empty($resourceType)) { - $query[] = Query::equal('resourceType', [$resourceType]); - } + $this->deleteById( + $document, + $dbForProject, + function ($document) use ($cache, $projectId) { + $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); - $this->deleteByGroup( - 'cache', - $query, - $dbForProject, - function (Document $document) use ($cache, $projectId) { - $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); - - if ($cache->purge($document->getId())) { - Console::success('Deleting cache file: ' . $path); - } else { - Console::error('Failed to delete cache file: ' . $path); + if ($cache->purge($document->getId())) { + Console::success('Deleting cache file: ' . $path); + } else { + Console::error('Failed to delete cache file: ' . $path); + } } - } - ); + ); + } } /** @@ -264,6 +268,72 @@ class Deletes extends Action ); } + /** + * @param callable $getProjectDB + * @param Document $document + * @param Document $project + * @return void + * @throws Exception + */ + private function deleteDatabase(callable $getProjectDB, Document $document, Document $project): void + { + $databaseId = $document->getId(); + $dbForProject = $getProjectDB($project); + + $this->deleteByGroup('database_' . $document->getInternalId(), [], $dbForProject, function ($document) use ($getProjectDB, $project) { + $this->deleteCollection($getProjectDB, $document, $project); + }); + + $dbForProject->deleteCollection('database_' . $document->getInternalId()); + $this->deleteAuditLogsByResource($getProjectDB, 'database/' . $databaseId, $project); + } + + /** + * @param callable $getProjectDB + * @param Document $document teams document + * @param Document $project + * @return void + * @throws Exception + */ + private function deleteCollection(callable $getProjectDB, Document $document, Document $project): void + { + $collectionId = $document->getId(); + $collectionInternalId = $document->getInternalId(); + $databaseId = $document->getAttribute('databaseId'); + $databaseInternalId = $document->getAttribute('databaseInternalId'); + + $dbForProject = $getProjectDB($project); + + $relationships = \array_filter( + $document->getAttribute('attributes'), + fn ($attribute) => $attribute['type'] === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + if (!$relationship['twoWay']) { + continue; + } + $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->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); + + $this->deleteByGroup('attributes', [ + Query::equal('databaseInternalId', [$databaseInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) + ], $dbForProject); + + $this->deleteByGroup('indexes', [ + Query::equal('databaseInternalId', [$databaseInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) + ], $dbForProject); + + $this->deleteAuditLogsByResource($getProjectDB, 'database/' . $databaseId . '/collection/' . $collectionId, $project); + } + /** * @param Database $dbForConsole * @param callable $getProjectDB @@ -275,7 +345,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); // Delete Usage stats - $this->deleteByGroup('stats', [ + $this->deleteByGroup('stats_v2', [ Query::lessThan('time', $hourlyUsageRetentionDatetime), Query::equal('period', ['1h']), ], $dbForProject); diff --git a/src/Appwrite/Platform/Workers/Hamster.php b/src/Appwrite/Platform/Workers/Hamster.php index 6239f842e0..0fb705d0f7 100644 --- a/src/Appwrite/Platform/Workers/Hamster.php +++ b/src/Appwrite/Platform/Workers/Hamster.php @@ -286,7 +286,7 @@ class Hamster extends Action $limit = $periodValue['limit']; $period = $periodValue['period']; - $requestDocs = $dbForProject->find('stats', [ + $requestDocs = $dbForProject->find('stats_v2', [ Query::equal('period', [$period]), Query::equal('metric', [$metric]), Query::limit($limit), diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/Usage.php index 718dca8514..35c0e02cef 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/Usage.php @@ -130,8 +130,8 @@ class Usage extends Action } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); + $collections = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); if (!empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, @@ -149,7 +149,7 @@ class Usage extends Action case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; - $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); + $documents = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); if (!empty($documents['value'])) { $metrics[] = [ @@ -164,8 +164,8 @@ class Usage extends Action break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -183,13 +183,13 @@ class Usage extends Action break; case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats_v2', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/UsageDump.php index 1d296a929e..5a4324fd3e 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/UsageDump.php @@ -78,7 +78,7 @@ class UsageDump extends Action $id = \md5("{$time}_{$period}_{$key}"); try { - $dbForProject->createDocument('stats', new Document([ + $dbForProject->createDocument('stats_v2', new Document([ '$id' => $id, 'period' => $period, 'time' => $time, @@ -89,14 +89,14 @@ class UsageDump extends Action } catch (Duplicate $th) { if ($value < 0) { $dbForProject->decreaseDocumentAttribute( - 'stats', + 'stats_v2', $id, 'value', abs($value) ); } else { $dbForProject->increaseDocumentAttribute( - 'stats', + 'stats_v2', $id, 'value', $value diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index ce86235634..863966eedd 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -295,7 +295,7 @@ class OpenAPI3 extends Format switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Validator\Boolean': $node['schema']['type'] = $validator->getType(); @@ -303,14 +303,14 @@ class OpenAPI3 extends Format break; case 'Utopia\Database\Validator\UID': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Appwrite\Utopia\Database\Validator\CustomId': if ($route->getLabel('sdk.methodType', '') === 'upload') { $node['schema']['x-upload-id'] = true; } $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\DatetimeValidator': $node['schema']['type'] = $validator->getType(); diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index a458c30aa6..c6ae7a7ff1 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -297,7 +297,7 @@ class Swagger2 extends Format switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['type'] = $validator->getType(); - $node['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Validator\Boolean': $node['type'] = $validator->getType(); @@ -308,11 +308,11 @@ class Swagger2 extends Format $node['x-upload-id'] = true; } $node['type'] = $validator->getType(); - $node['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\UID': $node['type'] = $validator->getType(); - $node['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\DatetimeValidator': $node['type'] = $validator->getType(); diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 091b3bb781..dde89a6a71 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -512,52 +512,4 @@ class HealthCustomServerTest extends Scope return []; } - - public function testUsageSuccess() - { - /** - * Test for SUCCESS - */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), []); - - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertIsInt($response['body']['size']); - $this->assertLessThan(100, $response['body']['size']); - - /** - * Test for FAILURE - */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage?threshold=0', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), []); - $this->assertEquals(503, $response['headers']['status-code']); - } - - public function testUsageDumpSuccess() - { - /** - * Test for SUCCESS - */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage-dump', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), []); - - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertIsInt($response['body']['size']); - $this->assertLessThan(100, $response['body']['size']); - - /** - * Test for FAILURE - */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage-dump?threshold=0', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), []); - $this->assertEquals(503, $response['headers']['status-code']); - } } From d2787c85553154597d6955d064deb85c316a2b44 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 22 Feb 2024 12:26:01 +0530 Subject: [PATCH 87/99] Revert "Fix: Router CURL" --- app/controllers/general.php | 275 +++++++----------------------------- 1 file changed, 48 insertions(+), 227 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index d9f6e5f280..bfec8b46be 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -9,8 +9,9 @@ use Utopia\Logger\Logger; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Swoole\Http\Request as SwooleRequest; +use Utopia\Cache\Cache; +use Utopia\Pools\Group; use Appwrite\Utopia\Request; -use MaxMind\Db\Reader; use Appwrite\Utopia\Response; use Appwrite\Utopia\View; use Appwrite\Extend\Exception as AppwriteException; @@ -18,9 +19,6 @@ use Utopia\Config\Config; use Utopia\Domains\Domain; use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; -use Appwrite\Event\Event; -use Appwrite\Event\Usage; -use Appwrite\ID; use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Response\Filters\V11 as ResponseV11; use Appwrite\Utopia\Response\Filters\V12 as ResponseV12; @@ -40,7 +38,6 @@ use Appwrite\Utopia\Request\Filters\V13 as RequestV13; use Appwrite\Utopia\Request\Filters\V14 as RequestV14; use Appwrite\Utopia\Request\Filters\V15 as RequestV15; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; -use Executor\Executor; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; @@ -48,7 +45,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) +function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleRequest, Request $request, Response $response) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); @@ -120,226 +117,49 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $path .= '?' . $query; } - - $body = $swooleRequest->getContent() ?? ''; - $method = $swooleRequest->server['request_method']; - $requestHeaders = $request->getHeaders(); - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); - - $dbForProject = $getProjectDB($project); - - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - - if ($function->isEmpty() || !$function->getAttribute('enabled')) { - throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND); - } - - $version = $function->getAttribute('version', 'v2'); - $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); - - $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; - - if (\is_null($runtime)) { - throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); - } - - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); - - if ($deployment->getAttribute('resourceId') !== $function->getId()) { - throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); - } - - if ($deployment->isEmpty()) { - throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); - } - - /** Check if build has completed */ - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - if ($build->isEmpty()) { - throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { - throw new AppwriteException(AppwriteException::BUILD_NOT_READY); - } - - $permissions = $function->getAttribute('execute'); - - if (!(\in_array('any', $permissions)) && (\in_array('guests', $permissions))) { - throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"'); - } - - $headers = \array_merge([], $requestHeaders); - $headers['x-appwrite-trigger'] = 'http'; - $headers['x-appwrite-user-id'] = ''; - $headers['x-appwrite-user-jwt'] = ''; - $headers['x-appwrite-country-code'] = ''; - $headers['x-appwrite-continent-code'] = ''; - $headers['x-appwrite-continent-eu'] = 'false'; - - $ip = $headers['x-real-ip'] ?? ''; - if (!empty($ip)) { - $record = $geodb->get($ip); - - if ($record) { - $eu = Config::getParam('locale-eu'); - - $headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? ''; - $headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? ''; - $headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false'; - } - } - - $headersFiltered = []; - foreach ($headers as $key => $value) { - if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) { - $headersFiltered[] = ['name' => $key, 'value' => $value]; - } - } - - $executionId = ID::unique(); - - $execution = new Document([ - '$id' => $executionId, - '$permissions' => [], - 'functionInternalId' => $function->getInternalId(), - 'functionId' => $function->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'trigger' => 'http', // http / schedule / event - 'status' => 'processing', // waiting / processing / completed / failed - 'responseStatusCode' => 0, - 'responseHeaders' => [], - 'requestPath' => $path, - 'requestMethod' => $method, - 'requestHeaders' => $headersFiltered, - 'errors' => '', - 'logs' => '', - 'duration' => 0.0, - 'search' => implode(' ', [$functionId, $executionId]), + $body = \json_encode([ + 'async' => false, + 'body' => $swooleRequest->getContent() ?? '', + 'method' => $swooleRequest->server['request_method'], + 'path' => $path, + 'headers' => $requestHeaders ]); - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('executionId', $execution->getId()) - ->setContext('function', $function); + $headers = [ + 'Content-Type: application/json', + 'Content-Length: ' . \strlen($body), + 'X-Appwrite-Project: ' . $projectId + ]; - $durationStart = \microtime(true); + $ch = \curl_init(); + \curl_setopt($ch, CURLOPT_URL, "http://localhost/v1/functions/{$functionId}/executions"); + \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + // \curl_setopt($ch, CURLOPT_HEADER, true); + \curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + \curl_setopt($ch, CURLOPT_TIMEOUT, 30); - $vars = []; + $executionResponse = \curl_exec($ch); + $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE); + $error = \curl_error($ch); + $errNo = \curl_errno($ch); - // V2 vars - if ($version === 'v2') { - $vars = \array_merge($vars, [ - 'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '', - 'APPWRITE_FUNCTION_DATA' => $body ?? '', - 'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '', - 'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? '' - ]); + \curl_close($ch); + + if ($errNo !== 0) { + throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Internal error: " . $error); } - // Shared vars - foreach ($function->getAttribute('varsProject', []) as $var) { - $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + if ($statusCode >= 400) { + $error = \json_decode($executionResponse, true)['message']; + throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Execution error: " . $error); } - // Function vars - foreach ($function->getAttribute('vars', []) as $var) { - $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); - } - - // Appwrite vars - $vars = \array_merge($vars, [ - 'APPWRITE_FUNCTION_ID' => $functionId, - 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), - 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), - 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), - 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', - 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - ]); - - /** Execute function */ - $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); - try { - $version = $function->getAttribute('version', 'v2'); - $command = $runtime['startCommand']; - $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; - $executionResponse = $executor->createExecution( - projectId: $project->getId(), - deploymentId: $deployment->getId(), - body: \strlen($body) > 0 ? $body : null, - variables: $vars, - timeout: $function->getAttribute('timeout', 0), - image: $runtime['image'], - source: $build->getAttribute('path', ''), - entrypoint: $deployment->getAttribute('entrypoint', ''), - version: $version, - path: $path, - method: $method, - headers: $headers, - runtimeEntrypoint: $command, - requestTimeout: 30 - ); - - $headersFiltered = []; - foreach ($executionResponse['headers'] as $key => $value) { - if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { - $headersFiltered[] = ['name' => $key, 'value' => $value]; - } - } - - /** Update execution status */ - $status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed'; - $execution->setAttribute('status', $status); - $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); - $execution->setAttribute('responseHeaders', $headersFiltered); - $execution->setAttribute('logs', $executionResponse['logs']); - $execution->setAttribute('errors', $executionResponse['errors']); - $execution->setAttribute('duration', $executionResponse['duration']); - } catch (\Throwable $th) { - $durationEnd = \microtime(true); - - $execution - ->setAttribute('duration', $durationEnd - $durationStart) - ->setAttribute('status', 'failed') - ->setAttribute('responseStatusCode', 500) - ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); - Console::error($th->getMessage()); - } finally { - $queueForUsage - ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) - ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function - ; - } - - if ($function->getAttribute('logging')) { - /** @var Document $execution */ - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); - } - - $execution->setAttribute('logs', ''); - $execution->setAttribute('errors', ''); - - $headers = []; - foreach (($executionResponse['headers'] ?? []) as $key => $value) { - $headers[] = ['name' => $key, 'value' => $value]; - } - - $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); - $execution->setAttribute('responseHeaders', $headers); - - $body = $execution['responseBody'] ?? ''; - - $encodingKey = \array_search('x-open-runtimes-encoding', \array_column($execution['responseHeaders'], 'name')); - if ($encodingKey !== false) { - if (($execution['responseHeaders'][$encodingKey]['value'] ?? '') === 'base64') { - $body = \base64_decode($body); - } - } + $execution = \json_decode($executionResponse, true); $contentType = 'text/plain'; foreach ($execution['responseHeaders'] as $header) { @@ -350,6 +170,15 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $response->setHeader($header['name'], $header['value']); } + $body = $execution['responseBody'] ?? ''; + + $encodingKey = \array_search('x-open-runtimes-encoding', \array_column($execution['responseHeaders'], 'name')); + if ($encodingKey !== false) { + if (($execution['responseHeaders'][$encodingKey]['value'] ?? '') === 'base64') { + $body = \base64_decode($body); + } + } + $response ->setContentType($contentType) ->setStatusCode($execution['responseStatusCode'] ?? 200) @@ -376,17 +205,13 @@ App::init() ->inject('console') ->inject('project') ->inject('dbForConsole') - ->inject('getProjectDB') ->inject('user') ->inject('locale') ->inject('localeCodes') ->inject('clients') ->inject('servers') ->inject('queueForCertificates') - ->inject('queueForEvents') - ->inject('queueForUsage') - ->inject('geodb') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates) { /* * Appwrite Router */ @@ -395,7 +220,7 @@ App::init() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { + if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) { return; } } @@ -746,11 +571,7 @@ App::options() ->inject('request') ->inject('response') ->inject('dbForConsole') - ->inject('getProjectDB') - ->inject('queueForEvents') - ->inject('queueForUsage') - ->inject('geodb') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole) { /* * Appwrite Router */ @@ -758,7 +579,7 @@ App::options() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { + if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) { return; } } From c04f54da647aead11c0d9adeea7c4077e5f78546 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 22 Feb 2024 15:10:18 +0530 Subject: [PATCH 88/99] Revert "Revert "Fix: Router CURL"" --- app/controllers/general.php | 267 ++++++++++++++++++++++++++++++------ 1 file changed, 223 insertions(+), 44 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index bfec8b46be..d9f6e5f280 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -9,9 +9,8 @@ use Utopia\Logger\Logger; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Swoole\Http\Request as SwooleRequest; -use Utopia\Cache\Cache; -use Utopia\Pools\Group; use Appwrite\Utopia\Request; +use MaxMind\Db\Reader; use Appwrite\Utopia\Response; use Appwrite\Utopia\View; use Appwrite\Extend\Exception as AppwriteException; @@ -19,6 +18,9 @@ use Utopia\Config\Config; use Utopia\Domains\Domain; use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; +use Appwrite\Event\Event; +use Appwrite\Event\Usage; +use Appwrite\ID; use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Response\Filters\V11 as ResponseV11; use Appwrite\Utopia\Response\Filters\V12 as ResponseV12; @@ -38,6 +40,7 @@ use Appwrite\Utopia\Request\Filters\V13 as RequestV13; use Appwrite\Utopia\Request\Filters\V14 as RequestV14; use Appwrite\Utopia\Request\Filters\V15 as RequestV15; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; +use Executor\Executor; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; @@ -45,7 +48,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleRequest, Request $request, Response $response) +function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); @@ -117,59 +120,218 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques $path .= '?' . $query; } + + $body = $swooleRequest->getContent() ?? ''; + $method = $swooleRequest->server['request_method']; + $requestHeaders = $request->getHeaders(); - $body = \json_encode([ - 'async' => false, - 'body' => $swooleRequest->getContent() ?? '', - 'method' => $swooleRequest->server['request_method'], - 'path' => $path, - 'headers' => $requestHeaders + $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + + $dbForProject = $getProjectDB($project); + + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + + if ($function->isEmpty() || !$function->getAttribute('enabled')) { + throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND); + } + + $version = $function->getAttribute('version', 'v2'); + $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); + + $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; + + if (\is_null($runtime)) { + throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + } + + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); + + if ($deployment->getAttribute('resourceId') !== $function->getId()) { + throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + } + + if ($deployment->isEmpty()) { + throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + } + + /** Check if build has completed */ + $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); + if ($build->isEmpty()) { + throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND); + } + + if ($build->getAttribute('status') !== 'ready') { + throw new AppwriteException(AppwriteException::BUILD_NOT_READY); + } + + $permissions = $function->getAttribute('execute'); + + if (!(\in_array('any', $permissions)) && (\in_array('guests', $permissions))) { + throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"'); + } + + $headers = \array_merge([], $requestHeaders); + $headers['x-appwrite-trigger'] = 'http'; + $headers['x-appwrite-user-id'] = ''; + $headers['x-appwrite-user-jwt'] = ''; + $headers['x-appwrite-country-code'] = ''; + $headers['x-appwrite-continent-code'] = ''; + $headers['x-appwrite-continent-eu'] = 'false'; + + $ip = $headers['x-real-ip'] ?? ''; + if (!empty($ip)) { + $record = $geodb->get($ip); + + if ($record) { + $eu = Config::getParam('locale-eu'); + + $headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? ''; + $headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? ''; + $headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false'; + } + } + + $headersFiltered = []; + foreach ($headers as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } + } + + $executionId = ID::unique(); + + $execution = new Document([ + '$id' => $executionId, + '$permissions' => [], + 'functionInternalId' => $function->getInternalId(), + 'functionId' => $function->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentId' => $deployment->getId(), + 'trigger' => 'http', // http / schedule / event + 'status' => 'processing', // waiting / processing / completed / failed + 'responseStatusCode' => 0, + 'responseHeaders' => [], + 'requestPath' => $path, + 'requestMethod' => $method, + 'requestHeaders' => $headersFiltered, + 'errors' => '', + 'logs' => '', + 'duration' => 0.0, + 'search' => implode(' ', [$functionId, $executionId]), ]); - $headers = [ - 'Content-Type: application/json', - 'Content-Length: ' . \strlen($body), - 'X-Appwrite-Project: ' . $projectId - ]; + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('executionId', $execution->getId()) + ->setContext('function', $function); - $ch = \curl_init(); - \curl_setopt($ch, CURLOPT_URL, "http://localhost/v1/functions/{$functionId}/executions"); - \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); - \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - // \curl_setopt($ch, CURLOPT_HEADER, true); - \curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); - \curl_setopt($ch, CURLOPT_TIMEOUT, 30); + $durationStart = \microtime(true); - $executionResponse = \curl_exec($ch); - $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE); - $error = \curl_error($ch); - $errNo = \curl_errno($ch); + $vars = []; - \curl_close($ch); - - if ($errNo !== 0) { - throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Internal error: " . $error); + // V2 vars + if ($version === 'v2') { + $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '', + 'APPWRITE_FUNCTION_DATA' => $body ?? '', + 'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '', + 'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? '' + ]); } - if ($statusCode >= 400) { - $error = \json_decode($executionResponse, true)['message']; - throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Execution error: " . $error); + // Shared vars + foreach ($function->getAttribute('varsProject', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); } - $execution = \json_decode($executionResponse, true); + // Function vars + foreach ($function->getAttribute('vars', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + } - $contentType = 'text/plain'; - foreach ($execution['responseHeaders'] as $header) { - if (\strtolower($header['name']) === 'content-type') { - $contentType = $header['value']; + // Appwrite vars + $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_ID' => $functionId, + 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), + 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), + 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), + 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', + 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', + ]); + + /** Execute function */ + $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); + try { + $version = $function->getAttribute('version', 'v2'); + $command = $runtime['startCommand']; + $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; + $executionResponse = $executor->createExecution( + projectId: $project->getId(), + deploymentId: $deployment->getId(), + body: \strlen($body) > 0 ? $body : null, + variables: $vars, + timeout: $function->getAttribute('timeout', 0), + image: $runtime['image'], + source: $build->getAttribute('path', ''), + entrypoint: $deployment->getAttribute('entrypoint', ''), + version: $version, + path: $path, + method: $method, + headers: $headers, + runtimeEntrypoint: $command, + requestTimeout: 30 + ); + + $headersFiltered = []; + foreach ($executionResponse['headers'] as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } } - $response->setHeader($header['name'], $header['value']); + /** Update execution status */ + $status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed'; + $execution->setAttribute('status', $status); + $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); + $execution->setAttribute('responseHeaders', $headersFiltered); + $execution->setAttribute('logs', $executionResponse['logs']); + $execution->setAttribute('errors', $executionResponse['errors']); + $execution->setAttribute('duration', $executionResponse['duration']); + } catch (\Throwable $th) { + $durationEnd = \microtime(true); + + $execution + ->setAttribute('duration', $durationEnd - $durationStart) + ->setAttribute('status', 'failed') + ->setAttribute('responseStatusCode', 500) + ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); + Console::error($th->getMessage()); + } finally { + $queueForUsage + ->addMetric(METRIC_EXECUTIONS, 1) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ; } + if ($function->getAttribute('logging')) { + /** @var Document $execution */ + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + } + + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); + + $headers = []; + foreach (($executionResponse['headers'] ?? []) as $key => $value) { + $headers[] = ['name' => $key, 'value' => $value]; + } + + $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); + $execution->setAttribute('responseHeaders', $headers); + $body = $execution['responseBody'] ?? ''; $encodingKey = \array_search('x-open-runtimes-encoding', \array_column($execution['responseHeaders'], 'name')); @@ -179,6 +341,15 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques } } + $contentType = 'text/plain'; + foreach ($execution['responseHeaders'] as $header) { + if (\strtolower($header['name']) === 'content-type') { + $contentType = $header['value']; + } + + $response->setHeader($header['name'], $header['value']); + } + $response ->setContentType($contentType) ->setStatusCode($execution['responseStatusCode'] ?? 200) @@ -205,13 +376,17 @@ App::init() ->inject('console') ->inject('project') ->inject('dbForConsole') + ->inject('getProjectDB') ->inject('user') ->inject('locale') ->inject('localeCodes') ->inject('clients') ->inject('servers') ->inject('queueForCertificates') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates) { + ->inject('queueForEvents') + ->inject('queueForUsage') + ->inject('geodb') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { /* * Appwrite Router */ @@ -220,7 +395,7 @@ App::init() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { return; } } @@ -571,7 +746,11 @@ App::options() ->inject('request') ->inject('response') ->inject('dbForConsole') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole) { + ->inject('getProjectDB') + ->inject('queueForEvents') + ->inject('queueForUsage') + ->inject('geodb') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { /* * Appwrite Router */ @@ -579,7 +758,7 @@ App::options() $mainDomain = App::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) { + if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) { return; } } From 141cdf4c822ff7a6c9f46b339d62d5802f49dc72 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Fri, 23 Feb 2024 20:10:25 +0530 Subject: [PATCH 89/99] Fix content-type of file --- app/controllers/api/health.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index c007d629b6..d9faf998e6 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -722,7 +722,7 @@ App::get('/v1/health/storage') $checkStart = \microtime(true); foreach ($devices as $device) { - if (!$device->write($device->getPath('health.txt'), 'test', '')) { + if (!$device->write($device->getPath('health.txt'), 'test', 'text/plain')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); } From 8c4473932ff61ad28541383f798f131e82b79d26 Mon Sep 17 00:00:00 2001 From: Utkarsh Ahuja Date: Sat, 24 Feb 2024 10:55:33 +0000 Subject: [PATCH 90/99] fix: list api select query --- app/controllers/api/databases.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5fdb2edb2f..ef30d062f9 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2997,6 +2997,33 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); } + $select = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT); + }, false); + + // Check if the SELECT query includes $databaseId and $collectionId + $hasDatabaseId = false; + $hasCollectionId = false; + if ($select) { + $hasDatabaseId = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues())); + }, false); + $hasCollectionId = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues())); + }, false); + } + + if ($select) { + foreach ($documents as $document) { + if (!$hasDatabaseId) { + $document->removeAttribute('$databaseId'); + } + if (!$hasCollectionId) { + $document->removeAttribute('$collectionId'); + } + } + } + $response->dynamic(new Document([ 'total' => $total, 'documents' => $documents, From ca1c83c2cf68a839f11a470034ff003959ee3e29 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sat, 24 Feb 2024 14:33:38 +0000 Subject: [PATCH 91/99] method to reset attachment --- src/Appwrite/Event/Mail.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index ca8fe7d202..bbd05a018f 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -338,6 +338,14 @@ class Mail extends Event return $this; } + /** + * Set attachment + * @param string $content + * @param string $filename + * @param string $encoding + * @param string $type + * @return self + */ public function setAttachment(string $content, string $filename, string $encoding = 'base64', string $type = 'plain/text') { $this->attachment = [ @@ -349,11 +357,27 @@ class Mail extends Event return $this; } + /** + * Get attachment + * + * @return array + */ public function getAttachment(): array { return $this->attachment; } + /** + * Reset attachment + * + * @return self + */ + public function resetAttachment(): self + { + $this->attachment = []; + return $this; + } + /** * Executes the event and sends it to the mails worker. * From ea484e593b9325e99e1dd45ed8a374595074d7c1 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sat, 24 Feb 2024 14:49:17 +0000 Subject: [PATCH 92/99] format --- src/Appwrite/Event/Mail.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index bbd05a018f..ac021e71a2 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -359,7 +359,7 @@ class Mail extends Event /** * Get attachment - * + * * @return array */ public function getAttachment(): array @@ -369,7 +369,7 @@ class Mail extends Event /** * Reset attachment - * + * * @return self */ public function resetAttachment(): self From d91a0e30481b0ade36ec837c866baf038124b91a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sat, 24 Feb 2024 14:56:53 +0000 Subject: [PATCH 93/99] reset variables --- src/Appwrite/Event/Mail.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index ac021e71a2..6ded33e02e 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -378,6 +378,23 @@ class Mail extends Event return $this; } + /** + * Reset + * + * @return self + */ + public function reset(): self + { + $this->project = null; + $this->recipient = ''; + $this->name = ''; + $this->subject = ''; + $this->body = ''; + $this->variables = []; + $this->bodyTemplate = ''; + $this->attachment = []; + } + /** * Executes the event and sends it to the mails worker. * From 9fe0a5a31b71f4d2016ff7c2f355596c07adeb26 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sat, 24 Feb 2024 21:03:18 +0545 Subject: [PATCH 94/99] Update Mail.php --- src/Appwrite/Event/Mail.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index 6ded33e02e..9bdbf6044d 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -393,6 +393,7 @@ class Mail extends Event $this->variables = []; $this->bodyTemplate = ''; $this->attachment = []; + return $this; } /** From e7a847a417f891e0a5d217bc56899be25b3ece25 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 24 Feb 2024 19:01:00 +0100 Subject: [PATCH 95/99] Fixed ID class namespace --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index d9f6e5f280..87008a7c4a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -20,7 +20,6 @@ use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; use Appwrite\Event\Event; use Appwrite\Event\Usage; -use Appwrite\ID; use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Response\Filters\V11 as ResponseV11; use Appwrite\Utopia\Response\Filters\V12 as ResponseV12; @@ -33,6 +32,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Validator\Hostname; use Appwrite\Utopia\Request\Filters\V12 as RequestV12; From b78725e650dbcf797ba9dba2f25dc69459f6f90a Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 24 Feb 2024 19:12:27 +0100 Subject: [PATCH 96/99] Hide error messages from HTML templates --- app/controllers/general.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 87008a7c4a..e945189b24 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -936,10 +936,10 @@ App::error() ->setParam('development', App::isDevelopment()) ->setParam('projectName', $project->getAttribute('name')) ->setParam('projectURL', $project->getAttribute('url')) - ->setParam('message', $error->getMessage()) - ->setParam('type', $type) - ->setParam('code', $code) - ->setParam('trace', $trace); + ->setParam('message', $output['message'] ?? '') + ->setParam('type', $output['type'] ?? '') + ->setParam('code', $output['code'] ?? '') + ->setParam('trace', $output['trace'] ?? []); $response->html($layout->render()); } From faeb9aa8d4c6174c1c88b948910cbed9eb49494a Mon Sep 17 00:00:00 2001 From: Utkarsh Ahuja Date: Sun, 25 Feb 2024 14:22:12 +0000 Subject: [PATCH 97/99] tests: internal id in query select --- tests/e2e/Services/Databases/DatabasesBase.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 4d5eb4b803..dbb6d795c6 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -4068,6 +4068,8 @@ trait DatabasesBase $this->assertEquals(2, count($response['body']['documents'])); $this->assertEquals(null, $response['body']['documents'][0]['fullName']); $this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$collectionId', $response['body']['documents'][0]); } /** @@ -4087,6 +4089,8 @@ trait DatabasesBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$collectionId', $response['body']['documents'][0]); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4099,6 +4103,8 @@ trait DatabasesBase $document = $response['body']['documents'][0]; $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); + $this->assertArrayNotHasKey('$databaseId', $document); + $this->assertArrayNotHasKey('$collectionId', $document); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', From 3a8c5a2e65c3b6b24caac31ad1f288d15a1ddfe4 Mon Sep 17 00:00:00 2001 From: navjotNSK Date: Sat, 24 Feb 2024 18:49:43 +0530 Subject: [PATCH 98/99] Default value added for name --- app/controllers/api/account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 17b2984471..0536f3f1b3 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2526,7 +2526,7 @@ App::post('/v1/account/recovery') $queueForMails ->setRecipient($profile->getAttribute('email', '')) - ->setName($profile->getAttribute('name')) + ->setName($profile->getAttribute('name','')) ->setBody($body) ->setVariables($emailVariables) ->setSubject($subject) From cab2233816a9d87c3fa8aa630cf1d7bc7c58969b Mon Sep 17 00:00:00 2001 From: navjotNSK Date: Sat, 24 Feb 2024 18:51:00 +0530 Subject: [PATCH 99/99] Formatting --- app/controllers/api/account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 0536f3f1b3..b59ab40e0d 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2526,7 +2526,7 @@ App::post('/v1/account/recovery') $queueForMails ->setRecipient($profile->getAttribute('email', '')) - ->setName($profile->getAttribute('name','')) + ->setName($profile->getAttribute('name', '')) ->setBody($body) ->setVariables($emailVariables) ->setSubject($subject)