2022-09-07 08:43:05 +00:00
< ? php
namespace Appwrite\Migration\Version ;
use Appwrite\Migration\Migration ;
2022-09-08 16:46:18 +00:00
use Appwrite\OpenSSL\OpenSSL ;
2022-09-07 08:43:05 +00:00
use Exception ;
2022-09-08 16:46:18 +00:00
use Utopia\App ;
2022-09-07 08:43:05 +00:00
use Utopia\CLI\Console ;
use Utopia\Database\Database ;
use Utopia\Database\Document ;
2022-09-08 16:46:18 +00:00
use Utopia\Database\ID ;
use Utopia\Database\Permission ;
use Utopia\Database\Role ;
2022-09-07 08:43:05 +00:00
class V15 extends Migration
{
/**
* @ var \PDO $pdo
*/
private $pdo ;
public function execute () : void
{
global $register ;
$this -> pdo = $register -> get ( 'db' );
/**
* Disable SubQueries for Speed .
*/
2022-09-08 16:46:18 +00:00
foreach ([ 'subQueryAttributes' , 'subQueryIndexes' , 'subQueryPlatforms' , 'subQueryDomains' , 'subQueryKeys' , 'subQueryWebhooks' , 'subQuerySessions' , 'subQueryTokens' , 'subQueryMemberships' , 'subqueryVariables' ] as $name ) {
2022-09-07 08:43:05 +00:00
Database :: addFilter ( $name , fn () => null , fn () => []);
}
Console :: log ( 'Migrating project: ' . $this -> project -> getAttribute ( 'name' ) . ' (' . $this -> project -> getId () . ')' );
Console :: info ( 'Migrating Collections' );
$this -> migrateCollections ();
2022-09-08 16:46:18 +00:00
Console :: info ( 'Migrating Databases' );
$this -> migrateDatabases ();
Console :: info ( 'Migrating Buckets' );
$this -> migrateBuckets ();
Console :: info ( 'Migrating Documents' );
$this -> forEachDocument ([ $this , 'fixDocument' ]);
Console :: info ( " Clean up 'write' Permissions " );
foreach ( $this -> collections as $collection ) {
if ( $collection [ '$collection' ] === Database :: METADATA ) {
$this -> removeWritePermissions ( $collection [ '$id' ]);
}
}
}
protected function migrateBuckets () : void
{
foreach ( $this -> documentsIterator ( 'buckets' ) as $bucket ) {
$bucketTable = " bucket_ { $bucket -> getInternalId () } " ;
$this -> createPermissionsColumn ( $bucketTable );
$this -> migrateDateTimeAttribute ( $bucketTable , '_createdAt' );
$this -> migrateDateTimeAttribute ( $bucketTable , '_updatedAt' );
$this -> populatePermissionsAttribute (
document : $bucket ,
addCreatePermission : true
);
if ( ! is_null ( $bucket -> getAttribute ( 'permission' ))) {
$bucket -> setAttribute ( 'fileSecurity' , $bucket -> getAttribute ( 'permissions' ) === 'document' );
}
if ( is_null ( $bucket -> getAttribute ( 'compression' ))) {
$bucket -> setAttribute ( 'compression' , 'none' );
}
$this -> projectDB -> updateDocument ( 'buckets' , $bucket -> getId (), $bucket );
Console :: info ( " Migrating Files of { $bucket -> getId () } ( { $bucket -> getAttribute ( 'name' ) } ) " );
foreach ( $this -> documentsIterator ( $bucketTable ) as $file ) {
$this -> populatePermissionsAttribute (
document : $file ,
table : $bucketTable ,
addCreatePermission : false
);
$this -> projectDB -> updateDocument ( $bucketTable , $file -> getId (), $file );
}
$this -> removeWritePermissions ( $bucketTable );
}
try {
$this -> projectDB -> deleteAttribute ( 'buckets' , 'permission' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'permissions' from buckets: { $th -> getMessage () } " );
}
}
protected function migrateDatabases () : void
{
foreach ( $this -> documentsIterator ( 'databases' ) as $database ) {
$databaseTable = " database_ { $database -> getInternalId () } " ;
$this -> createPermissionsColumn ( $databaseTable );
$this -> migrateDateTimeAttribute ( $databaseTable , '_createdAt' );
$this -> migrateDateTimeAttribute ( $databaseTable , '_updatedAt' );
$this -> populatePermissionsAttribute (
document : $database ,
table : 'databases' ,
addCreatePermission : false
);
$this -> projectDB -> updateDocument ( 'databases' , $database -> getId (), $database );
try {
$this -> createAttributeFromCollection ( $this -> projectDB , $databaseTable , 'documentSecurity' , 'collections' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'documentSecurity' from { $databaseTable } : { $th -> getMessage () } " );
}
Console :: info ( " Migrating Collections of { $database -> getId () } ( { $database -> getAttribute ( 'name' ) } ) " );
foreach ( $this -> documentsIterator ( $databaseTable ) as $collection ) {
$collectionTable = " { $databaseTable } _collection_ { $collection -> getInternalId () } " ;
$this -> createPermissionsColumn ( $collectionTable );
$this -> migrateDateTimeAttribute ( $collectionTable , '_createdAt' );
$this -> migrateDateTimeAttribute ( $collectionTable , '_updatedAt' );
$this -> populatePermissionsAttribute (
document : $collection ,
table : $databaseTable ,
addCreatePermission : true
);
if ( ! is_null ( $collection -> getAttribute ( 'permission' ))) {
$collection -> setAttribute ( 'documentSecurity' , $collection -> getAttribute ( 'permissions' ) === 'document' );
}
$this -> projectDB -> updateDocument ( $databaseTable , $collection -> getId (), $collection );
Console :: info ( " Migrating Documents of { $collection -> getId () } ( { $collection -> getAttribute ( 'name' ) } ) " );
foreach ( $this -> documentsIterator ( $collectionTable ) as $document ) {
$this -> populatePermissionsAttribute (
document : $document ,
table : $collectionTable ,
addCreatePermission : false
);
$this -> projectDB -> updateDocument ( $collectionTable , $document -> getId (), $document );
}
$this -> removeWritePermissions ( $collectionTable );
}
$this -> removeWritePermissions ( $databaseTable );
try {
$this -> projectDB -> deleteAttribute ( " database_ { $database -> getInternalId () } " , 'permission' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'permission' from { $databaseTable } : { $th -> getMessage () } " );
}
}
}
/**
*
* @ param string $table
* @ return void
*/
protected function removeWritePermissions ( string $table ) : void
{
try {
$this -> pdo -> prepare ( " DELETE FROM ` { $this -> projectDB -> getDefaultDatabase () } `.`_ { $this -> project -> getInternalId () } _ { $table } _perms` WHERE _type = 'write' " ) -> execute ();
} catch ( \Throwable $th ) {
Console :: warning ( " Remove 'write' permissions from { $table } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
}
/**
* Returns all columns from the Table .
* @ param string $table
* @ return array
* @ throws \Exception
* @ throws \PDOException
*/
protected function getSQLColumnTypes ( string $table ) : array
{
$query = $this -> pdo -> prepare ( " SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_ { $this -> project -> getInternalId () } _ { $table } ' AND table_schema = ' { $this -> projectDB -> getDefaultDatabase () } ' " );
$query -> execute ();
return array_reduce ( $query -> fetchAll (), function ( array $carry , array $item ) {
$carry [ $item [ 'COLUMN_NAME' ]] = $item [ 'DATA_TYPE' ];
return $carry ;
}, []);
}
/**
* Migrates all Integer colums for timestamps to DateTime
* @ return void
* @ throws \Exception
*/
protected function migrateDateTimeAttribute ( string $table , string $attribute ) : void
{
$columns = $this -> getSQLColumnTypes ( $table );
if ( $columns [ $attribute ] === 'int' ) {
try {
$this -> pdo -> prepare ( " ALTER TABLE IF EXISTS ` { $this -> projectDB -> getDefaultDatabase () } `.`_ { $this -> project -> getInternalId () } _ { $table } ` MODIFY { $attribute } VARCHAR(64) " ) -> execute ();
2022-09-08 16:46:18 +00:00
$this -> pdo -> prepare ( " UPDATE ` { $this -> projectDB -> getDefaultDatabase () } `.`_ { $this -> project -> getInternalId () } _ { $table } ` SET { $attribute } = IF( { $attribute } = 0, NULL, FROM_UNIXTIME( { $attribute } )) " ) -> execute ();
$columns [ $attribute ] = 'varchar' ;
2022-09-07 08:43:05 +00:00
} catch ( \Throwable $th ) {
Console :: warning ( $th -> getMessage ());
}
}
if ( $columns [ $attribute ] === 'varchar' ) {
try {
$this -> pdo -> prepare ( " ALTER TABLE IF EXISTS ` { $this -> projectDB -> getDefaultDatabase () } `.`_ { $this -> project -> getInternalId () } _ { $table } ` MODIFY { $attribute } DATETIME(3) " ) -> execute ();
} catch ( \Throwable $th ) {
Console :: warning ( $th -> getMessage ());
}
}
2022-09-08 16:46:18 +00:00
/**
* Skip adding filter on internal attributes .
*/
if ( ! str_starts_with ( $attribute , '_' )) {
try {
/**
* Add datetime filter .
*/
$this -> projectDB -> updateAttributeFilters ( $table , ID :: custom ( $attribute ), [ 'datetime' ]);
/**
* Change data type to DateTime .
*/
$this -> projectDB -> updateAttribute (
collection : $table ,
id : $attribute ,
type : Database :: VAR_DATETIME ,
signed : false
);
} catch ( \Throwable $th ) {
Console :: warning ( " Add 'datetime' filter to ' { $attribute } ' from { $table } : { $th -> getMessage () } " );
}
}
$this -> projectDB -> deleteCachedCollection ( $table );
}
protected function createPermissionsColumn ( string $table ) : void
{
$columns = $this -> getSQLColumnTypes ( $table );
if ( ! array_key_exists ( '_permissions' , $columns )) {
try {
$this -> pdo -> prepare ( " ALTER TABLE IF EXISTS ` { $this -> projectDB -> getDefaultDatabase () } `.`_ { $this -> project -> getInternalId () } _ { $table } ` ADD `_permissions` MEDIUMTEXT DEFAULT NULL " ) -> execute ();
} catch ( \Throwable $th ) {
Console :: warning ( " Add '_permissions' column to ' { $table } ': { $th -> getMessage () } " );
}
}
}
protected function populatePermissionsAttribute ( Document & $document , ? string $table = null , bool $addCreatePermission = true ) : void
{
$table ? ? = $document -> getCollection ();
$query = $this -> pdo -> prepare ( " SELECT * FROM ` { $this -> projectDB -> getDefaultDatabase () } `.`_ { $this -> project -> getInternalId () } _ { $table } _perms` WHERE _document = ' { $document -> getId () } ' " );
$query -> execute ();
$results = $query -> fetchAll ();
$permissions = [];
foreach ( $results as $result ) {
$type = $result [ '_type' ];
$permission = $result [ '_permission' ];
if ( $type === 'write' ) {
$permissions [] = " update( \" { $permission } \" ) " ;
$permissions [] = " delete( \" { $permission } \" ) " ;
if ( $addCreatePermission ) {
$permissions [] = " create( \" { $permission } \" ) " ;
}
} else {
$permissions [] = " { $type } ( \" { $permission } \" ) " ;
}
}
$document -> setAttribute ( '$permissions' , $permissions );
2022-09-07 08:43:05 +00:00
}
/**
* Migrate all Collections .
*
* @ return void
*/
protected function migrateCollections () : void
{
foreach ( $this -> collections as $collection ) {
$id = $collection [ '$id' ];
Console :: log ( " - { $id } " );
$this -> projectDB -> setNamespace ( " _ { $this -> project -> getInternalId () } " );
switch ( $id ) {
case '_metadata' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
Console :: log ( ' - create "cache" collection' );
$this -> createCollection ( 'cache' );
Console :: log ( ' - create "variables" collection' );
$this -> createCollection ( 'variables' );
$this -> projectDB -> deleteCachedCollection ( $id );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'abuse' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'attributes' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
break ;
2022-09-07 08:43:05 +00:00
case 'audit' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'buckets' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
try {
/**
* Create 'compression' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'compression' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'compression' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create 'fileSecurity' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'fileSecurity' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'fileSecurity' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_enabled' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_enabled' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_enabled' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_name' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_name' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_name' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_fileSecurity' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_fileSecurity' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_fileSecurity' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_maximumFileSize' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_maximumFileSize' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_maximumFileSize' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_encryption' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_encryption' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_encryption' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_antivirus' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_antivirus' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_antivirus' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'builds' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'startTime' );
$this -> migrateDateTimeAttribute ( $id , 'endTime' );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'certificates' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'issueDate' );
$this -> migrateDateTimeAttribute ( $id , 'renewDate' );
$this -> migrateDateTimeAttribute ( $id , 'updated' );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'databases' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'deployments' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
try {
/**
* Create '_key_entrypoint' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_entrypoint' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_entrypoint' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_size' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_size' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_size' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_buildId' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_buildId' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_buildId' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_activate' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_activate' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_activate' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'domains' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'updated' );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'executions' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
try {
/**
* Create 'stdout' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'stdout' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'stdout' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_trigger' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_trigger' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_trigger' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_status' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_status' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_status' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_statusCode' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_statusCode' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_statusCode' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_time' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_time' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_time' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'functions' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'scheduleNext' );
$this -> migrateDateTimeAttribute ( $id , 'schedulePrevious' );
/**
* Migrate function variables .
*/
Console :: info ( " Migrating Variables " );
foreach ( $this -> documentsIterator ( 'functions' ) as $function ) {
foreach ( $function -> getAttribute ( 'vars' , []) as $key => $value ) {
$variableId = ID :: unique ();
$variable = new Document ([
'$id' => $variableId ,
'$permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
'functionId' => $function -> getId (),
'functionInternalId' => $function -> getInternalId (),
'key' => $key ,
'value' => $value ,
'search' => implode ( ' ' , [ $variableId , $key , $function -> getId ()])
]);
$this -> projectDB -> createDocument ( 'variables' , $variable );
}
$this -> projectDB -> deleteAttribute ( 'functions' , 'vars' );
$this -> createAttributeFromCollection ( $this -> projectDB , 'functions' , 'vars' );
}
try {
/**
* Create '_key_name' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_name' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_name' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_status' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_status' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_status' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_runtime' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_runtime' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_runtime' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_deployment' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_deployment' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_deployment' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_schedule' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_schedule' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_schedule' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_scheduleNext' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_scheduleNext' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_scheduleNext' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_schedulePrevious' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_schedulePrevious' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_schedulePrevious' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_timeout' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_timeout' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_timeout' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'indexes' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'keys' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'expire' );
try {
/**
* Create 'accessedAt' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'accessedAt' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'accessedAt' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create 'sdks' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'sdks' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'sdks' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_accessedAt' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_accessedAt' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_accessedAt' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'memberships' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'invited' );
$this -> migrateDateTimeAttribute ( $id , 'joined' );
try {
/**
* Create '_key_userId' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_userId' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_userId' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_teamId' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_teamId' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_teamId' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_invited' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_invited' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_invited' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_joined' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_joined' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_joined' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_confirm' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_confirm' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_confirm' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'platforms' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'projects' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
try {
/**
* Create '_key_name' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_name' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_name' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'realtime' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'timestamp' );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'sessions' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'expire' );
$this -> migrateDateTimeAttribute ( $id , 'providerAccessTokenExpiry' );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'stats' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'time' );
try {
/**
* Re - Create '_key_metric' index
*/
@ $this -> projectDB -> deleteIndex ( $id , '_key_metric' );
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_period_time' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_period_time' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Re - Create '_key_metric_period' index
*/
@ $this -> projectDB -> deleteIndex ( $id , '_key_metric_period' );
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_metric_period_time' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_metric_period_time' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'teams' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
try {
/**
* Create '_key_name' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_name' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_name' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_total' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_total' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_total' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'tokens' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'expire' );
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'users' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
2022-09-08 16:46:18 +00:00
$this -> migrateDateTimeAttribute ( $id , 'registration' );
$this -> migrateDateTimeAttribute ( $id , 'passwordUpdate' );
try {
/**
* Create 'hash' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'hash' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'hash' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create 'hashOptions' attribute
*/
$this -> createAttributeFromCollection ( $this -> projectDB , $id , 'hashOptions' );
} catch ( \Throwable $th ) {
Console :: warning ( " 'hashOptions' from { $id } : { $th -> getMessage () } " );
}
/**
* Update user password before adding encrypt filter .
*/
Console :: info ( " Migrating Passwords " );
foreach ( $this -> documentsIterator ( 'users' ) as $user ) {
/**
* Skip when no password .
*/
if ( is_null ( $user -> getAttribute ( 'password' ))) {
continue ;
}
/**
* Skip when password is JSON .
*/
json_decode ( $user -> getAttribute ( 'password' ));
if ( json_last_error () === JSON_ERROR_NONE ) {
continue ;
}
/**
* Add default hash .
*/
$user -> setAttribute ( 'hash' , 'bcrypt' );
/**
* Add default hash options .
*/
$user -> setAttribute ( 'hashOptions' , json_encode ([ 'cost' => 8 ]));
/**
* Encrypt hashed password .
*/
$user -> setAttribute ( 'password' , $this -> encryptFilter ( $user -> getAttribute ( 'password' )));
$this -> projectDB -> updateDocument ( 'users' , $user -> getId (), $user );
}
try {
/**
* Add datetime filter to password .
*/
$this -> projectDB -> updateAttributeFilters ( $id , 'password' , [ 'encrypt' ]);
} catch ( \Throwable $th ) {
Console :: warning ( " Add 'encrypt' filter to 'password' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_name' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_name' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_name' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_status' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_status' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_status' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_passwordUpdate' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_passwordUpdate' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_passwordUpdate' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_registration' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_registration' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_registration' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_emailVerification' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_emailVerification' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_emailVerification' from { $id } : { $th -> getMessage () } " );
}
try {
/**
* Create '_key_phoneVerification' index
*/
$this -> createIndexFromCollection ( $this -> projectDB , $id , '_key_phoneVerification' );
} catch ( \Throwable $th ) {
Console :: warning ( " '_key_phoneVerification' from { $id } : { $th -> getMessage () } " );
}
2022-09-07 08:43:05 +00:00
break ;
2022-09-08 16:46:18 +00:00
2022-09-07 08:43:05 +00:00
case 'webhooks' :
2022-09-08 16:46:18 +00:00
$this -> createPermissionsColumn ( $id );
2022-09-07 08:43:05 +00:00
$this -> migrateDateTimeAttribute ( $id , '_createdAt' );
$this -> migrateDateTimeAttribute ( $id , '_updatedAt' );
break ;
default :
2022-09-09 09:38:54 +00:00
break ;
2022-09-07 08:43:05 +00:00
}
usleep ( 50000 );
}
}
/**
* Fix run on each document
*
* @ param \Utopia\Database\Document $document
* @ return \Utopia\Database\Document
*/
protected function fixDocument ( Document $document )
{
switch ( $document -> getCollection ()) {
2022-09-08 16:46:18 +00:00
case 'cache' :
case 'variables' :
return null ;
2022-09-07 08:43:05 +00:00
case 'projects' :
/**
2022-09-08 16:46:18 +00:00
* Populate permissions attribute .
2022-09-07 08:43:05 +00:00
*/
2022-09-08 16:46:18 +00:00
$this -> populatePermissionsAttribute ( $document , addCreatePermission : false );
2022-09-07 08:43:05 +00:00
/**
2022-09-08 16:46:18 +00:00
* Bump version number .
2022-09-07 08:43:05 +00:00
*/
2022-09-08 16:46:18 +00:00
$document -> setAttribute ( 'version' , '1.0.0-RC1' );
2022-09-07 08:43:05 +00:00
break ;
case 'users' :
/**
2022-09-08 16:46:18 +00:00
* Populate permissions attribute .
2022-09-07 08:43:05 +00:00
*/
2022-09-08 16:46:18 +00:00
$this -> populatePermissionsAttribute ( $document , addCreatePermission : false );
2022-09-09 09:38:54 +00:00
$document -> setAttribute ( '$permissions' , Permission :: read ( Role :: any ()), Document :: SET_TYPE_APPEND );
break ;
case 'sessions' :
$userId = $document -> getAttribute ( 'userId' );
$document
-> setAttribute ( '$permissions' , Permission :: read ( Role :: user ( $userId )), Document :: SET_TYPE_APPEND )
-> setAttribute ( '$permissions' , Permission :: update ( Role :: user ( $userId )), Document :: SET_TYPE_APPEND )
-> setAttribute ( '$permissions' , Permission :: delete ( Role :: user ( $userId )), Document :: SET_TYPE_APPEND );
2022-09-07 08:43:05 +00:00
break ;
}
return $document ;
}
2022-09-08 16:46:18 +00:00
protected function encryptFilter ( string $value )
{
$key = App :: getEnv ( '_APP_OPENSSL_KEY_V1' );
$iv = OpenSSL :: randomPseudoBytes ( OpenSSL :: cipherIVLength ( OpenSSL :: CIPHER_AES_128_GCM ));
$tag = null ;
return json_encode ([
'data' => OpenSSL :: encrypt ( $value , OpenSSL :: CIPHER_AES_128_GCM , $key , 0 , $iv , $tag ),
'method' => OpenSSL :: CIPHER_AES_128_GCM ,
'iv' => \bin2hex ( $iv ),
'tag' => \bin2hex ( $tag ? ? '' ),
'version' => '1' ,
]);
}
2022-09-07 08:43:05 +00:00
}