1
0
Fork 0
mirror of synced 2024-09-20 11:37:45 +12:00

get project db key by region

This commit is contained in:
shimon 2024-08-05 15:26:20 +03:00
parent 3c749153f0
commit 6b3051f131
5 changed files with 346 additions and 444 deletions

View file

@ -35,8 +35,7 @@ CLI::setResource('cache', function ($pools) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
->getResource();
}
return new Cache(new Sharding($adapters));
@ -85,7 +84,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) {
} while ($attempts < $maxAttempts && ! $ready);
if (! $ready) {
throw new Exception("Console is not ready yet. Please try again later.");
throw new Exception('Console is not ready yet. Please try again later.');
}
return $dbForConsole;
@ -108,8 +107,8 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()];
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
@ -133,7 +132,8 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
$databases[$dsn->getHost()] = $database;
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())

View file

@ -135,7 +135,7 @@ App::post('/v1/projects')
// TODO: Temporary until all projects are using shared tables.
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn, $sharedTablesKeys)) {
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$schema = 'appwrite';
$database = 'appwrite';
$namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '');
@ -199,7 +199,8 @@ App::post('/v1/projects')
$adapter = $pools->get($dsn->getHost())->pop()->getResource();
$dbForProject = new Database($adapter, $cache);
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$dbForProject
->setSharedTables(true)
->setTenant($project->getInternalId())

View file

@ -5,9 +5,7 @@
*
* Initializes both Appwrite API entry point, queue workers, and CLI tasks.
* Set configuration, framework resources & app constants
*
*/
if (\file_exists(__DIR__.'/../vendor/autoload.php')) {
require_once __DIR__.'/../vendor/autoload.php';
}
@ -345,8 +343,7 @@ Database::addFilter(
if (isset($formatOptions['min']) || isset($formatOptions['max'])) {
$attribute
->setAttribute('min', $formatOptions['min'])
->setAttribute('max', $formatOptions['max'])
;
->setAttribute('max', $formatOptions['max']);
}
return $value;
@ -355,9 +352,7 @@ Database::addFilter(
Database::addFilter(
'subQueryAttributes',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
$attributes = $database->find('attributes', [
Query::equal('collectionInternalId', [$document->getInternalId()]),
@ -381,9 +376,7 @@ Database::addFilter(
Database::addFilter(
'subQueryIndexes',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return $database
->find('indexes', [
@ -396,9 +389,7 @@ Database::addFilter(
Database::addFilter(
'subQueryPlatforms',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return $database
->find('platforms', [
@ -410,9 +401,7 @@ Database::addFilter(
Database::addFilter(
'subQueryKeys',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return $database
->find('keys', [
@ -424,9 +413,7 @@ Database::addFilter(
Database::addFilter(
'subQueryWebhooks',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return $database
->find('webhooks', [
@ -438,9 +425,7 @@ Database::addFilter(
Database::addFilter(
'subQuerySessions',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database->find('sessions', [
Query::equal('userInternalId', [$document->getInternalId()]),
@ -451,9 +436,7 @@ Database::addFilter(
Database::addFilter(
'subQueryTokens',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('tokens', [
@ -465,9 +448,7 @@ Database::addFilter(
Database::addFilter(
'subQueryChallenges',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('challenges', [
@ -479,9 +460,7 @@ Database::addFilter(
Database::addFilter(
'subQueryAuthenticators',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('authenticators', [
@ -493,9 +472,7 @@ Database::addFilter(
Database::addFilter(
'subQueryMemberships',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('memberships', [
@ -507,9 +484,7 @@ Database::addFilter(
Database::addFilter(
'subQueryVariables',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return $database
->find('variables', [
@ -548,14 +523,12 @@ Database::addFilter(
Database::addFilter(
'subQueryProjectVariables',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return $database
->find('variables', [
Query::equal('resourceType', ['project']),
Query::limit(APP_LIMIT_SUBQUERY)
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
);
@ -567,7 +540,7 @@ Database::addFilter(
$user->getId(),
$user->getAttribute('email', ''),
$user->getAttribute('name', ''),
$user->getAttribute('phone', '')
$user->getAttribute('phone', ''),
];
foreach ($user->getAttribute('labels', []) as $label) {
@ -585,36 +558,33 @@ Database::addFilter(
Database::addFilter(
'subQueryTargets',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('targets', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBQUERY)
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
);
Database::addFilter(
'subQueryTopicTargets',
function (mixed $value) {
return;
},
function (mixed $value) {},
function (mixed $value, Document $document, Database $database) {
$targetIds = Authorization::skip(fn () => \array_map(
fn ($document) => $document->getAttribute('targetInternalId'),
$database->find('subscribers', [
Query::equal('topicInternalId', [$document->getInternalId()]),
Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY)
Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY),
])
));
if (\count($targetIds) > 0) {
return $database->skipValidation(fn () => $database->find('targets', [
Query::equal('$internalId', $targetIds)
Query::equal('$internalId', $targetIds),
]));
}
return [];
}
);
@ -626,7 +596,7 @@ Database::addFilter(
$provider->getId(),
$provider->getAttribute('name', ''),
$provider->getAttribute('provider', ''),
$provider->getAttribute('type', '')
$provider->getAttribute('type', ''),
];
$search = \implode(' ', \array_filter($searchValues));
@ -698,6 +668,7 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () {
Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) {
$elements = $attribute['formatOptions']['elements'];
return new WhiteList($elements, true);
}, Database::VAR_STRING);
@ -712,12 +683,14 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () {
Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) {
$min = $attribute['formatOptions']['min'] ?? -INF;
$max = $attribute['formatOptions']['max'] ?? INF;
return new Range($min, $max, Range::TYPE_INTEGER);
}, Database::VAR_INTEGER);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) {
$min = $attribute['formatOptions']['min'] ?? -INF;
$max = $attribute['formatOptions']['max'] ?? INF;
return new Range($min, $max, Range::TYPE_FLOAT);
}, Database::VAR_FLOAT);
@ -734,12 +707,12 @@ $register->set('logger', function () {
}
if (! Logger::hasProvider($providerName)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled");
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Logging provider not supported. Logging is disabled');
}
// Old Sentry Format conversion. Fallback until the old syntax is completely deprecated.
if (str_contains($providerConfig, ';') && strtolower($providerName) == 'sentry') {
$configChunks = \explode(";", $providerConfig);
$configChunks = \explode(';', $providerConfig);
$sentryKey = $configChunks[0];
$projectId = $configChunks[1];
@ -749,6 +722,7 @@ $register->set('logger', function () {
$classname = '\\Utopia\\Logger\\Adapter\\'.\ucfirst($providerName);
$adapter = new $classname($providerConfig);
return new Logger($adapter);
});
$register->set('pools', function () {
@ -845,7 +819,7 @@ $register->set('pools', function () {
$dsnDatabase = $dsn->getPath();
if (! in_array($dsnScheme, $schemes)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme");
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid console database scheme');
}
/**
@ -859,13 +833,13 @@ $register->set('pools', function () {
'mysql',
'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array(
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [
PDO::ATTR_TIMEOUT => 3, // Seconds
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => true
));
PDO::ATTR_STRINGIFY_FETCHES => true,
]);
});
},
'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) {
@ -910,7 +884,7 @@ $register->set('pools', function () {
break;
default:
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation.");
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Server error: Missing adapter implementation.');
}
return $adapter;
@ -976,6 +950,7 @@ $register->set('passwordsDictionary', function () {
$content = \file_get_contents(__DIR__.'/assets/security/10k-common-passwords');
$content = explode("\n", $content);
$content = array_flip($content);
return $content;
});
$register->set('promiseAdapter', function () {
@ -1131,12 +1106,11 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Database $dbForConsole */
/** @var string $mode */
Authorization::setDefaultStatus(true);
Auth::setCookieName('a_session_'.$project->getId());
if (APP_MODE_ADMIN === $mode) {
if ($mode === APP_MODE_ADMIN) {
Auth::setCookieName('a_session_'.$console->getId());
}
@ -1173,7 +1147,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
Auth::$unique = $session['id'] ?? '';
Auth::$secret = $session['secret'] ?? '';
if (APP_MODE_ADMIN !== $mode) {
if ($mode !== APP_MODE_ADMIN) {
if ($project->isEmpty()) {
$user = new Document([]);
} else {
@ -1194,7 +1168,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
$user = new Document([]);
}
if (APP_MODE_ADMIN === $mode) {
if ($mode === APP_MODE_ADMIN) {
if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
} else {
@ -1235,7 +1209,6 @@ App::setResource('project', function ($dbForConsole, $request, $console) {
/** @var Appwrite\Utopia\Request $request */
/** @var Utopia\Database\Database $dbForConsole */
/** @var Utopia\Database\Document $console */
$projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', ''));
if (empty($projectId) || $projectId === 'console') {
@ -1265,7 +1238,6 @@ App::setResource('session', function (Document $user) {
}
}
return;
}, ['user']);
App::setResource('console', function () {
@ -1303,7 +1275,7 @@ App::setResource('console', function () {
'oAuthProviders' => [
'githubEnabled' => true,
'githubSecret' => System::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''),
'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '')
'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', ''),
],
]);
}, []);
@ -1339,7 +1311,8 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole,
$dsn = new DSN('mysql://'.$project->getAttribute('database'));
}
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
@ -1392,7 +1365,8 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS);
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
@ -1408,6 +1382,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()];
$configure($database);
return $database;
}
@ -1432,8 +1407,7 @@ App::setResource('cache', function (Group $pools) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
->getResource();
}
return new Cache(new Sharding($adapters));
@ -1484,6 +1458,7 @@ function getDevice($root): Device
case STORAGE::DEVICE_DO_SPACES:
$device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl);
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
return $device;
case Storage::DEVICE_BACKBLAZE:
return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl);
@ -1506,6 +1481,7 @@ function getDevice($root): Device
$s3Region = System::getEnv('_APP_STORAGE_S3_REGION', '');
$s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', '');
$s3Acl = 'private';
return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
case Storage::DEVICE_DO_SPACES:
$doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', '');
@ -1515,6 +1491,7 @@ function getDevice($root): Device
$doSpacesAcl = 'private';
$device = new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
return $device;
case Storage::DEVICE_BACKBLAZE:
$backblazeAccessKey = System::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', '');
@ -1522,6 +1499,7 @@ function getDevice($root): Device
$backblazeRegion = System::getEnv('_APP_STORAGE_BACKBLAZE_REGION', '');
$backblazeBucket = System::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', '');
$backblazeAcl = 'private';
return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl);
case Storage::DEVICE_LINODE:
$linodeAccessKey = System::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', '');
@ -1529,6 +1507,7 @@ function getDevice($root): Device
$linodeRegion = System::getEnv('_APP_STORAGE_LINODE_REGION', '');
$linodeBucket = System::getEnv('_APP_STORAGE_LINODE_BUCKET', '');
$linodeAcl = 'private';
return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl);
case Storage::DEVICE_WASABI:
$wasabiAccessKey = System::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', '');
@ -1536,6 +1515,7 @@ function getDevice($root): Device
$wasabiRegion = System::getEnv('_APP_STORAGE_WASABI_REGION', '');
$wasabiBucket = System::getEnv('_APP_STORAGE_WASABI_BUCKET', '');
$wasabiAcl = 'private';
return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl);
}
}
@ -1562,7 +1542,6 @@ App::setResource('passwordsDictionary', function ($register) {
return $register->get('passwordsDictionary');
}, ['register']);
App::setResource('servers', function () {
$platforms = Config::getParam('platforms');
$server = $platforms[APP_PLATFORM_SERVER];
@ -1667,18 +1646,21 @@ App::setResource('schema', function ($utopia, $dbForProject) {
App::setResource('contributors', function () {
$path = 'app/config/contributors.json';
$list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : [];
return $list;
});
App::setResource('employees', function () {
$path = 'app/config/employees.json';
$list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : [];
return $list;
});
App::setResource('heroes', function () {
$path = 'app/config/heroes.json';
$list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : [];
return $list;
});
@ -1697,6 +1679,7 @@ App::setResource('requestTimestamp', function ($request) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid X-Appwrite-Timestamp header value');
}
}
return $requestTimestamp;
}, ['request']);
App::setResource('plan', function (array $plan = []) {

View file

@ -93,7 +93,8 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
$dsn = new DSN('mysql://'.$project->getAttribute('database'));
}
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
@ -126,7 +127,8 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()];
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
@ -150,7 +152,8 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
$databases[$dsn->getHost()] = $database;
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
@ -187,8 +190,7 @@ Server::setResource('cache', function (Registry $register) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
->getResource();
}
return new Cache(new Sharding($adapters));
@ -272,7 +274,6 @@ Server::setResource('deviceForCache', function (Document $project) {
return getDevice(APP_STORAGE_CACHE.'/app-'.$project->getId());
}, ['project']);
$pools = $register->get('pools');
$platform = new Appwrite();
$args = $platform->getEnv('argv');
@ -302,7 +303,7 @@ try {
'workersNum' => System::getEnv('_APP_WORKERS_NUM', 1),
'connection' => $pools->get('queue')->pop()->getResource(),
'workerName' => strtolower($workerName) ?? null,
'queueName' => $queueName
'queueName' => $queueName,
]);
} catch (\Throwable $e) {
Console::error($e->getMessage().', File: '.$e->getFile().', Line: '.$e->getLine());
@ -329,7 +330,7 @@ $worker
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
if ($logger) {
$log->setNamespace("appwrite-worker");
$log->setNamespace('appwrite-worker');
$log->setServer(\gethostname());
$log->setVersion($version);
$log->setType(Log::TYPE_ERROR);

View file

@ -166,11 +166,8 @@ class Deletes extends Action
}
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @param string $datetime
* @param Document|null $document
* @return void
*
* @throws Authorization
* @throws Conflict
* @throws Restricted
@ -193,6 +190,7 @@ class Deletes extends Action
if ($project->isEmpty()) {
$dbForConsole->deleteDocument('schedules', $document->getId());
Console::success('Deleted schedule for deleted project '.$document->getAttribute('projectId'));
return;
}
@ -223,31 +221,26 @@ class Deletes extends Action
}
/**
* @param Document $project
* @param callable $getProjectDB
* @param Document $topic
* @throws Exception
*/
private function deleteTopic(Document $project, callable $getProjectDB, Document $topic)
{
if ($topic->isEmpty()) {
Console::error('Failed to delete subscribers. Topic not found');
return;
}
$this->deleteByGroup(
'subscribers',
[
Query::equal('topicInternalId', [$topic->getInternalId()])
Query::equal('topicInternalId', [$topic->getInternalId()]),
],
$getProjectDB($project)
);
}
/**
* @param Document $project
* @param callable $getProjectDB
* @param Document $target
* @throws Exception
*/
private function deleteTargetSubscribers(Document $project, callable $getProjectDB, Document $target): void
@ -259,7 +252,7 @@ class Deletes extends Action
$this->deleteByGroup(
'subscribers',
[
Query::equal('targetInternalId', [$target->getInternalId()])
Query::equal('targetInternalId', [$target->getInternalId()]),
],
$dbForProject,
function (Document $subscriber) use ($dbForProject, $target) {
@ -285,10 +278,8 @@ class Deletes extends Action
}
/**
* @param Document $project
* @param callable $getProjectDB
* @param Document $target
* @return void
*
* @throws Exception
*/
private function deleteExpiredTargets(Document $project, callable $getProjectDB): void
@ -296,7 +287,7 @@ class Deletes extends Action
$this->deleteByGroup(
'targets',
[
Query::equal('expired', [true])
Query::equal('expired', [true]),
],
$getProjectDB($project),
function (Document $target) use ($getProjectDB, $project) {
@ -310,7 +301,7 @@ class Deletes extends Action
$this->deleteByGroup(
'targets',
[
Query::equal('sessionInternalId', [$session->getInternalId()])
Query::equal('sessionInternalId', [$session->getInternalId()]),
],
$getProjectDB($project),
function (Document $target) use ($getProjectDB, $project) {
@ -320,15 +311,10 @@ class Deletes extends Action
}
/**
* @param Document $project
* @param callable $getProjectDB
* @param string $resource
* @return void
* @throws Authorization
* @param string|null $resourceType
* @throws Exception
*/
private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, string $resourceType = null): void
private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, ?string $resourceType = null): void
{
$projectId = $project->getId();
$dbForProject = $getProjectDB($project);
@ -360,10 +346,7 @@ class Deletes extends Action
/**
* Document $project
* @param Document $project
* @param callable $getProjectDB
* @param string $datetime
* @return void
*
* @throws Exception
*/
private function deleteCacheByDate(Document $project, callable $getProjectDB, string $datetime): void
@ -397,9 +380,7 @@ class Deletes extends Action
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @param string $hourlyUsageRetentionDatetime
* @return void
*
* @throws Exception
*/
private function deleteUsageStats(Document $project, callable $getProjectDB, string $hourlyUsageRetentionDatetime): void
@ -413,10 +394,8 @@ class Deletes extends Action
}
/**
* @param callable $getProjectDB
* @param Document $document teams document
* @param Document $project
* @return void
*
* @throws Exception
*/
private function deleteMemberships(callable $getProjectDB, Document $document, Document $project): void
@ -428,7 +407,7 @@ class Deletes extends Action
$this->deleteByGroup(
'memberships',
[
Query::equal('teamInternalId', [$teamInternalId])
Query::equal('teamInternalId', [$teamInternalId]),
],
$dbForProject,
function (Document $membership) use ($dbForProject) {
@ -439,9 +418,6 @@ class Deletes extends Action
}
/**
* @param Database $dbForConsole
* @param Document $document
* @return void
* @throws Authorization
* @throws DatabaseException
* @throws Conflict
@ -452,7 +428,7 @@ class Deletes extends Action
{
$projects = $dbForConsole->find('projects', [
Query::equal('teamInternalId', [$document->getInternalId()])
Query::equal('teamInternalId', [$document->getInternalId()]),
]);
foreach ($projects as $project) {
$this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $project);
@ -461,14 +437,6 @@ class Deletes extends Action
}
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @param Device $deviceForFiles
* @param Device $deviceForFunctions
* @param Device $deviceForBuilds
* @param Device $deviceForCache
* @param Document $document
* @return void
* @throws Exception
* @throws Authorization
* @throws DatabaseException
@ -498,14 +466,15 @@ class Deletes extends Action
$collections = $dbForProject->listCollections($limit);
foreach ($collections as $collection) {
if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '') || !\in_array($collection->getId(), $projectCollectionIds)) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (! in_array($dsn->getHost(), $sharedTablesKeys) || ! \in_array($collection->getId(), $projectCollectionIds)) {
$dbForProject->deleteCollection($collection->getId());
} else {
$this->deleteByGroup($collection->getId(), [], database: $dbForProject);
}
}
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
$collectionsIds = \array_map(fn ($collection) => $collection->getId(), $collections);
if (empty(\array_diff($collectionsIds, $projectCollectionIds))) {
@ -518,29 +487,29 @@ class Deletes extends Action
// Delete Platforms
$this->deleteByGroup('platforms', [
Query::equal('projectInternalId', [$projectInternalId])
Query::equal('projectInternalId', [$projectInternalId]),
], $dbForConsole);
// Delete project and function rules
$this->deleteByGroup('rules', [
Query::equal('projectInternalId', [$projectInternalId])
Query::equal('projectInternalId', [$projectInternalId]),
], $dbForConsole, function (Document $document) use ($dbForConsole) {
$this->deleteRule($dbForConsole, $document);
});
// Delete Keys
$this->deleteByGroup('keys', [
Query::equal('projectInternalId', [$projectInternalId])
Query::equal('projectInternalId', [$projectInternalId]),
], $dbForConsole);
// Delete Webhooks
$this->deleteByGroup('webhooks', [
Query::equal('projectInternalId', [$projectInternalId])
Query::equal('projectInternalId', [$projectInternalId]),
], $dbForConsole);
// Delete VCS Installations
$this->deleteByGroup('installations', [
Query::equal('projectInternalId', [$projectInternalId])
Query::equal('projectInternalId', [$projectInternalId]),
], $dbForConsole);
// Delete VCS Repositories
@ -554,7 +523,8 @@ class Deletes extends Action
], $dbForConsole);
// Delete metadata table
if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (! in_array($dsn, $sharedTablesKeys)) {
$dbForProject->deleteCollection('_metadata');
} else {
$this->deleteByGroup('_metadata', [], $dbForProject);
@ -568,10 +538,8 @@ class Deletes extends Action
}
/**
* @param callable $getProjectDB
* @param Document $document user document
* @param Document $project
* @return void
*
* @throws Exception
*/
private function deleteUser(callable $getProjectDB, Document $document, Document $project): void
@ -582,14 +550,14 @@ class Deletes extends Action
// Delete all sessions of this user from the sessions table and update the sessions field of the user record
$this->deleteByGroup('sessions', [
Query::equal('userInternalId', [$userInternalId])
Query::equal('userInternalId', [$userInternalId]),
], $dbForProject);
$dbForProject->purgeCachedDocument('users', $userId);
// Delete Memberships and decrement team membership counts
$this->deleteByGroup('memberships', [
Query::equal('userInternalId', [$userInternalId])
Query::equal('userInternalId', [$userInternalId]),
], $dbForProject, function (Document $document) use ($dbForProject) {
if ($document->getAttribute('confirm')) { // Count only confirmed members
$teamId = $document->getAttribute('teamId');
@ -602,19 +570,19 @@ class Deletes extends Action
// Delete tokens
$this->deleteByGroup('tokens', [
Query::equal('userInternalId', [$userInternalId])
Query::equal('userInternalId', [$userInternalId]),
], $dbForProject);
// Delete identities
$this->deleteByGroup('identities', [
Query::equal('userInternalId', [$userInternalId])
Query::equal('userInternalId', [$userInternalId]),
], $dbForProject);
// Delete targets
$this->deleteByGroup(
'targets',
[
Query::equal('userInternalId', [$userInternalId])
Query::equal('userInternalId', [$userInternalId]),
],
$dbForProject,
function (Document $target) use ($getProjectDB, $project) {
@ -625,9 +593,7 @@ class Deletes extends Action
/**
* @param database $dbForConsole
* @param callable $getProjectDB
* @param string $datetime
* @return void
*
* @throws Exception
*/
private function deleteExecutionLogs(Document $project, callable $getProjectDB, string $datetime): void
@ -635,14 +601,13 @@ class Deletes extends Action
$dbForProject = $getProjectDB($project);
// Delete Executions
$this->deleteByGroup('executions', [
Query::lessThan('$createdAt', $datetime)
Query::lessThan('$createdAt', $datetime),
], $dbForProject);
}
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @return void
*
* @throws Exception|Throwable
*/
private function deleteExpiredSessions(Document $project, callable $getProjectDB): void
@ -653,36 +618,32 @@ class Deletes extends Action
// Delete Sessions
$this->deleteByGroup('sessions', [
Query::lessThan('$createdAt', $expired)
Query::lessThan('$createdAt', $expired),
], $dbForProject);
}
/**
* @param Database $dbForConsole
* @param string $datetime
* @return void
* @throws Exception
*/
private function deleteRealtimeUsage(Database $dbForConsole, string $datetime): void
{
// Delete Dead Realtime Logs
$this->deleteByGroup('realtime', [
Query::lessThan('timestamp', $datetime)
Query::lessThan('timestamp', $datetime),
], $dbForConsole);
}
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @param string $datetime
* @return void
*
* @throws Exception
*/
private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention): void
{
$projectId = $project->getId();
$dbForProject = $getProjectDB($project);
$timeLimit = new TimeLimit("", 0, 1, $dbForProject);
$timeLimit = new TimeLimit('', 0, 1, $dbForProject);
$abuse = new Abuse($timeLimit);
try {
@ -694,9 +655,8 @@ class Deletes extends Action
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @param string $datetime
* @return void
*
* @throws Exception
*/
private function deleteAuditLogs(Document $project, callable $getProjectDB, string $auditRetention): void
@ -713,10 +673,6 @@ class Deletes extends Action
}
/**
* @param callable $getProjectDB
* @param string $resource
* @param Document $project
* @return void
* @throws Exception
*/
private function deleteAuditLogsByResource(callable $getProjectDB, string $resource, Document $project): void
@ -724,17 +680,13 @@ class Deletes extends Action
$dbForProject = $getProjectDB($project);
$this->deleteByGroup(Audit::COLLECTION, [
Query::equal('resource', [$resource])
Query::equal('resource', [$resource]),
], $dbForProject);
}
/**
* @param callable $getProjectDB
* @param Device $deviceForFunctions
* @param Device $deviceForBuilds
* @param Document $document function document
* @param Document $project
* @return void
*
* @throws Exception
*/
private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project): void
@ -747,32 +699,32 @@ class Deletes extends Action
/**
* Delete rules
*/
Console::info("Deleting rules for function " . $functionId);
Console::info('Deleting rules for function '.$functionId);
$this->deleteByGroup('rules', [
Query::equal('resourceType', ['function']),
Query::equal('resourceInternalId', [$functionInternalId]),
Query::equal('projectInternalId', [$project->getInternalId()])
], $dbForConsole, function (Document $document) use ($project, $dbForConsole) {
Query::equal('projectInternalId', [$project->getInternalId()]),
], $dbForConsole, function (Document $document) use ($dbForConsole) {
$this->deleteRule($dbForConsole, $document);
});
/**
* Delete Variables
*/
Console::info("Deleting variables for function " . $functionId);
Console::info('Deleting variables for function '.$functionId);
$this->deleteByGroup('variables', [
Query::equal('resourceType', ['function']),
Query::equal('resourceInternalId', [$functionInternalId])
Query::equal('resourceInternalId', [$functionInternalId]),
], $dbForProject);
/**
* Delete Deployments
*/
Console::info("Deleting deployments for function " . $functionId);
Console::info('Deleting deployments for function '.$functionId);
$deploymentInternalIds = [];
$this->deleteByGroup('deployments', [
Query::equal('resourceInternalId', [$functionInternalId])
Query::equal('resourceInternalId', [$functionInternalId]),
], $dbForProject, function (Document $document) use ($deviceForFunctions, &$deploymentInternalIds) {
$deploymentInternalIds[] = $document->getInternalId();
$this->deleteDeploymentFiles($deviceForFunctions, $document);
@ -781,11 +733,11 @@ class Deletes extends Action
/**
* Delete builds
*/
Console::info("Deleting builds for function " . $functionId);
Console::info('Deleting builds for function '.$functionId);
foreach ($deploymentInternalIds as $deploymentInternalId) {
$this->deleteByGroup('builds', [
Query::equal('deploymentInternalId', [$deploymentInternalId])
Query::equal('deploymentInternalId', [$deploymentInternalId]),
], $dbForProject, function (Document $document) use ($deviceForBuilds) {
$this->deleteBuildFiles($deviceForBuilds, $document);
});
@ -794,15 +746,15 @@ class Deletes extends Action
/**
* Delete Executions
*/
Console::info("Deleting executions for function " . $functionId);
Console::info('Deleting executions for function '.$functionId);
$this->deleteByGroup('executions', [
Query::equal('functionInternalId', [$functionInternalId])
Query::equal('functionInternalId', [$functionInternalId]),
], $dbForProject);
/**
* Delete VCS Repositories and VCS Comments
*/
Console::info("Deleting VCS repositories and comments linked to function " . $functionId);
Console::info('Deleting VCS repositories and comments linked to function '.$functionId);
$this->deleteByGroup('repositories', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('resourceInternalId', [$functionInternalId]),
@ -819,26 +771,22 @@ class Deletes extends Action
/**
* Request executor to delete all deployment containers
*/
Console::info("Requesting executor to delete all deployment containers for function " . $functionId);
Console::info('Requesting executor to delete all deployment containers for function '.$functionId);
$this->deleteRuntimes($getProjectDB, $document, $project);
}
/**
* @param Device $device
* @param Document $deployment
* @return void
*/
private function deleteDeploymentFiles(Device $device, Document $deployment): void
{
$deploymentId = $deployment->getId();
$deploymentPath = $deployment->getAttribute('path', '');
if (empty($deploymentPath)) {
Console::info("No deployment files for deployment " . $deploymentId);
Console::info('No deployment files for deployment '.$deploymentId);
return;
}
Console::info("Deleting deployment files for deployment " . $deploymentId);
Console::info('Deleting deployment files for deployment '.$deploymentId);
try {
if ($device->delete($deploymentPath, true)) {
@ -855,18 +803,14 @@ class Deletes extends Action
}
}
/**
* @param Device $device
* @param Document $build
* @return void
*/
private function deleteBuildFiles(Device $device, Document $build): void
{
$buildId = $build->getId();
$buildPath = $build->getAttribute('path', '');
if (empty($buildPath)) {
Console::info("No build files for build " . $buildId);
Console::info('No build files for build '.$buildId);
return;
}
@ -886,12 +830,6 @@ class Deletes extends Action
}
/**
* @param callable $getProjectDB
* @param Device $deviceForFunctions
* @param Device $deviceForBuilds
* @param Document $document
* @param Document $project
* @return void
* @throws Exception
*/
private function deleteDeployment(callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project): void
@ -909,10 +847,10 @@ class Deletes extends Action
/**
* Delete builds
*/
Console::info("Deleting builds for deployment " . $deploymentId);
Console::info('Deleting builds for deployment '.$deploymentId);
$this->deleteByGroup('builds', [
Query::equal('deploymentInternalId', [$deploymentInternalId])
Query::equal('deploymentInternalId', [$deploymentInternalId]),
], $dbForProject, function (Document $document) use ($deviceForBuilds) {
$this->deleteBuildFiles($deviceForBuilds, $document);
});
@ -920,7 +858,7 @@ class Deletes extends Action
/**
* Request executor to delete all deployment containers
*/
Console::info("Requesting executor to delete deployment container for deployment " . $deploymentId);
Console::info('Requesting executor to delete deployment container for deployment '.$deploymentId);
$this->deleteRuntimes($getProjectDB, $document, $project);
}
@ -928,9 +866,8 @@ class Deletes extends Action
* @param Document $document to be deleted
* @param Database $database to delete it from
* @param callable|null $callback to perform after document is deleted
* @return void
*/
private function deleteById(Document $document, Database $database, callable $callback = null): void
private function deleteById(Document $document, Database $database, ?callable $callback = null): void
{
if ($database->deleteDocument($document->getCollection(), $document->getId())) {
Console::success('Deleted document "'.$document->getId().'" successfully');
@ -945,13 +882,10 @@ class Deletes extends Action
/**
* @param string $collection collectionID
* @param array $queries
* @param Database $database
* @param callable|null $callback
* @return void
*
* @throws Exception
*/
private function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
private function deleteByGroup(string $collection, array $queries, Database $database, ?callable $callback = null): void
{
$count = 0;
$chunk = 0;
@ -967,6 +901,7 @@ class Deletes extends Action
$results = $database->find($collection, [Query::limit($limit), ...$queries]);
} catch (DatabaseException $e) {
Console::error('Failed to find documents for collection '.$collection.': '.$e->getMessage());
return;
}
@ -982,18 +917,16 @@ class Deletes extends Action
$executionEnd = \microtime(true);
Console::info("Deleted {$count} document by group in " . ($executionEnd - $executionStart) . " seconds");
Console::info("Deleted {$count} document by group in ".($executionEnd - $executionStart).' seconds');
}
/**
* @param string $collection collectionID
* @param Query[] $queries
* @param Database $database
* @param callable|null $callback
* @return void
*
* @throws Exception
*/
private function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
private function listByGroup(string $collection, array $queries, Database $database, ?callable $callback = null): void
{
$count = 0;
$chunk = 0;
@ -1031,13 +964,11 @@ class Deletes extends Action
$executionEnd = \microtime(true);
Console::info("Listed {$count} document by group in " . ($executionEnd - $executionStart) . " seconds");
Console::info("Listed {$count} document by group in ".($executionEnd - $executionStart).' seconds');
}
/**
* @param Database $dbForConsole
* @param Document $document rule document
* @return void
*/
private function deleteRule(Database $dbForConsole, Document $document): void
{
@ -1061,13 +992,6 @@ class Deletes extends Action
}
}
/**
* @param callable $getProjectDB
* @param Device $deviceForFiles
* @param Document $document
* @param Document $project
* @return void
*/
private function deleteBucket(callable $getProjectDB, Device $deviceForFiles, Document $document, Document $project): void
{
$dbForProject = $getProjectDB($project);
@ -1078,11 +1002,6 @@ class Deletes extends Action
}
/**
* @param Database $dbForConsole
* @param callable $getProjectDB
* @param Document $document
* @param Document $project
* @return void
* @throws Exception
*/
private function deleteInstallation(Database $dbForConsole, callable $getProjectDB, Document $document, Document $project): void
@ -1090,7 +1009,7 @@ class Deletes extends Action
$dbForProject = $getProjectDB($project);
$this->listByGroup('functions', [
Query::equal('installationInternalId', [$document->getInternalId()])
Query::equal('installationInternalId', [$document->getInternalId()]),
], $dbForProject, function ($function) use ($dbForProject, $dbForConsole) {
$dbForConsole->deleteDocument('repositories', $function->getAttribute('repositoryId'));
@ -1108,10 +1027,8 @@ class Deletes extends Action
}
/**
* @param callable $getProjectDB
* @param ?Document $function
* @param Document $project
* @return void
*
* @throws Exception
*/
private function deleteRuntimes(callable $getProjectDB, ?Document $function, Document $project): void