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:56:45 +03:00
parent 6b3051f131
commit d6dfe7dfb3
2 changed files with 66 additions and 69 deletions

View file

@ -133,6 +133,12 @@ App::post('/v1/projects')
throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project.");
}
var_dump([
'_APP_DATABASE_SHARED_TABLES' => System::getEnv('_APP_DATABASE_SHARED_TABLES', ''),
'region' => $region,
'dsn' => $dsn,
]);
// TODO: Temporary until all projects are using shared tables.
$sharedTablesKeys = explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (in_array($dsn->getHost(), $sharedTablesKeys)) {
@ -146,12 +152,6 @@ App::post('/v1/projects')
}
}
var_dump([
'_APP_DATABASE_SHARED_TABLES' => System::getEnv('_APP_DATABASE_SHARED_TABLES', ''),
'region' => $region,
'dsn' => $dsn,
]);
try {
$project = $dbForConsole->createDocument('projects', new Document([
'$id' => $projectId,

View file

@ -43,7 +43,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar
$replace = $parts[1] ?? '';
$params = match ($namespace) {
'user' => (array)$user,
'user' => (array) $user,
'request' => $requestParams,
default => $responsePayload,
};
@ -52,6 +52,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar
$label = \str_replace($find, $params[$replace], $label);
}
}
return $label;
};
@ -88,13 +89,12 @@ $databaseListener = function (string $event, Document $document, Document $proje
->addReduce($document);
}
break;
case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections
case str_starts_with($document->getCollection(), 'database_') && ! str_contains($document->getCollection(), 'collection'): //collections
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$queueForUsage
->addMetric(METRIC_COLLECTIONS, $value) // per project
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value) // per database
;
->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value); // per database
if ($event === Database::EVENT_DOCUMENT_DELETE) {
$queueForUsage
@ -103,7 +103,7 @@ $databaseListener = function (string $event, Document $document, Document $proje
break;
case str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_'): //documents
$parts = explode('_', $document->getCollection());
$databaseInternalId = $parts[1] ?? 0;
$databaseInternalId = $parts[1] ?? 0;
$collectionInternalId = $parts[3] ?? 0;
$queueForUsage
->addMetric(METRIC_DOCUMENTS, $value) // per project
@ -120,7 +120,7 @@ $databaseListener = function (string $event, Document $document, Document $proje
break;
case str_starts_with($document->getCollection(), 'bucket_'): // files
$parts = explode('_', $document->getCollection());
$bucketInternalId = $parts[1];
$bucketInternalId = $parts[1];
$queueForUsage
->addMetric(METRIC_FILES, $value) // per project
->addMetric(METRIC_FILES_STORAGE, $document->getAttribute('sizeOriginal') * $value) // per project
@ -197,9 +197,9 @@ App::init()
$authKey = $request->getHeader('x-appwrite-key', '');
if (!empty($authKey)) { // API Key authentication
if (! empty($authKey)) { // API Key authentication
// Do not allow API key and session to be set at the same time
if (!$user->isEmpty()) {
if (! $user->isEmpty()) {
throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET);
}
@ -209,7 +209,7 @@ App::init()
$user = new Document([
'$id' => '',
'status' => true,
'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(),
'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(),
'password' => '',
'name' => $project->getAttribute('name', 'Untitled'),
]);
@ -218,7 +218,7 @@ App::init()
$scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', []));
$expire = $key->getAttribute('expire');
if (!empty($expire) && $expire < DateTime::formatTz(DateTime::now())) {
if (! empty($expire) && $expire < DateTime::formatTz(DateTime::now())) {
throw new Exception(Exception::PROJECT_KEY_EXPIRED);
}
@ -236,7 +236,7 @@ App::init()
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
if ($sdkValidator->isValid($sdk)) {
$sdks = $key->getAttribute('sdks', []);
if (!in_array($sdk, $sdks)) {
if (! in_array($sdk, $sdks)) {
array_push($sdks, $sdk);
$key->setAttribute('sdks', $sdks);
@ -256,24 +256,24 @@ App::init()
}
$service = $route->getLabel('sdk.namespace', '');
if (!empty($service)) {
if (! empty($service)) {
if (
array_key_exists($service, $project->getAttribute('services', []))
&& !$project->getAttribute('services', [])[$service]
&& !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles()))
&& ! $project->getAttribute('services', [])[$service]
&& ! (Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles()))
) {
throw new Exception(Exception::GENERAL_SERVICE_DISABLED);
}
}
if (!\in_array($scope, $scopes)) {
if (! \in_array($scope, $scopes)) {
if ($project->isEmpty()) { // Check if permission is denied because project is missing
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')');
throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User').' (role: '.\strtolower($roles[$role]['label']).') missing scope ('.$scope.')');
}
if (false === $user->getAttribute('status')) { // Account is blocked
if ($user->getAttribute('status') === false) { // Account is blocked
throw new Exception(Exception::USER_BLOCKED);
}
@ -288,7 +288,7 @@ App::init()
$hasMoreFactors = $hasVerifiedEmail || $hasVerifiedPhone || $hasVerifiedAuthenticator;
$minimumFactors = ($mfaEnabled && $hasMoreFactors) ? 2 : 1;
if (!in_array('mfa', $route->getGroups())) {
if (! in_array('mfa', $route->getGroups())) {
if ($session && \count($session->getAttribute('factors', [])) < $minimumFactors) {
throw new Exception(Exception::USER_MORE_FACTORS_REQUIRED);
}
@ -317,8 +317,8 @@ App::init()
if (
array_key_exists('rest', $project->getAttribute('apis', []))
&& !$project->getAttribute('apis', [])['rest']
&& !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles()))
&& ! $project->getAttribute('apis', [])['rest']
&& ! (Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles()))
) {
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
}
@ -329,7 +329,7 @@ App::init()
$abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}');
$timeLimitArray = [];
$abuseKeyLabel = (!is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel;
$abuseKeyLabel = (! is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel;
foreach ($abuseKeyLabel as $abuseKey) {
$start = $request->getContentRangeStart();
@ -340,7 +340,7 @@ App::init()
->setParam('{userId}', $user->getId())
->setParam('{userAgent}', $request->getUserAgent(''))
->setParam('{ip}', $request->getIP())
->setParam('{url}', $request->getHostname() . $route->getPath())
->setParam('{url}', $request->getHostname().$route->getPath())
->setParam('{method}', $request->getMethod())
->setParam('{chunkId}', (int) ($start / ($end + 1 - $start)));
$timeLimitArray[] = $timeLimit;
@ -354,8 +354,8 @@ App::init()
foreach ($timeLimitArray as $timeLimit) {
foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
if (!empty($value)) {
$timeLimit->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value);
if (! empty($value)) {
$timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value);
}
}
@ -376,8 +376,8 @@ App::init()
if (
$enabled // Abuse is enabled
&& !$isAppUser // User is not API key
&& !$isPrivilegedUser // User is not an admin
&& ! $isAppUser // User is not API key
&& ! $isPrivilegedUser // User is not an admin
&& $abuse->check() // Route is rate-limited
) {
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED);
@ -411,26 +411,26 @@ App::init()
$useCache = $route->getLabel('cache', false);
if ($useCache) {
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$key = md5($request->getURI().'*'.implode('*', $request->getParams()).'*'.APP_CACHE_BUSTER);
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$cache = new Cache(
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId())
new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$project->getId())
);
$timestamp = 60 * 60 * 24 * 30;
$data = $cache->load($key, $timestamp);
if (!empty($data) && !$cacheLog->isEmpty()) {
if (! empty($data) && ! $cacheLog->isEmpty()) {
$parts = explode('/', $cacheLog->getAttribute('resourceType'));
$type = $parts[0] ?? null;
if ($type === 'bucket') {
$bucketId = $parts[1] ?? null;
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && ! $isAPIKey && ! $isPrivilegedUser)) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
@ -438,17 +438,17 @@ App::init()
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
if (!$fileSecurity && !$valid) {
if (! $fileSecurity && ! $valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$parts = explode('/', $cacheLog->getAttribute('resource'));
$fileId = $parts[1] ?? null;
if ($fileSecurity && !$valid) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
if ($fileSecurity && ! $valid) {
$file = $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId);
} else {
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_'.$bucket->getInternalId(), $fileId));
}
if ($file->isEmpty()) {
@ -457,7 +457,7 @@ App::init()
}
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT')
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp).' GMT')
->addHeader('X-Appwrite-Cache', 'hit')
->setContentType($cacheLog->getAttribute('mimeType'))
->send($data);
@ -466,8 +466,7 @@ App::init()
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
->addHeader('Pragma', 'no-cache')
->addHeader('Expires', 0)
->addHeader('X-Appwrite-Cache', 'miss')
;
->addHeader('X-Appwrite-Cache', 'miss');
}
}
});
@ -481,7 +480,7 @@ App::init()
return;
}
if (!$user->isEmpty()) {
if (! $user->isEmpty()) {
throw new Exception(Exception::USER_SESSION_ALREADY_EXISTS);
}
});
@ -548,7 +547,7 @@ App::shutdown()
$responsePayload = $response->getPayload();
if (!empty($queueForEvents->getEvent())) {
if (! empty($queueForEvents->getEvent())) {
if (empty($queueForEvents->getPayload())) {
$queueForEvents->setPayload($responsePayload);
}
@ -597,7 +596,7 @@ App::shutdown()
roles: $target['roles'],
options: [
'permissionsChanged' => $target['permissionsChanged'],
'userId' => $queueForEvents->getParam('userId')
'userId' => $queueForEvents->getParam('userId'),
]
);
}
@ -610,24 +609,24 @@ App::shutdown()
* Audit labels
*/
$pattern = $route->getLabel('audits.resource', null);
if (!empty($pattern)) {
if (! empty($pattern)) {
$resource = $parseLabel($pattern, $responsePayload, $requestParams, $user);
if (!empty($resource) && $resource !== $pattern) {
if (! empty($resource) && $resource !== $pattern) {
$queueForAudits->setResource($resource);
}
}
if (!$user->isEmpty()) {
if (! $user->isEmpty()) {
$queueForAudits->setUser($user);
}
if (!empty($queueForAudits->getResource()) && !empty($queueForAudits->getUser()->getId())) {
if (! empty($queueForAudits->getResource()) && ! empty($queueForAudits->getUser()->getId())) {
/**
* audits.payload is switched to default true
* in order to auto audit payload for all endpoints
*/
$pattern = $route->getLabel('audits.payload', true);
if (!empty($pattern)) {
if (! empty($pattern)) {
$queueForAudits->setPayload($responsePayload);
}
@ -637,19 +636,19 @@ App::shutdown()
$queueForAudits->trigger();
}
if (!empty($queueForDeletes->getType())) {
if (! empty($queueForDeletes->getType())) {
$queueForDeletes->trigger();
}
if (!empty($queueForDatabase->getType())) {
if (! empty($queueForDatabase->getType())) {
$queueForDatabase->trigger();
}
if (!empty($queueForBuilds->getType())) {
if (! empty($queueForBuilds->getType())) {
$queueForBuilds->trigger();
}
if (!empty($queueForMessaging->getType())) {
if (! empty($queueForMessaging->getType())) {
$queueForMessaging->trigger();
}
@ -660,20 +659,20 @@ App::shutdown()
if ($useCache) {
$resource = $resourceType = null;
$data = $response->getPayload();
if (!empty($data['payload'])) {
if (! empty($data['payload'])) {
$pattern = $route->getLabel('cache.resource', null);
if (!empty($pattern)) {
if (! empty($pattern)) {
$resource = $parseLabel($pattern, $responsePayload, $requestParams, $user);
}
$pattern = $route->getLabel('cache.resourceType', null);
if (!empty($pattern)) {
if (! empty($pattern)) {
$resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user);
}
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
$key = md5($request->getURI().'*'.implode('*', $request->getParams()).'*'.APP_CACHE_BUSTER);
$signature = md5($data['payload']);
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$accessedAt = $cacheLog->getAttribute('accessedAt', '');
$now = DateTime::now();
if ($cacheLog->isEmpty()) {
@ -692,20 +691,18 @@ App::shutdown()
if ($signature !== $cacheLog->getAttribute('signature')) {
$cache = new Cache(
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId())
new Filesystem(APP_STORAGE_CACHE.DIRECTORY_SEPARATOR.'app-'.$project->getId())
);
$cache->save($key, $data['payload']);
}
}
}
if ($project->getId() !== 'console') {
if (!Auth::isPrivilegedUser(Authorization::getRoles())) {
if (! Auth::isPrivilegedUser(Authorization::getRoles())) {
$fileSize = 0;
$file = $request->getFiles('file');
if (!empty($file)) {
if (! empty($file)) {
$fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
}
@ -723,12 +720,12 @@ App::shutdown()
/**
* Update user last activity
*/
if (!$user->isEmpty()) {
if (! $user->isEmpty()) {
$accessedAt = $user->getAttribute('accessedAt', '');
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCCESS)) > $accessedAt) {
$user->setAttribute('accessedAt', DateTime::now());
if (APP_MODE_ADMIN !== $mode) {
if ($mode !== APP_MODE_ADMIN) {
$dbForProject->updateDocument('users', $user->getId(), $user);
} else {
$dbForConsole->updateDocument('users', $user->getId(), $user);