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 1f61b8aef6..44aa2fb24f 100644 --- a/composer.lock +++ b/composer.lock @@ -4812,16 +4812,16 @@ }, { "name": "sebastian/type", - "version": "3.1.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb44e1cc6e557418387ad815780360057e40753e" + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb44e1cc6e557418387ad815780360057e40753e", - "reference": "fb44e1cc6e557418387ad815780360057e40753e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", "shasum": "" }, "require": { @@ -4833,7 +4833,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -4856,7 +4856,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.1.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" }, "funding": [ { @@ -4864,7 +4864,7 @@ "type": "github" } ], - "time": "2022-08-29T06:55:37+00:00" + "time": "2022-09-12T14:47:03+00:00" }, { "name": "sebastian/version", @@ -5384,5 +5384,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } 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); + } +}