From ac90f8fddc8bafce19be01f66f0e9f076f43d423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 30 Jun 2022 14:37:20 +0200 Subject: [PATCH 01/29] Deprecate all parameter --- app/tasks/install.php | 2 +- docs/sdks/cli/GETTING_STARTED.md | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/app/tasks/install.php b/app/tasks/install.php index 6349a162fa..e6fe5f4439 100644 --- a/app/tasks/install.php +++ b/app/tasks/install.php @@ -25,7 +25,7 @@ $cli * 2. Check for older setup and get older version - DONE * 2.1 If older version is equal or bigger(?) than current version, **stop setup** * 2.2. Get ENV vars - DONE - * 2.2.1 Fetch from older docker-compose.yml file + * 2.2.1 Fetch from older ompo.yml file * 2.2.2 Fetch from older .env file (manually parse) * 2.3 Use old ENV vars as default values * 2.4 Ask for all required vars not given as CLI args and if in interactive mode diff --git a/docs/sdks/cli/GETTING_STARTED.md b/docs/sdks/cli/GETTING_STARTED.md index 2c71d37c0b..4d0f6fcba7 100644 --- a/docs/sdks/cli/GETTING_STARTED.md +++ b/docs/sdks/cli/GETTING_STARTED.md @@ -31,12 +31,6 @@ You can also fetch all the collections in your current project using appwrite init collection ``` -The CLI also comes with a convenient `--all` flag to perform both these steps at once. - -```sh -appwrite init --all -``` - * ### Creating and deploying cloud functions The CLI makes it extremely easy to create and deploy Appwrite's cloud functions. Initialise your new function using @@ -82,12 +76,6 @@ Similarly, you can deploy all your collections to your Appwrite server using appwrite deploy collections ``` -The `deploy` command also comes with a convenient `--all` flag to deploy all your functions and collections at once. - -```sh -appwrite deploy --all -``` - > ### Note > By default, requests to domains with self signed SSL certificates (or no certificates) are disabled. If you trust the domain, you can bypass the certificate validation using ```sh From 4acd56e6611166381b76dbcbb5388fe286d4bb42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 1 Jul 2022 08:13:33 +0200 Subject: [PATCH 02/29] Update app/tasks/install.php Co-authored-by: Christy Jacob --- app/tasks/install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/tasks/install.php b/app/tasks/install.php index e6fe5f4439..6349a162fa 100644 --- a/app/tasks/install.php +++ b/app/tasks/install.php @@ -25,7 +25,7 @@ $cli * 2. Check for older setup and get older version - DONE * 2.1 If older version is equal or bigger(?) than current version, **stop setup** * 2.2. Get ENV vars - DONE - * 2.2.1 Fetch from older ompo.yml file + * 2.2.1 Fetch from older docker-compose.yml file * 2.2.2 Fetch from older .env file (manually parse) * 2.3 Use old ENV vars as default values * 2.4 Ask for all required vars not given as CLI args and if in interactive mode From 10884f2371881f4876d6eeed13ebfa255340fb62 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 4 Jul 2022 13:52:29 +0545 Subject: [PATCH 03/29] fix typo --- docs/sdks/dart/CHANGELOG.md | 4 ++-- docs/sdks/flutter/CHANGELOG.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sdks/dart/CHANGELOG.md b/docs/sdks/dart/CHANGELOG.md index 7d8f2aefc0..23aea11553 100644 --- a/docs/sdks/dart/CHANGELOG.md +++ b/docs/sdks/dart/CHANGELOG.md @@ -5,8 +5,8 @@ * **BREAKING** `dateCreated` attribute removed from `Team`, `Execution`, `File` models * **BREAKING** `dateCreated` and `dateUpdated` attribute removed from `Func`, `Deployment`, `Bucket` models * **BREAKING** Realtime channels - * collections.[COLLECTION_ID] is now databases.[DATABASE_ID].ollections.[COLLECTION_ID] - * collections.[COLLECTION_ID].documents is now databases.[DATABASE_ID].ollections.[COLLECTION_ID].documents + * collections.[COLLECTION_ID] is now databases.[DATABASE_ID].collections.[COLLECTION_ID] + * collections.[COLLECTION_ID].documents is now databases.[DATABASE_ID].collections.[COLLECTION_ID].documents **Full Changelog for Appwrite 0.15 can be found here**: https://github.com/appwrite/appwrite/blob/master/CHANGES.md#version-0150 diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 80a4e03981..f6fd906a7d 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -6,8 +6,8 @@ * **BREAKING** `dateCreated` attribute removed from `Team`, `Execution`, `File` models * **BREAKING** `dateCreated` and `dateUpdated` attribute removed from `Func`, `Deployment`, `Bucket` models * **BREAKING** Realtime channels - * collections.[COLLECTION_ID] is now databases.[DATABASE_ID].ollections.[COLLECTION_ID] - * collections.[COLLECTION_ID].documents is now databases.[DATABASE_ID].ollections.[COLLECTION_ID].documents + * collections.[COLLECTION_ID] is now databases.[DATABASE_ID].collections.[COLLECTION_ID] + * collections.[COLLECTION_ID].documents is now databases.[DATABASE_ID].collections.[COLLECTION_ID].documents **Full Changelog for Appwrite 0.15 can be found here**: https://github.com/appwrite/appwrite/blob/master/CHANGES.md#version-0150 From 804c2dc3aeb8d890cd678b332d4f48b8d541c913 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 4 Jul 2022 21:51:48 +0000 Subject: [PATCH 04/29] Explain how creating a phone session can create a new user --- docs/references/account/create-phone-session.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/account/create-phone-session.md b/docs/references/account/create-phone-session.md index 677c315ac2..58cf35265d 100644 --- a/docs/references/account/create-phone-session.md +++ b/docs/references/account/create-phone-session.md @@ -1 +1 @@ -Sends the user an SMS with a secret key for creating a session. Use the returned user ID and secret and submit a request to the [PUT /account/sessions/phone](/docs/client/account#accountUpdatePhoneSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes. \ No newline at end of file +Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [PUT /account/sessions/phone](/docs/client/account#accountUpdatePhoneSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes. \ No newline at end of file From c1b9a9477e068d692057adf99ea96053089a7133 Mon Sep 17 00:00:00 2001 From: Bishwajeet Parhi <62933155+2002Bishwajeet@users.noreply.github.com> Date: Tue, 5 Jul 2022 18:42:13 +0530 Subject: [PATCH 05/29] fix typo --- CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4016a982fb..a13319fb11 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,8 +26,8 @@ - `collections.[COLLECTION_ID]` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID]` - `collections.[COLLECTION_ID].documents.[DOCUMENT_ID]` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID].documents.[DOCUMENT_ID]` - Following Realtime Channels are changed: - - `collections.[COLLECTION_ID]` is now `databases.[DATABASE_ID].ollections.[COLLECTION_ID]` - - `collections.[COLLECTION_ID].documents` is now `databases.[DATABASE_ID].ollections.[COLLECTION_ID].documents` + - `collections.[COLLECTION_ID]` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID]` + - `collections.[COLLECTION_ID].documents` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID].documents` - After Migration a Database called `default` is created for all your existing Database Collections ## Features From 9f364bb9dd298dd327408df703bc1e06e04e18e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 5 Jul 2022 16:07:07 +0000 Subject: [PATCH 06/29] Fix document date --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5ce5dea75c..a476dfab2e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2279,7 +2279,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data = \array_merge($document->getArrayCopy(), $data); $data['$collection'] = $collection->getId(); // Make sure user don't switch collectionID - $data['$createdAt'] = $collection->getCreatedAt(); // Make sure user don't switch createdAt + $data['$createdAt'] = $document->getCreatedAt(); // Make sure user don't switch createdAt $data['$id'] = $document->getId(); // Make sure user don't switch document unique ID $data['$read'] = (is_null($read)) ? ($document->getRead() ?? []) : $read; // By default inherit read permissions $data['$write'] = (is_null($write)) ? ($document->getWrite() ?? []) : $write; // By default inherit write permissions From ee4aff0ca4e2a23681e52070d2c84d663c0fe7b0 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 5 Jul 2022 23:13:48 +0000 Subject: [PATCH 07/29] Fix get collection usage alias --- app/controllers/api/databases.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 59 ++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5ce5dea75c..a18058af5e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2669,7 +2669,7 @@ App::get('/v1/databases/:databaseId/usage') }); App::get('/v1/databases/:databaseId/collections/:collectionId/usage') - ->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default']) + ->alias('/v1/database/:collectionId/usage', ['databaseId' => 'default']) ->desc('Get usage stats for a collection') ->groups(['api', 'database']) ->label('scope', 'collections.read') diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 747d725e6c..35f2b78770 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -922,6 +922,63 @@ trait DatabasesBase return ['documents' => $documents['body']['documents'], 'databaseId' => $databaseId]; } + public function testCreateCollectionAlias(): array + { + // Create default database + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => 'default', + 'name' => 'Default' + ]); + + $this->assertNotEmpty($database['body']['$id']); + $this->assertEquals(201, $database['headers']['status-code']); + + /** + * Test for SUCCESS + */ + + $movies = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => 'unique()', + 'name' => 'Movies', + 'read' => [], + 'write' => [], + 'permission' => 'document', + ]); + + $this->assertEquals($movies['headers']['status-code'], 201); + $this->assertEquals($movies['body']['name'], 'Movies'); + + return ['moviesId' => $movies['body']['$id']]; + } + + /** + * @depends testCreateCollectionAlias + */ + public function testListDocumentsAlias(array $data): array + { + /** + * Test for SUCCESS + */ + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($documents['headers']['status-code'], 200); + $this->assertEquals($documents['body']['total'], 0); + + return []; + } + /** * @depends testListDocuments */ @@ -2376,7 +2433,7 @@ trait DatabasesBase $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ + ], $this->getHeaders()), [ 'read' => ['user:' . $this->getUser()['$id']], ]); From 937240f244d7d26c819db75506eb68a8b31355b0 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 6 Jul 2022 17:11:26 +1200 Subject: [PATCH 08/29] Fix attribute databaseId --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5ce5dea75c..8e355f45e9 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -96,7 +96,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att '$id' => $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, 'key' => $key, 'databaseInternalId' => $db->getInternalId(), - 'databaseId' => $db->getInternalId(), + 'databaseId' => $db->getId(), 'collectionInternalId' => $collection->getInternalId(), 'collectionId' => $collectionId, 'type' => $type, From 806a67b1b041447b6a5dd8744c556f655c0d8e94 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 6 Jul 2022 12:53:30 +0200 Subject: [PATCH 09/29] fix: realtime authentication on console --- app/realtime.php | 8 +- .../Realtime/RealtimeConsoleClientTest.php | 105 ++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index d13e1c867f..09e419dcce 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -491,8 +491,12 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $database = new Database(new MariaDB($db), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); $database->setNamespace("_console"); - $project = Authorization::skip(fn() => $database->getDocument('projects', $realtime->connections[$connection]['projectId'])); - $database->setNamespace("_{$project->getInternalId()}"); + $projectId = $realtime->connections[$connection]['projectId']; + + if ($projectId !== 'console') { + $project = Authorization::skip(fn() => $database->getDocument('projects', $projectId)); + $database->setNamespace("_{$project->getInternalId()}"); + } /* * Abuse Check diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 466c432825..8217f46539 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -13,6 +13,111 @@ class RealtimeConsoleClientTest extends Scope use ProjectCustom; use SideConsole; + public function testManualAuthentication() + { + $user = $this->getUser(); + $userId = $user['$id'] ?? ''; + $session = $user['session'] ?? ''; + + /** + * Test for SUCCESS + */ + $client = $this->getWebsocket(['account'], [ + 'origin' => 'http://localhost' + ]); + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('account', $response['data']['channels']); + + $client->send(\json_encode([ + 'type' => 'authentication', + 'data' => [ + 'session' => $session + ] + ])); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('response', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertEquals('authentication', $response['data']['to']); + $this->assertTrue($response['data']['success']); + $this->assertNotEmpty($response['data']['user']); + $this->assertEquals($userId, $response['data']['user']['$id']); + + /** + * Test for FAILURE + */ + $client->send(\json_encode([ + 'type' => 'authentication', + 'data' => [ + 'session' => 'invalid_session' + ] + ])); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('error', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertEquals(1003, $response['data']['code']); + $this->assertEquals('Session is not valid.', $response['data']['message']); + + $client->send(\json_encode([ + 'type' => 'authentication', + 'data' => [] + ])); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('error', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertEquals(1003, $response['data']['code']); + $this->assertEquals('Payload is not valid.', $response['data']['message']); + + $client->send(\json_encode([ + 'type' => 'unknown', + 'data' => [ + 'session' => 'invalid_session' + ] + ])); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('error', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertEquals(1003, $response['data']['code']); + $this->assertEquals('Message type is not valid.', $response['data']['message']); + + $client->send(\json_encode([ + 'test' => '123', + ])); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('error', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertEquals(1003, $response['data']['code']); + $this->assertEquals('Message format is not valid.', $response['data']['message']); + + + $client->close(); + } + public function testAttributes() { $user = $this->getUser(); From 6683e5f8eca2fcc17bcc17d1fe3bb8518ca6d1d3 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 6 Jul 2022 13:25:42 +0200 Subject: [PATCH 10/29] prepare: 0.15.2 --- CHANGES.md | 8 ++++++++ README-CN.md | 6 +++--- README.md | 6 +++--- app/config/platforms.php | 2 +- app/init.php | 4 ++-- composer.json | 2 +- composer.lock | 24 ++++++++++++------------ src/Appwrite/Migration/Migration.php | 3 ++- 8 files changed, 32 insertions(+), 23 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a13319fb11..5ba47ab638 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +# Version 0.15.2 +## Bugs +- Fixed Realtime Authentication for the Console by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3506 +- Fixed Collection Usage by @stnguyen90 in https://github.com/appwrite/appwrite/pull/3505 +- Fixed `$createdAt` after updating document by @Meldiron in https://github.com/appwrite/appwrite/pull/3498 +- Fixed Redirect after deleting Collection in Console @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3476 +- Fixed broken Link for Documents under Collections by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3469 + # Version 0.15.1 ## Bugs - Fixed SMS for `createVerification` by @christyjacob4 in https://github.com/appwrite/appwrite/pull/3454 diff --git a/README-CN.md b/README-CN.md index 5b1cdcda91..095d06e221 100644 --- a/README-CN.md +++ b/README-CN.md @@ -59,7 +59,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:0.15.1 + appwrite/appwrite:0.15.2 ``` ### Windows @@ -71,7 +71,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:0.15.1 + appwrite/appwrite:0.15.2 ``` #### PowerShell @@ -81,7 +81,7 @@ docker run -it --rm , --volume /var/run/docker.sock:/var/run/docker.sock , --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw , --entrypoint="install" , - appwrite/appwrite:0.15.1 + appwrite/appwrite:0.15.2 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 diff --git a/README.md b/README.md index 171203b29c..35c8c6e67c 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:0.15.1 + appwrite/appwrite:0.15.2 ``` ### Windows @@ -77,7 +77,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:0.15.1 + appwrite/appwrite:0.15.2 ``` #### PowerShell @@ -87,7 +87,7 @@ docker run -it --rm , --volume /var/run/docker.sock:/var/run/docker.sock , --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw , --entrypoint="install" , - appwrite/appwrite:0.15.1 + appwrite/appwrite:0.15.2 ``` Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after installation completes. diff --git a/app/config/platforms.php b/app/config/platforms.php index f54ded0807..71412482af 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -180,7 +180,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '0.18.0', + 'version' => '0.18.1', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/app/init.php b/app/init.php index 606e7f8bd7..f2d8d63298 100644 --- a/app/init.php +++ b/app/init.php @@ -86,8 +86,8 @@ const APP_LIMIT_COMPRESSION = 20000000; //20MB const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length. const APP_LIMIT_SUBQUERY = 1000; -const APP_CACHE_BUSTER = 401; -const APP_VERSION_STABLE = '0.15.1'; +const APP_CACHE_BUSTER = 402; +const APP_VERSION_STABLE = '0.15.2'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/composer.json b/composer.json index d2c87052fc..ded0834bb3 100644 --- a/composer.json +++ b/composer.json @@ -71,7 +71,7 @@ } ], "require-dev": { - "appwrite/sdk-generator": "0.19.4", + "appwrite/sdk-generator": "0.19.5", "phpunit/phpunit": "9.5.20", "squizlabs/php_codesniffer": "^3.6", "swoole/ide-helper": "4.8.9", diff --git a/composer.lock b/composer.lock index 788679d311..9d29bc8ac7 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": "266a47c93a9de6f1c36211aa5cf52799", + "content-hash": "dedc6a6328b4fdc5dfbd556a08534403", "packages": [ { "name": "adhocore/jwt", @@ -236,16 +236,16 @@ }, { "name": "chillerlan/php-settings-container", - "version": "2.1.3", + "version": "2.1.4", "source": { "type": "git", "url": "https://github.com/chillerlan/php-settings-container.git", - "reference": "125dd573b45ffc7cabecf385986a356ba2c6f602" + "reference": "1beb7df3c14346d4344b0b2e12f6f9a74feabd4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/125dd573b45ffc7cabecf385986a356ba2c6f602", - "reference": "125dd573b45ffc7cabecf385986a356ba2c6f602", + "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/1beb7df3c14346d4344b0b2e12f6f9a74feabd4a", + "reference": "1beb7df3c14346d4344b0b2e12f6f9a74feabd4a", "shasum": "" }, "require": { @@ -296,7 +296,7 @@ "type": "ko_fi" } ], - "time": "2022-03-09T13:18:58+00:00" + "time": "2022-07-05T22:32:14+00:00" }, { "name": "colinmollenhour/credis", @@ -2828,16 +2828,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.19.4", + "version": "0.19.5", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "51a8e4205cd4809deeff8121a24e717642d68564" + "reference": "04de540cf683e2b08b3192c137dde7f2c37003d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/51a8e4205cd4809deeff8121a24e717642d68564", - "reference": "51a8e4205cd4809deeff8121a24e717642d68564", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/04de540cf683e2b08b3192c137dde7f2c37003d9", + "reference": "04de540cf683e2b08b3192c137dde7f2c37003d9", "shasum": "" }, "require": { @@ -2872,9 +2872,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.19.4" + "source": "https://github.com/appwrite/sdk-generator/tree/0.19.5" }, - "time": "2022-06-29T15:19:58+00:00" + "time": "2022-07-06T11:05:57+00:00" }, { "name": "doctrine/instantiator", diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index fe14c61aa8..a60272f3bd 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -46,7 +46,8 @@ abstract class Migration '0.14.1' => 'V13', '0.14.2' => 'V13', '0.15.0' => 'V14', - '0.15.1' => 'V14' + '0.15.1' => 'V14', + '0.15.2' => 'V14' ]; /** From 8a0f2010a2b23ce1b6090de5f48c6c6473fc7b09 Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 6 Jul 2022 17:04:29 +0000 Subject: [PATCH 11/29] Fix hardcoded appwrite database schema --- app/controllers/api/projects.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 1cfed5c58e..86996f4a58 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -113,7 +113,7 @@ App::post('/v1/projects') $collections = Config::getParam('collections', []); $dbForProject->setNamespace("_{$project->getInternalId()}"); - $dbForProject->create('appwrite'); + $dbForProject->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); $audit = new Audit($dbForProject); $audit->setup(); From d13afe0b2e1a328364a7962c7da0ade39dbbbba8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 7 Jul 2022 16:49:44 +1200 Subject: [PATCH 12/29] Fix get deployment response type --- app/controllers/api/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index e464fb7929..37fe6674c0 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -696,7 +696,7 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId') ->label('sdk.description', '/docs/references/functions/get-deployment.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST) + ->label('sdk.response.model', Response::MODEL_DEPLOYMENT) ->param('functionId', '', new UID(), 'Function ID.') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') From 79dc3ab3fa0f8353fa9a798e64dc7538ece29ab6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 7 Jul 2022 13:37:29 +0545 Subject: [PATCH 13/29] set proper log namespace --- app/tasks/usage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/tasks/usage.php b/app/tasks/usage.php index 26e47adfea..7a22d7e79f 100644 --- a/app/tasks/usage.php +++ b/app/tasks/usage.php @@ -83,7 +83,7 @@ $logError = function (Throwable $error, string $action = 'syncUsageStats') use ( $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $log = new Log(); - $log->setNamespace("realtime"); + $log->setNamespace("usage"); $log->setServer(\gethostname()); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); From 7a486e1158d321aee40f5aa112db5ab90b4b26c1 Mon Sep 17 00:00:00 2001 From: Dineshkumar Date: Thu, 7 Jul 2022 16:40:29 +0530 Subject: [PATCH 14/29] Added Msg91 Flow Adapter --- app/workers/messaging.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 409304c595..79d99e2292 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -36,6 +36,7 @@ class MessagingV1 extends Worker 'twilio' => new Twilio($user, $secret), 'text-magic' => new TextMagic($user, $secret), 'telesign' => new Telesign($user, $secret), + 'msg91-flow' => new Msg91Flow($user, $secret), default => null }; From d2bf2f8f5aaaa656576d99161096ba1e3a243d4c Mon Sep 17 00:00:00 2001 From: Dineshkumar Date: Thu, 7 Jul 2022 16:41:50 +0530 Subject: [PATCH 15/29] Added Msg91 Adaptor Using Flow --- src/Appwrite/Auth/Phone/Msg91Flow.php | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/Appwrite/Auth/Phone/Msg91Flow.php diff --git a/src/Appwrite/Auth/Phone/Msg91Flow.php b/src/Appwrite/Auth/Phone/Msg91Flow.php new file mode 100644 index 0000000000..2ada52c406 --- /dev/null +++ b/src/Appwrite/Auth/Phone/Msg91Flow.php @@ -0,0 +1,46 @@ + utilized from for flow id + * @param string $to + * @param string $message + * @return void + */ + public function send(string $from, string $to, string $message): void + { + $to = ltrim($to, '+'); + $this->request( + method: 'POST', + url: $this->endpoint . '/messages', + payload: \http_build_query([ + 'sender' => $this->user, + 'otp' => $message, + 'flow_id' => $from, + 'mobiles' => $to + ]), + headers: [ + "content-type: application/JSON", + "authkey: {$this->secret}", + ] + ); + } +} From 5eab0d47e4a879ab4f482f5fa31f8fa1761bc16b Mon Sep 17 00:00:00 2001 From: Dineshkumar Date: Thu, 7 Jul 2022 20:57:48 +0530 Subject: [PATCH 16/29] renamed msg91-flow as msg91 --- app/workers/messaging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/messaging.php b/app/workers/messaging.php index 79d99e2292..d5e1b8a311 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -36,7 +36,7 @@ class MessagingV1 extends Worker 'twilio' => new Twilio($user, $secret), 'text-magic' => new TextMagic($user, $secret), 'telesign' => new Telesign($user, $secret), - 'msg91-flow' => new Msg91Flow($user, $secret), + 'msg91' => new Msg91Flow($user, $secret), default => null }; From b5b5abdc820dccb656c4a75d1de37c09e417ef0f Mon Sep 17 00:00:00 2001 From: Dineshkumar Date: Thu, 7 Jul 2022 20:59:34 +0530 Subject: [PATCH 17/29] Updated Functional Document Provider name as msg91 --- src/Appwrite/Auth/Phone/Msg91Flow.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Auth/Phone/Msg91Flow.php b/src/Appwrite/Auth/Phone/Msg91Flow.php index 2ada52c406..a3dac21b51 100644 --- a/src/Appwrite/Auth/Phone/Msg91Flow.php +++ b/src/Appwrite/Auth/Phone/Msg91Flow.php @@ -16,9 +16,9 @@ class Msg91Flow extends Phone /** * For Flow based sending SMS sender ID should not be set in flow - * In environment _APP_PHONE_PROVIDER format is 'phone://[senderID]:[authKey]@msg91-flow'. + * In environment _APP_PHONE_PROVIDER format is 'phone://[senderID]:[authKey]@msg91'. * _APP_PHONE_FROM value is flow ID created in Msg91 - * Eg. _APP_PHONE_PROVIDER = phone://DINESH:5e1e93cad6fc054d8e759a5b@msg91-flow + * Eg. _APP_PHONE_PROVIDER = phone://DINESH:5e1e93cad6fc054d8e759a5b@msg91 * _APP_PHONE_FROM = 3968636f704b303135323339 * @param string $from-> utilized from for flow id * @param string $to From 43e9f9998f3044eb3b9395cd2889c35ee9bceea2 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Thu, 7 Jul 2022 17:40:21 +0000 Subject: [PATCH 18/29] Add comments in auth docs about where/how to create accounts. --- docs/references/account/create-magic-url-session.md | 2 +- docs/services/account.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/references/account/create-magic-url-session.md b/docs/references/account/create-magic-url-session.md index 4be53f1381..78bf99d55e 100644 --- a/docs/references/account/create-magic-url-session.md +++ b/docs/references/account/create-magic-url-session.md @@ -1 +1 @@ -Sends the user an email with a secret key for creating a session. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [PUT /account/sessions/magic-url](/docs/client/account#accountUpdateMagicURLSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default. \ No newline at end of file +Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [PUT /account/sessions/magic-url](/docs/client/account#accountUpdateMagicURLSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default. \ No newline at end of file diff --git a/docs/services/account.md b/docs/services/account.md index d0495b3ba7..356f3c0be0 100644 --- a/docs/services/account.md +++ b/docs/services/account.md @@ -1,6 +1,6 @@ The Account service allows you to authenticate and manage a user account. You can use the account service to update user information, retrieve the user sessions across different devices, and fetch the user security logs with his or her recent activity. -You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings. +Register new user accounts with the [Create Account](/docs/client/account#accountCreate), [Create Magic URL session](/docs/client/account#accountCreateMagicURLSession), or [Create Phone session](/docs/client/accountt#accountCreatePhoneSession) endpoint. You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings. This service also exposes an endpoint to save and read the [user preferences](/docs/client/account#accountUpdatePrefs) as a key-value object. This feature is handy if you want to allow extra customization in your app. Common usage for this feature may include saving the user preferred locale, timezone, or custom app theme. From b45256c31b8ee149db14998c40d1609cd43b420b Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Thu, 7 Jul 2022 19:25:39 +0000 Subject: [PATCH 19/29] fix typo in ref link --- docs/services/account.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/services/account.md b/docs/services/account.md index 356f3c0be0..999a9be4a4 100644 --- a/docs/services/account.md +++ b/docs/services/account.md @@ -1,6 +1,6 @@ The Account service allows you to authenticate and manage a user account. You can use the account service to update user information, retrieve the user sessions across different devices, and fetch the user security logs with his or her recent activity. -Register new user accounts with the [Create Account](/docs/client/account#accountCreate), [Create Magic URL session](/docs/client/account#accountCreateMagicURLSession), or [Create Phone session](/docs/client/accountt#accountCreatePhoneSession) endpoint. You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings. +Register new user accounts with the [Create Account](/docs/client/account#accountCreate), [Create Magic URL session](/docs/client/account#accountCreateMagicURLSession), or [Create Phone session](/docs/client/account#accountCreatePhoneSession) endpoint. You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings. This service also exposes an endpoint to save and read the [user preferences](/docs/client/account#accountUpdatePrefs) as a key-value object. This feature is handy if you want to allow extra customization in your app. Common usage for this feature may include saving the user preferred locale, timezone, or custom app theme. From 3666d0ab735e23b21c6be65e57367ff1d4672ed9 Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 7 Jul 2022 22:23:52 +0000 Subject: [PATCH 20/29] Add alias for POST /v1/account/sessions/email Add /v1/account/sessions as an alias for POST /v1/account/sessions/email for backwards compatibility. --- app/controllers/api/account.php | 1 + tests/e2e/Services/Account/AccountBase.php | 61 +++++++++++++--------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 5144441a1f..6c90441afb 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -133,6 +133,7 @@ App::post('/v1/account') }); App::post('/v1/account/sessions/email') + ->alias('/v1/account/sessions') ->desc('Create Account Session with Email') ->groups(['api', 'account', 'auth']) ->label('event', 'users.[userId].sessions.[sessionId].create') diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 9e36632354..283c76a34b 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -120,6 +120,17 @@ trait AccountBase $sessionId = $response['body']['$id']; $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; + $response = $this->client->call(Client::METHOD_POST, '/account/sessions', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'email' => $email, + 'password' => $password, + ]); + + $this->assertEquals($response['headers']['status-code'], 201); + /** * Test for FAILURE */ @@ -267,7 +278,7 @@ trait AccountBase $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertCount(2, $response['body']); - $this->assertEquals(1, $response['body']['total']); + $this->assertEquals(2, $response['body']['total']); $this->assertEquals($sessionId, $response['body']['sessions'][0]['$id']); $this->assertEquals('Windows', $response['body']['sessions'][0]['osName']); @@ -325,30 +336,8 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 200); $this->assertIsArray($response['body']['logs']); $this->assertNotEmpty($response['body']['logs']); - $this->assertCount(2, $response['body']['logs']); + $this->assertCount(3, $response['body']['logs']); $this->assertIsNumeric($response['body']['total']); - $this->assertContains($response['body']['logs'][0]['event'], ["users.{$userId}.create", "users.{$userId}.sessions.{$sessionId}.create"]); - $this->assertEquals($response['body']['logs'][0]['ip'], filter_var($response['body']['logs'][0]['ip'], FILTER_VALIDATE_IP)); - $this->assertIsNumeric($response['body']['logs'][0]['time']); - - $this->assertEquals('Windows', $response['body']['logs'][0]['osName']); - $this->assertEquals('WIN', $response['body']['logs'][0]['osCode']); - $this->assertEquals('10', $response['body']['logs'][0]['osVersion']); - - $this->assertEquals('browser', $response['body']['logs'][0]['clientType']); - $this->assertEquals('Chrome', $response['body']['logs'][0]['clientName']); - $this->assertEquals('CH', $response['body']['logs'][0]['clientCode']); - $this->assertEquals('70.0', $response['body']['logs'][0]['clientVersion']); - $this->assertEquals('Blink', $response['body']['logs'][0]['clientEngine']); - - $this->assertEquals('desktop', $response['body']['logs'][0]['deviceName']); - $this->assertEquals('', $response['body']['logs'][0]['deviceBrand']); - $this->assertEquals('', $response['body']['logs'][0]['deviceModel']); - $this->assertEquals($response['body']['logs'][0]['ip'], filter_var($response['body']['logs'][0]['ip'], FILTER_VALIDATE_IP)); - - $this->assertEquals('--', $response['body']['logs'][0]['countryCode']); - $this->assertEquals('Unknown', $response['body']['logs'][0]['countryName']); - $this->assertContains($response['body']['logs'][1]['event'], ["users.{$userId}.create", "users.{$userId}.sessions.{$sessionId}.create"]); $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); $this->assertIsNumeric($response['body']['logs'][1]['time']); @@ -371,6 +360,28 @@ trait AccountBase $this->assertEquals('--', $response['body']['logs'][1]['countryCode']); $this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']); + $this->assertContains($response['body']['logs'][2]['event'], ["users.{$userId}.create", "users.{$userId}.sessions.{$sessionId}.create"]); + $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); + $this->assertIsNumeric($response['body']['logs'][2]['time']); + + $this->assertEquals('Windows', $response['body']['logs'][2]['osName']); + $this->assertEquals('WIN', $response['body']['logs'][2]['osCode']); + $this->assertEquals('10', $response['body']['logs'][2]['osVersion']); + + $this->assertEquals('browser', $response['body']['logs'][2]['clientType']); + $this->assertEquals('Chrome', $response['body']['logs'][2]['clientName']); + $this->assertEquals('CH', $response['body']['logs'][2]['clientCode']); + $this->assertEquals('70.0', $response['body']['logs'][2]['clientVersion']); + $this->assertEquals('Blink', $response['body']['logs'][2]['clientEngine']); + + $this->assertEquals('desktop', $response['body']['logs'][2]['deviceName']); + $this->assertEquals('', $response['body']['logs'][2]['deviceBrand']); + $this->assertEquals('', $response['body']['logs'][2]['deviceModel']); + $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); + + $this->assertEquals('--', $response['body']['logs'][2]['countryCode']); + $this->assertEquals('Unknown', $response['body']['logs'][2]['countryName']); + $responseLimit = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', @@ -400,7 +411,7 @@ trait AccountBase $this->assertEquals($responseOffset['headers']['status-code'], 200); $this->assertIsArray($responseOffset['body']['logs']); $this->assertNotEmpty($responseOffset['body']['logs']); - $this->assertCount(1, $responseOffset['body']['logs']); + $this->assertCount(2, $responseOffset['body']['logs']); $this->assertIsNumeric($responseOffset['body']['total']); $this->assertEquals($response['body']['logs'][1], $responseOffset['body']['logs'][0]); From 76921ced710d0645974505d2014d3817daf7d44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 8 Jul 2022 09:36:19 +0000 Subject: [PATCH 21/29] Implemented updateDocument date tests --- .../e2e/Services/Databases/DatabasesBase.php | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 35f2b78770..5abf2b331e 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2359,6 +2359,65 @@ trait DatabasesBase return $data; } + /** + * @depends testUniqueIndexDuplicate + */ + public function testPersistantCreatedAt(array $data): array + { + $headers = $this->getSide() === 'client' ? array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()) : [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]; + + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents', $headers, [ + 'documentId' => 'unique()', + 'data' => [ + 'title' => 'Creation Date Test', + 'releaseYear' => 2000 + ] + ]); + + $this->assertEquals($document['body']['title'], 'Creation Date Test'); + + $documentId = $document['body']['$id']; + $createdAt = $document['body']['$createdAt']; + $updatedAt = $document['body']['$updatedAt']; + + \sleep(1); + + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ + 'data' => [ + 'title' => 'Updated Date Test', + ] + ]); + + $updatedAtSecond = $document['body']['$updatedAt']; + + $this->assertEquals($document['body']['title'], 'Updated Date Test'); + $this->assertEquals($document['body']['$createdAt'], $createdAt); + $this->assertNotEquals($document['body']['$updatedAt'], $updatedAt); + + \sleep(1); + + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ + 'data' => [ + 'title' => 'Again Updated Date Test', + '$createdAt' => 1657271810 // Try to update it, should not work + ] + ]); + + $this->assertEquals($document['body']['title'], 'Again Updated Date Test'); + $this->assertEquals($document['body']['$createdAt'], $createdAt); + $this->assertNotEquals($document['body']['$updatedAt'], $updatedAt); + $this->assertNotEquals($document['body']['$updatedAt'], $updatedAtSecond); + + return $data; + } + public function testUpdatePermissionsWithEmptyPayload(): array { // Create Database From 8fa227f3da8672f3482d71192d4af605434de4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 8 Jul 2022 09:38:49 +0000 Subject: [PATCH 22/29] New date test --- tests/e2e/Services/Databases/DatabasesBase.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 5abf2b331e..34a4160fde 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2406,7 +2406,8 @@ trait DatabasesBase $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [ 'data' => [ 'title' => 'Again Updated Date Test', - '$createdAt' => 1657271810 // Try to update it, should not work + '$createdAt' => 1657271810, // Try to update it, should not work + '$updatedAt' => 1657271810 // Try to update it, should not work ] ]); @@ -2414,6 +2415,7 @@ trait DatabasesBase $this->assertEquals($document['body']['$createdAt'], $createdAt); $this->assertNotEquals($document['body']['$updatedAt'], $updatedAt); $this->assertNotEquals($document['body']['$updatedAt'], $updatedAtSecond); + $this->assertNotEquals($document['body']['$updatedAt'], 1657271810); return $data; } From 0c46022f1b67ce980f16ccb11582ce6cc692312a Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 8 Jul 2022 17:17:20 +0200 Subject: [PATCH 23/29] feat: composer scripts --- CONTRIBUTING.md | 14 +++++++------- composer.json | 5 +++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 255595c590..0a0cf85c11 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,19 +51,19 @@ $ git checkout -b [name_of_your_new_branch] 4. Before you push your changes, make sure your code follows the `PSR12` coding standards , which is the standard Appwrite follows currently. You can easily do this by running the formatter. ```bash -./vendor/bin/phpcbf +composer format ``` Now, go a step further by running the linter by the following command to manually fix the issues the formatter wasn't able to fix. ```bash -./vendor/bin/phpcs +composer lint ``` This will give you a list of errors for you to rectify , if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues. ```bash -./vendor/bin/phpcs --report=diff +composer lint --report=diff ``` 5. Push changes to GitHub @@ -413,18 +413,18 @@ We use some automation tools to help us keep a healthy codebase. ```bash # Run on all files -./vendor/bin/phpcbf +composer format # Run on single file or folder -./vendor/bin/phpcbf +composer format ``` **Run Linter:** ```bash # Run on all files -./vendor/bin/phpcs +composer lint # Run on single file or folder -./vendor/bin/phpcs +composer lint ``` ## Tutorials diff --git a/composer.json b/composer.json index ded0834bb3..1cc1385c13 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,11 @@ "email": "eldad@appwrite.io" } ], + "scripts": { + "test": "vendor/bin/phpunit", + "lint": "vendor/bin/phpcs", + "format": "vendor/bin/phpcbf" + }, "autoload": { "psr-4": { "Appwrite\\": "src/Appwrite", From 5d70a4749ab590f1297e8a054637d2cf25034158 Mon Sep 17 00:00:00 2001 From: Aditya Oberai <31401437+adityaoberai@users.noreply.github.com> Date: Fri, 8 Jul 2022 23:14:09 +0530 Subject: [PATCH 24/29] Correct TeleSign reference material link --- src/Appwrite/Auth/Phone/Telesign.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/Phone/Telesign.php b/src/Appwrite/Auth/Phone/Telesign.php index 5272b732ee..520dfc61bf 100644 --- a/src/Appwrite/Auth/Phone/Telesign.php +++ b/src/Appwrite/Auth/Phone/Telesign.php @@ -5,7 +5,7 @@ namespace Appwrite\Auth\Phone; use Appwrite\Auth\Phone; // Reference Material -// https://www.twilio.com/docs/sms/api +// https://developer.telesign.com/enterprise/docs/sms-api-send-an-sms class Telesign extends Phone { From 817524de4bcbcae2c2311e5ef7a4adb2f94ffd4f Mon Sep 17 00:00:00 2001 From: Dineshkumar Date: Sat, 9 Jul 2022 19:34:57 +0530 Subject: [PATCH 25/29] Renamed Msg91Flow to Msg91 --- app/init.php | 2 ++ app/workers/messaging.php | 3 ++- src/Appwrite/Auth/Phone/{Msg91Flow.php => Msg91.php} | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) rename src/Appwrite/Auth/Phone/{Msg91Flow.php => Msg91.php} (94%) diff --git a/app/init.php b/app/init.php index f2d8d63298..0861f67e7a 100644 --- a/app/init.php +++ b/app/init.php @@ -27,6 +27,7 @@ use Appwrite\Auth\Phone\Mock; use Appwrite\Auth\Phone\Telesign; use Appwrite\Auth\Phone\TextMagic; use Appwrite\Auth\Phone\Twilio; +use Appwrite\Auth\Phone\Msg91; use Appwrite\DSN\DSN; use Appwrite\Event\Audit; use Appwrite\Event\Database as EventDatabase; @@ -990,6 +991,7 @@ App::setResource('phone', function () { 'twilio' => new Twilio($user, $secret), 'text-magic' => new TextMagic($user, $secret), 'telesign' => new Telesign($user, $secret), + 'msg91' => new Msg91($user, $secret), default => null }; }); diff --git a/app/workers/messaging.php b/app/workers/messaging.php index d5e1b8a311..c83eaa2d7b 100644 --- a/app/workers/messaging.php +++ b/app/workers/messaging.php @@ -5,6 +5,7 @@ use Appwrite\Auth\Phone\Mock; use Appwrite\Auth\Phone\Telesign; use Appwrite\Auth\Phone\TextMagic; use Appwrite\Auth\Phone\Twilio; +use Appwrite\Auth\Phone\Msg91; use Appwrite\DSN\DSN; use Appwrite\Resque\Worker; use Utopia\App; @@ -36,7 +37,7 @@ class MessagingV1 extends Worker 'twilio' => new Twilio($user, $secret), 'text-magic' => new TextMagic($user, $secret), 'telesign' => new Telesign($user, $secret), - 'msg91' => new Msg91Flow($user, $secret), + 'msg91' => new Msg91($user, $secret), default => null }; diff --git a/src/Appwrite/Auth/Phone/Msg91Flow.php b/src/Appwrite/Auth/Phone/Msg91.php similarity index 94% rename from src/Appwrite/Auth/Phone/Msg91Flow.php rename to src/Appwrite/Auth/Phone/Msg91.php index a3dac21b51..8ae7c44665 100644 --- a/src/Appwrite/Auth/Phone/Msg91Flow.php +++ b/src/Appwrite/Auth/Phone/Msg91.php @@ -7,7 +7,7 @@ use Appwrite\Auth\Phone; // Reference Material // https://docs.msg91.com/p/tf9GTextN/e/Irz7-x1PK/MSG91 -class Msg91Flow extends Phone +class Msg91 extends Phone { /** * @var string @@ -30,7 +30,7 @@ class Msg91Flow extends Phone $to = ltrim($to, '+'); $this->request( method: 'POST', - url: $this->endpoint . '/messages', + url: $this->endpoint, payload: \http_build_query([ 'sender' => $this->user, 'otp' => $message, From 020bb160b9fe2cccac29874ca29d9a3566ad8691 Mon Sep 17 00:00:00 2001 From: Dineshkumar Date: Sat, 9 Jul 2022 20:12:48 +0530 Subject: [PATCH 26/29] changed payload encodings --- src/Appwrite/Auth/Phone/Msg91.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Auth/Phone/Msg91.php b/src/Appwrite/Auth/Phone/Msg91.php index 8ae7c44665..64e5973597 100644 --- a/src/Appwrite/Auth/Phone/Msg91.php +++ b/src/Appwrite/Auth/Phone/Msg91.php @@ -31,7 +31,7 @@ class Msg91 extends Phone $this->request( method: 'POST', url: $this->endpoint, - payload: \http_build_query([ + payload: json_encode([ 'sender' => $this->user, 'otp' => $message, 'flow_id' => $from, From aae7ec61465dad24baae580c04813ab7f1cbaece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sun, 10 Jul 2022 17:25:27 +0000 Subject: [PATCH 27/29] Upgrade to use new permissiosn validator features --- app/controllers/api/databases.php | 16 +++++------ app/controllers/api/functions.php | 5 ++-- app/controllers/api/storage.php | 16 +++++------ composer.json | 2 +- composer.lock | 27 ++++++++++++------- .../Functions/FunctionsConsoleClientTest.php | 12 +++++++++ .../Webhooks/WebhooksCustomServerTest.php | 10 +++++++ 7 files changed, 60 insertions(+), 28 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5ebc8666aa..16995a77db 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -498,8 +498,8 @@ App::post('/v1/databases/:databaseId/collections') ->param('collectionId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') ->param('permission', null, new WhiteList(['document', 'collection']), 'Specifies the permissions model used in this collection, which accepts either \'collection\' or \'document\'. For \'collection\' level permission, the permissions specified in read and write params are applied to all documents in the collection. For \'document\' level permissions, read and write permissions are specified in each document. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') ->inject('response') ->inject('dbForProject') ->inject('audits') @@ -752,8 +752,8 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') ->param('permission', null, new WhiteList(['document', 'collection']), 'Permissions type model to use for reading documents in this collection. You can use collection-level permission set once on the collection using the `read` and `write` params, or you can set document-level permission where each document read and write params will decide who has access to read and write to each document individually. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.') - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->param('enabled', true, new Boolean(), 'Is collection enabled?', true) ->inject('response') ->inject('dbForProject') @@ -1822,8 +1822,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->param('documentId', '', new CustomId(), 'Document ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection). Make sure to define attributes before creating documents.') ->param('data', [], new JSON(), 'Document data as JSON object.') - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->inject('response') ->inject('dbForProject') ->inject('user') @@ -2223,8 +2223,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->param('collectionId', null, new UID(), 'Collection ID.') ->param('documentId', null, new UID(), 'Document ID.') ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true) - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->inject('response') ->inject('dbForProject') ->inject('audits') diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 37fe6674c0..0137ab92a8 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -33,6 +33,7 @@ use Utopia\Config\Config; use Cron\CronExpression; use Executor\Executor; use Utopia\CLI\Console; +use Utopia\Database\Validator\Permissions; use Utopia\Validator\Boolean; include_once __DIR__ . '/../shared/api.php'; @@ -51,7 +52,7 @@ App::post('/v1/functions') ->label('sdk.response.model', Response::MODEL_FUNCTION) ->param('functionId', '', new CustomId(), 'Function ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('execute', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.') + ->param('execute', [], new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.') ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.') ->param('vars', [], new Assoc(), 'Key-value JSON object that will be passed to the function as environment variables.', true) ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) @@ -289,7 +290,7 @@ App::put('/v1/functions/:functionId') ->label('sdk.response.model', Response::MODEL_FUNCTION) ->param('functionId', '', new UID(), 'Function ID.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('execute', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.') + ->param('execute', [], new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.') ->param('vars', [], new Assoc(), 'Key-value JSON object that will be passed to the function as environment variables.', true) ->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 554d739ec5..b62aa750db 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -56,8 +56,8 @@ App::post('/v1/storage/buckets') ->param('bucketId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Bucket name') ->param('permission', null, new WhiteList(['file', 'bucket']), 'Permissions type model to use for reading files in this bucket. You can use bucket-level permission set once on the bucket using the `read` and `write` params, or you can set file-level permission where each file read and write params will decide who has access to read and write to each file individually. [learn more about permissions](/docs/permissions) and get a full list of available permissions.') - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true) ->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) @@ -224,8 +224,8 @@ App::put('/v1/storage/buckets/:bucketId') ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->param('name', null, new Text(128), 'Bucket name', false) ->param('permission', null, new WhiteList(['file', 'bucket']), 'Permissions type model to use for reading files in this bucket. You can use bucket-level permission set once on the bucket using the `read` and `write` params, or you can set file-level permission where each file read and write params will decide who has access to read and write to each file individually. [learn more about permissions](/docs/permissions) and get a full list of available permissions.') - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true) ->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) @@ -342,8 +342,8 @@ App::post('/v1/storage/buckets/:bucketId/files') ->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).') ->param('fileId', '', new CustomId(), 'File ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('file', [], new File(), 'Binary file.', false) - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->inject('request') ->inject('response') ->inject('dbForProject') @@ -1288,8 +1288,8 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->label('sdk.response.model', Response::MODEL_FILE) ->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') - ->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) - ->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) + ->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true) ->inject('response') ->inject('dbForProject') ->inject('user') diff --git a/composer.json b/composer.json index ded0834bb3..0e3318cd52 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.6.*", "utopia-php/cli": "0.12.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.18.*", + "utopia-php/database": "dev-feat-permissions-maxlength as 0.18.1", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index 9d29bc8ac7..e079cf0bc0 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": "dedc6a6328b4fdc5dfbd556a08534403", + "content-hash": "eacaae6ec0973349a9b9f4ec78877b0a", "packages": [ { "name": "adhocore/jwt", @@ -2051,16 +2051,16 @@ }, { "name": "utopia-php/database", - "version": "0.18.6", + "version": "dev-feat-permissions-maxlength", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "e9e163642546343267c2fe0ee90016a4a0230b4a" + "reference": "85c304075bb42b91e3cb98762921f15fa28af13c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/e9e163642546343267c2fe0ee90016a4a0230b4a", - "reference": "e9e163642546343267c2fe0ee90016a4a0230b4a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/85c304075bb42b91e3cb98762921f15fa28af13c", + "reference": "85c304075bb42b91e3cb98762921f15fa28af13c", "shasum": "" }, "require": { @@ -2109,9 +2109,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.18.6" + "source": "https://github.com/utopia-php/database/tree/feat-permissions-maxlength" }, - "time": "2022-06-27T17:28:05+00:00" + "time": "2022-07-10T17:08:47+00:00" }, { "name": "utopia-php/domains", @@ -5346,9 +5346,18 @@ "time": "2022-05-17T05:48:52+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-feat-permissions-maxlength", + "alias": "0.18.1", + "alias_normalized": "0.18.1.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index 0180a87de3..c344114364 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -37,6 +37,18 @@ class FunctionsConsoleClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); + $response = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'functionId' => 'unique()', + 'name' => 'Test Failure', + 'execute' => ['some-random-string'], + 'runtime' => 'php-8.0' + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + return [ 'functionId' => $function['body']['$id'] ]; diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index 1a6aed65a7..c60e57f6af 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -467,6 +467,16 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $function = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Test Failure', + 'execute' => [ 'not-valid-permission' ] + ]); + + $this->assertEquals($function['headers']['status-code'], 400); + return $data; } From 1616f15a40ba10b1c8809f1ef96d7b6d6b949452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 11 Jul 2022 08:40:58 +0000 Subject: [PATCH 28/29] Fix database dates --- app/views/console/databases/database.phtml | 4 ++-- src/Appwrite/Utopia/Response/Model/Database.php | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/views/console/databases/database.phtml b/app/views/console/databases/database.phtml index 612863507d..6af07cb091 100644 --- a/app/views/console/databases/database.phtml +++ b/app/views/console/databases/database.phtml @@ -292,8 +292,8 @@
  • -
  • Last Updated:
  • -
  • Created:
  • +
  • Last Updated:
  • +
  • Created:
'', 'example' => 'My Database', ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Collection creation date in Unix timestamp.', + 'default' => 0, + 'example' => 1592981250, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Collection update date in Unix timestamp.', + 'default' => 0, + 'example' => 1592981250, + ]) ; } From 2760f40a7cd77ecbfe1e3683d77d65a51c9d1f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 11 Jul 2022 10:51:31 +0000 Subject: [PATCH 29/29] Changes after library release --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0e3318cd52..ded0834bb3 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.6.*", "utopia-php/cli": "0.12.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-feat-permissions-maxlength as 0.18.1", + "utopia-php/database": "0.18.*", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*",