merge resolve conflicts

This commit is contained in:
prateek banga
2023-08-21 14:07:18 +05:30
57 changed files with 3493 additions and 108 deletions
+9 -3
View File
@@ -16,9 +16,15 @@ class Exception extends AppwriteException
$this->message = $response;
$decoded = json_decode($response, true);
if (\is_array($decoded)) {
$this->error = $decoded['error'];
$this->errorDescription = $decoded['error_description'];
$this->message = $this->error . ': ' . $this->errorDescription;
if (\is_array($decoded['error'])) {
$this->error = $decoded['error']['status'];
$this->errorDescription = $decoded['error']['message'];
$this->message = $this->error . ': ' . $this->errorDescription;
} else {
$this->error = $decoded['error'];
$this->errorDescription = $decoded['error_description'];
$this->message = $this->error . ': ' . $this->errorDescription;
}
}
$type = match ($code) {
400 => AppwriteException::USER_OAUTH2_BAD_REQUEST,
+270
View File
@@ -0,0 +1,270 @@
<?php
namespace Appwrite\Auth\OAuth2;
use Appwrite\Auth\OAuth2;
class Firebase extends OAuth2
{
/**
* @var array
*/
protected array $user = [];
/**
* @var array
*/
protected array $tokens = [];
/**
* @var array
*/
protected array $scopes = [
'https://www.googleapis.com/auth/firebase',
'https://www.googleapis.com/auth/datastore',
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/identitytoolkit',
'https://www.googleapis.com/auth/userinfo.profile'
];
/**
* @return string
*/
public function getName(): string
{
return 'firebase';
}
/**
* @return string
*/
public function getLoginURL(): string
{
return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([
'access_type' => 'offline',
'client_id' => $this->appID,
'redirect_uri' => $this->callback,
'scope' => \implode(' ', $this->getScopes()),
'state' => \json_encode($this->state),
'response_type' => 'code',
'prompt' => 'consent',
]);
}
/**
* @param string $code
*
* @return array
*/
protected function getTokens(string $code): array
{
if (empty($this->tokens)) {
$response = $this->request(
'POST',
'https://oauth2.googleapis.com/token',
[],
\http_build_query([
'client_id' => $this->appID,
'redirect_uri' => $this->callback,
'client_secret' => $this->appSecret,
'code' => $code,
'grant_type' => 'authorization_code'
])
);
$this->tokens = \json_decode($response, true);
}
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken): array
{
$response = $this->request(
'POST',
'https://oauth2.googleapis.com/token',
[],
\http_build_query([
'client_id' => $this->appID,
'client_secret' => $this->appSecret,
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken
])
);
$output = [];
\parse_str($response, $output);
$this->tokens = $output;
if (empty($this->tokens['refresh_token'])) {
$this->tokens['refresh_token'] = $refreshToken;
}
return $this->tokens;
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserID(string $accessToken): string
{
$user = $this->getUser($accessToken);
return $user['id'] ?? '';
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserEmail(string $accessToken): string
{
$user = $this->getUser($accessToken);
return $user['email'] ?? '';
}
/**
* Check if the OAuth email is verified
*
* @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user
*
* @param string $accessToken
*
* @return bool
*/
public function isEmailVerified(string $accessToken): bool
{
$user = $this->getUser($accessToken);
if ($user['verified'] ?? false) {
return true;
}
return false;
}
/**
* @param string $accessToken
*
* @return string
*/
public function getUserName(string $accessToken): string
{
$user = $this->getUser($accessToken);
return $user['name'] ?? '';
}
/**
* @param string $accessToken
*
* @return array
*/
protected function getUser(string $accessToken)
{
if (empty($this->user)) {
$response = $this->request(
'GET',
'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' . \urlencode($accessToken),
[],
);
$this->user = \json_decode($response, true);
}
return $this->user;
}
public function getProjects(string $accessToken): array
{
$projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer ' . \urlencode($accessToken)]);
$projects = \json_decode($projects, true);
return $projects['results'];
}
/*
Be careful with the setIAMPolicy method, it will overwrite all existing policies
**/
public function assignIAMRoles(string $accessToken, string $email, string $projectId)
{
// Get IAM Roles
$iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':getIamPolicy', [
'Authorization: Bearer ' . \urlencode($accessToken),
'Content-Type: application/json'
]);
$iamRoles = \json_decode($iamRoles, true);
$iamRoles['bindings'][] = [
'role' => 'roles/identitytoolkit.admin',
'members' => [
'serviceAccount:' . $email
]
];
$iamRoles['bindings'][] = [
'role' => 'roles/firebase.admin',
'members' => [
'serviceAccount:' . $email
]
];
// Set IAM Roles
$this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':setIamPolicy', [
'Authorization: Bearer ' . \urlencode($accessToken),
'Content-Type: application/json'
], json_encode([
'policy' => $iamRoles
]));
}
public function createServiceAccount(string $accessToken, string $projectId): array
{
// Create Service Account
$response = $this->request(
'POST',
'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts',
[
'Authorization: Bearer ' . \urlencode($accessToken),
'Content-Type: application/json'
],
json_encode([
'accountId' => 'appwrite-migrations',
'serviceAccount' => [
'displayName' => 'Appwrite Migrations'
]
])
);
$response = json_decode($response, true);
$this->assignIAMRoles($accessToken, $response['email'], $projectId);
// Create Service Account Key
$responseKey = $this->request(
'POST',
'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $response['email'] . '/keys',
[
'Authorization: Bearer ' . \urlencode($accessToken),
'Content-Type: application/json'
]
);
$responseKey = json_decode($responseKey, true);
return json_decode(base64_decode($responseKey['privateKeyData']), true);
}
}
+3
View File
@@ -38,6 +38,9 @@ class Event
public const MESSAGING_QUEUE_NAME = 'v1-messaging';
public const MESSAGING_CLASS_NAME = 'MessagingV1';
public const MIGRATIONS_QUEUE_NAME = 'v1-migrations';
public const MIGRATIONS_CLASS_NAME = 'MigrationsV1';
protected string $queue = '';
protected string $class = '';
protected string $event = '';
+98
View File
@@ -0,0 +1,98 @@
<?php
namespace Appwrite\Event;
use DateTime;
use Resque;
use ResqueScheduler;
use Utopia\Database\Document;
class Migration extends Event
{
protected string $type = '';
protected ?Document $migration = null;
public function __construct()
{
parent::__construct(Event::MIGRATIONS_QUEUE_NAME, Event::MIGRATIONS_CLASS_NAME);
}
/**
* Sets migration document for the migration event.
*
* @param Document $migration
* @return self
*/
public function setMigration(Document $migration): self
{
$this->migration = $migration;
return $this;
}
/**
* Returns set migration document for the function event.
*
* @return null|Document
*/
public function getMigration(): ?Document
{
return $this->migration;
}
/**
* Sets migration type for the migration event.
*
* @param string $type
*
* @return self
*/
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
/**
* Returns set migration type for the migration event.
*
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Executes the migration event and sends it to the migrations worker.
*
* @return string|bool
* @throws \InvalidArgumentException
*/
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
'project' => $this->project,
'user' => $this->user,
'migration' => $this->migration
]);
}
/**
* Schedules the migration event and schedules it in the migrations worker queue.
*
* @param \DateTime|int $at
* @return void
* @throws \Resque_Exception
* @throws \ResqueScheduler_InvalidTimestampException
*/
public function schedule(DateTime|int $at): void
{
ResqueScheduler::enqueueAt($at, $this->queue, $this->class, [
'project' => $this->project,
'user' => $this->user,
'migration' => $this->migration
]);
}
}
+7
View File
@@ -32,6 +32,7 @@ class Exception extends \Exception
* - Platform
* - Domain
* - GraphQL
* - Migrations
*/
/** General */
@@ -73,6 +74,7 @@ class Exception extends \Exception
public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists';
public const USER_PASSWORD_MISMATCH = 'user_password_mismatch';
public const USER_SESSION_NOT_FOUND = 'user_session_not_found';
public const USER_IDENTITY_NOT_FOUND = 'user_identity_not_found';
public const USER_UNAUTHORIZED = 'user_unauthorized';
public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported';
public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists';
@@ -205,6 +207,11 @@ class Exception extends \Exception
public const GRAPHQL_NO_QUERY = 'graphql_no_query';
public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries';
/** Migrations */
public const MIGRATION_NOT_FOUND = 'migration_not_found';
public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists';
public const MIGRATION_IN_PROGRESS = 'migration_in_progress';
/** Provider */
public const PROVIDER_NOT_FOUND = 'provider_not_found';
+19 -1
View File
@@ -29,6 +29,7 @@ class V19 extends Migration
$this->projectDB->setNamespace("_{$this->project->getInternalId()}");
$this->alterPermissionIndex('_metadata');
$this->alterUidType('_metadata');
Console::info('Migrating Databases');
$this->migrateDatabases();
@@ -57,11 +58,13 @@ class V19 extends Migration
$databaseTable = "database_{$database->getInternalId()}";
$this->alterPermissionIndex($databaseTable);
$this->alterUidType($databaseTable);
foreach ($this->documentsIterator($databaseTable) as $collection) {
$collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}";
Console::log("Migrating Collections of {$collectionTable} {$collection->getId()} ({$collection->getAttribute('name')})");
$this->alterPermissionIndex($collectionTable);
$this->alterUidType($collectionTable);
}
}
}
@@ -98,6 +101,7 @@ class V19 extends Migration
}
if (!in_array($id, ['files', 'collections'])) {
$this->alterPermissionIndex($id);
$this->alterUidType($id);
}
usleep(50000);
@@ -131,7 +135,7 @@ class V19 extends Migration
protected function alterPermissionIndex($collectionName): void
{
try {
$table = "`{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$collectionName}_perms";
$table = "`{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$collectionName}_perms`";
$this->pdo->prepare("
ALTER TABLE {$table}
DROP INDEX `_permission`,
@@ -142,6 +146,19 @@ class V19 extends Migration
}
}
protected function alterUidType($collectionName): void
{
try {
$table = "`{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$collectionName}`";
$this->pdo->prepare("
ALTER TABLE {$table}
CHANGE COLUMN `_uid` `_uid` VARCHAR(255) NOT NULL ;
")->execute();
} catch (\Throwable $th) {
Console::warning($th->getMessage());
}
}
/**
* Migrating all Bucket tables.
*
@@ -155,6 +172,7 @@ class V19 extends Migration
$id = "bucket_{$bucket->getInternalId()}";
Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})");
$this->alterPermissionIndex($id);
$this->alterUidType($id);
}
}
}
@@ -0,0 +1,23 @@
<?php
namespace Appwrite\Utopia\Database\Validator\Queries;
class Identities extends Base
{
public const ALLOWED_ATTRIBUTES = [
'userId',
'provider',
'providerUid',
'providerEmail',
'providerAccessTokenExpiry',
];
/**
* Expression constructor
*
*/
public function __construct()
{
parent::__construct('identities', self::ALLOWED_ATTRIBUTES);
}
}
@@ -0,0 +1,25 @@
<?php
namespace Appwrite\Utopia\Database\Validator\Queries;
class Migrations extends Base
{
public const ALLOWED_ATTRIBUTES = [
'status',
'stage',
'source',
'resources',
'statusCounters',
'resourceData',
'errors'
];
/**
* Expression constructor
*
*/
public function __construct()
{
parent::__construct('migrations', self::ALLOWED_ATTRIBUTES);
}
}
+20
View File
@@ -51,6 +51,7 @@ use Appwrite\Utopia\Response\Model\File;
use Appwrite\Utopia\Response\Model\Bucket;
use Appwrite\Utopia\Response\Model\ConsoleVariables;
use Appwrite\Utopia\Response\Model\Func;
use Appwrite\Utopia\Response\Model\Identity;
use Appwrite\Utopia\Response\Model\Index;
use Appwrite\Utopia\Response\Model\JWT;
use Appwrite\Utopia\Response\Model\Key;
@@ -93,6 +94,9 @@ use Appwrite\Utopia\Response\Model\UsageProject;
use Appwrite\Utopia\Response\Model\UsageStorage;
use Appwrite\Utopia\Response\Model\UsageUsers;
use Appwrite\Utopia\Response\Model\Variable;
use Appwrite\Utopia\Response\Model\Migration;
use Appwrite\Utopia\Response\Model\MigrationFirebaseProject;
use Appwrite\Utopia\Response\Model\MigrationReport;
/**
* @method int getStatusCode()
@@ -150,6 +154,8 @@ class Response extends SwooleResponse
public const MODEL_USER_LIST = 'userList';
public const MODEL_SESSION = 'session';
public const MODEL_SESSION_LIST = 'sessionList';
public const MODEL_IDENTITY = 'identity';
public const MODEL_IDENTITY_LIST = 'identityList';
public const MODEL_TOKEN = 'token';
public const MODEL_JWT = 'jwt';
public const MODEL_PREFERENCES = 'preferences';
@@ -215,6 +221,13 @@ class Response extends SwooleResponse
public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet
public const MODEL_FUNC_PERMISSIONS = 'funcPermissions';
// Migrations
public const MODEL_MIGRATION = 'migration';
public const MODEL_MIGRATION_LIST = 'migrationList';
public const MODEL_MIGRATION_REPORT = 'migrationReport';
public const MODEL_MIGRATION_FIREBASE_PROJECT = 'firebaseProject';
public const MODEL_MIGRATION_FIREBASE_PROJECT_LIST = 'firebaseProjectList';
// Project
public const MODEL_PROJECT = 'project';
public const MODEL_PROJECT_LIST = 'projectList';
@@ -282,6 +295,7 @@ class Response extends SwooleResponse
->setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX))
->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER))
->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION))
->setModel(new BaseList('Identities List', self::MODEL_IDENTITY_LIST, 'identities', self::MODEL_IDENTITY))
->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG))
->setModel(new BaseList('Files List', self::MODEL_FILE_LIST, 'files', self::MODEL_FILE))
->setModel(new BaseList('Buckets List', self::MODEL_BUCKET_LIST, 'buckets', self::MODEL_BUCKET))
@@ -312,6 +326,8 @@ class Response extends SwooleResponse
->setModel(new BaseList('Topic list', self::MODEL_TOPIC_LIST, 'topics', self::MODEL_TOPIC))
->setModel(new BaseList('Subscriber list', self::MODEL_SUBSCRIBER_LIST, 'subscribers', self::MODEL_SUBSCRIBER))
->setModel(new BaseList('Target list', self::MODEL_TARGET_LIST, 'targets', self::MODEL_TARGET))
->setModel(new BaseList('Migrations List', self::MODEL_MIGRATION_LIST, 'migrations', self::MODEL_MIGRATION))
->setModel(new BaseList('Migrations Firebase Projects List', self::MODEL_MIGRATION_FIREBASE_PROJECT_LIST, 'projects', self::MODEL_MIGRATION_FIREBASE_PROJECT))
// Entities
->setModel(new Database())
->setModel(new Collection())
@@ -341,6 +357,7 @@ class Response extends SwooleResponse
->setModel(new Account())
->setModel(new Preferences())
->setModel(new Session())
->setModel(new Identity())
->setModel(new Token())
->setModel(new JWT())
->setModel(new Locale())
@@ -389,6 +406,9 @@ class Response extends SwooleResponse
->setModel(new Topic())
->setModel(new Subscriber())
->setModel(new Target())
->setModel(new Migration())
->setModel(new MigrationReport())
->setModel(new MigrationFirebaseProject())
// Verification
// Recovery
// Tests (keep last)
@@ -0,0 +1,95 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class Identity extends Model
{
public function __construct()
{
$this
->addRule('$id', [
'type' => self::TYPE_STRING,
'description' => 'Identity ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Identity creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Identity update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('userId', [
'type' => self::TYPE_STRING,
'description' => 'User ID.',
'default' => '',
'example' => '5e5bb8c16897e',
])
->addRule('provider', [
'type' => self::TYPE_STRING,
'description' => 'Identity Provider.',
'default' => '',
'example' => 'email',
])
->addRule('providerUid', [
'type' => self::TYPE_STRING,
'description' => 'ID of the User in the Identity Provider.',
'default' => '',
'example' => '5e5bb8c16897e',
])
->addRule('providerEmail', [
'type' => self::TYPE_STRING,
'description' => 'Email of the User in the Identity Provider.',
'default' => '',
'example' => 'user@example.com',
])
->addRule('providerAccessToken', [
'type' => self::TYPE_STRING,
'description' => 'Identity Provider Access Token.',
'default' => '',
'example' => 'MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3',
])
->addRule('providerAccessTokenExpiry', [
'type' => self::TYPE_DATETIME,
'description' => 'The date of when the access token expires in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('providerRefreshToken', [
'type' => self::TYPE_STRING,
'description' => 'Identity Provider Refresh Token.',
'default' => '',
'example' => 'MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3',
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Identity';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_IDENTITY;
}
}
@@ -0,0 +1,96 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class Migration extends Model
{
public function __construct()
{
$this
->addRule('$id', [
'type' => self::TYPE_STRING,
'description' => 'Migration ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Variable creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Variable creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('status', [
'type' => self::TYPE_STRING,
'description' => 'Migration status ( pending, processing, failed, completed ) ',
'default' => '',
'example' => 'pending',
])
->addRule('stage', [
'type' => self::TYPE_STRING,
'description' => 'Migration stage ( init, processing, source-check, destination-check, migrating, finished )',
'default' => '',
'example' => 'init',
])
->addRule('source', [
'type' => self::TYPE_STRING,
'description' => 'A string containing the type of source of the migration.',
'default' => '',
'example' => 'Appwrite',
])
->addRule('resources', [
'type' => self::TYPE_STRING,
'description' => 'Resources to migration.',
'default' => [],
'example' => ['user'],
'array' => true
])
->addRule('statusCounters', [
'type' => self::TYPE_JSON,
'description' => 'A group of counters that represent the total progress of the migration.',
'default' => [],
'example' => '{"Database": {"PENDING": 0, "SUCCESS": 1, "ERROR": 0, "SKIP": 0, "PROCESSING": 0, "WARNING": 0}}',
])
->addRule('resourceData', [
'type' => self::TYPE_JSON,
'description' => 'An array of objects containing the report data of the resources that were migrated.',
'default' => [],
'example' => '[{"resource":"Database","id":"public","status":"SUCCESS","message":""}]',
])
->addRule('errors', [
'type' => self::TYPE_STRING,
'description' => 'All errors that occurred during the migration process.',
'default' => [],
'example' => [],
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Migration';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_MIGRATION;
}
}
@@ -0,0 +1,46 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class MigrationFirebaseProject extends Model
{
public function __construct()
{
$this
->addRule('projectId', [
'type' => self::TYPE_STRING,
'description' => 'Project ID.',
'default' => '',
'example' => 'my-project',
])
->addRule('displayName', [
'type' => self::TYPE_STRING,
'description' => 'Project display name.',
'default' => '',
'example' => 'My Project',
]);
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'MigrationFirebaseProject';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_MIGRATION_FIREBASE_PROJECT;
}
}
@@ -0,0 +1,89 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use Utopia\Migration\Resource;
class MigrationReport extends Model
{
public function __construct()
{
$this
->addRule(Resource::TYPE_USER, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of users to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule(Resource::TYPE_TEAM, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of teams to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule(Resource::TYPE_DATABASE, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of databases to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule(Resource::TYPE_DOCUMENT, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of documents to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule(Resource::TYPE_FILE, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of files to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule(Resource::TYPE_BUCKET, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of buckets to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule(Resource::TYPE_FUNCTION, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of functions to be migrated.',
'default' => 0,
'example' => 20,
])
->addRule('size', [
'type' => self::TYPE_INTEGER,
'description' => 'Size of files to be migrated in mb.',
'default' => 0,
'example' => 30000,
])
->addRule('version', [
'type' => self::TYPE_STRING,
'description' => 'Version of the Appwrite instance to be migrated.',
'default' => '',
'example' => '1.4.0',
]);
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Migration Report';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_MIGRATION_REPORT;
}
}