mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
merge resolve conflicts
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 = '';
|
||||
|
||||
@@ -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
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user