diff --git a/app/controllers/general.php b/app/controllers/general.php index e24c0a8a41..e56357869d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -21,6 +21,7 @@ use Appwrite\Utopia\Response\Filters\V11 as ResponseV11; use Appwrite\Utopia\Response\Filters\V12 as ResponseV12; use Appwrite\Utopia\Response\Filters\V13 as ResponseV13; use Appwrite\Utopia\Response\Filters\V14 as ResponseV14; +use Appwrite\Utopia\Response\Filters\V15 as ResponseV15; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -31,6 +32,7 @@ use Utopia\Validator\Hostname; use Appwrite\Utopia\Request\Filters\V12 as RequestV12; use Appwrite\Utopia\Request\Filters\V13 as RequestV13; use Appwrite\Utopia\Request\Filters\V14 as RequestV14; +use Appwrite\Utopia\Request\Filters\V15 as RequestV15; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; @@ -68,6 +70,9 @@ App::init() case version_compare($requestFormat, '0.14.0', '<'): Request::setFilter(new RequestV14()); break; + case version_compare($requestFormat, '0.15.3', '<'): + Request::setFilter(new RequestV15()); + break; default: Request::setFilter(null); } @@ -194,6 +199,9 @@ App::init() case version_compare($responseFormat, '0.14.0', '<='): Response::setFilter(new ResponseV14()); break; + case version_compare($responseFormat, '0.15.3', '<='): + Response::setFilter(new ResponseV15()); + break; default: Response::setFilter(null); } diff --git a/composer.lock b/composer.lock index 7c9830602d..78f79514b9 100644 --- a/composer.lock +++ b/composer.lock @@ -5393,5 +5393,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/docs/sdks/android/GETTING_STARTED.md b/docs/sdks/android/GETTING_STARTED.md index 0c00bf6019..684f98e0f6 100644 --- a/docs/sdks/android/GETTING_STARTED.md +++ b/docs/sdks/android/GETTING_STARTED.md @@ -51,7 +51,7 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos // Register User val account = Account(client) val response = account.create( - "[USER_ID]", + ID.unique(), "email@example.com", "password" ) @@ -62,6 +62,7 @@ val response = account.create( ```kotlin import io.appwrite.Client import io.appwrite.services.Account +import io.appwrite.ID val client = Client(context) .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint @@ -69,8 +70,8 @@ val client = Client(context) .setSelfSigned(true) // Remove in production val account = Account(client) -val response = account.create( - "[USER_ID]", +val user = account.create( + ID.unique(), "email@example.com", "password" ) @@ -81,10 +82,10 @@ The Appwrite Android SDK raises an `AppwriteException` object with `message`, `c ```kotlin try { - var response = account.create("[USER_ID]", "email@example.com", "password") - Log.d("Appwrite response", response.body?.string()) + var user = account.create(ID.unique(), "email@example.com", "password") + Log.d("Appwrite user", user.toMap()) } catch(e : AppwriteException) { - Log.e("AppwriteException",e.message.toString()) + e.printStackTrace() } ``` diff --git a/docs/sdks/swift-client/CHANGELOG.md b/docs/sdks/apple/CHANGELOG.md similarity index 100% rename from docs/sdks/swift-client/CHANGELOG.md rename to docs/sdks/apple/CHANGELOG.md diff --git a/docs/sdks/swift-client/GETTING_STARTED.md b/docs/sdks/apple/GETTING_STARTED.md similarity index 62% rename from docs/sdks/swift-client/GETTING_STARTED.md rename to docs/sdks/apple/GETTING_STARTED.md index 51e5a5bc83..1da041112c 100644 --- a/docs/sdks/swift-client/GETTING_STARTED.md +++ b/docs/sdks/apple/GETTING_STARTED.md @@ -53,30 +53,35 @@ For UIKit, you need to add the following function to your `SceneDelegate.swift`. ### Init your SDK -Initialize your SDK with your Appwrite server API endpoint and project ID which can be found in your project settings page and your new API secret Key project API keys section. +Initialize your SDK with your Appwrite server API endpoint and project ID which can be found in your project settings page. ```swift import Appwrite func main() { let client = Client() - .setEndpoint("http://[HOSTNAME_OR_IP]/v1") // Your API Endpoint - .setProject("5df5acd0d48c2") // Your project ID - .setSelfSigned() // Use only on dev mode with a self-signed SSL cert + .setEndpoint("http://[HOSTNAME_OR_IP]/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + .setSelfSigned() // Use only on dev mode with a self-signed SSL cert } ``` ### Make Your First Request -Once your SDK object is set, create any of the Appwrite service objects and choose any request to send. Full documentation for any service method you would like to use can be found in your SDK documentation or in the [API References](https://appwrite.io/docs) section. +Once your SDK object is initialized, create any of the Appwrite service objects and choose any request to send. Full documentation for any service method you would like to use can be found in your SDK documentation or in the [API References](https://appwrite.io/docs) section. ```swift -let users = Users(client: client) -users.create(userId: "[USER_ID]", email: "email@example.com", password: "password") { result in - switch result { - case .failure(let error): print(error.message) - case .success(let user): print(String(describing: user)) - } +let account = Account(client) + +do { + let user = try await account.create( + userId: ID.unique(), + email: "email@example.com", + password: "password" + ) + print(String(describing: user.toMap())) +} catch { + print(error.localizedDescription) } ``` @@ -87,37 +92,40 @@ import Appwrite func main() { let client = Client() - .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint - .setProject("5df5acd0d48c2") // Your project ID - .setSelfSigned() // Use only on dev mode with a self-signed SSL cert + .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + .setSelfSigned() // Use only on dev mode with a self-signed SSL cert - let users = Users(client: client) - users.create(userId: "[USER_ID]", email: "email@example.com", password: "password") { result in - switch result { - case .failure(let error): print(error.message) - case .success(let user): print(String(describing: user)) - } + let account = Account(client) + + do { + let user = try await account.create( + userId: ID.unique(), + email: "email@example.com", + password: "password" + ) + print(String(describing: account.toMap())) + } catch { + print(error.localizedDescription) } } ``` ### Error Handling -When an error occurs, the Appwrite Swift SDK responds with a result wrapping an `AppwriteError` object with `message` and `code` properties. You can handle any errors in the result's `.failure` case and present the `message` to the user or handle it yourself based on the provided error information. Below is an example. +When an error occurs, the Appwrite Apple SDK throws an `AppwriteError` object with `message` and `code` properties. You can handle any errors in a catch block and present the `message` or `localizedDescription` to the user or handle it yourself based on the provided error information. Below is an example. ```swift import Appwrite func main() { - let users = Users(client: client) + let account = Account(client) - users.create(userId: "[USER_ID]", email: "email@example.com", password: "password") { result in - switch result { - case .failure(let error): - print(error.message) - case .success(var response): - ... - } + do { + let user = try await account.get() + print(String(describing: user.toMap())) + } catch { + print(error.localizedDescription) } } ``` diff --git a/docs/sdks/dart/GETTING_STARTED.md b/docs/sdks/dart/GETTING_STARTED.md index e6c4ecf677..559c0894a3 100644 --- a/docs/sdks/dart/GETTING_STARTED.md +++ b/docs/sdks/dart/GETTING_STARTED.md @@ -16,8 +16,8 @@ void main() async { Users users = Users(client); try { - final response = await users.create(userId: '[USER_ID]', email: ‘email@example.com’,password: ‘password’, name: ‘name’); - print(response.data); + final user = await users.create(userId: ID.unique(), email: ‘email@example.com’,password: ‘password’, name: ‘name’); + print(user.toMap()); } on AppwriteException catch(e) { print(e.message); } @@ -31,8 +31,8 @@ The Appwrite Dart SDK raises `AppwriteException` object with `message`, `code` a Users users = Users(client); try { - final response = await users.create(userId: '[USER_ID]', email: ‘email@example.com’,password: ‘password’, name: ‘name’); - print(response.data); + final user = await users.create(userId: ID.unique(), email: ‘email@example.com’,password: ‘password’, name: ‘name’); + print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required print(e.message); diff --git a/docs/sdks/deno/GETTING_STARTED.md b/docs/sdks/deno/GETTING_STARTED.md index 08c9eb461e..6546719a61 100644 --- a/docs/sdks/deno/GETTING_STARTED.md +++ b/docs/sdks/deno/GETTING_STARTED.md @@ -21,8 +21,8 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```typescript let users = new sdk.Users(client); -let response = await users.create('[USER_ID]', 'email@example.com', 'password'); -console.log(response); +let user = await users.create(ID.unique(), 'email@example.com', 'password'); +console.log(user); ``` ### Full Example @@ -39,8 +39,8 @@ client .setSelfSigned() // Use only on dev mode with a self-signed SSL cert ; -let response = await users.create('[USER_ID]', 'email@example.com', 'password'); -console.log(response); +let user = await users.create(ID.unique(), 'email@example.com', 'password'); +console.log(user); ``` ### Error Handling @@ -50,7 +50,7 @@ The Appwrite Deno SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let response = await users.create('[USER_ID]', 'email@example.com', 'password'); + let user = await users.create(ID.unique(), 'email@example.com', 'password'); } catch(e) { console.log(e.message); } diff --git a/docs/sdks/dotnet/GETTING_STARTED.md b/docs/sdks/dotnet/GETTING_STARTED.md index cffbce2078..23bab6f70a 100644 --- a/docs/sdks/dotnet/GETTING_STARTED.md +++ b/docs/sdks/dotnet/GETTING_STARTED.md @@ -20,9 +20,8 @@ static async Task Main(string[] args) var users = Users(client); try { - var request = await users.create('[USER_ID]', 'email@example.com', 'password', 'name'); - var response = await request.Content.ReadAsStringAsync(); - Console.WriteLine(response); + var user = await users.Create(ID.Unique(), 'email@example.com', 'password', 'name'); + Console.WriteLine(user.ToMap()); } catch (AppwriteException e) { Console.WriteLine(e.Message); } @@ -36,9 +35,8 @@ The Appwrite .NET SDK raises `AppwriteException` object with `message`, `code` a var users = Users(client); try { - var request = await users.create('[USER_ID]', 'email@example.com', 'password', 'name'); - var response = await request.Content.ReadAsStringAsync(); - Console.WriteLine(response); + var user = await users.Create(ID.Unique(), 'email@example.com', 'password', 'name'); + Console.WriteLine(user.ToMap()); } catch (AppwriteException e) { Console.WriteLine(e.Message); } diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index a9c121d2b9..78a334e9f7 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -101,9 +101,9 @@ When trying to connect to Appwrite from an emulator or a mobile device, localhos ```dart // Register User Account account = Account(client); -Response user = await account +final user = await account .create( - userId: '[USER_ID]', + userId: ID.unique(), email: 'me@appwrite.io', password: 'password', name: 'My Name' @@ -129,9 +129,9 @@ void main() { // Register User Account account = Account(client); - Response user = await account + final user = await account .create( - userId: '[USER_ID]', + userId: ID.unique(), email: 'me@appwrite.io', password: 'password', name: 'My Name' @@ -140,14 +140,14 @@ void main() { ``` ### Error Handling -The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example. +The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `type`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example. ```dart -Users users = Users(client); +Account account = Account(client); try { - final response = await users.create(userId: '[USER_ID]', email: ‘email@example.com’,password: ‘password’, name: ‘name’); - print(response.data); + final user = await account.create(userId: ID.unique(), email: ‘email@example.com’,password: ‘password’, name: ‘name’); + print(user.toMap()); } on AppwriteException catch(e) { //show message to user or do other operation based on error as required print(e.message); diff --git a/docs/sdks/kotlin/GETTING_STARTED.md b/docs/sdks/kotlin/GETTING_STARTED.md index be4da1a090..99d5e719af 100644 --- a/docs/sdks/kotlin/GETTING_STARTED.md +++ b/docs/sdks/kotlin/GETTING_STARTED.md @@ -23,12 +23,11 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```kotlin val users = Users(client) -val response = users.create( - user = "[USER_ID]", +val user = users.create( + user = ID.unique(), email = "email@example.com", password = "password", ) -val json = response.body?.string() ``` ### Full Example @@ -36,6 +35,7 @@ val json = response.body?.string() ```kotlin import io.appwrite.Client import io.appwrite.services.Users +import io.appwrite.ID suspend fun main() { val client = Client(context) @@ -45,12 +45,11 @@ suspend fun main() { .setSelfSigned(true) // Use only on dev mode with a self-signed SSL cert val users = Users(client) - val response = users.create( - user = "[USER_ID]", + val user = users.create( + user = ID.unique(), email = "email@example.com", password = "password", ) - val json = response.body?.string() } ``` @@ -60,20 +59,19 @@ The Appwrite Kotlin SDK raises `AppwriteException` object with `message`, `code` ```kotlin import io.appwrite.Client +import io.appwrite.ID import io.appwrite.services.Users suspend fun main() { val users = Users(client) try { - val response = users.create( - user = "[USER_ID]", + val user = users.create( + user = ID.unique(), email = "email@example.com", password = "password", ) - var jsonString = response.body?.string() ?: "" - } catch (e: AppwriteException) { - println(e) + e.printStackTrace() } } ``` diff --git a/docs/sdks/nodejs/GETTING_STARTED.md b/docs/sdks/nodejs/GETTING_STARTED.md index 7db3288479..70767e159b 100644 --- a/docs/sdks/nodejs/GETTING_STARTED.md +++ b/docs/sdks/nodejs/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```js let users = new sdk.Users(client); -let promise = users.create('[USER_ID]', 'email@example.com', 'password'); +let promise = users.create(ID.unique(), 'email@example.com', 'password'); promise.then(function (response) { console.log(response); @@ -45,7 +45,7 @@ client ; let users = new sdk.Users(client); -let promise = users.create('[USER_ID]', 'email@example.com', 'password'); +let promise = users.create(ID.unique(), 'email@example.com', 'password'); promise.then(function (response) { console.log(response); @@ -61,7 +61,7 @@ The Appwrite Node SDK raises `AppwriteException` object with `message`, `code` a let users = new sdk.Users(client); try { - let res = await users.create('[USER_ID]', 'email@example.com', 'password'); + let res = await users.create(ID.unique(), 'email@example.com', 'password'); } catch(e) { console.log(e.message); } diff --git a/docs/sdks/php/GETTING_STARTED.md b/docs/sdks/php/GETTING_STARTED.md index 0dcb7f2475..faa3dcf654 100644 --- a/docs/sdks/php/GETTING_STARTED.md +++ b/docs/sdks/php/GETTING_STARTED.md @@ -20,12 +20,13 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```php $users = new Users($client); -$result = $users->create('email@example.com', 'password'); +$user = $users->create(ID::unique(), 'email@example.com', 'password'); ``` ### Full Example ```php use Appwrite\Client; +use Appwrite\ID; use Appwrite\Services\Users; $client = new Client(); @@ -39,7 +40,7 @@ $client $users = new Users($client); -$result = $users->create('[USER_ID]', 'email@example.com', 'password'); +$user = $users->create(ID::unique(), 'email@example.com', 'password'); ``` ### Error Handling @@ -48,7 +49,7 @@ The Appwrite PHP SDK raises `AppwriteException` object with `message`, `code` an ```php $users = new Users($client); try { - $result = $users->create('[USER_ID]', 'email@example.com', 'password'); + $user = $users->create(ID::unique(), 'email@example.com', 'password'); } catch(AppwriteException $error) { echo $error->message; } diff --git a/docs/sdks/python/GETTING_STARTED.md b/docs/sdks/python/GETTING_STARTED.md index 46a3001ab9..9f693b65c6 100644 --- a/docs/sdks/python/GETTING_STARTED.md +++ b/docs/sdks/python/GETTING_STARTED.md @@ -30,6 +30,7 @@ result = users.create('[USER_ID]', 'email@example.com', 'password') ```python from appwrite.client import Client from appwrite.services.users import Users +from appwrite.id import ID client = Client() @@ -42,7 +43,7 @@ client = Client() users = Users(client) -result = users.create('[USER_ID]', 'email@example.com', 'password') +result = users.create(ID.unique(), 'email@example.com', 'password') ``` ### Error Handling @@ -51,7 +52,7 @@ The Appwrite Python SDK raises `AppwriteException` object with `message`, `code` ```python users = Users(client) try: - result = users.create('[USER_ID]', 'email@example.com', 'password') + result = users.create(ID.unique(), 'email@example.com', 'password') except AppwriteException as e: print(e.message) ``` diff --git a/docs/sdks/ruby/GETTING_STARTED.md b/docs/sdks/ruby/GETTING_STARTED.md index ff714c103c..da10e1aebc 100644 --- a/docs/sdks/ruby/GETTING_STARTED.md +++ b/docs/sdks/ruby/GETTING_STARTED.md @@ -22,7 +22,7 @@ Once your SDK object is set, create any of the Appwrite service objects and choo ```ruby users = Appwrite::Users.new(client); -result = users.create(userId: '[USER_ID]', email: 'email@example.com', password: 'password'); +user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', password: 'password'); ``` ### Full Example @@ -40,7 +40,7 @@ client users = Appwrite::Users.new(client); -result = users.create(userId: '[USER_ID]', email: 'email@example.com', password: 'password'); +user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', password: 'password'); ``` ### Error Handling @@ -50,7 +50,7 @@ The Appwrite Ruby SDK raises `Appwrite::Exception` object with `message`, `code` users = Appwrite::Users.new(client); begin - result = users.create(userId: '[USER_ID]', email: 'email@example.com', password: 'password'); + user = users.create(userId: Appwrite::ID::unique(), email: 'email@example.com', password: 'password'); rescue Appwrite::Exception => error puts error.message end diff --git a/docs/sdks/swift-server/GETTING_STARTED.md b/docs/sdks/swift-server/GETTING_STARTED.md deleted file mode 100644 index c27fbb34a0..0000000000 --- a/docs/sdks/swift-server/GETTING_STARTED.md +++ /dev/null @@ -1,83 +0,0 @@ -## Getting Started - -### Init your SDK - -Initialize your SDK with your Appwrite server API endpoint and project ID which can be found in your project settings page and your new API secret Key project API keys section. - -```swift -import Appwrite - -func main() { - let client = Client() - .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint - .setProject("5df5acd0d48c2") // Your project ID - .setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key - .setSelfSigned() // Use only on dev mode with a self-signed SSL cert -} -``` - -### Make Your First Request - -Once your SDK object is set, create any of the Appwrite service objects and choose any request to send. Full documentation for any service method you would like to use can be found in your SDK documentation or in the [API References](https://appwrite.io/docs) section. - -```swift -let users = Users(client: client) -users.create(userId: "[USER_ID]", email: "email@example.com", password: "password") { result in - switch result { - case .failure(let error): print(error.message) - case .success(let user): print(String(describing: user)) - } -} -``` - -### Full Example - -```swift -import Appwrite - -func main() { - let client = Client() - .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint - .setProject("5df5acd0d48c2") // Your project ID - .setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key - .setSelfSigned() // Use only on dev mode with a self-signed SSL cert - - let users = Users(client: client) - users.create(userId: "[USER_ID]", email: "email@example.com", password: "password") { result in - switch result { - case .failure(let error): print(error.message) - case .success(let user): print(String(describing: user)) - } - } -} -``` - -### Error Handling - -When an error occurs, the Appwrite Swift SDK responds with a result wrapping an `AppwriteError` object with `message` and `code` properties. You can handle any errors in the result's `.failure` case and present the `message` to the user or handle it yourself based on the provided error information. Below is an example. - -```swift -import Appwrite - -func main() { - let users = Users(client: client) - - users.create(userId: "[USER_ID]", email: "email@example.com", password: "password") { result in - switch result { - case .failure(let error): - print(error.message) - case .success(var response): - ... - } - } -} -``` - -### Learn more - -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) -- 🚂 [Appwrite Swift Playground](https://github.com/appwrite/playground-for-swift-server) diff --git a/docs/sdks/swift-server/CHANGELOG.md b/docs/sdks/swift/CHANGELOG.md similarity index 100% rename from docs/sdks/swift-server/CHANGELOG.md rename to docs/sdks/swift/CHANGELOG.md diff --git a/docs/sdks/swift/GETTING_STARTED.md b/docs/sdks/swift/GETTING_STARTED.md new file mode 100644 index 0000000000..e0fb45dd7d --- /dev/null +++ b/docs/sdks/swift/GETTING_STARTED.md @@ -0,0 +1,91 @@ +## Getting Started + +### Init your SDK + +Initialize your SDK with your Appwrite server API endpoint and project ID which can be found in your project settings page and your new API secret Key project API keys section. + +```swift +import Appwrite + +func main() { + let client = Client() + .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + .setKey("919c2d184...a2ae413dad2") // Your secret API key + .setSelfSigned() // Use only on dev mode with a self-signed SSL cert +} +``` + +### Make Your First Request + +Once your SDK object is initialized, create any of the Appwrite service objects and choose any request to send. Full documentation for any service method you would like to use can be found in your SDK documentation or in the [API References](https://appwrite.io/docs) section. + +```swift +let users = Users(client) + +do { + let user = try await users.create( + userId: ID.unique(), + email: "email@example.com", + password: "password" + ) + print(String(describing: user.toMap())) +} catch { + print(error.localizedDescription) +} +``` + +### Full Example + +```swift +import Appwrite + +func main() { + let client = Client() + .setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + .setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key + .setSelfSigned() // Use only on dev mode with a self-signed SSL cert + + let users = Users(client) + + do { + let user = try await users.create( + userId: ID.unique(), + email: "email@example.com", + password: "password" + ) + print(String(describing: user.toMap())) + } catch { + print(error.localizedDescription) + } +} +``` + +### Error Handling + +When an error occurs, the Appwrite Swift SDK throws an `AppwriteError` object with `message` and `code` properties. You can handle any errors in a catch block and present the `message` or `localizedDescription` to the user or handle it yourself based on the provided error information. Below is an example. + +```swift +import Appwrite + +func main() { + let users = Users(client) + + do { + let users = try await users.list() + print(String(describing: users.toMap())) + } catch { + print(error.localizedDescription) + } +} +``` + +### Learn more + +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) +- 🚂 [Appwrite Swift Playground](https://github.com/appwrite/playground-for-swift-server) diff --git a/docs/sdks/web/GETTING_STARTED.md b/docs/sdks/web/GETTING_STARTED.md index a1d387d7d4..2c09704af2 100644 --- a/docs/sdks/web/GETTING_STARTED.md +++ b/docs/sdks/web/GETTING_STARTED.md @@ -25,7 +25,7 @@ Once your SDK object is set, access any of the Appwrite services and choose any const account = new Account(client); // Register User -account.create('[USER_ID]', 'me@example.com', 'password', 'Jane Doe') +account.create(ID.unique(), 'me@example.com', 'password', 'Jane Doe') .then(function (response) { console.log(response); }, function (error) { @@ -47,7 +47,7 @@ client const account = new Account(client); // Register User -account.create('[USER_ID]', 'me@example.com', 'password', 'Jane Doe') +account.create(ID.unique(), 'me@example.com', 'password', 'Jane Doe') .then(function (response) { console.log(response); }, function (error) { diff --git a/src/Appwrite/Utopia/Request/Filters/V15.php b/src/Appwrite/Utopia/Request/Filters/V15.php new file mode 100644 index 0000000000..65b09e1f24 --- /dev/null +++ b/src/Appwrite/Utopia/Request/Filters/V15.php @@ -0,0 +1,275 @@ +convertLimitAndOffset($content); + break; + case 'account.initials': + unset($content['color']); + break; + case 'databases.list': + case 'databases.listCollections': + case 'functions.list': + case 'functions.listDeployments': + case 'projects.list': + case 'storage.listBuckets': + case 'storage.listFiles': + case 'teams.list': + case 'teams.listMemberships': + case 'users.list': + $content = $this->convertLimitAndOffset($content); + $content = $this->convertCursor($content); + $content = $this->convertOrderType($content); + break; + case 'databases.createCollection': + case 'databases.updateCollection': + $content = $this->convertCollectionPermission($content); + $content = $this->convertReadWrite($content); + break; + case 'databases.createDocument': + case 'databases.updateDocument': + case 'storage.createFile': + case 'storage.updateFile': + $content = $this->convertReadWrite($content); + break; + case 'databases.listDocuments': + $content = $this->convertFilters($content); + $content = $this->convertLimitAndOffset($content); + $content = $this->convertCursor($content); + $content = $this->convertOrders($content); + break; + case 'functions.create': + case 'functions.update': + $content = $this->convertExecute($content); + break; + case 'functions.listExecutions': + $content = $this->convertLimitAndOffset($content); + $content = $this->convertCursor($content); + break; + case 'projects.createKey': + case 'projects.updateKey': + $content = $this->convertExpire($content); + break; + case 'storage.createBucket': + case 'storage.updateBucket': + $content = $this->convertBucketPermission($content); + $content = $this->convertReadWrite($content); + break; + } + + return $content; + } + + protected function convertLimitAndOffset($content) + { + if (isset($content['limit'])) { + $content['queries'][] = 'limit(' . $content['limit'] . ')'; + } + + if (isset($content['offset'])) { + $content['queries'][] = 'offset(' . $content['offset'] . ')'; + } + + unset($content['limit']); + unset($content['offset']); + + return $content; + } + + protected function convertCursor($content) + { + if (isset($content['cursor'])) { + $cursorDirection = $content['cursorDirection'] ?? Database::CURSOR_AFTER; + + if ($cursorDirection === Database::CURSOR_BEFORE) { + $content['queries'][] = 'cursorBefore("' . $content["cursor"] . '")'; + } else { + $content['queries'][] = 'cursorAfter("' . $content["cursor"] . '")'; + } + } + + unset($content['cursor']); + unset($content['cursorDirection']); + + return $content; + } + + protected function convertOrderType($content) + { + if (isset($content['orderType'])) { + if ($content['orderType'] === Database::ORDER_DESC) { + $content['queries'][] = 'orderDesc("")'; + } else { + $content['queries'][] = 'orderAsc("")'; + } + } + unset($content['orderType']); + + return $content; + } + + protected function convertOrders($content) + { + if (isset($content['orderTypes'])) { + foreach ($content['orderTypes'] as $i => $type) { + $attribute = $content['orderAttributes'][$i] ?? ''; + + if ($type === Database::ORDER_DESC) { + $content['queries'][] = 'orderDesc("' . $attribute . '")'; + } else { + $content['queries'][] = 'orderAsc("' . $attribute . '")'; + } + } + } + + unset($content['orderAttributes']); + unset($content['orderTypes']); + + return $content; + } + + protected function convertCollectionPermission($content) + { + if (isset($content['permission'])) { + $content['documentSecurity'] = $content['permission'] === 'document'; + } + + unset($content['permission']); + + return $content; + } + + protected function convertReadWrite($content) + { + if (isset($content['read'])) { + foreach ($content['read'] as $read) { + if ($read === 'role:all') { + $content['permissions'][] = Permission::read(Role::any()); + } elseif ($read === 'role:guest') { + $content['permissions'][] = Permission::read(Role::guests()); + } elseif ($read === 'role:member') { + $content['permissions'][] = Permission::read(Role::users()); + } elseif (str_contains($read, ':')) { + $content['permissions'][] = Permission::read(Role::parse($read)); + } + } + } + + if (isset($content['write'])) { + foreach ($content['write'] as $write) { + if ($write === 'role:all' || $write === 'role:member') { + $content['permissions'][] = Permission::write(Role::users()); + } elseif ($write === 'role:guest') { + // don't add because, historically, + // role:guest for write did nothing + } elseif (str_contains($write, ':')) { + $content['permissions'][] = Permission::write(Role::parse($write)); + } + } + } + + unset($content['read']); + unset($content['write']); + + return $content; + } + + protected function convertFilters($content) + { + if (!isset($content['queries'])) { + return $content; + } + + $operations = [ + 'equal' => Query::TYPE_EQUAL, + 'notEqual' => Query::TYPE_NOTEQUAL, + 'lesser' => Query::TYPE_LESSER, + 'lesserEqual' => Query::TYPE_LESSEREQUAL, + 'greater' => Query::TYPE_GREATER, + 'greaterEqual' => Query::TYPE_GREATEREQUAL, + 'search' => Query::TYPE_SEARCH, + ]; + foreach ($content['queries'] as $i => $query) { + foreach ($operations as $oldOperation => $newOperation) { + $middle = ".$oldOperation("; + if (str_contains($query, $middle)) { + $parts = explode($middle, $query); + if (count($parts) > 1) { + $attribute = $parts[0]; + $value = rtrim($parts[1], ")"); + $content['queries'][$i] = $newOperation . '("' . $attribute . '", [' . $value . '])'; + } + } + } + } + return $content; + } + + protected function convertExecute($content) + { + if (!isset($content['execute'])) { + return $content; + } + + $execute = []; + foreach ($content['execute'] as $role) { + if ($role === 'role:all' || $role === 'role:member') { + $execute[] = Role::users()->toString(); + } elseif ($role === 'role:guest') { + // don't add because, historically, + // role:guest for write did nothing + } elseif (str_contains($role, ':')) { + $execute[] = $role; + } + } + $content['execute'] = $execute; + + return $content; + } + + protected function convertExpire($content) + { + if (!isset($content['expire'])) { + return $content; + } + + $expire = (int) $content['expire']; + + if ($expire === 0) { + $content['expire'] = null; + } else { + $content['expire'] = date(\DateTime::RFC3339_EXTENDED, $expire); + } + + return $content; + } + + protected function convertBucketPermission($content) + { + if (isset($content['permission'])) { + $content['fileSecurity'] = $content['permission'] === 'file'; + } + + unset($content['permission']); + + return $content; + } +} diff --git a/src/Appwrite/Utopia/Response/Filters/V15.php b/src/Appwrite/Utopia/Response/Filters/V15.php new file mode 100644 index 0000000000..8e688d58ff --- /dev/null +++ b/src/Appwrite/Utopia/Response/Filters/V15.php @@ -0,0 +1,577 @@ +parseUser($parsedResponse); + break; + case Response::MODEL_USER_LIST: + $listKey = 'users'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseUser($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_METRIC: + $parsedResponse = $this->parseMetric($parsedResponse); + break; + case Response::MODEL_BUILD: + $parsedResponse = $this->parseBuild($parsedResponse); + break; + case Response::MODEL_BUILD_LIST: + $listKey = 'builds'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseBuild($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_BUCKET: + $parsedResponse = $this->parseBucket($parsedResponse); + break; + case Response::MODEL_BUCKET_LIST: + $listKey = 'buckets'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseBucket($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_COLLECTION: + $parsedResponse = $this->parseCollection($parsedResponse); + break; + case Response::MODEL_COLLECTION_LIST: + $listKey = 'collections'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseCollection($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_DATABASE: + case Response::MODEL_DEPLOYMENT: + case Response::MODEL_DOMAIN: + case Response::MODEL_PLATFORM: + case Response::MODEL_PROJECT: + case Response::MODEL_TEAM: + case Response::MODEL_WEBHOOK: + $parsedResponse = $this->parseCreatedAtUpdatedAt($parsedResponse); + break; + case Response::MODEL_DATABASE_LIST: + case Response::MODEL_DEPLOYMENT_LIST: + case Response::MODEL_DOMAIN_LIST: + case Response::MODEL_PLATFORM_LIST: + case Response::MODEL_PROJECT_LIST: + case Response::MODEL_TEAM_LIST: + case Response::MODEL_WEBHOOK_LIST: + $listKey = ''; + switch ($model) { + case Response::MODEL_DATABASE_LIST: + $listKey = 'databases'; + break; + case Response::MODEL_DEPLOYMENT_LIST: + $listKey = 'deployments'; + break; + case Response::MODEL_DOMAIN_LIST: + $listKey = 'domains'; + break; + case Response::MODEL_PLATFORM_LIST: + $listKey = 'platforms'; + break; + case Response::MODEL_PROJECT_LIST: + $listKey = 'projects'; + break; + case Response::MODEL_TEAM_LIST: + $listKey = 'teams'; + break; + case Response::MODEL_WEBHOOK_LIST: + $listKey = 'webhooks'; + break; + } + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseCreatedAtUpdatedAt($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_DOCUMENT: + case Response::MODEL_FILE: + $parsedResponse = $this->parsePermissionsCreatedAtUpdatedAt($parsedResponse); + break; + case Response::MODEL_DOCUMENT_LIST: + case Response::MODEL_FILE_LIST: + $listKey = ''; + switch ($model) { + case Response::MODEL_DOCUMENT_LIST: + $listKey = 'documents'; + break; + case Response::MODEL_FILE_LIST: + $listKey = 'files'; + break; + } + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parsePermissionsCreatedAtUpdatedAt($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_EXECUTION: + $parsedResponse = $this->parseExecution($parsedResponse); + break; + case Response::MODEL_EXECUTION_LIST: + $listKey = 'executions'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseExecution($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_FUNCTION: + $parsedResponse = $this->parseFunction($parsedResponse); + break; + case Response::MODEL_FUNCTION_LIST: + $listKey = 'functions'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseFunction($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_KEY: + $parsedResponse = $this->parseKey($parsedResponse); + break; + case Response::MODEL_KEY_LIST: + $listKey = 'keys'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseKey($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_LOG: + $parsedResponse = $this->parseLog($parsedResponse); + break; + case Response::MODEL_LOG_LIST: + $listKey = 'logs'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseLog($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_MEMBERSHIP: + $parsedResponse = $this->parseMembership($parsedResponse); + break; + case Response::MODEL_MEMBERSHIP_LIST: + $listKey = 'memberships'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseMembership($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_SESSION: + $parsedResponse = $this->parseSession($parsedResponse); + break; + case Response::MODEL_SESSION_LIST: + $listKey = 'sessions'; + $parsedResponse[$listKey] = array_map(fn ($content) => $this->parseSession($content), $parsedResponse[$listKey]); + break; + case Response::MODEL_TOKEN: + $parsedResponse = $this->parseDatetimeAttributes($parsedResponse, ['$createdAt', 'expire']); + break; + case Response::MODEL_USAGE_DATABASES: + $parsedResponse = $this->parseUsageDatabases($parsedResponse); + break; + case Response::MODEL_USAGE_DATABASE: + $parsedResponse = $this->parseUsageDatabase($parsedResponse); + break; + case Response::MODEL_USAGE_COLLECTION: + $parsedResponse = $this->parseUsageCollection($parsedResponse); + break; + case Response::MODEL_USAGE_USERS: + $parsedResponse = $this->parseUsageUsers($parsedResponse); + break; + case Response::MODEL_USAGE_BUCKETS: + $parsedResponse = $this->parseUsageBuckets($parsedResponse); + break; + case Response::MODEL_USAGE_FUNCTIONS: + $parsedResponse = $this->parseUsageFuncs($parsedResponse); + break; + case Response::MODEL_USAGE_PROJECT: + $parsedResponse = $this->parseUsageProject($parsedResponse); + break; + case Response::MODEL_USAGE_STORAGE: + $parsedResponse = $this->parseUsageStorage($parsedResponse); + break; + } + + return $parsedResponse; + } + + protected function parseBuild(array $content) + { + $content = $this->parseDatetimeAttributes($content, ['startTime', 'endTime']); + + return $content; + } + + protected function parseBucket(array $content) + { + if (isset($content['fileSecurity'])) { + if ($content['fileSecurity']) { + $content['permission'] = 'file'; + } else { + $content['permission'] = 'bucket'; + } + } + + unset($content['fileSecurity']); + unset($content['compression']); + + $content = $this->parsePermissions($content); + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + + return $content; + } + + protected function parseDatetimeAttributes(array $content, array $attributes): array + { + foreach ($attributes as $attribute) { + if (isset($content[$attribute])) { + $content[$attribute] = strtotime($content[$attribute]); + } + } + return $content; + } + + protected function parseUser(array $content): array + { + unset($content['password']); + unset($content['hash']); + unset($content['hashOptions']); + + $content = $this->parseDatetimeAttributes($content, ['registration', 'passwordUpdate', '$createdAt', '$updatedAt']); + return $content; + } + + protected function parseMetric(array $content) + { + $content = $this->parseDatetimeAttributes($content, ['date']); + return $content; + } + + protected function parsePermissions(array $content) + { + if (!isset($content['$permissions'])) { + return $content; + } + + $read = []; + $write = []; + + // downgrade the permissions + foreach ($content['$permissions'] as $permission) { + $permission = Permission::parse($permission); + $permission_value = $permission->getRole(); + if ($permission->getIdentifier()) { + $permission_value .= ':' . $permission->getIdentifier(); + } + if ($permission->getDimension()) { + $permission_value .= '/' . $permission->getDimension(); + } + + // Old type permissions meant that 'write' is equivalent to 'create', 'update' and 'delete' + switch ($permission->getPermission()) { + case Database::PERMISSION_UPDATE: + case Database::PERMISSION_DELETE: + case Database::PERMISSION_WRITE: + case Database::PERMISSION_CREATE: + $write[$this->parseRole($permission_value)] = true; + break; + case Database::PERMISSION_READ: + $read[$this->parseRole($permission_value)] = true; + break; + } + } + + $content['$read'] = array_keys($read); + $content['$write'] = array_keys($write); + + unset($content['$permissions']); + + return $content; + } + + protected function parseRole(string $role) + { + switch ($role) { + case Role::any()->toString(): + return 'role:all'; + case Role::users()->toString(): + return 'role:member'; + case Role::guests()->toString(): + return 'role:guest'; + default: + return $role; + } + + return $role; + } + + protected function parseCollection(array $content) + { + if (isset($content['documentSecurity'])) { + if ($content['documentSecurity']) { + $content['permission'] = 'document'; + } else { + $content['permission'] = 'collection'; + } + } + + unset($content['documentSecurity']); + $content = $this->parsePermissions($content); + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + return $content; + } + + protected function parsePermissionsCreatedAtUpdatedAt(array $content) + { + $content = $this->parsePermissions($content); + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + return $content; + } + + private function parseExecution($content) + { + unset($content['stdout']); + + if (isset($content['$permissions'])) { + $read = []; + foreach ($content['$permissions'] as $role) { + $read[] = $this->parseRole($role); + } + $content['$read'] = $read; + unset($content['$permissions']); + } + + if (isset($content['duration'])) { + $content['time'] = $content['duration']; + unset($content['duration']); + } + + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + + return $content; + } + + private function parseCreatedAtUpdatedAt($content) + { + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt']); + return $content; + } + + private function parseFunction($content) + { + if (isset($content['execute'])) { + foreach ($content['execute'] as $i => $role) { + $content['execute'][$i] = $this->parseRole($role); + } + } + + if (isset($content['vars'])) { + $vars = []; + foreach ($content['vars'] as $i => $var) { + $vars[$var['key']] = $var['value']; + } + $content['vars'] = $vars; + } + + if (isset($content['enabled'])) { + $content['status'] = $content['enabled'] ? 'enabled' : 'disabled'; + unset($content['enabled']); + } + + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'scheduleNext', 'schedulePrevious']); + + return $content; + } + + private function parseKey($content) + { + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'expire']); + return $content; + } + + private function parseLog($content) + { + $content = $this->parseDatetimeAttributes($content, ['time']); + return $content; + } + + private function parseMembership($content) + { + $content = $this->parseDatetimeAttributes($content, ['$createdAt', '$updatedAt', 'invited', 'joined']); + return $content; + } + + private function parseSession($content) + { + $content = $this->parseDatetimeAttributes($content, ['$createdAt', 'expire', 'providerAccessTokenExpiry']); + return $content; + } + + private function parseUsage($content, $keys) + { + foreach ($keys as $key) { + $data = []; + foreach ($content[$key] as $metric) { + $data[] = $this->parseMetric($metric); + } + $content[$key] = $data; + } + + return $content; + } + + private function parseUsageDatabases($content) + { + $keys = [ + 'databasesCount', + 'documentsCount', + 'collectionsCount', + 'databasesCreate', + 'databasesRead', + 'databasesUpdate', + 'databasesDelete', + 'documentsCreate', + 'documentsRead', + 'documentsUpdate', + 'documentsDelete', + 'collectionsCreate', + 'collectionsRead', + 'collectionsUpdate', + 'collectionsDelete', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } + + private function parseUsageDatabase($content) + { + $keys = [ + 'documentsCount', + 'collectionsCount', + 'documentsCreate', + 'documentsRead', + 'documentsUpdate', + 'documentsDelete', + 'collectionsCreate', + 'collectionsRead', + 'collectionsUpdate', + 'collectionsDelete', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } + + private function parseUsageCollection($content) + { + $keys = [ + 'documentsCount', + 'documentsCreate', + 'documentsRead', + 'documentsUpdate', + 'documentsDelete', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } + + private function parseUsageUsers($content) + { + $keys = [ + 'usersCount', + 'usersCreate', + 'usersRead', + 'usersUpdate', + 'usersDelete', + 'sessionsCreate', + 'sessionsProviderCreate', + 'sessionsDelete', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } + + private function parseUsageBuckets($content) + { + $keys = [ + 'filesCount', + 'filesStorage', + 'filesCreate', + 'filesRead', + 'filesUpdate', + 'filesDelete', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } + + private function parseUsageFuncs($content) + { + $mapping = [ + 'executionsTotal' => 'functionsExecutions', + 'executionsFailure' => 'functionsFailures', + 'executionsTime' => 'functionsCompute', + ]; + + foreach ($mapping as $new => $old) { + if (isset($content[$new])) { + $data = []; + foreach ($content[$new] as $metric) { + $data[] = $this->parseMetric($metric); + } + $content[$old] = $data; + unset($content[$new]); + } + } + + unset($content['functionExecutions']); + unset($content['functionFailure']); + unset($content['executionsTime']); + unset($content['buildsTotal']); + unset($content['executionsSuccess']); + unset($content['buildsFailure']); + unset($content['buildsSuccess']); + unset($content['buildsTime']); + + return $content; + } + + private function parseUsageProject($content) + { + $content['functions'] = $content['executions']; + unset($content['executions']); + + $keys = [ + 'collections', + 'documents', + 'functions', + 'network', + 'requests', + 'storage', + 'users', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } + + private function parseUsageStorage($content) + { + $content['filesStorage'] = $content['storage']; + unset($content['storage']); + + $keys = [ + 'bucketsCount', + 'bucketsCreate', + 'bucketsDelete', + 'bucketsRead', + 'bucketsUpdate', + 'filesCount', + 'filesCreate', + 'filesDelete', + 'filesRead', + 'filesStorage', + 'filesUpdate', + ]; + + $content = $this->parseUsage($content, $keys); + + return $content; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Metric.php b/src/Appwrite/Utopia/Response/Model/Metric.php index 7fb1b98386..16cf7f7df2 100644 --- a/src/Appwrite/Utopia/Response/Model/Metric.php +++ b/src/Appwrite/Utopia/Response/Model/Metric.php @@ -17,12 +17,11 @@ class Metric extends Model 'example' => 1, ]) ->addRule('date', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The UNIX timestamp at which this metric was aggregated.', - 'default' => 0, - 'example' => 1592981250 - ]) - ; + 'type' => self::TYPE_DATETIME, + 'description' => 'The date at which this metric was aggregated in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE + ]); } /** diff --git a/tests/unit/Utopia/Request/Filters/V15Test.php b/tests/unit/Utopia/Request/Filters/V15Test.php new file mode 100644 index 0000000000..70bf71d4cb --- /dev/null +++ b/tests/unit/Utopia/Request/Filters/V15Test.php @@ -0,0 +1,742 @@ +filter = new V15(); + } + + public function tearDown(): void + { + } + + public function limitOffsetProvider(): array + { + return [ + 'basic test' => [ + ['limit' => '12', 'offset' => '0'], + ['queries' => ['limit(12)', 'offset(0)']] + ], + ]; + } + + /** + * @dataProvider limitOffsetProvider + */ + public function testListAccountLogs(array $content, array $expected): void + { + $model = 'account.listLogs'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function testGetAccountInitials(): void + { + $model = 'account.initials'; + + $content = ['color' => 'deadbeef']; + $expected = []; + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function limitOffsetCursorOrderTypeProvider(): array + { + return [ + 'basic test' => [ + [ + 'limit' => '12', + 'offset' => '0', + 'cursor' => 'abcd', + 'cursorDirection' => 'before', + 'orderType' => 'asc', + ], + [ + 'queries' => [ + 'limit(12)', + 'offset(0)', + 'cursorBefore("abcd")', + 'orderAsc("")' + ] + ], + ], + ]; + } + + public function cursorProvider(): array + { + return [ + 'cursorDirection after' => [ + [ + 'cursor' => 'abcd', + 'cursorDirection' => 'after', + ], + [ + 'queries' => [ + 'cursorAfter("abcd")', + ] + ], + ], + 'cursorDirection invalid' => [ + [ + 'cursor' => 'abcd', + 'cursorDirection' => 'invalid', + ], + [ + 'queries' => [ + 'cursorAfter("abcd")', + ] + ], + ], + ]; + } + + public function orderTypeProvider(): array + { + return [ + 'orderType desc' => [ + [ + 'orderType' => 'DESC', + ], + [ + 'queries' => [ + 'orderDesc("")', + ] + ], + ], + 'orderType invalid' => [ + [ + 'orderType' => 'invalid', + ], + [ + 'queries' => [ + 'orderAsc("")', + ] + ], + ], + ]; + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListDatabases(array $content, array $expected): void + { + $model = 'databases.list'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetProvider + */ + public function testListDatabaseLogs(array $content, array $expected): void + { + $model = 'databases.listLogs'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function collectionPermissionProvider(): array + { + return [ + 'permission collection' => [ + ['permission' => 'collection'], + ['documentSecurity' => false], + ], + 'permission document' => [ + ['permission' => 'document'], + ['documentSecurity' => true], + ], + 'permission empty' => [ + [], + [], + ], + 'permission invalid' => [ + ['permission' => 'invalid'], + ['documentSecurity' => false], + ], + ]; + } + + public function readWriteProvider(): array + { + return [ + 'read all types' => [ + [ + 'read' => [ + 'role:all', + 'role:guest', + 'role:member', + 'user:a', + 'team:b', + 'team:c/member', + 'member:z', + ], + ], + [ + 'permissions' => [ + 'read("any")', + 'read("guests")', + 'read("users")', + 'read("user:a")', + 'read("team:b")', + 'read("team:c/member")', + 'read("member:z")', + ], + ], + ], + 'read invalid' => [ + ['read' => ['invalid', 'invalid:a']], + ['permissions' => ['read("invalid:a")']], + ], + 'write all types' => [ + [ + 'write' => [ + 'role:all', + 'role:guest', + 'role:member', + 'user:a', + 'team:b', + 'team:c/member', + 'member:z', + ], + ], + [ + 'permissions' => [ + 'write("users")', + 'write("users")', + 'write("user:a")', + 'write("team:b")', + 'write("team:c/member")', + 'write("member:z")', + ], + ], + ], + 'write invalid' => [ + ['write' => ['invalid', 'invalid:a']], + ['permissions' => ['write("invalid:a")']], + ] + ]; + } + + /** + * @dataProvider collectionPermissionProvider + * @dataProvider readWriteProvider + */ + public function testCreateCollection(array $content, array $expected): void + { + $model = 'databases.createCollection'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListCollections(array $content, array $expected): void + { + $model = 'databases.listCollections'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetProvider + */ + public function testListCollectionLogs(array $content, array $expected): void + { + $model = 'databases.listCollectionLogs'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider collectionPermissionProvider + * @dataProvider readWriteProvider + */ + public function testUpdateCollection(array $content, array $expected): void + { + $model = 'databases.updateCollection'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider readWriteProvider + */ + public function testCreateDocument(array $content, array $expected): void + { + $model = 'databases.createDocument'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function ordersProvider(): array + { + return [ + 'basic test' => [ + [ + 'orderAttributes' => ['lastName', 'firstName'], + 'orderTypes' => ['DESC', 'ASC'], + ], + [ + 'queries' => [ + 'orderDesc("lastName")', + 'orderAsc("firstName")', + ] + ], + ], + 'orderType only' => [ + [ + 'orderTypes' => ['DESC'], + ], + [ + 'queries' => [ + 'orderDesc("")', + ] + ], + ], + 'orderType invalid' => [ + [ + 'orderAttributes' => ['lastName'], + 'orderTypes' => ['invalid'], + ], + [ + 'queries' => [ + 'orderAsc("lastName")', + ] + ], + ], + ]; + } + + public function filtersProvider(): array + { + return [ + 'all filters' => [ + [ + 'queries' => [ + 'lastName.equal("Smith", "Jackson")', + 'firstName.notEqual("John")', + 'age.lesser(50)', + 'age.lesserEqual(51)', + 'age.greater(20)', + 'age.greaterEqual(21)', + 'address.search("pla")', + ], + ], + [ + 'queries' => [ + 'equal("lastName", ["Smith", "Jackson"])', + 'notEqual("firstName", ["John"])', + 'lessThan("age", [50])', + 'lessThanEqual("age", [51])', + 'greaterThan("age", [20])', + 'greaterThanEqual("age", [21])', + 'search("address", ["pla"])', + ] + ], + ], + ]; + } + + /** + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider ordersProvider + * @dataProvider filtersProvider + */ + public function testListDocuments(array $content, array $expected): void + { + $model = 'databases.listDocuments'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetProvider + */ + public function testListDocumentLogs(array $content, array $expected): void + { + $model = 'databases.listDocumentLogs'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider readWriteProvider + */ + public function testUpdateDocument(array $content, array $expected): void + { + $model = 'databases.updateDocument'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function executeProvider(): array + { + return [ + 'all roles' => [ + [ + 'execute' => [ + 'role:all', + 'role:guest', + 'role:member', + 'user:a', + 'team:b', + 'team:c/member', + 'member:z', + ], + ], + [ + 'execute' => [ + 'users', + 'users', + 'user:a', + 'team:b', + 'team:c/member', + 'member:z', + ] + ], + ], + ]; + } + + /** + * @dataProvider executeProvider + */ + public function testCreateFunction(array $content, array $expected): void + { + $model = 'functions.create'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListFunctions(array $content, array $expected): void + { + $model = 'functions.list'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider executeProvider + */ + public function testUpdateFunction(array $content, array $expected): void + { + $model = 'functions.update'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListDeployments(array $content, array $expected): void + { + $model = 'functions.listDeployments'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + */ + public function testListExecutions(array $content, array $expected): void + { + $model = 'functions.listExecutions'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListProjects(array $content, array $expected): void + { + $model = 'projects.list'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function expireProvider(): array + { + return [ + 'empty' => [ + [], + [], + ], + 'zero' => [ + ['expire' => '0'], + ['expire' => null], + ], + 'value' => [ + ['expire' => '1602743880'], + ['expire' => Model::TYPE_DATETIME_EXAMPLE], + ], + ]; + } + + /** + * @dataProvider expireProvider + */ + public function testCreateKey(array $content, array $expected) + { + $model = 'projects.createKey'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider expireProvider + */ + public function testUpdateKey(array $content, array $expected) + { + $model = 'projects.updateKey'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function bucketPermissionProvider(): array + { + return [ + 'permission bucket' => [ + ['permission' => 'bucket'], + ['fileSecurity' => false], + ], + 'permission document' => [ + ['permission' => 'file'], + ['fileSecurity' => true], + ], + 'permission empty' => [ + [], + [], + ], + 'permission invalid' => [ + ['permission' => 'invalid'], + ['fileSecurity' => false], + ], + ]; + } + + /** + * @dataProvider bucketPermissionProvider + * @dataProvider readWriteProvider + */ + public function testCreateBucket(array $content, array $expected) + { + $model = 'storage.createBucket'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListBuckets(array $content, array $expected): void + { + $model = 'storage.listBuckets'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider bucketPermissionProvider + * @dataProvider readWriteProvider + */ + public function testUpdateBucket(array $content, array $expected) + { + $model = 'storage.updateBucket'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider readWriteProvider + */ + public function testCreateFile(array $content, array $expected) + { + $model = 'storage.createFile'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListFiles(array $content, array $expected): void + { + $model = 'storage.listFiles'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider readWriteProvider + */ + public function testUpdateFile(array $content, array $expected) + { + $model = 'storage.updateFile'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListTeams(array $content, array $expected): void + { + $model = 'teams.list'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListTeamMemberships(array $content, array $expected): void + { + $model = 'teams.listMemberships'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetProvider + */ + public function testListTeamLogs(array $content, array $expected): void + { + $model = 'teams.listLogs'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetCursorOrderTypeProvider + * @dataProvider limitOffsetProvider + * @dataProvider cursorProvider + * @dataProvider orderTypeProvider + */ + public function testListUsers(array $content, array $expected): void + { + $model = 'users.list'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider limitOffsetProvider + */ + public function testListUserLogs(array $content, array $expected): void + { + $model = 'users.listLogs'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } +} diff --git a/tests/unit/Utopia/Response/Filters/V15Test.php b/tests/unit/Utopia/Response/Filters/V15Test.php new file mode 100644 index 0000000000..a68da474d9 --- /dev/null +++ b/tests/unit/Utopia/Response/Filters/V15Test.php @@ -0,0 +1,1888 @@ +filter = new V15(); + } + + public function tearDown(): void + { + } + + public function createdAtUpdatedAtProvider(): array + { + return [ + 'basic datetimes' => [ + [ + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + ], + [ + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + ], + ], + 'null datetime' => [ + [ + '$createdAt' => null, + '$updatedAt' => null, + ], + [ + '$createdAt' => 0, + '$updatedAt' => 0, + ], + ], + 'empty datetime' => [ + [ + '$createdAt' => '', + '$updatedAt' => '', + ], + [ + '$createdAt' => 0, + '$updatedAt' => 0, + ], + ], + ]; + } + + public function permissionsProvider(): array + { + return [ + 'basic permissions' => [ + [ + '$permissions' => [ + Permission::read(Role::any()), + Permission::write(Role::user('608f9da25e7e1')), + ], + ], + [ + '$read' => ['role:all'], + '$write' => ['user:608f9da25e7e1'], + ], + ], + 'all roles' => [ + [ + '$permissions' => [ + Permission::read(Role::any()), + Permission::read(Role::guests()), + Permission::read(Role::users()), + Permission::read(Role::user('asdf')), + Permission::read(Role::team('qwer')), + Permission::read(Role::team('qwer', 'uiop')), + Permission::read(Role::member('zxcv')), + ], + ], + [ + '$read' => [ + 'role:all', + 'role:guest', + 'role:member', + 'user:asdf', + 'team:qwer', + 'team:qwer/uiop', + 'member:zxcv', + ], + '$write' => [], + ], + ], + 'create conversion' => [ + [ + '$permissions' => [Permission::create(Role::user('a'))], + ], + [ + '$read' => [], + '$write' => ['user:a'], + ], + ], + 'update conversion' => [ + [ + '$permissions' => [Permission::update(Role::user('a'))], + ], + [ + '$read' => [], + '$write' => ['user:a'], + ], + ], + 'delete conversion' => [ + [ + '$permissions' => [Permission::delete(Role::user('a'))], + ], + [ + '$read' => [], + '$write' => ['user:a'], + ], + ], + 'write conversion' => [ + [ + '$permissions' => [Permission::write(Role::user('a'))], + ], + [ + '$read' => [], + '$write' => ['user:a'], + ], + ], + ]; + } + + public function testAccount(): void + { + $model = Response::MODEL_ACCOUNT; + + $content = [ + '$id' => '6264711f995c5b012b48', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + 'name' => 'John Doe', + 'registration' => '2020-06-24T06:47:30.000Z', + 'status' => true, + 'passwordUpdate' => '2020-06-24T06:47:30.000Z', + 'email' => 'john@appwrite.io', + 'phone' => '+4930901820', + 'emailVerification' => true, + 'phoneVerification' => true, + 'prefs' => new \stdClass(), + ]; + + $expected = [ + '$id' => '6264711f995c5b012b48', + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + 'name' => 'John Doe', + 'registration' => 1592981250, + 'status' => true, + 'passwordUpdate' => 1592981250, + 'email' => 'john@appwrite.io', + 'phone' => '+4930901820', + 'emailVerification' => true, + 'phoneVerification' => true, + 'prefs' => new \stdClass(), + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function bucketProvider(): array + { + return [ + 'basic bucket' => [ + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + 'fileSecurity' => true, + '$permissions' => [ + Permission::read(Role::any()), + Permission::write(Role::user('608f9da25e7e1')), + ], + 'name' => 'Documents', + 'enabled' => false, + 'maximumFileSize' => 100, + 'allowedFileExtensions' => [ + 'jpg', + 'png' + ], + 'encryption' => false, + 'antivirus' => false, + ], + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + '$read' => ['role:all'], + '$write' => ['user:608f9da25e7e1'], + 'permission' => 'file', + 'name' => 'Documents', + 'enabled' => false, + 'maximumFileSize' => 100, + 'allowedFileExtensions' => [ + 'jpg', + 'png' + ], + 'encryption' => false, + 'antivirus' => false, + ], + ], + 'false fileSecurity' => [ + ['fileSecurity' => false], + ['permission' => 'bucket'], + ], + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + * @dataProvider bucketProvider + */ + public function testBucket(array $content, array $expected): void + { + $model = Response::MODEL_BUCKET; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + * @dataProvider bucketProvider + */ + public function testBucketList(array $content, array $expected): void + { + $model = Response::MODEL_BUCKET_LIST; + + $content = [ + 'buckets' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'buckets' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function buildProvider(): array + { + return [ + 'build start and end time' => [ + [ + 'startTime' => '2020-06-24T06:47:30.000Z', + 'endTime' => '2020-06-24T06:47:30.000Z', + ], + [ + 'startTime' => 1592981250, + 'endTime' => 1592981250, + ] + ] + ]; + } + + /** + * @dataProvider buildProvider + */ + public function testBuild(): void + { + $model = Response::MODEL_BUILD; + + $content = [ + 'startTime' => '2020-06-24T06:47:30.000Z', + 'endTime' => '2020-06-24T06:47:30.000Z', + ]; + + $expected = [ + 'startTime' => 1592981250, + 'endTime' => 1592981250, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider buildProvider + */ + public function testBuildList(array $content, array $expected): void + { + $model = Response::MODEL_BUILD_LIST; + + $content = [ + 'builds' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'builds' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function collectionProvider(): array + { + return [ + 'basic collection' => [ + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + '$permissions' => [ + Permission::read(Role::any()), + Permission::write(Role::user('608f9da25e7e1')), + ], + 'documentSecurity' => true, + 'databaseId' => '5e5ea5c16897e', + 'name' => 'My Collection', + 'enabled' => false, + 'attributes' => [ + 'key' => 'isEnabled', + 'type' => 'boolean', + 'status' => 'available', + 'required' => true, + 'array' => false, + 'default' => false + ], + 'indexes' => [ + 'key' => 'index1', + 'type' => 'primary', + 'status' => 'available', + 'attributes' => [], + 'orders' => [] + ], + ], + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + '$read' => [ + 'role:all' + ], + '$write' => [ + 'user:608f9da25e7e1' + ], + 'databaseId' => '5e5ea5c16897e', + 'name' => 'My Collection', + 'enabled' => false, + 'permission' => 'document', + 'attributes' => [ + 'key' => 'isEnabled', + 'type' => 'boolean', + 'status' => 'available', + 'required' => true, + 'array' => false, + 'default' => false + ], + 'indexes' => [ + 'key' => 'index1', + 'type' => 'primary', + 'status' => 'available', + 'attributes' => [], + 'orders' => [] + ], + ], + ], + 'false documentSecurity' => [ + ['documentSecurity' => false], + ['permission' => 'collection'], + ], + + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + * @dataProvider collectionProvider + */ + public function testCollection(array $content, array $expected): void + { + $model = Response::MODEL_COLLECTION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + * @dataProvider collectionProvider + */ + public function testCollectionList(array $content, array $expected): void + { + $model = Response::MODEL_COLLECTION_LIST; + + $content = [ + 'collections' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'collections' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testDatabase(array $content, array $expected): void + { + $model = Response::MODEL_DATABASE; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testDatabaseList(array $content, array $expected): void + { + $model = Response::MODEL_DATABASE_LIST; + + $content = [ + 'databases' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'databases' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testDeployment(array $content, array $expected): void + { + $model = Response::MODEL_DEPLOYMENT; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testDeploymentList(array $content, array $expected): void + { + $model = Response::MODEL_DEPLOYMENT_LIST; + + $content = [ + 'deployments' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'deployments' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + */ + public function testDocument(array $content, array $expected): void + { + $model = Response::MODEL_DOCUMENT; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + */ + public function testDocumentList(array $content, array $expected): void + { + $model = Response::MODEL_DOCUMENT_LIST; + + $content = [ + 'documents' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'documents' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testDomain(array $content, array $expected): void + { + $model = Response::MODEL_DOMAIN; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testDomainList(array $content, array $expected): void + { + $model = Response::MODEL_DOMAIN_LIST; + + $content = [ + 'domains' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'domains' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function executionProvider(): array + { + return [ + 'basic execution' => [ + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + '$permissions' => [ + "any" + ], + 'functionId' => '5e5ea6g16897e', + 'trigger' => 'http', + 'status' => 'processing', + 'statusCode' => 0, + 'response' => '', + 'stdout' => '', + 'stderr' => '', + 'duration' => 0.4 + ], + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + '$read' => [ + "role:all" + ], + 'functionId' => '5e5ea6g16897e', + 'trigger' => 'http', + 'status' => 'processing', + 'statusCode' => 0, + 'response' => '', + 'stderr' => '', + 'time' => 0.4 + ], + ], + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider executionProvider + */ + public function testExecution(array $content, array $expected): void + { + $model = Response::MODEL_EXECUTION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider executionProvider + */ + public function testExecutionList(array $content, array $expected): void + { + $model = Response::MODEL_EXECUTION_LIST; + + $content = [ + 'executions' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'executions' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + */ + public function testFile(array $content, array $expected): void + { + $model = Response::MODEL_FILE; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider permissionsProvider + */ + public function testFileList(array $content, array $expected): void + { + $model = Response::MODEL_FILE_LIST; + + $content = [ + 'files' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'files' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function functionProvider(): array + { + return [ + 'basic function' => [ + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + 'execute' => [ + Role::users()->toString(), + ], + 'name' => 'My Function', + 'enabled' => true, + 'runtime' => 'python-3.8', + 'deployment' => '5e5ea5c16897e', + 'vars' => [ + [ + '$id' => '631bd31717e034f14aa8', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + 'key' => 'key', + 'value' => 'value', + 'functionId' => '5e5ea5c16897e', + ] + ], + 'events' => [ + 'account.create' + ], + 'schedule' => '5 4 * * *', + 'scheduleNext' => '2020-06-24T06:48:12.000Z', + 'schedulePrevious' => '2020-06-24T06:47:17.000Z', + 'timeout' => 1592981237 + ], + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + 'execute' => [ + 'role:member' + ], + 'name' => 'My Function', + 'status' => 'enabled', + 'runtime' => 'python-3.8', + 'deployment' => '5e5ea5c16897e', + 'vars' => [ + 'key' => 'value' + ], + 'events' => [ + 'account.create' + ], + 'schedule' => '5 4 * * *', + 'scheduleNext' => 1592981292, + 'schedulePrevious' => 1592981237, + 'timeout' => 1592981237 + ], + ], + 'enabled false' => [ + ['enabled' => false], + ['status' => 'disabled'], + ], + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider functionProvider + */ + public function testFunc(array $content, array $expected): void + { + $model = Response::MODEL_FUNCTION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider functionProvider + */ + public function testFuncList(array $content, array $expected): void + { + $model = Response::MODEL_FUNCTION_LIST; + + $content = [ + 'functions' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'functions' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function keyProvider(): array + { + return [ + 'basic key' => [ + ['expire' => '2020-06-24T06:47:30.000Z'], + ['expire' => 1592981250], + ], + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider keyProvider + */ + public function testKey(array $content, array $expected): void + { + $model = Response::MODEL_KEY; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider keyProvider + */ + public function testKeyList(array $content, array $expected): void + { + $model = Response::MODEL_KEY_LIST; + + $content = [ + 'keys' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'keys' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function logProvider(): array + { + return [ + 'basic log' => [ + [ + 'event' => 'account.sessions.create', + 'userId' => '610fc2f985ee0', + 'userEmail' => 'john@appwrite.io', + 'userName' => 'John Doe', + 'mode' => 'admin', + 'ip' => '127.0.0.1', + 'time' => '2020-06-24T06:47:30.000Z', + 'osCode' => 'Mac', + 'osName' => 'Mac', + 'osVersion' => 'Mac', + 'clientType' => 'browser', + 'clientCode' => 'CM', + 'clientName' => 'Chrome Mobile iOS', + 'clientVersion' => '84.0', + 'clientEngine' => 'WebKit', + 'clientEngineVersion' => '605.1.15', + 'deviceName' => 'smartphone', + 'deviceBrand' => 'Google', + 'deviceModel' => 'Nexus 5', + 'countryCode' => 'US', + 'countryName' => 'United States' + ], + [ + 'event' => 'account.sessions.create', + 'userId' => '610fc2f985ee0', + 'userEmail' => 'john@appwrite.io', + 'userName' => 'John Doe', + 'mode' => 'admin', + 'ip' => '127.0.0.1', + 'time' => 1592981250, + 'osCode' => 'Mac', + 'osName' => 'Mac', + 'osVersion' => 'Mac', + 'clientType' => 'browser', + 'clientCode' => 'CM', + 'clientName' => 'Chrome Mobile iOS', + 'clientVersion' => '84.0', + 'clientEngine' => 'WebKit', + 'clientEngineVersion' => '605.1.15', + 'deviceName' => 'smartphone', + 'deviceBrand' => 'Google', + 'deviceModel' => 'Nexus 5', + 'countryCode' => 'US', + 'countryName' => 'United States' + ] + ], + ]; + } + + /** + * @dataProvider logProvider + */ + public function testLog(array $content, array $expected): void + { + $model = Response::MODEL_LOG; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider logProvider + */ + public function testLogList(array $content, array $expected): void + { + $model = Response::MODEL_LOG_LIST; + + $content = [ + 'logs' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'logs' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function membershipProvider(): array + { + return [ + 'basic membership' => [ + [ + 'invited' => '2020-06-24T06:47:30.000Z', + 'joined' => '2020-06-24T06:47:30.000Z', + ], + [ + 'invited' => 1592981250, + 'joined' => 1592981250, + ], + ], + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider membershipProvider + */ + public function testMembership(array $content, array $expected): void + { + $model = Response::MODEL_MEMBERSHIP; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider membershipProvider + */ + public function testMembershipList(array $content, array $expected): void + { + $model = Response::MODEL_MEMBERSHIP_LIST; + + $content = [ + 'memberships' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'memberships' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function metricProvider(): array + { + return [ + 'basic metric' => [ + [ + 'date' => '2020-06-24T06:47:30.000Z', + ], + [ + 'date' => 1592981250, + ], + ], + ]; + } + + /** + * @dataProvider metricProvider + */ + public function testMetric(array $content, array $expected): void + { + $model = Response::MODEL_METRIC; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testPlatform(array $content, array $expected): void + { + $model = Response::MODEL_PLATFORM; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testPlatformList(array $content, array $expected): void + { + $model = Response::MODEL_PLATFORM_LIST; + + $content = [ + 'platforms' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'platforms' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testProject(array $content, array $expected): void + { + $model = Response::MODEL_PROJECT; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testProjectList(array $content, array $expected): void + { + $model = Response::MODEL_PROJECT_LIST; + + $content = [ + 'projects' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'projects' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function sessionProvider(): array + { + return [ + 'basic session' => [ + [ + '$createdAt' => '2020-06-24T06:47:30.000Z', + 'expire' => '2020-06-24T06:47:30.000Z', + 'providerAccessTokenExpiry' => '2020-06-24T06:47:30.000Z', + ], + [ + '$createdAt' => 1592981250, + 'expire' => 1592981250, + 'providerAccessTokenExpiry' => 1592981250, + ], + ], + ]; + } + + /** + * @dataProvider sessionProvider + */ + public function testSession(array $content, array $expected): void + { + $model = Response::MODEL_SESSION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider sessionProvider + */ + public function testSessionList(array $content, array $expected): void + { + $model = Response::MODEL_SESSION_LIST; + + $content = [ + 'sessions' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'sessions' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testTeam(array $content, array $expected): void + { + $model = Response::MODEL_TEAM; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testTeamList(array $content, array $expected): void + { + $model = Response::MODEL_TEAM_LIST; + + $content = [ + 'teams' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'teams' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function tokenProvider(): array + { + return [ + 'basic token' => [ + [ + '$createdAt' => '2020-06-24T06:47:30.000Z', + 'expire' => '2020-06-24T06:47:30.000Z', + ], + [ + '$createdAt' => 1592981250, + 'expire' => 1592981250, + ], + ], + ]; + } + + /** + * @dataProvider tokenProvider + */ + public function testToken(array $content, array $expected): void + { + $model = Response::MODEL_TOKEN; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageDatabasesProvider(): array + { + return [ + 'basic usage databases' => [ + [ + 'databasesCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'databasesCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'databasesRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'databasesUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'databasesDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'databasesCount' => [ + ['date' => 1592981250], + ], + 'documentsCount' => [ + ['date' => 1592981250], + ], + 'collectionsCount' => [ + ['date' => 1592981250], + ], + 'databasesCreate' => [ + ['date' => 1592981250], + ], + 'databasesRead' => [ + ['date' => 1592981250], + ], + 'databasesUpdate' => [ + ['date' => 1592981250], + ], + 'databasesDelete' => [ + ['date' => 1592981250], + ], + 'documentsCreate' => [ + ['date' => 1592981250], + ], + 'documentsRead' => [ + ['date' => 1592981250], + ], + 'documentsUpdate' => [ + ['date' => 1592981250], + ], + 'documentsDelete' => [ + ['date' => 1592981250], + ], + 'collectionsCreate' => [ + ['date' => 1592981250], + ], + 'collectionsRead' => [ + ['date' => 1592981250], + ], + 'collectionsUpdate' => [ + ['date' => 1592981250], + ], + 'collectionsDelete' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageDatabasesProvider + */ + public function testUsageDatabases(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_DATABASES; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageDatabaseProvider(): array + { + return [ + 'basic usage database' => [ + [ + 'documentsCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'collectionsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'documentsCount' => [ + ['date' => 1592981250], + ], + 'collectionsCount' => [ + ['date' => 1592981250], + ], + 'documentsCreate' => [ + ['date' => 1592981250], + ], + 'documentsRead' => [ + ['date' => 1592981250], + ], + 'documentsUpdate' => [ + ['date' => 1592981250], + ], + 'documentsDelete' => [ + ['date' => 1592981250], + ], + 'collectionsCreate' => [ + ['date' => 1592981250], + ], + 'collectionsRead' => [ + ['date' => 1592981250], + ], + 'collectionsUpdate' => [ + ['date' => 1592981250], + ], + 'collectionsDelete' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageDatabaseProvider + */ + public function testUsageDatabase(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_DATABASE; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageCollectionProvider(): array + { + return [ + 'basic usage collection' => [ + [ + 'documentsCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documentsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'documentsCount' => [ + ['date' => 1592981250], + ], + 'documentsCreate' => [ + ['date' => 1592981250], + ], + 'documentsRead' => [ + ['date' => 1592981250], + ], + 'documentsUpdate' => [ + ['date' => 1592981250], + ], + 'documentsDelete' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageCollectionProvider + */ + public function testUsageCollection(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_COLLECTION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageUsersProvider(): array + { + return [ + 'basic usage users' => [ + [ + 'usersCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'usersCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'usersRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'usersUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'usersDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'sessionsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'sessionsProviderCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'sessionsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'usersCount' => [ + ['date' => 1592981250], + ], + 'usersCreate' => [ + ['date' => 1592981250], + ], + 'usersRead' => [ + ['date' => 1592981250], + ], + 'usersUpdate' => [ + ['date' => 1592981250], + ], + 'usersDelete' => [ + ['date' => 1592981250], + ], + 'sessionsCreate' => [ + ['date' => 1592981250], + ], + 'sessionsProviderCreate' => [ + ['date' => 1592981250], + ], + 'sessionsDelete' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageUsersProvider + */ + public function testUsageUsers(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_USERS; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageBucketsProvider(): array + { + return [ + 'basic usage buckets' => [ + [ + 'filesCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesStorage' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'filesCount' => [ + ['date' => 1592981250], + ], + 'filesStorage' => [ + ['date' => 1592981250], + ], + 'filesCreate' => [ + ['date' => 1592981250], + ], + 'filesRead' => [ + ['date' => 1592981250], + ], + 'filesUpdate' => [ + ['date' => 1592981250], + ], + 'filesDelete' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageBucketsProvider + */ + public function testUsageBuckets(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_BUCKETS; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageFunctionsProvider(): array + { + return [ + 'basic usage functions' => [ + [ + 'executionsTotal' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'executionsFailure' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'executionsSuccess' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'executionsTime' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'buildsTotal' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'buildsFailure' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'buildsSuccess' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'buildsTime' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'functionsExecutions' => [ + ['date' => 1592981250], + ], + 'functionsFailures' => [ + ['date' => 1592981250], + ], + 'functionsCompute' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageFunctionsProvider + */ + public function testUsageFunctions(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_FUNCTIONS; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageProjectProvider(): array + { + return [ + 'basic usage project' => [ + [ + 'collections' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'documents' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'executions' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'network' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'requests' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'storage' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'users' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'collections' => [ + ['date' => 1592981250], + ], + 'documents' => [ + ['date' => 1592981250], + ], + 'functions' => [ + ['date' => 1592981250], + ], + 'network' => [ + ['date' => 1592981250], + ], + 'requests' => [ + ['date' => 1592981250], + ], + 'storage' => [ + ['date' => 1592981250], + ], + 'users' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageProjectProvider + */ + public function testUsageProject(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_PROJECT; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function usageStorageProvider(): array + { + return [ + 'basic usage storage' => [ + [ + 'bucketsCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'bucketsCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'bucketsDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'bucketsRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'bucketsUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesCount' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesCreate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesDelete' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesRead' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'storage' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + 'filesUpdate' => [ + ['date' => '2020-06-24T06:47:30.000Z'], + ], + ], + [ + 'bucketsCount' => [ + ['date' => 1592981250], + ], + 'bucketsCreate' => [ + ['date' => 1592981250], + ], + 'bucketsDelete' => [ + ['date' => 1592981250], + ], + 'bucketsRead' => [ + ['date' => 1592981250], + ], + 'bucketsUpdate' => [ + ['date' => 1592981250], + ], + 'filesCount' => [ + ['date' => 1592981250], + ], + 'filesCreate' => [ + ['date' => 1592981250], + ], + 'filesDelete' => [ + ['date' => 1592981250], + ], + 'filesRead' => [ + ['date' => 1592981250], + ], + 'filesStorage' => [ + ['date' => 1592981250], + ], + 'filesUpdate' => [ + ['date' => 1592981250], + ], + ], + ], + ]; + } + + /** + * @dataProvider usageStorageProvider + */ + public function testUsageStorage(array $content, array $expected): void + { + $model = Response::MODEL_USAGE_STORAGE; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function userProvider(): array + { + return [ + 'basic user' => [ + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => '2020-06-24T06:47:30.000Z', + '$updatedAt' => '2020-06-24T06:47:30.000Z', + 'name' => 'John Doe', + 'password' => '$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L/4LdgrVRXxE', + 'hash' => 'argon2', + 'hashOptions' => [ + 'memoryCost' => 65536, + 'timeCost' => 4, + 'threads' => 3, + ], + 'registration' => '2020-06-24T06:47:30.000Z', + 'status' => true, + 'passwordUpdate' => '2020-06-24T06:47:30.000Z', + 'email' => 'john@appwrite.io', + 'phone' => '+4930901820', + 'emailVerification' => true, + 'phoneVerification' => true, + 'prefs' => new \stdClass(), + ], + [ + '$id' => '5e5ea5c16897e', + '$createdAt' => 1592981250, + '$updatedAt' => 1592981250, + 'name' => 'John Doe', + 'registration' => 1592981250, + 'status' => true, + 'passwordUpdate' => 1592981250, + 'email' => 'john@appwrite.io', + 'phone' => '+4930901820', + 'emailVerification' => true, + 'phoneVerification' => true, + 'prefs' => new \stdClass(), + ], + ], + ]; + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider userProvider + */ + public function testUser(array $content, array $expected): void + { + $model = Response::MODEL_USER; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + * @dataProvider userProvider + */ + public function testUserList(array $content, array $expected): void + { + $model = Response::MODEL_USER_LIST; + + $content = [ + 'users' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'users' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testWebhook(array $content, array $expected): void + { + $model = Response::MODEL_WEBHOOK; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider createdAtUpdatedAtProvider + */ + public function testWebhookList(array $content, array $expected): void + { + $model = Response::MODEL_WEBHOOK_LIST; + + $content = [ + 'webhooks' => [$content], + 'total' => 1, + ]; + + $expected = [ + 'webhooks' => [$expected], + 'total' => 1, + ]; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } +}