From 999a6b664fc0768cb504d4acc7f7e2ec1e5e0459 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 5 Jul 2021 08:55:07 +0300 Subject: [PATCH 01/38] Updated logo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0596bee316..f7e0b7d651 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- Appwrite Logo + Appwrite Logo

A complete backend solution for your [Flutter / Vue / Angular / React / iOS / Android / *ANY OTHER*] app From 46b109b25a41cf8b7808eb55398f142dd24ac559 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 7 Jul 2021 15:04:41 +0530 Subject: [PATCH 02/38] feat(docs): update version in readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f7e0b7d651..eb696e7c15 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![Build Status](https://img.shields.io/travis/com/appwrite/appwrite?style=flat-square)](https://travis-ci.com/appwrite/appwrite) [![Twitter Account](https://img.shields.io/twitter/follow/appwrite_io?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite_io) -[**Appwrite 0.8 has been released! Learn what's new!**](https://dev.to/appwrite/announcing-appwrite-0-8-an-open-source-self-hosted-baas-kda) +[**Appwrite 0.9 has been released! Learn what's new!**](https://dev.to/appwrite/announcing-appwrite-0-8-an-open-source-self-hosted-baas-kda) Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster. @@ -56,7 +56,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.8.0 + appwrite/appwrite:0.9.0 ``` ### Windows @@ -68,7 +68,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.8.0 + appwrite/appwrite:0.9.0 ``` #### PowerShell @@ -78,7 +78,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.8.0 + appwrite/appwrite:0.9.0 ``` 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. From 8f71b9618c2781b8aa59a589c9317f557c020b3c Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 7 Jul 2021 11:25:49 +0100 Subject: [PATCH 03/38] Fix Mistype --- docs/sdks/android/GETTING_STARTED.md | 2 +- docs/sdks/dart/GETTING_STARTED.md | 2 +- docs/sdks/deno/GETTING_STARTED.md | 2 +- docs/sdks/dotnet/GETTING_STARTED.md | 2 +- docs/sdks/flutter/GETTING_STARTED.md | 2 +- docs/sdks/kotlin/GETTING_STARTED.md | 2 +- docs/sdks/nodejs/GETTING_STARTED.md | 2 +- docs/sdks/php/GETTING_STARTED.md | 2 +- docs/sdks/python/GETTING_STARTED.md | 2 +- docs/sdks/ruby/GETTING_STARTED.md | 2 +- docs/sdks/web/GETTING_STARTED.md | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/sdks/android/GETTING_STARTED.md b/docs/sdks/android/GETTING_STARTED.md index c0bba25051..72ea5d1071 100644 --- a/docs/sdks/android/GETTING_STARTED.md +++ b/docs/sdks/android/GETTING_STARTED.md @@ -87,7 +87,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +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) diff --git a/docs/sdks/dart/GETTING_STARTED.md b/docs/sdks/dart/GETTING_STARTED.md index d838324813..0fc1430ea2 100644 --- a/docs/sdks/dart/GETTING_STARTED.md +++ b/docs/sdks/dart/GETTING_STARTED.md @@ -40,7 +40,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/deno/GETTING_STARTED.md b/docs/sdks/deno/GETTING_STARTED.md index b06b26e94c..5fae9f634b 100644 --- a/docs/sdks/deno/GETTING_STARTED.md +++ b/docs/sdks/deno/GETTING_STARTED.md @@ -68,7 +68,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/dotnet/GETTING_STARTED.md b/docs/sdks/dotnet/GETTING_STARTED.md index cb982bf381..12084b23eb 100644 --- a/docs/sdks/dotnet/GETTING_STARTED.md +++ b/docs/sdks/dotnet/GETTING_STARTED.md @@ -45,7 +45,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 6369bbae28..28899ff18d 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -128,7 +128,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-flutter) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/kotlin/GETTING_STARTED.md b/docs/sdks/kotlin/GETTING_STARTED.md index 60d78861e8..18f2b94c41 100644 --- a/docs/sdks/kotlin/GETTING_STARTED.md +++ b/docs/sdks/kotlin/GETTING_STARTED.md @@ -77,7 +77,7 @@ suspend fun main() { ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) diff --git a/docs/sdks/nodejs/GETTING_STARTED.md b/docs/sdks/nodejs/GETTING_STARTED.md index beb139c14b..e934faf3d9 100644 --- a/docs/sdks/nodejs/GETTING_STARTED.md +++ b/docs/sdks/nodejs/GETTING_STARTED.md @@ -68,7 +68,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/php/GETTING_STARTED.md b/docs/sdks/php/GETTING_STARTED.md index af9f8d011f..49f916a139 100644 --- a/docs/sdks/php/GETTING_STARTED.md +++ b/docs/sdks/php/GETTING_STARTED.md @@ -56,7 +56,7 @@ try { ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/python/GETTING_STARTED.md b/docs/sdks/python/GETTING_STARTED.md index 2af9b088de..06645904ed 100644 --- a/docs/sdks/python/GETTING_STARTED.md +++ b/docs/sdks/python/GETTING_STARTED.md @@ -57,7 +57,7 @@ except AppwriteException as e: ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/ruby/GETTING_STARTED.md b/docs/sdks/ruby/GETTING_STARTED.md index c31a04a9e3..b2aa767a3f 100644 --- a/docs/sdks/ruby/GETTING_STARTED.md +++ b/docs/sdks/ruby/GETTING_STARTED.md @@ -57,7 +57,7 @@ end ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) diff --git a/docs/sdks/web/GETTING_STARTED.md b/docs/sdks/web/GETTING_STARTED.md index cf065cdd3d..f67ed5fe83 100644 --- a/docs/sdks/web/GETTING_STARTED.md +++ b/docs/sdks/web/GETTING_STARTED.md @@ -52,7 +52,7 @@ sdk.account.create('me@example.com', 'password', 'Jane Doe') ``` ### Learn more -You can use following resources to learn more and get help +You can use the following resources to learn more and get help - 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-flutter) - 📜 [Appwrite Docs](https://appwrite.io/docs) - 💬 [Discord Community](https://appwrite.io/discord) From 190d9607b01a7f6371dae15cbd938bb55436c21d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 7 Jul 2021 23:12:01 +1200 Subject: [PATCH 04/38] Fixed kotlin sdk java docs --- .../server-kotlin/java/account/create-recovery.md | 6 +++--- .../server-kotlin/java/account/create-verification.md | 4 ++-- .../0.9.x/server-kotlin/java/account/delete-session.md | 4 ++-- .../server-kotlin/java/account/delete-sessions.md | 2 +- .../0.9.x/server-kotlin/java/account/delete.md | 2 +- .../0.9.x/server-kotlin/java/account/get-logs.md | 2 +- .../0.9.x/server-kotlin/java/account/get-prefs.md | 2 +- .../0.9.x/server-kotlin/java/account/get-session.md | 4 ++-- .../0.9.x/server-kotlin/java/account/get-sessions.md | 2 +- docs/examples/0.9.x/server-kotlin/java/account/get.md | 2 +- .../0.9.x/server-kotlin/java/account/update-email.md | 6 +++--- .../0.9.x/server-kotlin/java/account/update-name.md | 4 ++-- .../server-kotlin/java/account/update-password.md | 4 ++-- .../0.9.x/server-kotlin/java/account/update-prefs.md | 4 ++-- .../server-kotlin/java/account/update-recovery.md | 10 +++++----- .../server-kotlin/java/account/update-verification.md | 6 +++--- .../0.9.x/server-kotlin/java/avatars/get-browser.md | 4 ++-- .../server-kotlin/java/avatars/get-credit-card.md | 4 ++-- .../0.9.x/server-kotlin/java/avatars/get-favicon.md | 4 ++-- .../0.9.x/server-kotlin/java/avatars/get-flag.md | 4 ++-- .../0.9.x/server-kotlin/java/avatars/get-image.md | 4 ++-- .../0.9.x/server-kotlin/java/avatars/get-initials.md | 2 +- .../0.9.x/server-kotlin/java/avatars/get-q-r.md | 4 ++-- .../server-kotlin/java/database/create-collection.md | 10 +++++----- .../server-kotlin/java/database/create-document.md | 6 +++--- .../server-kotlin/java/database/delete-collection.md | 4 ++-- .../server-kotlin/java/database/delete-document.md | 6 +++--- .../server-kotlin/java/database/get-collection.md | 4 ++-- .../0.9.x/server-kotlin/java/database/get-document.md | 6 +++--- .../server-kotlin/java/database/list-collections.md | 2 +- .../server-kotlin/java/database/list-documents.md | 4 ++-- .../server-kotlin/java/database/update-collection.md | 6 +++--- .../server-kotlin/java/database/update-document.md | 8 ++++---- .../server-kotlin/java/functions/create-execution.md | 4 ++-- .../0.9.x/server-kotlin/java/functions/create-tag.md | 8 ++++---- .../0.9.x/server-kotlin/java/functions/create.md | 8 ++++---- .../0.9.x/server-kotlin/java/functions/delete-tag.md | 6 +++--- .../0.9.x/server-kotlin/java/functions/delete.md | 4 ++-- .../server-kotlin/java/functions/get-execution.md | 6 +++--- .../0.9.x/server-kotlin/java/functions/get-tag.md | 6 +++--- .../examples/0.9.x/server-kotlin/java/functions/get.md | 4 ++-- .../server-kotlin/java/functions/list-executions.md | 4 ++-- .../0.9.x/server-kotlin/java/functions/list-tags.md | 4 ++-- .../0.9.x/server-kotlin/java/functions/list.md | 2 +- .../0.9.x/server-kotlin/java/functions/update-tag.md | 6 +++--- .../0.9.x/server-kotlin/java/functions/update.md | 8 ++++---- .../0.9.x/server-kotlin/java/health/get-anti-virus.md | 2 +- .../0.9.x/server-kotlin/java/health/get-cache.md | 2 +- .../0.9.x/server-kotlin/java/health/get-d-b.md | 2 +- .../java/health/get-queue-certificates.md | 2 +- .../server-kotlin/java/health/get-queue-functions.md | 2 +- .../0.9.x/server-kotlin/java/health/get-queue-logs.md | 2 +- .../0.9.x/server-kotlin/java/health/get-queue-tasks.md | 2 +- .../0.9.x/server-kotlin/java/health/get-queue-usage.md | 2 +- .../server-kotlin/java/health/get-queue-webhooks.md | 2 +- .../server-kotlin/java/health/get-storage-local.md | 2 +- .../0.9.x/server-kotlin/java/health/get-time.md | 2 +- docs/examples/0.9.x/server-kotlin/java/health/get.md | 2 +- .../0.9.x/server-kotlin/java/locale/get-continents.md | 2 +- .../server-kotlin/java/locale/get-countries-e-u.md | 2 +- .../server-kotlin/java/locale/get-countries-phones.md | 2 +- .../0.9.x/server-kotlin/java/locale/get-countries.md | 2 +- .../0.9.x/server-kotlin/java/locale/get-currencies.md | 2 +- .../0.9.x/server-kotlin/java/locale/get-languages.md | 2 +- docs/examples/0.9.x/server-kotlin/java/locale/get.md | 2 +- .../0.9.x/server-kotlin/java/storage/create-file.md | 4 ++-- .../0.9.x/server-kotlin/java/storage/delete-file.md | 4 ++-- .../server-kotlin/java/storage/get-file-download.md | 4 ++-- .../server-kotlin/java/storage/get-file-preview.md | 4 ++-- .../0.9.x/server-kotlin/java/storage/get-file-view.md | 4 ++-- .../0.9.x/server-kotlin/java/storage/get-file.md | 4 ++-- .../0.9.x/server-kotlin/java/storage/list-files.md | 2 +- .../0.9.x/server-kotlin/java/storage/update-file.md | 8 ++++---- .../server-kotlin/java/teams/create-membership.md | 10 +++++----- docs/examples/0.9.x/server-kotlin/java/teams/create.md | 4 ++-- .../server-kotlin/java/teams/delete-membership.md | 6 +++--- docs/examples/0.9.x/server-kotlin/java/teams/delete.md | 4 ++-- .../0.9.x/server-kotlin/java/teams/get-memberships.md | 4 ++-- docs/examples/0.9.x/server-kotlin/java/teams/get.md | 4 ++-- docs/examples/0.9.x/server-kotlin/java/teams/list.md | 2 +- .../java/teams/update-membership-roles.md | 8 ++++---- .../java/teams/update-membership-status.md | 10 +++++----- docs/examples/0.9.x/server-kotlin/java/teams/update.md | 6 +++--- docs/examples/0.9.x/server-kotlin/java/users/create.md | 6 +++--- .../0.9.x/server-kotlin/java/users/delete-session.md | 6 +++--- .../0.9.x/server-kotlin/java/users/delete-sessions.md | 4 ++-- docs/examples/0.9.x/server-kotlin/java/users/delete.md | 4 ++-- .../0.9.x/server-kotlin/java/users/get-logs.md | 4 ++-- .../0.9.x/server-kotlin/java/users/get-prefs.md | 4 ++-- .../0.9.x/server-kotlin/java/users/get-sessions.md | 4 ++-- docs/examples/0.9.x/server-kotlin/java/users/get.md | 4 ++-- docs/examples/0.9.x/server-kotlin/java/users/list.md | 2 +- .../0.9.x/server-kotlin/java/users/update-prefs.md | 6 +++--- .../0.9.x/server-kotlin/java/users/update-status.md | 6 +++--- .../server-kotlin/java/users/update-verification.md | 6 +++--- 95 files changed, 201 insertions(+), 201 deletions(-) diff --git a/docs/examples/0.9.x/server-kotlin/java/account/create-recovery.md b/docs/examples/0.9.x/server-kotlin/java/account/create-recovery.md index 83fbe91a95..f6563c3f12 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/create-recovery.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/create-recovery.md @@ -9,9 +9,9 @@ public void main() { Account account = new Account(client); account.createRecovery( - email = "email@example.com", - url = "https://example.com" - new Continuation() { + "email@example.com", + "https://example.com" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/create-verification.md b/docs/examples/0.9.x/server-kotlin/java/account/create-verification.md index 2ca770e2e1..3ccaba861c 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/create-verification.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/create-verification.md @@ -9,8 +9,8 @@ public void main() { Account account = new Account(client); account.createVerification( - url = "https://example.com" - new Continuation() { + "https://example.com" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/delete-session.md b/docs/examples/0.9.x/server-kotlin/java/account/delete-session.md index bb925a77e3..96628f92c7 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/delete-session.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/delete-session.md @@ -9,8 +9,8 @@ public void main() { Account account = new Account(client); account.deleteSession( - sessionId = "[SESSION_ID]" - new Continuation() { + "[SESSION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/delete-sessions.md b/docs/examples/0.9.x/server-kotlin/java/account/delete-sessions.md index 4cda782b99..ae9bbc95dc 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/delete-sessions.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/delete-sessions.md @@ -8,7 +8,7 @@ public void main() { .setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token Account account = new Account(client); - account.deleteSessions(new Continuation() { + account.deleteSessions(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/delete.md b/docs/examples/0.9.x/server-kotlin/java/account/delete.md index bec268b8e0..17db76c4d3 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/delete.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/delete.md @@ -8,7 +8,7 @@ public void main() { .setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token Account account = new Account(client); - account.delete(new Continuation() { + account.delete(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/get-logs.md b/docs/examples/0.9.x/server-kotlin/java/account/get-logs.md index 1d0f604519..df4f150275 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/get-logs.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/get-logs.md @@ -8,7 +8,7 @@ public void main() { .setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token Account account = new Account(client); - account.getLogs(new Continuation() { + account.getLogs(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/get-prefs.md b/docs/examples/0.9.x/server-kotlin/java/account/get-prefs.md index 501e2d08c7..4f1a7c081c 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/get-prefs.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/get-prefs.md @@ -8,7 +8,7 @@ public void main() { .setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token Account account = new Account(client); - account.getPrefs(new Continuation() { + account.getPrefs(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/get-session.md b/docs/examples/0.9.x/server-kotlin/java/account/get-session.md index 6f3e9e1a82..d99f4f98f2 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/get-session.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/get-session.md @@ -9,8 +9,8 @@ public void main() { Account account = new Account(client); account.getSession( - sessionId = "[SESSION_ID]" - new Continuation() { + "[SESSION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/get-sessions.md b/docs/examples/0.9.x/server-kotlin/java/account/get-sessions.md index 1f42599185..561267ab6d 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/get-sessions.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/get-sessions.md @@ -8,7 +8,7 @@ public void main() { .setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token Account account = new Account(client); - account.getSessions(new Continuation() { + account.getSessions(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/get.md b/docs/examples/0.9.x/server-kotlin/java/account/get.md index 2429a5d5d9..513a719a8a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/get.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/get.md @@ -8,7 +8,7 @@ public void main() { .setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token Account account = new Account(client); - account.get(new Continuation() { + account.get(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/update-email.md b/docs/examples/0.9.x/server-kotlin/java/account/update-email.md index 187fa22e2d..9017a8f239 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/update-email.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/update-email.md @@ -9,9 +9,9 @@ public void main() { Account account = new Account(client); account.updateEmail( - email = "email@example.com", - password = "password" - new Continuation() { + "email@example.com", + "password" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/update-name.md b/docs/examples/0.9.x/server-kotlin/java/account/update-name.md index 6f15d10e41..58291fe7d3 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/update-name.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/update-name.md @@ -9,8 +9,8 @@ public void main() { Account account = new Account(client); account.updateName( - name = "[NAME]" - new Continuation() { + "[NAME]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/update-password.md b/docs/examples/0.9.x/server-kotlin/java/account/update-password.md index 5058503b4c..6d460b5de1 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/update-password.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/update-password.md @@ -9,8 +9,8 @@ public void main() { Account account = new Account(client); account.updatePassword( - password = "password", - new Continuation() { + "password", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/update-prefs.md b/docs/examples/0.9.x/server-kotlin/java/account/update-prefs.md index ca085e904c..6cc967c4cc 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/update-prefs.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/update-prefs.md @@ -9,8 +9,8 @@ public void main() { Account account = new Account(client); account.updatePrefs( - prefs = mapOf( "a" to "b" ) - new Continuation() { + mapOf( "a" to "b" ) + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/update-recovery.md b/docs/examples/0.9.x/server-kotlin/java/account/update-recovery.md index d2b79d3dc5..4a77021b00 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/update-recovery.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/update-recovery.md @@ -9,11 +9,11 @@ public void main() { Account account = new Account(client); account.updateRecovery( - userId = "[USER_ID]", - secret = "[SECRET]", - password = "password", - passwordAgain = "password" - new Continuation() { + "[USER_ID]", + "[SECRET]", + "password", + "password" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/account/update-verification.md b/docs/examples/0.9.x/server-kotlin/java/account/update-verification.md index 0c0eb6c962..cb2d467c42 100644 --- a/docs/examples/0.9.x/server-kotlin/java/account/update-verification.md +++ b/docs/examples/0.9.x/server-kotlin/java/account/update-verification.md @@ -9,9 +9,9 @@ public void main() { Account account = new Account(client); account.updateVerification( - userId = "[USER_ID]", - secret = "[SECRET]" - new Continuation() { + "[USER_ID]", + "[SECRET]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-browser.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-browser.md index 3042e77002..5400828c2a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-browser.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-browser.md @@ -9,8 +9,8 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getBrowser( - code = "aa", - new Continuation() { + "aa", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-credit-card.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-credit-card.md index 956f6b76f3..9f2a02e360 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-credit-card.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-credit-card.md @@ -9,8 +9,8 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getCreditCard( - code = "amex", - new Continuation() { + "amex", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-favicon.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-favicon.md index 35b64fcc0b..d713cfc3bf 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-favicon.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-favicon.md @@ -9,8 +9,8 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getFavicon( - url = "https://example.com" - new Continuation() { + "https://example.com" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-flag.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-flag.md index ccc90df1e6..31c5e5cef3 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-flag.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-flag.md @@ -9,8 +9,8 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getFlag( - code = "af", - new Continuation() { + "af", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-image.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-image.md index 357f6bf29c..3c84fb04b1 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-image.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-image.md @@ -9,8 +9,8 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getImage( - url = "https://example.com", - new Continuation() { + "https://example.com", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-initials.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-initials.md index c6ef8ce8e7..906f1a62db 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-initials.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-initials.md @@ -9,7 +9,7 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getInitials( - new Continuation() { + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/avatars/get-q-r.md b/docs/examples/0.9.x/server-kotlin/java/avatars/get-q-r.md index 07031b38ce..30559ae369 100644 --- a/docs/examples/0.9.x/server-kotlin/java/avatars/get-q-r.md +++ b/docs/examples/0.9.x/server-kotlin/java/avatars/get-q-r.md @@ -9,8 +9,8 @@ public void main() { Avatars avatars = new Avatars(client); avatars.getQR( - text = "[TEXT]", - new Continuation() { + "[TEXT]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/create-collection.md b/docs/examples/0.9.x/server-kotlin/java/database/create-collection.md index e6cce6c375..4492ce25ca 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/create-collection.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/create-collection.md @@ -9,11 +9,11 @@ public void main() { Database database = new Database(client); database.createCollection( - name = "[NAME]", - read = listOf(), - write = listOf(), - rules = listOf() - new Continuation() { + "[NAME]", + listOf(), + listOf(), + listOf() + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/create-document.md b/docs/examples/0.9.x/server-kotlin/java/database/create-document.md index 5d86b83094..03e0cafd3a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/create-document.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/create-document.md @@ -9,9 +9,9 @@ public void main() { Database database = new Database(client); database.createDocument( - collectionId = "[COLLECTION_ID]", - data = mapOf( "a" to "b" ), - new Continuation() { + "[COLLECTION_ID]", + mapOf( "a" to "b" ), + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/delete-collection.md b/docs/examples/0.9.x/server-kotlin/java/database/delete-collection.md index ea666ca565..d0dd0cac77 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/delete-collection.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/delete-collection.md @@ -9,8 +9,8 @@ public void main() { Database database = new Database(client); database.deleteCollection( - collectionId = "[COLLECTION_ID]" - new Continuation() { + "[COLLECTION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/delete-document.md b/docs/examples/0.9.x/server-kotlin/java/database/delete-document.md index 9bc26e85f0..de39f36d5d 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/delete-document.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/delete-document.md @@ -9,9 +9,9 @@ public void main() { Database database = new Database(client); database.deleteDocument( - collectionId = "[COLLECTION_ID]", - documentId = "[DOCUMENT_ID]" - new Continuation() { + "[COLLECTION_ID]", + "[DOCUMENT_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/get-collection.md b/docs/examples/0.9.x/server-kotlin/java/database/get-collection.md index 1d6e96e45d..be4e39dab9 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/get-collection.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/get-collection.md @@ -9,8 +9,8 @@ public void main() { Database database = new Database(client); database.getCollection( - collectionId = "[COLLECTION_ID]" - new Continuation() { + "[COLLECTION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/get-document.md b/docs/examples/0.9.x/server-kotlin/java/database/get-document.md index 4ed6fe7ff9..b92c404f69 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/get-document.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/get-document.md @@ -9,9 +9,9 @@ public void main() { Database database = new Database(client); database.getDocument( - collectionId = "[COLLECTION_ID]", - documentId = "[DOCUMENT_ID]" - new Continuation() { + "[COLLECTION_ID]", + "[DOCUMENT_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/list-collections.md b/docs/examples/0.9.x/server-kotlin/java/database/list-collections.md index 9fbda9f9c6..6d0fe9ad02 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/list-collections.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/list-collections.md @@ -9,7 +9,7 @@ public void main() { Database database = new Database(client); database.listCollections( - new Continuation() { + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/list-documents.md b/docs/examples/0.9.x/server-kotlin/java/database/list-documents.md index 05e890783a..25bc741f11 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/list-documents.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/list-documents.md @@ -9,8 +9,8 @@ public void main() { Database database = new Database(client); database.listDocuments( - collectionId = "[COLLECTION_ID]", - new Continuation() { + "[COLLECTION_ID]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/update-collection.md b/docs/examples/0.9.x/server-kotlin/java/database/update-collection.md index e05700427a..db9fd9e325 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/update-collection.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/update-collection.md @@ -9,9 +9,9 @@ public void main() { Database database = new Database(client); database.updateCollection( - collectionId = "[COLLECTION_ID]", - name = "[NAME]", - new Continuation() { + "[COLLECTION_ID]", + "[NAME]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/database/update-document.md b/docs/examples/0.9.x/server-kotlin/java/database/update-document.md index 9c06624d4b..ca8399609f 100644 --- a/docs/examples/0.9.x/server-kotlin/java/database/update-document.md +++ b/docs/examples/0.9.x/server-kotlin/java/database/update-document.md @@ -9,10 +9,10 @@ public void main() { Database database = new Database(client); database.updateDocument( - collectionId = "[COLLECTION_ID]", - documentId = "[DOCUMENT_ID]", - data = mapOf( "a" to "b" ), - new Continuation() { + "[COLLECTION_ID]", + "[DOCUMENT_ID]", + mapOf( "a" to "b" ), + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/create-execution.md b/docs/examples/0.9.x/server-kotlin/java/functions/create-execution.md index eb13aed5c3..f71c52554a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/create-execution.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/create-execution.md @@ -9,8 +9,8 @@ public void main() { Functions functions = new Functions(client); functions.createExecution( - functionId = "[FUNCTION_ID]", - new Continuation() { + "[FUNCTION_ID]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/create-tag.md b/docs/examples/0.9.x/server-kotlin/java/functions/create-tag.md index 2ab53ae359..d6252f3425 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/create-tag.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/create-tag.md @@ -9,10 +9,10 @@ public void main() { Functions functions = new Functions(client); functions.createTag( - functionId = "[FUNCTION_ID]", - command = "[COMMAND]", - code = File("./path-to-files/image.jpg") - new Continuation() { + "[FUNCTION_ID]", + "[COMMAND]", + File("./path-to-files/image.jpg") + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/create.md b/docs/examples/0.9.x/server-kotlin/java/functions/create.md index 2cd762a3b5..2d02c2a066 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/create.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/create.md @@ -9,10 +9,10 @@ public void main() { Functions functions = new Functions(client); functions.create( - name = "[NAME]", - execute = listOf(), - runtime = "java-11.0", - new Continuation() { + "[NAME]", + listOf(), + "java-11.0", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/delete-tag.md b/docs/examples/0.9.x/server-kotlin/java/functions/delete-tag.md index 35cd36fbdc..b1b32f43cf 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/delete-tag.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/delete-tag.md @@ -9,9 +9,9 @@ public void main() { Functions functions = new Functions(client); functions.deleteTag( - functionId = "[FUNCTION_ID]", - tagId = "[TAG_ID]" - new Continuation() { + "[FUNCTION_ID]", + "[TAG_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/delete.md b/docs/examples/0.9.x/server-kotlin/java/functions/delete.md index a51709b874..d6ac9c3a66 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/delete.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/delete.md @@ -9,8 +9,8 @@ public void main() { Functions functions = new Functions(client); functions.delete( - functionId = "[FUNCTION_ID]" - new Continuation() { + "[FUNCTION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/get-execution.md b/docs/examples/0.9.x/server-kotlin/java/functions/get-execution.md index 4161b28eaf..9cf872a793 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/get-execution.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/get-execution.md @@ -9,9 +9,9 @@ public void main() { Functions functions = new Functions(client); functions.getExecution( - functionId = "[FUNCTION_ID]", - executionId = "[EXECUTION_ID]" - new Continuation() { + "[FUNCTION_ID]", + "[EXECUTION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/get-tag.md b/docs/examples/0.9.x/server-kotlin/java/functions/get-tag.md index 4e805f8386..290730d383 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/get-tag.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/get-tag.md @@ -9,9 +9,9 @@ public void main() { Functions functions = new Functions(client); functions.getTag( - functionId = "[FUNCTION_ID]", - tagId = "[TAG_ID]" - new Continuation() { + "[FUNCTION_ID]", + "[TAG_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/get.md b/docs/examples/0.9.x/server-kotlin/java/functions/get.md index 8e1cd5ef29..96d0eba931 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/get.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/get.md @@ -9,8 +9,8 @@ public void main() { Functions functions = new Functions(client); functions.get( - functionId = "[FUNCTION_ID]" - new Continuation() { + "[FUNCTION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/list-executions.md b/docs/examples/0.9.x/server-kotlin/java/functions/list-executions.md index 915bf64d4b..412d78bf88 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/list-executions.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/list-executions.md @@ -9,8 +9,8 @@ public void main() { Functions functions = new Functions(client); functions.listExecutions( - functionId = "[FUNCTION_ID]", - new Continuation() { + "[FUNCTION_ID]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/list-tags.md b/docs/examples/0.9.x/server-kotlin/java/functions/list-tags.md index 4d67eb99dd..3982c7dfc2 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/list-tags.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/list-tags.md @@ -9,8 +9,8 @@ public void main() { Functions functions = new Functions(client); functions.listTags( - functionId = "[FUNCTION_ID]", - new Continuation() { + "[FUNCTION_ID]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/list.md b/docs/examples/0.9.x/server-kotlin/java/functions/list.md index e365f30f1f..a23792d898 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/list.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/list.md @@ -9,7 +9,7 @@ public void main() { Functions functions = new Functions(client); functions.list( - new Continuation() { + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/update-tag.md b/docs/examples/0.9.x/server-kotlin/java/functions/update-tag.md index 572e514ec0..5266d0e963 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/update-tag.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/update-tag.md @@ -9,9 +9,9 @@ public void main() { Functions functions = new Functions(client); functions.updateTag( - functionId = "[FUNCTION_ID]", - tag = "[TAG]" - new Continuation() { + "[FUNCTION_ID]", + "[TAG]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/functions/update.md b/docs/examples/0.9.x/server-kotlin/java/functions/update.md index 80d95c2f4b..ac5c3c8e3d 100644 --- a/docs/examples/0.9.x/server-kotlin/java/functions/update.md +++ b/docs/examples/0.9.x/server-kotlin/java/functions/update.md @@ -9,10 +9,10 @@ public void main() { Functions functions = new Functions(client); functions.update( - functionId = "[FUNCTION_ID]", - name = "[NAME]", - execute = listOf(), - new Continuation() { + "[FUNCTION_ID]", + "[NAME]", + listOf(), + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-anti-virus.md b/docs/examples/0.9.x/server-kotlin/java/health/get-anti-virus.md index a27b1c58b9..8cca86bc26 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-anti-virus.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-anti-virus.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getAntiVirus(new Continuation() { + health.getAntiVirus(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-cache.md b/docs/examples/0.9.x/server-kotlin/java/health/get-cache.md index e7300a34f4..b5fb7e72de 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-cache.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-cache.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getCache(new Continuation() { + health.getCache(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-d-b.md b/docs/examples/0.9.x/server-kotlin/java/health/get-d-b.md index 9644806bd2..6d835fa52b 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-d-b.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-d-b.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getDB(new Continuation() { + health.getDB(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-certificates.md b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-certificates.md index 084576b65a..3498cb1e67 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-certificates.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-certificates.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getQueueCertificates(new Continuation() { + health.getQueueCertificates(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-functions.md b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-functions.md index 9809a03d2f..b89d2dd6cb 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-functions.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-functions.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getQueueFunctions(new Continuation() { + health.getQueueFunctions(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-logs.md b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-logs.md index 4a08fa9321..36e10755a6 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-logs.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-logs.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getQueueLogs(new Continuation() { + health.getQueueLogs(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-tasks.md b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-tasks.md index 8e28955770..cbcc13253f 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-tasks.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-tasks.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getQueueTasks(new Continuation() { + health.getQueueTasks(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-usage.md b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-usage.md index e7fd65f170..4bad82cf4c 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-usage.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-usage.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getQueueUsage(new Continuation() { + health.getQueueUsage(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-webhooks.md b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-webhooks.md index d8bc27a2bf..e969d7a04f 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-queue-webhooks.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-queue-webhooks.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getQueueWebhooks(new Continuation() { + health.getQueueWebhooks(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-storage-local.md b/docs/examples/0.9.x/server-kotlin/java/health/get-storage-local.md index 079eca49e1..fb652fdd96 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-storage-local.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-storage-local.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getStorageLocal(new Continuation() { + health.getStorageLocal(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get-time.md b/docs/examples/0.9.x/server-kotlin/java/health/get-time.md index a8ca3b91de..2f4e90f144 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get-time.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get-time.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.getTime(new Continuation() { + health.getTime(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/health/get.md b/docs/examples/0.9.x/server-kotlin/java/health/get.md index 30adbbbf60..c66131fe6b 100644 --- a/docs/examples/0.9.x/server-kotlin/java/health/get.md +++ b/docs/examples/0.9.x/server-kotlin/java/health/get.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Health health = new Health(client); - health.get(new Continuation() { + health.get(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get-continents.md b/docs/examples/0.9.x/server-kotlin/java/locale/get-continents.md index 836eadac9a..b57a999351 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get-continents.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get-continents.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.getContinents(new Continuation() { + locale.getContinents(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-e-u.md b/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-e-u.md index 3bb79f9482..da3f5be058 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-e-u.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-e-u.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.getCountriesEU(new Continuation() { + locale.getCountriesEU(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-phones.md b/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-phones.md index b1596d2ccb..1e0b166dcc 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-phones.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get-countries-phones.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.getCountriesPhones(new Continuation() { + locale.getCountriesPhones(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get-countries.md b/docs/examples/0.9.x/server-kotlin/java/locale/get-countries.md index 95d1fef52f..1899d5f3d3 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get-countries.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get-countries.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.getCountries(new Continuation() { + locale.getCountries(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get-currencies.md b/docs/examples/0.9.x/server-kotlin/java/locale/get-currencies.md index c7495f485a..3fdd0df45f 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get-currencies.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get-currencies.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.getCurrencies(new Continuation() { + locale.getCurrencies(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get-languages.md b/docs/examples/0.9.x/server-kotlin/java/locale/get-languages.md index f59054e699..77febddbe9 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get-languages.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get-languages.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.getLanguages(new Continuation() { + locale.getLanguages(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/locale/get.md b/docs/examples/0.9.x/server-kotlin/java/locale/get.md index bf2f34fb02..714f214f50 100644 --- a/docs/examples/0.9.x/server-kotlin/java/locale/get.md +++ b/docs/examples/0.9.x/server-kotlin/java/locale/get.md @@ -8,7 +8,7 @@ public void main() { .setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key Locale locale = new Locale(client); - locale.get(new Continuation() { + locale.get(new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/create-file.md b/docs/examples/0.9.x/server-kotlin/java/storage/create-file.md index 2de730aa7b..1b61e4e303 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/create-file.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/create-file.md @@ -9,8 +9,8 @@ public void main() { Storage storage = new Storage(client); storage.createFile( - file = File("./path-to-files/image.jpg"), - new Continuation() { + File("./path-to-files/image.jpg"), + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/delete-file.md b/docs/examples/0.9.x/server-kotlin/java/storage/delete-file.md index 8b9e6438c7..24c346021a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/delete-file.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/delete-file.md @@ -9,8 +9,8 @@ public void main() { Storage storage = new Storage(client); storage.deleteFile( - fileId = "[FILE_ID]" - new Continuation() { + "[FILE_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/get-file-download.md b/docs/examples/0.9.x/server-kotlin/java/storage/get-file-download.md index da9fe1c042..90bb8262b1 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/get-file-download.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/get-file-download.md @@ -9,8 +9,8 @@ public void main() { Storage storage = new Storage(client); storage.getFileDownload( - fileId = "[FILE_ID]" - new Continuation() { + "[FILE_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/get-file-preview.md b/docs/examples/0.9.x/server-kotlin/java/storage/get-file-preview.md index 928771a5aa..2692e0b8f9 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/get-file-preview.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/get-file-preview.md @@ -9,8 +9,8 @@ public void main() { Storage storage = new Storage(client); storage.getFilePreview( - fileId = "[FILE_ID]", - new Continuation() { + "[FILE_ID]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/get-file-view.md b/docs/examples/0.9.x/server-kotlin/java/storage/get-file-view.md index b74d121c89..0fb4398441 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/get-file-view.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/get-file-view.md @@ -9,8 +9,8 @@ public void main() { Storage storage = new Storage(client); storage.getFileView( - fileId = "[FILE_ID]" - new Continuation() { + "[FILE_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/get-file.md b/docs/examples/0.9.x/server-kotlin/java/storage/get-file.md index 9bf9860976..ce7c58e575 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/get-file.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/get-file.md @@ -9,8 +9,8 @@ public void main() { Storage storage = new Storage(client); storage.getFile( - fileId = "[FILE_ID]" - new Continuation() { + "[FILE_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/list-files.md b/docs/examples/0.9.x/server-kotlin/java/storage/list-files.md index 5a85543eae..3385e34962 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/list-files.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/list-files.md @@ -9,7 +9,7 @@ public void main() { Storage storage = new Storage(client); storage.listFiles( - new Continuation() { + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/storage/update-file.md b/docs/examples/0.9.x/server-kotlin/java/storage/update-file.md index 91fe0168a4..37201414b7 100644 --- a/docs/examples/0.9.x/server-kotlin/java/storage/update-file.md +++ b/docs/examples/0.9.x/server-kotlin/java/storage/update-file.md @@ -9,10 +9,10 @@ public void main() { Storage storage = new Storage(client); storage.updateFile( - fileId = "[FILE_ID]", - read = listOf(), - write = listOf() - new Continuation() { + "[FILE_ID]", + listOf(), + listOf() + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/create-membership.md b/docs/examples/0.9.x/server-kotlin/java/teams/create-membership.md index 077ce3f058..de0c70f0cf 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/create-membership.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/create-membership.md @@ -9,11 +9,11 @@ public void main() { Teams teams = new Teams(client); teams.createMembership( - teamId = "[TEAM_ID]", - email = "email@example.com", - roles = listOf(), - url = "https://example.com", - new Continuation() { + "[TEAM_ID]", + "email@example.com", + listOf(), + "https://example.com", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/create.md b/docs/examples/0.9.x/server-kotlin/java/teams/create.md index cdc269fa1a..dfd38f0ddf 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/create.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/create.md @@ -9,8 +9,8 @@ public void main() { Teams teams = new Teams(client); teams.create( - name = "[NAME]", - new Continuation() { + "[NAME]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/delete-membership.md b/docs/examples/0.9.x/server-kotlin/java/teams/delete-membership.md index 7a57a32d9a..cc7d19fcba 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/delete-membership.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/delete-membership.md @@ -9,9 +9,9 @@ public void main() { Teams teams = new Teams(client); teams.deleteMembership( - teamId = "[TEAM_ID]", - membershipId = "[MEMBERSHIP_ID]" - new Continuation() { + "[TEAM_ID]", + "[MEMBERSHIP_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/delete.md b/docs/examples/0.9.x/server-kotlin/java/teams/delete.md index 7ace480161..559602c337 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/delete.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/delete.md @@ -9,8 +9,8 @@ public void main() { Teams teams = new Teams(client); teams.delete( - teamId = "[TEAM_ID]" - new Continuation() { + "[TEAM_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/get-memberships.md b/docs/examples/0.9.x/server-kotlin/java/teams/get-memberships.md index af76419c43..a37cab43d3 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/get-memberships.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/get-memberships.md @@ -9,8 +9,8 @@ public void main() { Teams teams = new Teams(client); teams.getMemberships( - teamId = "[TEAM_ID]", - new Continuation() { + "[TEAM_ID]", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/get.md b/docs/examples/0.9.x/server-kotlin/java/teams/get.md index 23f52dc5c5..22072f9dd2 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/get.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/get.md @@ -9,8 +9,8 @@ public void main() { Teams teams = new Teams(client); teams.get( - teamId = "[TEAM_ID]" - new Continuation() { + "[TEAM_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/list.md b/docs/examples/0.9.x/server-kotlin/java/teams/list.md index 2a7bf89f6e..f17b0011e0 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/list.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/list.md @@ -9,7 +9,7 @@ public void main() { Teams teams = new Teams(client); teams.list( - new Continuation() { + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-roles.md b/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-roles.md index 7e8d68283d..4026515cfc 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-roles.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-roles.md @@ -9,10 +9,10 @@ public void main() { Teams teams = new Teams(client); teams.updateMembershipRoles( - teamId = "[TEAM_ID]", - membershipId = "[MEMBERSHIP_ID]", - roles = listOf() - new Continuation() { + "[TEAM_ID]", + "[MEMBERSHIP_ID]", + listOf() + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-status.md b/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-status.md index 0a528d4d81..c969cabad8 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-status.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/update-membership-status.md @@ -9,11 +9,11 @@ public void main() { Teams teams = new Teams(client); teams.updateMembershipStatus( - teamId = "[TEAM_ID]", - membershipId = "[MEMBERSHIP_ID]", - userId = "[USER_ID]", - secret = "[SECRET]" - new Continuation() { + "[TEAM_ID]", + "[MEMBERSHIP_ID]", + "[USER_ID]", + "[SECRET]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/teams/update.md b/docs/examples/0.9.x/server-kotlin/java/teams/update.md index 5c05d6a65f..b3c1476dee 100644 --- a/docs/examples/0.9.x/server-kotlin/java/teams/update.md +++ b/docs/examples/0.9.x/server-kotlin/java/teams/update.md @@ -9,9 +9,9 @@ public void main() { Teams teams = new Teams(client); teams.update( - teamId = "[TEAM_ID]", - name = "[NAME]" - new Continuation() { + "[TEAM_ID]", + "[NAME]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/create.md b/docs/examples/0.9.x/server-kotlin/java/users/create.md index 78f815c42f..57193cc85a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/create.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/create.md @@ -9,9 +9,9 @@ public void main() { Users users = new Users(client); users.create( - email = "email@example.com", - password = "password", - new Continuation() { + "email@example.com", + "password", + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/delete-session.md b/docs/examples/0.9.x/server-kotlin/java/users/delete-session.md index 7295506bc2..6f50727290 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/delete-session.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/delete-session.md @@ -9,9 +9,9 @@ public void main() { Users users = new Users(client); users.deleteSession( - userId = "[USER_ID]", - sessionId = "[SESSION_ID]" - new Continuation() { + "[USER_ID]", + "[SESSION_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/delete-sessions.md b/docs/examples/0.9.x/server-kotlin/java/users/delete-sessions.md index 6fb4028c37..759ddca58d 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/delete-sessions.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/delete-sessions.md @@ -9,8 +9,8 @@ public void main() { Users users = new Users(client); users.deleteSessions( - userId = "[USER_ID]" - new Continuation() { + "[USER_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/delete.md b/docs/examples/0.9.x/server-kotlin/java/users/delete.md index f004170a1e..2e8bba2007 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/delete.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/delete.md @@ -9,8 +9,8 @@ public void main() { Users users = new Users(client); users.delete( - userId = "[USER_ID]" - new Continuation() { + "[USER_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/get-logs.md b/docs/examples/0.9.x/server-kotlin/java/users/get-logs.md index 44e0ea272a..97ee90b0ad 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/get-logs.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/get-logs.md @@ -9,8 +9,8 @@ public void main() { Users users = new Users(client); users.getLogs( - userId = "[USER_ID]" - new Continuation() { + "[USER_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/get-prefs.md b/docs/examples/0.9.x/server-kotlin/java/users/get-prefs.md index d45fbf4682..79a9d09ef0 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/get-prefs.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/get-prefs.md @@ -9,8 +9,8 @@ public void main() { Users users = new Users(client); users.getPrefs( - userId = "[USER_ID]" - new Continuation() { + "[USER_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/get-sessions.md b/docs/examples/0.9.x/server-kotlin/java/users/get-sessions.md index cf2e06a858..eeed04069f 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/get-sessions.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/get-sessions.md @@ -9,8 +9,8 @@ public void main() { Users users = new Users(client); users.getSessions( - userId = "[USER_ID]" - new Continuation() { + "[USER_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/get.md b/docs/examples/0.9.x/server-kotlin/java/users/get.md index 98b3df0680..b64e8e8cfe 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/get.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/get.md @@ -9,8 +9,8 @@ public void main() { Users users = new Users(client); users.get( - userId = "[USER_ID]" - new Continuation() { + "[USER_ID]" + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/list.md b/docs/examples/0.9.x/server-kotlin/java/users/list.md index f0c4710b65..07e38fc32b 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/list.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/list.md @@ -9,7 +9,7 @@ public void main() { Users users = new Users(client); users.list( - new Continuation() { + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/update-prefs.md b/docs/examples/0.9.x/server-kotlin/java/users/update-prefs.md index 393366cf10..5e232fc65a 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/update-prefs.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/update-prefs.md @@ -9,9 +9,9 @@ public void main() { Users users = new Users(client); users.updatePrefs( - userId = "[USER_ID]", - prefs = mapOf( "a" to "b" ) - new Continuation() { + "[USER_ID]", + mapOf( "a" to "b" ) + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/update-status.md b/docs/examples/0.9.x/server-kotlin/java/users/update-status.md index 4c802b3bd7..9fbc8ce65b 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/update-status.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/update-status.md @@ -9,9 +9,9 @@ public void main() { Users users = new Users(client); users.updateStatus( - userId = "[USER_ID]", - status = 1 - new Continuation() { + "[USER_ID]", + 1 + new Continuation() { @NotNull @Override public CoroutineContext getContext() { diff --git a/docs/examples/0.9.x/server-kotlin/java/users/update-verification.md b/docs/examples/0.9.x/server-kotlin/java/users/update-verification.md index cf62364845..ef4a23f9cf 100644 --- a/docs/examples/0.9.x/server-kotlin/java/users/update-verification.md +++ b/docs/examples/0.9.x/server-kotlin/java/users/update-verification.md @@ -9,9 +9,9 @@ public void main() { Users users = new Users(client); users.updateVerification( - userId = "[USER_ID]", - emailVerification = false - new Continuation() { + "[USER_ID]", + false + new Continuation() { @NotNull @Override public CoroutineContext getContext() { From f158980963b8b6ace6fd7f567fb5c322d370d634 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 7 Jul 2021 13:46:44 +0200 Subject: [PATCH 05/38] fix(database): default value for empty rules --- app/controllers/api/database.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 4c87a6be12..16d320667b 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -437,7 +437,7 @@ App::get('/v1/database/collections/:collectionId/documents') } $types = []; - foreach ($collection->getAttribute('rules') as $rule) { + foreach ($collection->getAttribute('rules', []) as $rule) { /** @var Document $rule */ $types[$rule->getAttribute('key')] = $rule->getAttribute('type'); } @@ -630,4 +630,4 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') ; $response->noContent(); - }); \ No newline at end of file + }); From ce8a1dc8c21edb1d44a1f3b361f7010e4595e5b1 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 7 Jul 2021 20:17:24 +0530 Subject: [PATCH 06/38] feat(platforms): update maven links --- app/config/platforms.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index aee5eac750..b12bf41cd2 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -113,7 +113,7 @@ return [ 'name' => 'Android', 'version' => '0.0.1', 'url' => 'https://github.com/appwrite/sdk-for-android', - 'package' => 'https://repo1.maven.org/maven2/io/appwrite/sdk-for-android/', + 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', 'enabled' => true, 'beta' => true, 'dev' => false, @@ -355,7 +355,7 @@ return [ 'name' => 'Kotlin', 'version' => '0.0.1', 'url' => 'https://github.com/appwrite/sdk-for-kotlin', - 'package' => 'https://repo1.maven.org/maven2/io/appwrite/sdk-for-kotlin/', + 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin', 'enabled' => true, 'beta' => true, 'dev' => false, From 53a24217dc7f522c541873a07ea1b844b77918c1 Mon Sep 17 00:00:00 2001 From: "Eldad A. Fux" Date: Thu, 8 Jul 2021 17:50:02 +0300 Subject: [PATCH 07/38] Update CONTRIBUTING.md --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69d26d0aa4..e1d2cd3ec4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -123,6 +123,10 @@ Learn more at our [Technology Stack](## Technology Stack) section. Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures, but our final goal, as we grow, is to be using only microservices. +--- +![Appwrite](docs/specs/overview.drawio.svg) +--- + ### File Structure ```bash @@ -174,10 +178,6 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi └── unit ``` ---- -![Appwrite](docs/specs/overview.drawio.svg) ---- - ### The Monolithic Part Appwrite's main API container is designed as a monolithic app. This is a decision we made to allow us to develop the project faster while still being a very small team. From ce9ee59156f31807307c2d96a49463c7096f2dda Mon Sep 17 00:00:00 2001 From: "Eldad A. Fux" Date: Fri, 9 Jul 2021 07:39:58 +0300 Subject: [PATCH 08/38] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index eb696e7c15..19273cf3b1 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ Below is a list of currently supported platforms and languages. If you wish to h #### Client * ✅   [Web](https://github.com/appwrite/sdk-for-web) (Maintained by the Appwrite Team) * ✅   [Flutter](https://github.com/appwrite/sdk-for-flutter) (Maintained by the Appwrite Team) +* ✅   [Android](https://github.com/appwrite/sdk-for-android) (Maintained by the Appwrite Team) #### Server * ✅   [NodeJS](https://github.com/appwrite/sdk-for-node) (Maintained by the Appwrite Team) @@ -129,6 +130,7 @@ Below is a list of currently supported platforms and languages. If you wish to h * ✅   [Deno](https://github.com/appwrite/sdk-for-deno) - **Beta** (Maintained by the Appwrite Team) * ✅   [Ruby](https://github.com/appwrite/sdk-for-ruby) - **Beta** (Maintained by the Appwrite Team) * ✅   [Python](https://github.com/appwrite/sdk-for-python) - **Beta** (Maintained by the Appwrite Team) +* ✅   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) (Maintained by the Appwrite Team) * ✅   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Experimental** (Maintained by the Appwrite Team) Looking for more SDKs? - Help us by contributing a pull request to our [SDK Generator](https://github.com/appwrite/sdk-generator)! From bb95ec536b5120dd3755416cf375a72463178b70 Mon Sep 17 00:00:00 2001 From: "Eldad A. Fux" Date: Fri, 9 Jul 2021 07:44:45 +0300 Subject: [PATCH 09/38] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 19273cf3b1..670121eca1 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,9 @@ Below is a list of currently supported platforms and languages. If you wish to h * ✅   [PHP](https://github.com/appwrite/sdk-for-php) (Maintained by the Appwrite Team) * ✅   [Dart](https://github.com/appwrite/sdk-for-dart) **Beta** (Maintained by the Appwrite Team) * ✅   [Deno](https://github.com/appwrite/sdk-for-deno) - **Beta** (Maintained by the Appwrite Team) -* ✅   [Ruby](https://github.com/appwrite/sdk-for-ruby) - **Beta** (Maintained by the Appwrite Team) -* ✅   [Python](https://github.com/appwrite/sdk-for-python) - **Beta** (Maintained by the Appwrite Team) -* ✅   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) (Maintained by the Appwrite Team) +* ✅   [Ruby](https://github.com/appwrite/sdk-for-ruby) (Maintained by the Appwrite Team) +* ✅   [Python](https://github.com/appwrite/sdk-for-python) (Maintained by the Appwrite Team) +* ✅   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) - **Beta** (Maintained by the Appwrite Team) * ✅   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Experimental** (Maintained by the Appwrite Team) Looking for more SDKs? - Help us by contributing a pull request to our [SDK Generator](https://github.com/appwrite/sdk-generator)! From c7978bddfac7aac6cb51c13515cc27436387ac30 Mon Sep 17 00:00:00 2001 From: "Eldad A. Fux" Date: Sat, 10 Jul 2021 07:33:32 +0300 Subject: [PATCH 10/38] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 670121eca1..f584c93a97 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![Build Status](https://img.shields.io/travis/com/appwrite/appwrite?style=flat-square)](https://travis-ci.com/appwrite/appwrite) [![Twitter Account](https://img.shields.io/twitter/follow/appwrite_io?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite_io) -[**Appwrite 0.9 has been released! Learn what's new!**](https://dev.to/appwrite/announcing-appwrite-0-8-an-open-source-self-hosted-baas-kda) +[**Appwrite 0.9 has been released! Learn what's new!**](https://dev.to/appwrite/announcing-appwrite-0-9-the-open-source-firebase-alternative-53ho) Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster. From e8754111b971067b97f33dcd6411f64263704f12 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sat, 10 Jul 2021 21:06:46 +0545 Subject: [PATCH 11/38] install and enable yasd if testing is true --- Dockerfile | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b450b6a6d9..3987f998d5 100755 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,9 @@ RUN composer update --ignore-platform-reqs --optimize-autoloader \ FROM php:8.0-cli-alpine as step1 +ARG TESTING=false +ENV TESTING=$TESTING + ENV PHP_REDIS_VERSION=5.3.4 \ PHP_SWOOLE_VERSION=v4.6.7 \ PHP_IMAGICK_VERSION=3.5.0 \ @@ -75,11 +78,25 @@ RUN \ make && make install && \ cd ../.. +## Swoole Debugger setup +RUN if [ "$TESTING" == "true" ]; then \ + cd /tmp && \ + apk add boost-dev && \ + git clone --depth 1 https://github.com/swoole/yasd && \ + cd yasd && \ + phpize && \ + ./configure && \ + make && make install && \ + cd ..;\ + fi + FROM php:8.0-cli-alpine as final LABEL maintainer="team@appwrite.io" ARG VERSION=dev +ARG TESTING=false +ENV TESTING=$TESTING ENV _APP_SERVER=swoole \ _APP_ENV=production \ @@ -160,10 +177,15 @@ RUN \ && apk del .deps \ && rm -rf /var/cache/apk/* +RUN \ + if [ "$TESTING" == "true" ]; then \ + apk add boost boost-dev; \ + fi + WORKDIR /usr/src/code COPY --from=step0 /usr/local/src/vendor /usr/src/code/vendor -COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/ +COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yasd.so* /usr/local/lib/php/extensions/no-debug-non-zts-20200930/ COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/ COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/imagick.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/ COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yaml.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/ @@ -218,7 +240,9 @@ RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini +RUN if [ "$TESTING" == "true" ]; then printf 'zend_extension=yasd \nyasd.debug_mode=remote \nyasd.remote_host=192.168.1.64 \nyasd.remote_port=9005 \nyasd.log_level=0 \nyasd.breakpoints_file="yasd.log"' >> /usr/local/etc/php/conf.d/yasd.ini; fi +RUN if [ "$TESTING" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini RUN echo "opcache.preload=/usr/src/code/app/preload.php" >> /usr/local/etc/php/conf.d/appwrite.ini RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/appwrite.ini From 24f85cdc781a81ab9b52685719607c475e1781b7 Mon Sep 17 00:00:00 2001 From: Matej Baco Date: Sat, 10 Jul 2021 20:07:03 +0200 Subject: [PATCH 12/38] Added " to wrap environment name --- app/workers/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index fcd0d624e4..a85843b38d 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -337,7 +337,7 @@ class FunctionsV1 extends Worker : null; if(\is_null($runtime)) { - throw new Exception('Runtime "'.$function->getAttribute('runtime', '').' is not supported'); + throw new Exception('Runtime "'.$function->getAttribute('runtime', '').'" is not supported'); } $vars = \array_merge($function->getAttribute('vars', []), [ From 5073c264b73f46666783db1a97b389ae0cc39fe8 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 11 Jul 2021 15:49:31 +0545 Subject: [PATCH 13/38] modified entrypoint to support debugger --- docker-compose.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index fb8a8355f9..0117887fd2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -72,6 +72,13 @@ services: - redis # - clamav - influxdb + entrypoint: + - php + - -e + - app/http.php + - -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php + + environment: - _APP_ENV - _APP_LOCALE From 74b24dfe6917babd58bad0de9c9a60a3687c5afb Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 11 Jul 2021 17:20:03 +0545 Subject: [PATCH 14/38] properly setup debugger for everyone and contribution guide --- .gitignore | 3 ++- CONTRIBUTING.md | 24 ++++++++++++++++++++++++ Dockerfile | 2 +- dev/yasd_init.php.stub | 4 ++++ docker-compose.yml | 3 +-- 5 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 dev/yasd_init.php.stub diff --git a/.gitignore b/.gitignore index c7d23a9df8..33974acbe2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ .DS_Store .php_cs.cache debug/ -app/sdks \ No newline at end of file +app/sdks +dev/yasd_init.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e1d2cd3ec4..69d4e047c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -282,6 +282,30 @@ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7 The Runtimes for all supported cloud functions (multicore builds) can be found at the [appwrite/php-runtimes](https://github.com/appwrite/php-runtimes) repository. +## Debug + +Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which is available by default in debug build of Appwrite. You can connect to the debugger using VS Code [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection. + +Finally you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger wont connect. + +### VS Code Launch Configuration + +```json +{ + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9005, + "pathMappings": { + "/usr/src/code": "${workspaceRoot}" + }, +} +``` + +### PHPStorm Setup + +In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, there under **Xdebug** set the debug port to **9005** and enable **can accept external connections** checkbox. + ## Tests To run all tests manually, use the Appwrite Docker CLI from your terminal: diff --git a/Dockerfile b/Dockerfile index 3987f998d5..15cbcd107b 100755 --- a/Dockerfile +++ b/Dockerfile @@ -240,7 +240,7 @@ RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini -RUN if [ "$TESTING" == "true" ]; then printf 'zend_extension=yasd \nyasd.debug_mode=remote \nyasd.remote_host=192.168.1.64 \nyasd.remote_port=9005 \nyasd.log_level=0 \nyasd.breakpoints_file="yasd.log"' >> /usr/local/etc/php/conf.d/yasd.ini; fi +RUN if [ "$TESTING" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi RUN if [ "$TESTING" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini diff --git a/dev/yasd_init.php.stub b/dev/yasd_init.php.stub new file mode 100644 index 0000000000..a7d977fbf7 --- /dev/null +++ b/dev/yasd_init.php.stub @@ -0,0 +1,4 @@ + Date: Sun, 11 Jul 2021 18:10:39 +0545 Subject: [PATCH 15/38] update with DEBUG build args --- CONTRIBUTING.md | 4 ++-- Dockerfile | 16 ++++++++-------- docker-compose.yml | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69d4e047c4..552ff05612 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -284,9 +284,9 @@ The Runtimes for all supported cloud functions (multicore builds) can be found a ## Debug -Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which is available by default in debug build of Appwrite. You can connect to the debugger using VS Code [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection. +Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection. -Finally you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger wont connect. +First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger wont connect. And you also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file. ### VS Code Launch Configuration diff --git a/Dockerfile b/Dockerfile index 15cbcd107b..d15dbf508e 100755 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,8 @@ RUN composer update --ignore-platform-reqs --optimize-autoloader \ FROM php:8.0-cli-alpine as step1 -ARG TESTING=false -ENV TESTING=$TESTING +ARG DEBUG=false +ENV DEBUG=$DEBUG ENV PHP_REDIS_VERSION=5.3.4 \ PHP_SWOOLE_VERSION=v4.6.7 \ @@ -79,7 +79,7 @@ RUN \ cd ../.. ## Swoole Debugger setup -RUN if [ "$TESTING" == "true" ]; then \ +RUN if [ "$DEBUG" == "true" ]; then \ cd /tmp && \ apk add boost-dev && \ git clone --depth 1 https://github.com/swoole/yasd && \ @@ -95,8 +95,8 @@ FROM php:8.0-cli-alpine as final LABEL maintainer="team@appwrite.io" ARG VERSION=dev -ARG TESTING=false -ENV TESTING=$TESTING +ARG DEBUG=false +ENV DEBUG=$DEBUG ENV _APP_SERVER=swoole \ _APP_ENV=production \ @@ -178,7 +178,7 @@ RUN \ && rm -rf /var/cache/apk/* RUN \ - if [ "$TESTING" == "true" ]; then \ + if [ "$DEBUG" == "true" ]; then \ apk add boost boost-dev; \ fi @@ -240,9 +240,9 @@ RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini -RUN if [ "$TESTING" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi +RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi -RUN if [ "$TESTING" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi +RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini RUN echo "opcache.preload=/usr/src/code/app/preload.php" >> /usr/local/etc/php/conf.d/appwrite.ini RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/appwrite.ini diff --git a/docker-compose.yml b/docker-compose.yml index 4845e827e1..1037cf8557 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -39,6 +39,7 @@ services: build: context: . args: + - DEBUG=false - TESTING=true - VERSION=dev ports: From 18d4a0def0e6812e6c14e698ab50334cb518537f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 12 Jul 2021 11:51:58 +0200 Subject: [PATCH 16/38] fix(app): remove app resource and replace with utopia --- app/controllers/api/account.php | 8 ++++---- app/controllers/api/health.php | 16 ++++++++-------- app/controllers/api/users.php | 8 ++++---- app/http.php | 4 ---- composer.lock | 20 +++++++++----------- 5 files changed, 25 insertions(+), 31 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 850f42af58..37ab46166d 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -918,16 +918,16 @@ App::get('/v1/account/logs') ->inject('user') ->inject('locale') ->inject('geodb') - ->inject('app') - ->action(function ($response, $project, $user, $locale, $geodb, $app) { + ->inject('utopia') + ->action(function ($response, $project, $user, $locale, $geodb, $utopia) { /** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $user */ /** @var Utopia\Locale\Locale $locale */ /** @var MaxMind\Db\Reader $geodb */ - /** @var Utopia\App $app */ + /** @var Utopia\App $utopia */ - $adapter = new AuditAdapter($app->getResource('db')); + $adapter = new AuditAdapter($utopia->getResource('db')); $adapter->setNamespace('app_'.$project->getId()); $audit = new Audit($adapter); diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index a161b2bdea..cbccb8f59c 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -42,11 +42,11 @@ App::get('/v1/health/db') ->label('sdk.method', 'getDB') ->label('sdk.description', '/docs/references/health/get-db.md') ->inject('response') - ->inject('app') - ->action(function ($response, $app) { + ->inject('utopia') + ->action(function ($response, $utopia) { /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\App $app */ - $app->getResource('db'); + /** @var Utopia\App $utopia */ + $utopia->getResource('db'); $response->json(['status' => 'OK']); }); @@ -60,11 +60,11 @@ App::get('/v1/health/cache') ->label('sdk.method', 'getCache') ->label('sdk.description', '/docs/references/health/get-cache.md') ->inject('response') - ->inject('app') - ->action(function ($response, $app) { + ->inject('utopia') + ->action(function ($response, $utopia) { /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\App $register */ - $app->getResource('cache'); + /** @var Utopia\App $utopia */ + $utopia->getResource('cache'); $response->json(['status' => 'OK']); }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index a11c65edc5..e73a0a2f74 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -236,14 +236,14 @@ App::get('/v1/users/:userId/logs') ->inject('projectDB') ->inject('locale') ->inject('geodb') - ->inject('app') - ->action(function ($userId, $response, $project, $projectDB, $locale, $geodb, $app) { + ->inject('utopia') + ->action(function ($userId, $response, $project, $projectDB, $locale, $geodb, $utopia) { /** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Database $projectDB */ /** @var Utopia\Locale\Locale $locale */ /** @var MaxMind\Db\Reader $geodb */ - /** @var Utopia\App $app */ + /** @var Utopia\App $utopia */ $user = $projectDB->getDocument($userId); @@ -251,7 +251,7 @@ App::get('/v1/users/:userId/logs') throw new Exception('User not found', 404); } - $adapter = new AuditAdapter($app->getResource('db')); + $adapter = new AuditAdapter($utopia->getResource('db')); $adapter->setNamespace('app_'.$project->getId()); $audit = new Audit($adapter); diff --git a/app/http.php b/app/http.php index 6b216da802..baf069324d 100644 --- a/app/http.php +++ b/app/http.php @@ -87,10 +87,6 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo App::setResource('cache', function () use (&$redis) { return $redis; }); - - App::setResource('app', function() use (&$app) { - return $app; - }); try { Authorization::cleanRoles(); diff --git a/composer.lock b/composer.lock index 4bb236099e..fba3b66cee 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": "7983e9fe8946a99fbf818b79ff202486", + "content-hash": "e24aacead283e33130051470bb4312e6", "packages": [ { "name": "adhocore/jwt", @@ -2403,16 +2403,16 @@ }, { "name": "appwrite/sdk-generator", - "version": "dev-feat-kotlin-java-docs", + "version": "0.12.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "966d464728b41a8c449e99d7df4bd4ddca591a25" + "reference": "ca8e34f091b3a66f94a8972cb94b0b8e1161dada" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/966d464728b41a8c449e99d7df4bd4ddca591a25", - "reference": "966d464728b41a8c449e99d7df4bd4ddca591a25", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/ca8e34f091b3a66f94a8972cb94b0b8e1161dada", + "reference": "ca8e34f091b3a66f94a8972cb94b0b8e1161dada", "shasum": "" }, "require": { @@ -2446,9 +2446,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/feat-kotlin-java-docs" + "source": "https://github.com/appwrite/sdk-generator/tree/0.12.0" }, - "time": "2021-07-06T09:26:45+00:00" + "time": "2021-07-06T16:20:51+00:00" }, { "name": "composer/package-versions-deprecated", @@ -6066,9 +6066,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "appwrite/sdk-generator": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -6090,5 +6088,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } From df24011d8b8366a193baf8d40f7bbd1465205f53 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 12 Jul 2021 12:04:00 +0200 Subject: [PATCH 17/38] fix(http): reset pdo connection if broken --- app/http.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/http.php b/app/http.php index 6b216da802..1329814d9c 100644 --- a/app/http.php +++ b/app/http.php @@ -98,11 +98,20 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $app->run($request, $response); } catch (\Throwable $th) { - Console::error('[Error] Type: '.get_class($th)); + $type = get_class($th); + + Console::error('[Error] Type: '.$type); Console::error('[Error] Message: '.$th->getMessage()); Console::error('[Error] File: '.$th->getFile()); Console::error('[Error] Line: '.$th->getLine()); + /** + * Reset Database connection if PDOException was thrown. + */ + if ($type === 'PDOException') { + $db = null; + } + if(App::isDevelopment()) { $swooleResponse->end('error: '.$th->getMessage()); } From 76af58c646ce8e0564afff66f1a78f9f24726ee1 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 12 Jul 2021 17:27:26 +0200 Subject: [PATCH 18/38] fix(pdo): throw on general to parent --- app/controllers/general.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index cd95b74a0c..2a0dd7021d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -304,6 +304,10 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project) { /** @var Utopia\View $layout */ /** @var Appwrite\Database\Document $project */ + if (get_class($error) == 'PDOException') { + throw $error; + } + $route = $utopia->match($request); $template = ($route) ? $route->getLabel('error', null) : null; From cff517a2ab1ed2702db5c30022ca321e57869e0e Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 12 Jul 2021 18:15:21 +0200 Subject: [PATCH 19/38] adapt to review --- app/controllers/general.php | 2 +- app/http.php | 6 ++---- app/init.php | 5 ++--- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 2a0dd7021d..708e249853 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -304,7 +304,7 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project) { /** @var Utopia\View $layout */ /** @var Appwrite\Database\Document $project */ - if (get_class($error) == 'PDOException') { + if ($error instanceof PDOException) { throw $error; } diff --git a/app/http.php b/app/http.php index 1329814d9c..28e2fd2805 100644 --- a/app/http.php +++ b/app/http.php @@ -98,9 +98,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $app->run($request, $response); } catch (\Throwable $th) { - $type = get_class($th); - - Console::error('[Error] Type: '.$type); + Console::error('[Error] Type: '.get_class($th)); Console::error('[Error] Message: '.$th->getMessage()); Console::error('[Error] File: '.$th->getFile()); Console::error('[Error] Line: '.$th->getLine()); @@ -108,7 +106,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo /** * Reset Database connection if PDOException was thrown. */ - if ($type === 'PDOException') { + if ($th instanceof PDOException) { $db = null; } diff --git a/app/init.php b/app/init.php index 302ce0f650..617322f9d6 100644 --- a/app/init.php +++ b/app/init.php @@ -164,12 +164,11 @@ $register->set('dbPool', function () { // Register DB connection $pool = new PDOPool((new PDOConfig()) ->withHost($dbHost) ->withPort($dbPort) - // ->withUnixSocket('/tmp/mysql.sock') ->withDbName($dbScheme) ->withCharset('utf8mb4') ->withUsername($dbUser) ->withPassword($dbPass) - ); + , 16); return $pool; }); @@ -189,7 +188,7 @@ $register->set('redisPool', function () { ->withPort($redisPort) ->withAuth($redisAuth) ->withDbIndex(0) - ); + , 16); return $pool; }); diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 1acc350664..c110fcd4eb 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -342,7 +342,7 @@ services: - MYSQL_DATABASE=${_APP_DB_SCHEMA} - MYSQL_USER=${_APP_DB_USER} - MYSQL_PASSWORD=${_APP_DB_PASS} - command: 'mysqld --innodb-flush-method=fsync' + command: 'mysqld --innodb-flush-method=fsync --wait_timeout=86400' redis: image: redis:6.0-alpine3.12 diff --git a/docker-compose.yml b/docker-compose.yml index fb8a8355f9..621304f0a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -390,7 +390,7 @@ services: - MYSQL_DATABASE=${_APP_DB_SCHEMA} - MYSQL_USER=${_APP_DB_USER} - MYSQL_PASSWORD=${_APP_DB_PASS} - command: 'mysqld --innodb-flush-method=fsync' # add ' --query_cache_size=0' for DB tests + command: 'mysqld --innodb-flush-method=fsync --wait_timeout=86400' # add ' --query_cache_size=0' for DB tests # command: mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bu && mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bu # smtp: From 71941d8712d6606cdb78d9cf29add8812a707a93 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 12 Jul 2021 18:21:12 +0200 Subject: [PATCH 20/38] feat(release): 0.9.1 --- CHANGES.md | 6 ++++++ README.md | 6 +++--- app/init.php | 2 +- src/Appwrite/Migration/Migration.php | 1 + 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5743bd42e5..c3b03d8acd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +# Version 0.9.1 + +## Bugs + +- Fix PDO Connection timeout +- Remove unnecessary `app` resource and replace with `utopia` # Version 0.9.0 ## Features diff --git a/README.md b/README.md index 670121eca1..b32a84e277 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,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.9.0 + appwrite/appwrite:0.9.1 ``` ### Windows @@ -68,7 +68,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.9.0 + appwrite/appwrite:0.9.1 ``` #### PowerShell @@ -78,7 +78,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.9.0 + appwrite/appwrite:0.9.1 ``` 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/init.php b/app/init.php index 302ce0f650..ecf5d883f8 100644 --- a/app/init.php +++ b/app/init.php @@ -48,7 +48,7 @@ const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; const APP_CACHE_BUSTER = 149; -const APP_VERSION_STABLE = '0.9.0'; +const APP_VERSION_STABLE = '0.9.1'; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; const APP_STORAGE_CACHE = '/storage/cache'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 0d6995b064..bd03e7d339 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -39,6 +39,7 @@ abstract class Migration '0.7.0' => 'V06', '0.8.0' => 'V07', '0.9.0' => 'V08', + '0.9.1' => 'V08', ]; /** From 582f4e91f69cd8c9ee98717638ed52f28d55a7f3 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 12 Jul 2021 20:03:29 +0200 Subject: [PATCH 21/38] Update CHANGES.md --- CHANGES.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c3b03d8acd..94b56bc7a0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,8 +2,10 @@ ## Bugs -- Fix PDO Connection timeout -- Remove unnecessary `app` resource and replace with `utopia` +- Fixed PDO Connection timeout (#1385) +- Removed unnecessary `app` resource and replace with `utopia` (#1384) +- Fixed missing quote in Functions Worker logs (#1375) + # Version 0.9.0 ## Features From 6e69b0a82bbf06042f18cfc493984de66b14a176 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 15 Jul 2021 18:12:18 +0200 Subject: [PATCH 22/38] fix(install): escape shell args --- app/tasks/install.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/tasks/install.php b/app/tasks/install.php index 755e0b7e2c..483f5c5e04 100644 --- a/app/tasks/install.php +++ b/app/tasks/install.php @@ -129,7 +129,7 @@ $cli $httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')'); $httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort; } - + $input = []; foreach($vars as $key => $var) { @@ -196,7 +196,7 @@ $cli foreach ($input as $key => $value) { if($value) { - $env .= $key.'='.$value.' '; + $env .= $key.'='.\escapeshellarg($value).' '; } } From cf3ffcdf32bdf4909d53e0de290bd3b9324fb1a4 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 18 Jul 2021 16:19:50 +0545 Subject: [PATCH 23/38] update create membership doc --- docs/references/teams/create-team-membership.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/references/teams/create-team-membership.md b/docs/references/teams/create-team-membership.md index a920c260be..c6d81de484 100644 --- a/docs/references/teams/create-team-membership.md +++ b/docs/references/teams/create-team-membership.md @@ -1,5 +1,5 @@ -Use this endpoint to invite a new member to join your team. An email with a link to join the team will be sent to the new member email address if the member doesn't exist in the project it will be created automatically. +Use this endpoint to invite a new member to join your team. If initiated from Client SDK, an email with a link to join the team will be sent to the new member's email address if the member doesn't exist in the project it will be created automatically. If initiated from server side SDKs, new member will automatically be added to the team. -Use the 'URL' parameter to redirect the user from the invitation email back to your app. When the user is redirected, use the [Update Team Membership Status](/docs/client/teams#teamsUpdateMembershipStatus) endpoint to allow the user to accept the invitation to the team. +Use the 'URL' parameter to redirect the user from the invitation email back to your app. When the user is redirected, use the [Update Team Membership Status](/docs/client/teams#teamsUpdateMembershipStatus) endpoint to allow the user to accept the invitation to the team. While calling from side SDKs the redirect url can be empty string. Please note that in order to avoid a [Redirect Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when added your platforms in the console interface. \ No newline at end of file From c2f1389a568653fffdc385bbfce956ecea613421 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 19 Jul 2021 17:09:39 +0200 Subject: [PATCH 24/38] fix(jwt): correct session validation --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index a139a4f841..6461f50acb 100644 --- a/app/init.php +++ b/app/init.php @@ -467,7 +467,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response $user = $projectDB->getDocument($jwtUserId); } - if (empty($user->search('$id', $jwtSessionId, $user->getAttribute('tokens')))) { // Match JWT to active token + if (empty($user->search('$id', $jwtSessionId, $user->getAttribute('sessions')))) { // Match JWT to active token $user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]); } } From 4e1bc7aa1d0c24cf4af43c08a88d082ece58cc0d Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Jul 2021 11:02:07 +0200 Subject: [PATCH 25/38] feat(0.9.2): release --- app/init.php | 4 ++-- src/Appwrite/Migration/Migration.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/init.php b/app/init.php index a139a4f841..3ad673249c 100644 --- a/app/init.php +++ b/app/init.php @@ -47,8 +47,8 @@ const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s'; const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; -const APP_CACHE_BUSTER = 149; -const APP_VERSION_STABLE = '0.9.1'; +const APP_CACHE_BUSTER = 150; +const APP_VERSION_STABLE = '0.9.2'; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; const APP_STORAGE_CACHE = '/storage/cache'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index bd03e7d339..8eae515b9b 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -40,6 +40,7 @@ abstract class Migration '0.8.0' => 'V07', '0.9.0' => 'V08', '0.9.1' => 'V08', + '0.9.2' => 'V08', ]; /** From d235ed71908c9bdcf5c1ba1bfe66a8aa92e06dec Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Jul 2021 11:04:17 +0200 Subject: [PATCH 26/38] chore(changelog): add 0.9.2 --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 94b56bc7a0..54b353bd91 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +# Version 0.9.2 + +## Bugs + +- Fixed JWT session validation (#1408) + # Version 0.9.1 ## Bugs From ca3d677596d952eeb992f3bb73787771fc672c8a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Jul 2021 11:08:08 +0100 Subject: [PATCH 27/38] Make untarring the code file a blocking task --- app/workers/functions.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index a85843b38d..bbb20b823e 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -425,15 +425,24 @@ class FunctionsV1 extends Worker " --workdir /usr/local/src". " ".\implode(" ", $vars). " {$runtime['image']}". - " sh -c 'mv /tmp/code.tar.gz /usr/local/src/code.tar.gz && tar -zxf /usr/local/src/code.tar.gz --strip 1 && rm /usr/local/src/code.tar.gz && tail -f /dev/null'" + " tail -f /dev/null" , '', $stdout, $stderr, 30); - $executionEnd = \microtime(true); - if($exitCode !== 0) { throw new Exception('Failed to create function environment: '.$stderr); } + $exitCodeUntar = Console::execute("docker exec ". + $container. + " sh -c 'mv /tmp/code.tar.gz /usr/local/src/code.tar.gz && tar -zxf /usr/local/src/code.tar.gz --strip 1 && rm /usr/local/src/code.tar.gz'" + , '', $stdout, $stderr, 60); + + if($exitCodeUntar !== 0) { + throw new Exception('Failed to extract tar: '.$stderr); + } + + $executionEnd = \microtime(true); + $list[$container] = [ 'name' => $container, 'online' => true, From 70d4c4d7beb7d51ba33501b7e3cb785347f211d4 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Jul 2021 11:46:05 +0100 Subject: [PATCH 28/38] Update functions.php --- app/workers/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index bbb20b823e..2ab1f1f309 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -433,9 +433,9 @@ class FunctionsV1 extends Worker } $exitCodeUntar = Console::execute("docker exec ". - $container. - " sh -c 'mv /tmp/code.tar.gz /usr/local/src/code.tar.gz && tar -zxf /usr/local/src/code.tar.gz --strip 1 && rm /usr/local/src/code.tar.gz'" - , '', $stdout, $stderr, 60); + $container. + " sh -c 'mv /tmp/code.tar.gz /usr/local/src/code.tar.gz && tar -zxf /usr/local/src/code.tar.gz --strip 1 && rm /usr/local/src/code.tar.gz'" + , '', $stdout, $stderr, 60); if($exitCodeUntar !== 0) { throw new Exception('Failed to extract tar: '.$stderr); From d0e4e5cb29e73f45adbb9fb28b15d6e8bdc6113a Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 22 Jul 2021 17:49:52 +0300 Subject: [PATCH 29/38] Fixed bug --- app/controllers/api/functions.php | 14 ++++----- .../Functions/FunctionsCustomClientTest.php | 25 ++++++++++++++++ .../Functions/FunctionsCustomServerTest.php | 23 +++++++++++++++ tests/resources/functions/php-fn.tar.gz | Bin 24549 -> 24954 bytes tests/resources/functions/php-fn/index.php | 27 ++++++++++-------- 5 files changed, 70 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index dd58108893..1560355aa0 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -748,20 +748,20 @@ App::post('/v1/functions/:functionId/executions') $jwt = ''; // initialize if (!empty($user->getId())) { // If userId exists, generate a JWT for function - $tokens = $user->getAttribute('tokens', []); - $session = new Document(); + $sessions = $user->getAttribute('sessions', []); + $current = new Document(); - foreach ($tokens as $token) { /** @var Appwrite\Database\Document $token */ - if ($token->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too - $session = $token; + foreach ($sessions as $session) { /** @var Appwrite\Database\Document $session */ + if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too + $current = $session; } } - if(!$session->isEmpty()) { + if(!$current->isEmpty()) { $jwtObj = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway. $jwt = $jwtObj->encode([ 'userId' => $user->getId(), - 'sessionId' => $session->getId(), + 'sessionId' => $current->getId(), ]); } } diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 8ba16f8145..454a149c3c 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -185,7 +185,32 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $execution['headers']['status-code']); + $executionId = $execution['body']['$id'] ?? ''; + sleep(10); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ]); + + $output = json_decode($executions['body']['stdout'], true); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertEquals('completed', $executions['body']['status']); + $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); + $this->assertEquals('Test', $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals($tagId, $output['APPWRITE_FUNCTION_TAG']); + $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); + $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); + $this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT_DATA']); + $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); + $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); + $this->assertNotEmpty($output['APPWRITE_FUNCTION_JWT']); + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index cf0a1cafc4..775eca06e2 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -582,8 +582,31 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $execution['headers']['status-code']); + $executionId = $execution['body']['$id'] ?? ''; + sleep(10); + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $output = json_decode($executions['body']['stdout'], true); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertEquals('completed', $executions['body']['status']); + $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals($tagId, $output['APPWRITE_FUNCTION_TAG']); + $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); + $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); + $this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT_DATA']); + $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_USER_ID']); + $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/resources/functions/php-fn.tar.gz b/tests/resources/functions/php-fn.tar.gz index a97a2e23528ce5fd28269fd6d8e8e0798b994fb5..5e359122fa62f29d9de63305b82d9bb0b5680417 100644 GIT binary patch literal 24954 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 bDpQ%tRHibOsZ3>h?CJjlk4HwS0B{2Ub;Z~Q literal 24549 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['APPWRITE_FILEID']); -echo $_ENV['APPWRITE_FUNCTION_ID']."\n"; -echo $_ENV['APPWRITE_FUNCTION_NAME']."\n"; -echo $_ENV['APPWRITE_FUNCTION_TAG']."\n"; -echo $_ENV['APPWRITE_FUNCTION_TRIGGER']."\n"; -echo $_ENV['APPWRITE_FUNCTION_RUNTIME_NAME']."\n"; -echo $_ENV['APPWRITE_FUNCTION_RUNTIME_VERSION']."\n"; -// echo $result['$id']; -echo $_ENV['APPWRITE_FUNCTION_EVENT']."\n"; -echo $_ENV['APPWRITE_FUNCTION_EVENT_DATA']."\n"; -echo 'data:'.$_ENV['APPWRITE_FUNCTION_DATA']."\n"; -echo 'userId:'.$_ENV['APPWRITE_FUNCTION_USER_ID']."\n"; -echo 'jwt:'.$_ENV['APPWRITE_FUNCTION_JWT']."\n"; +$output = [ + 'APPWRITE_FUNCTION_ID' => $_ENV['APPWRITE_FUNCTION_ID'], + 'APPWRITE_FUNCTION_NAME' => $_ENV['APPWRITE_FUNCTION_NAME'], + 'APPWRITE_FUNCTION_TAG' => $_ENV['APPWRITE_FUNCTION_TAG'], + 'APPWRITE_FUNCTION_TRIGGER' => $_ENV['APPWRITE_FUNCTION_TRIGGER'], + 'APPWRITE_FUNCTION_RUNTIME_NAME' => $_ENV['APPWRITE_FUNCTION_RUNTIME_NAME'], + 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $_ENV['APPWRITE_FUNCTION_RUNTIME_VERSION'], + 'APPWRITE_FUNCTION_EVENT' => $_ENV['APPWRITE_FUNCTION_EVENT'], + 'APPWRITE_FUNCTION_EVENT_DATA' => $_ENV['APPWRITE_FUNCTION_EVENT_DATA'], + 'APPWRITE_FUNCTION_DATA' => $_ENV['APPWRITE_FUNCTION_DATA'], + 'APPWRITE_FUNCTION_USER_ID' => $_ENV['APPWRITE_FUNCTION_USER_ID'], + 'APPWRITE_FUNCTION_JWT' => $_ENV['APPWRITE_FUNCTION_JWT'], +]; + +echo json_encode($output); From 5815caf01e72f3f7073a4a276a606a323192404a Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Jul 2021 17:45:15 +0200 Subject: [PATCH 30/38] chore(changelog): update changelog --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 54b353bd91..ca647e7489 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,8 @@ ## Bugs - Fixed JWT session validation (#1408) +- Fixed passing valid JWT session to Cloud Functions (#1421) +- Fixed race condition when uploading and extracting bigger Cloud Functions (#1419) # Version 0.9.1 From d729d54de048b31711e5184051bd09e4bdbe0862 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 27 Jul 2021 12:07:39 +0100 Subject: [PATCH 31/38] Fix Create JWT abuse key --- 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 37ab46166d..06e42d662a 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -782,7 +782,7 @@ App::post('/v1/account/jwt') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_JWT) ->label('abuse-limit', 10) - ->label('abuse-key', 'url:{url},userId:{param-userId}') + ->label('abuse-key', 'url:{url},userId:{userId}') ->inject('response') ->inject('user') ->action(function ($response, $user) { From e0761e17376cce78cc0eca913c86a67a2dfe5536 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 27 Jul 2021 12:15:59 +0100 Subject: [PATCH 32/38] Fix create email verification abuse-key --- 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 06e42d662a..dea69037d6 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1668,7 +1668,7 @@ App::post('/v1/account/verification') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) - ->label('abuse-key', 'url:{url},email:{param-email}') + ->label('abuse-key', 'url:{url},email:{userId}') ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page ->inject('request') ->inject('response') From 7974a6ba5e3e1643c7ebd2ec5033129c611a52e9 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 27 Jul 2021 12:21:26 +0100 Subject: [PATCH 33/38] Update account.php --- 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 dea69037d6..7bb4cbb28a 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1668,7 +1668,7 @@ App::post('/v1/account/verification') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) - ->label('abuse-key', 'url:{url},email:{userId}') + ->label('abuse-key', 'url:{url},userId:{userId}') ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page ->inject('request') ->inject('response') From d3daa2be321775f1069aa2554d01331976731799 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 27 Jul 2021 14:43:08 +0200 Subject: [PATCH 34/38] feat(release): prepare 0.9.3 --- CHANGES.md | 6 ++++++ README.md | 6 +++--- app/init.php | 2 +- src/Appwrite/Migration/Migration.php | 1 + 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ca647e7489..c6e74d8528 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +# Version 0.9.3 + +## Bugs + +- Fixed Abuse Limit keys for JWT and E-Mail confirmation (#1434) + # Version 0.9.2 ## Bugs diff --git a/README.md b/README.md index 895da87d6c..c0c5077e0d 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,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.9.1 + appwrite/appwrite:0.9.3 ``` ### Windows @@ -68,7 +68,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.9.1 + appwrite/appwrite:0.9.3 ``` #### PowerShell @@ -78,7 +78,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.9.1 + appwrite/appwrite:0.9.3 ``` 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/init.php b/app/init.php index 872b1ba91a..d0271e2c41 100644 --- a/app/init.php +++ b/app/init.php @@ -48,7 +48,7 @@ const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; const APP_CACHE_BUSTER = 150; -const APP_VERSION_STABLE = '0.9.2'; +const APP_VERSION_STABLE = '0.9.3'; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; const APP_STORAGE_CACHE = '/storage/cache'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 8eae515b9b..9f5d12d47d 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -41,6 +41,7 @@ abstract class Migration '0.9.0' => 'V08', '0.9.1' => 'V08', '0.9.2' => 'V08', + '0.9.3' => 'V08', ]; /** From d8d141496274fc7692e74020271deef8c3875957 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 10 Aug 2021 10:30:39 +0200 Subject: [PATCH 35/38] prepare 0.9.4 version --- README.md | 6 +++--- app/init.php | 2 +- src/Appwrite/Migration/Migration.php | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c0c5077e0d..e8b8daf8f9 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,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.9.3 + appwrite/appwrite:0.9.4 ``` ### Windows @@ -68,7 +68,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.9.3 + appwrite/appwrite:0.9.4 ``` #### PowerShell @@ -78,7 +78,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.9.3 + appwrite/appwrite:0.9.4 ``` 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/init.php b/app/init.php index d0271e2c41..88ac10f294 100644 --- a/app/init.php +++ b/app/init.php @@ -48,7 +48,7 @@ const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; const APP_CACHE_BUSTER = 150; -const APP_VERSION_STABLE = '0.9.3'; +const APP_VERSION_STABLE = '0.9.4'; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; const APP_STORAGE_CACHE = '/storage/cache'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 9f5d12d47d..203af0c67d 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -42,6 +42,7 @@ abstract class Migration '0.9.1' => 'V08', '0.9.2' => 'V08', '0.9.3' => 'V08', + '0.9.4' => 'V08', ]; /** From c52672bc9a99e144febfdad644ee225215a6bc1e Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 1 Aug 2021 14:39:26 +0545 Subject: [PATCH 36/38] hot fix api issue --- app/controllers/api/projects.php | 8 ++++++++ app/views/console/home/index.phtml | 1 + 2 files changed, 9 insertions(+) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 2bac0efb85..bc4e5a6b1a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -21,6 +21,14 @@ use Appwrite\Network\Validator\Domain as DomainValidator; use Appwrite\Utopia\Response; use Cron\CronExpression; +App::init(function ($project) { + /** @var Utopia\Database\Document $project */ + + if($project->getId() !== 'console') { + throw new Exception('Access to this API is forbidden.', 401); + } +}, ['project'], 'projects'); + App::post('/v1/projects') ->desc('Create Project') ->groups(['api', 'projects']) diff --git a/app/views/console/home/index.phtml b/app/views/console/home/index.phtml index 021cf89928..2342a2af23 100644 --- a/app/views/console/home/index.phtml +++ b/app/views/console/home/index.phtml @@ -79,6 +79,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
From 0ad7d35bb038d298f1c8ea99397b11ebee1ecaad Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 10 Aug 2021 11:03:28 +0200 Subject: [PATCH 37/38] chore(changes): 0.9.4 changelog --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index c6e74d8528..210c82788f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +# Version 0.9.4 + +## Security + +- Fixed security vulnerability that exposes project ID's from other admin users + # Version 0.9.3 ## Bugs From 7af9bdbe3a454d12aefdb09a6002dbb34b7322fe Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 10 Aug 2021 11:07:53 +0200 Subject: [PATCH 38/38] chore(changes): 0.9.4 changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 210c82788f..c63d0205ef 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,7 @@ ## Security -- Fixed security vulnerability that exposes project ID's from other admin users +- Fixed security vulnerability that exposes project ID's from other admin users (#1453) # Version 0.9.3