diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 8b89393f09..6de5a87ea2 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -69,7 +69,7 @@ Http::post('/v1/projects') ->param('projectId', '', new ProjectId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can\'t start with a special char. Max length is 36 chars.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('teamId', '', new UID(), 'Team unique ID.') - ->param('region', System::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn ($config) => !$config['disabled']))), 'Project Region.', true) + ->param('region', System::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn($config) => !$config['disabled']))), 'Project Region.', true) ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) ->param('logo', '', new Text(1024), 'Project logo.', true) ->param('url', '', new URL(), 'Project URL.', true) @@ -88,7 +88,6 @@ Http::post('/v1/projects') ->inject('authorization') ->inject('connections') ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForConsole, Cache $cache, array $pools, Hooks $hooks, Authorization $authorization, Connections $connections) { - $team = $dbForConsole->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -164,9 +163,7 @@ Http::post('/v1/projects') && System::getEnv('_APP_DATABASE_SHARED_TABLES', 'enabled') === 'enabled' && System::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' ) || - ( - $dsn === DATABASE_SHARED_TABLES - ) + ($dsn === DATABASE_SHARED_TABLES) ) { $schema = 'appwrite'; $database = 'appwrite'; @@ -180,7 +177,7 @@ Http::post('/v1/projects') // TODO: Allow overriding in development mode. Temporary until all projects are using shared tables. if ( - App::isDevelopment() + Http::isDevelopment() && System::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' && $request->getHeader('x-appwrited-share-tables', false) ) { @@ -231,7 +228,6 @@ Http::post('/v1/projects') throw new Exception(Exception::PROJECT_ALREADY_EXISTS); } - $dbForProject = new Database($adapter, $cache); try { $dsn = new DSN($dsn); } catch (\InvalidArgumentException) { @@ -239,8 +235,8 @@ Http::post('/v1/projects') $dsn = new DSN('mysql://' . $dsn); } - $pool = $pools['pools-database-'.$dsn->getHost()['pool']; - $connectionDsn = $pools['pools-database-'.$dsn->getHost()['dsn']; + $pool = $pools['pools-database-' . $dsn->getHost()]['pool']; + $connectionDsn = $pools['pools-database-' . $dsn->getHost()]['dsn']; $connection = $pool->get(); $connections->add($connection, $pool); @@ -298,7 +294,7 @@ Http::post('/v1/projects') // Hook allowing instant project mirroring during migration // Outside of migration, hook is not registered and has no effect - $hooks->trigger('afterProjectCreation', [ $project, $pools, $cache ]); + $hooks->trigger('afterProjectCreation', [$project, $pools, $cache]); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -320,7 +316,6 @@ Http::get('/v1/projects') ->inject('response') ->inject('dbForConsole') ->action(function (array $queries, string $search, Response $response, Database $dbForConsole) { - try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -372,7 +367,6 @@ Http::get('/v1/projects/:projectId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -406,25 +400,28 @@ Http::patch('/v1/projects/:projectId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('name', $name) - ->setAttribute('description', $description) - ->setAttribute('logo', $logo) - ->setAttribute('url', $url) - ->setAttribute('legalName', $legalName) - ->setAttribute('legalCountry', $legalCountry) - ->setAttribute('legalState', $legalState) - ->setAttribute('legalCity', $legalCity) - ->setAttribute('legalAddress', $legalAddress) - ->setAttribute('legalTaxId', $legalTaxId) - ->setAttribute('search', implode(' ', [$projectId, $name]))); + $project = $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('name', $name) + ->setAttribute('description', $description) + ->setAttribute('logo', $logo) + ->setAttribute('url', $url) + ->setAttribute('legalName', $legalName) + ->setAttribute('legalCountry', $legalCountry) + ->setAttribute('legalState', $legalState) + ->setAttribute('legalCity', $legalCity) + ->setAttribute('legalAddress', $legalAddress) + ->setAttribute('legalTaxId', $legalTaxId) + ->setAttribute('search', implode(' ', [$projectId, $name])) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -444,7 +441,6 @@ Http::patch('/v1/projects/:projectId/team') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $teamId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); $team = $dbForConsole->getDocument('teams', $teamId); @@ -508,12 +504,11 @@ Http::patch('/v1/projects/:projectId/service') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.') + ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -543,14 +538,13 @@ Http::patch('/v1/projects/:projectId/service/all') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $allServices = array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])); + $allServices = array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])); $services = []; foreach ($allServices as $service) { @@ -578,7 +572,6 @@ Http::patch('/v1/projects/:projectId/api') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $api, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -608,7 +601,6 @@ Http::patch('/v1/projects/:projectId/api/all') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -645,7 +637,6 @@ Http::patch('/v1/projects/:projectId/oauth2') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -686,7 +677,6 @@ Http::patch('/v1/projects/:projectId/auth/limit') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -696,8 +686,12 @@ Http::patch('/v1/projects/:projectId/auth/limit') $auths = $project->getAttribute('auths', []); $auths['limit'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths)); + $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('auths', $auths) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -717,7 +711,6 @@ Http::patch('/v1/projects/:projectId/auth/duration') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $duration, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -727,8 +720,12 @@ Http::patch('/v1/projects/:projectId/auth/duration') $auths = $project->getAttribute('auths', []); $auths['duration'] = $duration; - $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths)); + $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('auths', $auths) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -749,7 +746,6 @@ Http::patch('/v1/projects/:projectId/auth/:method') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); $authConfig = Config::getParam('auth')[$method] ?? []; $authKey = $authConfig['key'] ?? ''; @@ -782,7 +778,6 @@ Http::patch('/v1/projects/:projectId/auth/password-history') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -792,8 +787,12 @@ Http::patch('/v1/projects/:projectId/auth/password-history') $auths = $project->getAttribute('auths', []); $auths['passwordHistory'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths)); + $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('auths', $auths) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -813,7 +812,6 @@ Http::patch('/v1/projects/:projectId/auth/password-dictionary') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -823,8 +821,12 @@ Http::patch('/v1/projects/:projectId/auth/password-dictionary') $auths = $project->getAttribute('auths', []); $auths['passwordDictionary'] = $enabled; - $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths)); + $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('auths', $auths) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -844,7 +846,6 @@ Http::patch('/v1/projects/:projectId/auth/personal-data') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -854,8 +855,12 @@ Http::patch('/v1/projects/:projectId/auth/personal-data') $auths = $project->getAttribute('auths', []); $auths['personalDataCheck'] = $enabled; - $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths)); + $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('auths', $auths) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -875,7 +880,6 @@ Http::patch('/v1/projects/:projectId/auth/max-sessions') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -885,8 +889,12 @@ Http::patch('/v1/projects/:projectId/auth/max-sessions') $auths = $project->getAttribute('auths', []); $auths['maxSessions'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths)); + $dbForConsole->updateDocument( + 'projects', + $project->getId(), + $project + ->setAttribute('auths', $auths) + ); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -939,21 +947,20 @@ Http::post('/v1/projects/:projectId/webhooks') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true) ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') - ->param('url', '', fn ($request) => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.', false, ['request']) + ->param('url', '', fn($request) => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.', false, ['request']) ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $security = (bool) filter_var($security, FILTER_VALIDATE_BOOLEAN); + $security = (bool)filter_var($security, FILTER_VALIDATE_BOOLEAN); $webhook = new Document([ '$id' => ID::unique(), @@ -997,7 +1004,6 @@ Http::get('/v1/projects/:projectId/webhooks') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1030,7 +1036,6 @@ Http::get('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1064,14 +1069,13 @@ Http::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true) ->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') - ->param('url', '', fn ($request) => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.', false, ['request']) + ->param('url', '', fn($request) => new Multiple([new URL(['http', 'https']), new PublicDomain()], Multiple::TYPE_STRING), 'Webhook URL.', false, ['request']) ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1123,7 +1127,6 @@ Http::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1161,7 +1164,6 @@ Http::delete('/v1/projects/:projectId/webhooks/:webhookId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1203,7 +1205,6 @@ Http::post('/v1/projects/:projectId/keys') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1250,7 +1251,6 @@ Http::get('/v1/projects/:projectId/keys') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1283,7 +1283,6 @@ Http::get('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1320,7 +1319,6 @@ Http::put('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1362,7 +1360,6 @@ Http::delete('/v1/projects/:projectId/keys/:keyId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1398,7 +1395,7 @@ Http::post('/v1/projects/:projectId/platforms') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PLATFORM) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY], true), 'Platform type.') + ->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY], true), 'Platform type.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') ->param('key', '', new Text(256), 'Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.', true) ->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true) @@ -1451,7 +1448,6 @@ Http::get('/v1/projects/:projectId/platforms') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1484,7 +1480,6 @@ Http::get('/v1/projects/:projectId/platforms/:platformId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1564,7 +1559,6 @@ Http::delete('/v1/projects/:projectId/platforms/:platformId') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1612,7 +1606,6 @@ Http::patch('/v1/projects/:projectId/smtp') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1750,11 +1743,10 @@ Http::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); $project = $dbForConsole->getDocument('projects', $projectId); @@ -1764,7 +1756,7 @@ Http::get('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['sms.' . $type . '-' . $locale] ?? null; + $template = $templates['sms.' . $type . '-' . $locale] ?? null; if (is_null($template)) { $template = [ @@ -1791,11 +1783,10 @@ Http::get('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1803,7 +1794,7 @@ Http::get('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['email.' . $type . '-' . $locale] ?? null; + $template = $templates['email.' . $type . '-' . $locale] ?? null; $localeObj = new Locale($locale); if (is_null($template)) { @@ -1843,12 +1834,11 @@ Http::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('message', '', new Text(0), 'Template message') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForConsole) { - throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); $project = $dbForConsole->getDocument('projects', $projectId); @@ -1883,7 +1873,7 @@ Http::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('subject', '', new Text(255), 'Email Subject') ->param('message', '', new Text(0), 'Template message') ->param('senderName', '', new Text(255, 0), 'Name of the email sender', true) @@ -1892,7 +1882,6 @@ Http::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1933,11 +1922,10 @@ Http::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); $project = $dbForConsole->getDocument('projects', $projectId); @@ -1947,7 +1935,7 @@ Http::delete('/v1/projects/:projectId/templates/sms/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['sms.' . $type . '-' . $locale] ?? null; + $template = $templates['sms.' . $type . '-' . $locale] ?? null; if (is_null($template)) { throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION); @@ -1976,11 +1964,10 @@ Http::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') - ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') ->inject('dbForConsole') ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -1988,7 +1975,7 @@ Http::delete('/v1/projects/:projectId/templates/email/:type/:locale') } $templates = $project->getAttribute('templates', []); - $template = $templates['email.' . $type . '-' . $locale] ?? null; + $template = $templates['email.' . $type . '-' . $locale] ?? null; if (is_null($template)) { throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION); diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 4a1278dcf5..b502204bd2 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -101,7 +101,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; - if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false) { + if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false)) { $latestComment = $auth->skip(fn () => $dbForConsole->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), diff --git a/app/controllers/general.php b/app/controllers/general.php index 77d09a6d80..0e35f8d599 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -45,7 +45,7 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request $host = $request->getHostname() ?? ''; $rule = $auth->skip( - fn () => $dbForConsole->find('rules', [ + fn() => $dbForConsole->find('rules', [ Query::equal('domain', [$host]), Query::limit(1) ]) @@ -73,7 +73,7 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request $projectId = $rule->getAttribute('projectId'); $project = $auth->skip( - fn () => $dbForConsole->getDocument('projects', $projectId) + fn() => $dbForConsole->getDocument('projects', $projectId) ); if (array_key_exists('proxy', $project->getAttribute('services', []))) { $status = $project->getAttribute('services', [])['proxy']; @@ -115,11 +115,11 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request $requestHeaders = $request->getHeaders(); - $project = $auth->skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $project = $auth->skip(fn() => $dbForConsole->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); - $function = $auth->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $auth->skip(fn() => $dbForProject->getDocument('functions', $functionId)); if ($function->isEmpty() || !$function->getAttribute('enabled')) { throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND); @@ -134,7 +134,7 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = $auth->skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); + $deployment = $auth->skip(fn() => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); @@ -145,7 +145,7 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request } /** Check if build has completed */ - $build = $auth->skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); + $build = $auth->skip(fn() => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); if ($build->isEmpty()) { throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND); } @@ -198,7 +198,7 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'trigger' => 'http', // http / schedule / event - 'status' => 'processing', // waiting / processing / completed / failed + 'status' => 'processing', // waiting / processing / completed / failed 'responseStatusCode' => 0, 'responseHeaders' => [], 'requestPath' => $path, @@ -287,7 +287,6 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request $execution->setAttribute('logs', $executionResponse['logs']); $execution->setAttribute('errors', $executionResponse['errors']); $execution->setAttribute('duration', $executionResponse['duration']); - } catch (\Throwable $th) { $durationEnd = \microtime(true); @@ -311,7 +310,7 @@ function router(Database $dbForConsole, callable $getProjectDB, Request $request if ($function->getAttribute('logging')) { /** @var Document $execution */ - $execution = $auth->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $auth->skip(fn() => $dbForProject->createDocument('executions', $execution)); } } @@ -509,7 +508,7 @@ Http::init() Config::setParam('domains', $domains); } - $localeParam = (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); + $localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); if (\in_array($localeParam, $localeCodes)) { $locale->setDefault($localeParam); } @@ -537,7 +536,7 @@ Http::init() Config::setParam( 'domainVerification', ($selfDomain->getRegisterable() === $endDomain->getRegisterable()) && - $endDomain->getRegisterable() !== '' + $endDomain->getRegisterable() !== '' ); $isLocalHost = $request->getHostname() === 'localhost' || $request->getHostname() === 'localhost:' . $request->getPort(); @@ -551,10 +550,10 @@ Http::init() $isLocalHost || $isIpAddress ? null : ( - $isConsoleProject && $isConsoleRootSession - ? '.' . $selfDomain->getRegisterable() - : '.' . $request->getHostname() - ) + $isConsoleProject && $isConsoleRootSession + ? '.' . $selfDomain->getRegisterable() + : '.' . $request->getHostname() + ) ); /* @@ -569,7 +568,7 @@ Http::init() $response->addFilter(new ResponseV17()); } if (version_compare($responseFormat, APP_VERSION_STABLE, '>')) { - $response->addHeader('X-Appwrite-Warning', "The current SDK is built for Appwrite " . $responseFormat . ". However, the current Appwrite server version is ". APP_VERSION_STABLE . ". Please downgrade your SDK to match the Appwrite version: https://appwrite.io/docs/sdks"); + $response->addHeader('X-Appwrite-Warning', "The current SDK is built for Appwrite " . $responseFormat . ". However, the current Appwrite server version is " . APP_VERSION_STABLE . ". Please downgrade your SDK to match the Appwrite version: https://appwrite.io/docs/sdks"); } } @@ -671,7 +670,7 @@ Http::error() ->action(function (Throwable $error, Document $user, ?Route $route, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Authorization $authorization, Connections $connections) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); - if(is_null($route)) { + if (is_null($route)) { $route = new Route($request->getMethod(), $request->getURI()); } @@ -891,8 +890,6 @@ Http::get('/robots.txt') ->desc('Robots.txt File') ->label('scope', 'public') ->label('docs', false) - ->inject('utopia') - ->inject('swooleRequest') ->inject('request') ->inject('response') ->inject('dbForConsole') @@ -900,7 +897,9 @@ Http::get('/robots.txt') ->inject('queueForEvents') ->inject('queueForUsage') ->inject('geodb') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { + ->inject('route') + ->inject('authorization') + ->action(function (Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb, ?Route $route, Authorization $authorization) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -908,7 +907,10 @@ Http::get('/robots.txt') $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb); + if (is_null($route)) { + $route = new Route($request->getMethod(), $request->getURI()); + } + router($dbForConsole, $getProjectDB, $request, $response, $route, $queueForEvents, $queueForUsage, $geodb, $authorization); } }); @@ -916,8 +918,6 @@ Http::get('/humans.txt') ->desc('Humans.txt File') ->label('scope', 'public') ->label('docs', false) - ->inject('utopia') - ->inject('swooleRequest') ->inject('request') ->inject('response') ->inject('dbForConsole') @@ -925,7 +925,9 @@ Http::get('/humans.txt') ->inject('queueForEvents') ->inject('queueForUsage') ->inject('geodb') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) { + ->inject('route') + ->inject('authorization') + ->action(function (Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb, ?Route $route, Authorization $authorization) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -933,7 +935,10 @@ Http::get('/humans.txt') $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb); + if (is_null($route)) { + $route = new Route($request->getMethod(), $request->getURI()); + } + router($dbForConsole, $getProjectDB, $request, $response, $route, $queueForEvents, $queueForUsage, $geodb, $authorization); } }); diff --git a/app/init/constants.php b/app/init/constants.php index 39eb4a7ad2..ca1790f71f 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -57,7 +57,7 @@ const APP_SOCIAL_DEV = 'https://dev.to/appwrite'; const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite'; const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1'; const APP_HOSTNAME_INTERNAL = 'appwrite'; - +const DATABASE_SHARED_TABLES = 'database_db_fra1_self_hosted_16_0'; // Database Reconnect const DATABASE_RECONNECT_SLEEP = 2; const DATABASE_RECONNECT_MAX_ATTEMPTS = 10; diff --git a/app/init2.php b/app/init2.php index f0432f5cee..2b7358d60b 100644 --- a/app/init2.php +++ b/app/init2.php @@ -202,144 +202,149 @@ $global->set('hooks', function () { return new Hooks(); }); -$global->set('pools', (function () { - $fallbackForDB = 'db_main=' . URL::unparse([ - 'scheme' => 'mariadb', - 'host' => System::getEnv('_APP_DB_HOST', 'mariadb'), - 'port' => System::getEnv('_APP_DB_PORT', '3306'), - 'user' => System::getEnv('_APP_DB_USER', ''), - 'pass' => System::getEnv('_APP_DB_PASS', ''), - 'path' => System::getEnv('_APP_DB_SCHEMA', ''), - ]); - $fallbackForRedis = 'redis_main=' . URL::unparse([ - 'scheme' => 'redis', - 'host' => System::getEnv('_APP_REDIS_HOST', 'redis'), - 'port' => System::getEnv('_APP_REDIS_PORT', '6379'), - 'user' => System::getEnv('_APP_REDIS_USER', ''), - 'pass' => System::getEnv('_APP_REDIS_PASS', ''), - ]); +$global->set( + 'pools', + (function () { + $fallbackForDB = 'db_main=' . URL::unparse([ + 'scheme' => 'mariadb', + 'host' => System::getEnv('_APP_DB_HOST', 'mariadb'), + 'port' => System::getEnv('_APP_DB_PORT', '3306'), + 'user' => System::getEnv('_APP_DB_USER', ''), + 'pass' => System::getEnv('_APP_DB_PASS', ''), + 'path' => System::getEnv('_APP_DB_SCHEMA', ''), + ]); + $fallbackForRedis = 'redis_main=' . URL::unparse([ + 'scheme' => 'redis', + 'host' => System::getEnv('_APP_REDIS_HOST', 'redis'), + 'port' => System::getEnv('_APP_REDIS_PORT', '6379'), + 'user' => System::getEnv('_APP_REDIS_USER', ''), + 'pass' => System::getEnv('_APP_REDIS_PASS', ''), + ]); - $connections = [ - 'console' => [ - 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_CONSOLE', $fallbackForDB), - 'multiple' => false, - 'schemes' => ['mariadb', 'mysql'], - ], - 'database' => [ - 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_PROJECT', $fallbackForDB), - 'multiple' => true, - 'schemes' => ['mariadb', 'mysql'], - ], - 'queue' => [ - 'type' => 'queue', - 'dsns' => System::getEnv('_APP_CONNECTIONS_QUEUE', $fallbackForRedis), - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'pubsub' => [ - 'type' => 'pubsub', - 'dsns' => System::getEnv('_APP_CONNECTIONS_PUBSUB', $fallbackForRedis), - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'cache' => [ - 'type' => 'cache', - 'dsns' => System::getEnv('_APP_CONNECTIONS_CACHE', $fallbackForRedis), - 'multiple' => true, - 'schemes' => ['redis'], - ], - ]; + $connections = [ + 'console' => [ + 'type' => 'database', + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_CONSOLE', $fallbackForDB), + 'multiple' => false, + 'schemes' => ['mariadb', 'mysql'], + ], + 'database' => [ + 'type' => 'database', + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_PROJECT', $fallbackForDB), + 'multiple' => true, + 'schemes' => ['mariadb', 'mysql'], + ], + 'queue' => [ + 'type' => 'queue', + 'dsns' => System::getEnv('_APP_CONNECTIONS_QUEUE', $fallbackForRedis), + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'pubsub' => [ + 'type' => 'pubsub', + 'dsns' => System::getEnv('_APP_CONNECTIONS_PUBSUB', $fallbackForRedis), + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'cache' => [ + 'type' => 'cache', + 'dsns' => System::getEnv('_APP_CONNECTIONS_CACHE', $fallbackForRedis), + 'multiple' => true, + 'schemes' => ['redis'], + ], + ]; - $pools = []; - $poolSize = (int)System::getEnv('_APP_POOL_CLIENTS', 9000); - $poolSize = 9000; + $pools = []; + $poolSize = (int)System::getEnv('_APP_POOL_CLIENTS', 9000); + $poolSize = 9000; - foreach ($connections as $key => $connection) { - $dsns = $connection['dsns'] ?? ''; - $multipe = $connection['multiple'] ?? false; - $schemes = $connection['schemes'] ?? []; - $dsns = explode(',', $connection['dsns'] ?? ''); - $config = []; + foreach ($connections as $key => $connection) { + $dsns = $connection['dsns'] ?? ''; + $multipe = $connection['multiple'] ?? false; + $schemes = $connection['schemes'] ?? []; + $dsns = explode(',', $connection['dsns'] ?? ''); + $config = []; - foreach ($dsns as &$dsn) { - $dsn = explode('=', $dsn); - $name = ($multipe) ? $dsn[0] : 'main'; - $config[] = $name; - $dsn = $dsn[1] ?? ''; + foreach ($dsns as &$dsn) { + $dsn = explode('=', $dsn); + $name = ($multipe) ? $dsn[0] : 'main'; + $config[] = $name; + $dsn = $dsn[1] ?? ''; - if (empty($dsn)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}"); + if (empty($dsn)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}"); + } + + $dsn = new DSN($dsn); + $dsnHost = $dsn->getHost(); + $dsnPort = $dsn->getPort(); + $dsnUser = $dsn->getUser(); + $dsnPass = $dsn->getPassword(); + $dsnScheme = $dsn->getScheme(); + $dsnDatabase = $dsn->getPath(); + + if (!in_array($dsnScheme, $schemes)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); + } + + /** + * Get Resource + * + * Creation could be reused accross connection types like database, cache, queue, etc. + * + * Resource assignment to an adapter will happen below. + */ + switch ($dsnScheme) { + case 'mysql': + case 'mariadb': + $pool = new PDOPool( + (new PDOConfig()) + ->withHost($dsnHost) + ->withPort($dsnPort) + ->withDbName($dsnDatabase) + ->withCharset('utf8mb4') + ->withUsername($dsnUser) + ->withPassword($dsnPass) + ->withOptions([ + // No need to set PDO::ATTR_ERRMODE it is overwitten in PDOProxy + // 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::MYSQL_ATTR_USE_BUFFERED_QUERY => true, + + ]), + $poolSize + ); + break; + case 'redis': + $pool = new RedisPool( + (new RedisConfig()) + ->withHost($dsnHost) + ->withPort((int)$dsnPort) + ->withAuth($dsnPass), $poolSize + ); + break; + + default: + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"); + } + + $pools['pools-' . $key . '-' . $name] = [ + 'pool' => $pool, + 'dsn' => $dsn, + ]; } - $dsn = new DSN($dsn); - $dsnHost = $dsn->getHost(); - $dsnPort = $dsn->getPort(); - $dsnUser = $dsn->getUser(); - $dsnPass = $dsn->getPassword(); - $dsnScheme = $dsn->getScheme(); - $dsnDatabase = $dsn->getPath(); - - if (!in_array($dsnScheme, $schemes)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); - } - - /** - * Get Resource - * - * Creation could be reused accross connection types like database, cache, queue, etc. - * - * Resource assignment to an adapter will happen below. - */ - switch ($dsnScheme) { - case 'mysql': - case 'mariadb': - $pool = new PDOPool( - (new PDOConfig()) - ->withHost($dsnHost) - ->withPort($dsnPort) - ->withDbName($dsnDatabase) - ->withCharset('utf8mb4') - ->withUsername($dsnUser) - ->withPassword($dsnPass) - ->withOptions([ - // No need to set PDO::ATTR_ERRMODE it is overwitten in PDOProxy - // 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::MYSQL_ATTR_USE_BUFFERED_QUERY => true, - - ]), - $poolSize - ); - break; - case 'redis': - $pool = new RedisPool((new RedisConfig()) - ->withHost($dsnHost) - ->withPort((int)$dsnPort) - ->withAuth($dsnPass), $poolSize); - break; - - default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"); - } - - $pools['pools-' . $key . '-' . $name] = [ - 'pool' => $pool, - 'dsn' => $dsn, - ]; + Config::setParam('pools-' . $key, $config); } - Config::setParam('pools-' . $key, $config); - } - - return function () use ($pools): array { - return $pools; - }; -})()); + return function () use ($pools): array { + return $pools; + }; + })() +); $global->set('smtp', function () { $mail = new PHPMailer(true); @@ -374,7 +379,52 @@ $global->set('promiseAdapter', function () { return new Swoole(); }); + +$log = new Dependency(); $mode = new Dependency(); +$user = new Dependency(); +$pools = new Dependency(); +$geodb = new Dependency(); +$cache = new Dependency(); +$pools = new Dependency(); +$queue = new Dependency(); +$hooks = new Dependency(); +$logger = new Dependency(); +$locale = new Dependency(); +$schema = new Dependency(); +$github = new Dependency(); +$session = new Dependency(); +$console = new Dependency(); +$project = new Dependency(); +$clients = new Dependency(); +$servers = new Dependency(); +$registry = new Dependency(); +$getProjectDB = new Dependency(); +$localeCodes = new Dependency(); +$connections = new Dependency(); +$dbForProject = new Dependency(); +$dbForConsole = new Dependency(); +$queueForUsage = new Dependency(); +$authorization = new Dependency(); +$queueForMails = new Dependency(); +$queueForBuilds = new Dependency(); +$deviceForLocal = new Dependency(); +$deviceForFiles = new Dependency(); +$queueForEvents = new Dependency(); +$queueForAudits = new Dependency(); +$promiseAdapter = new Dependency(); +$requestTimestamp = new Dependency(); +$deviceForBuilds = new Dependency(); +$queueForDeletes = new Dependency(); +$queueForDatabase = new Dependency(); +$queueForMessaging = new Dependency(); +$queueForFunctions = new Dependency(); +$queueForMigrations = new Dependency(); +$deviceForFunctions = new Dependency(); +$passwordsDictionary = new Dependency(); +$queueForCertificates = new Dependency(); + + $mode ->setName('mode') ->inject('request') @@ -386,9 +436,7 @@ $mode */ return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT)); }); -$container->set($mode); -$user = new Dependency(); $user ->setName('user') ->inject('mode') @@ -500,9 +548,8 @@ $user return $user; }); -$container->set($user); -$session = new Dependency(); + $session ->setName('session') ->inject('user') @@ -528,9 +575,7 @@ $session return; }); -$container->set($session); -$console = new Dependency(); $console ->setName('console') ->setCallback(function () { @@ -572,9 +617,8 @@ $console ], ]); }); -$container->set($console); -$project = new Dependency(); + $project ->setName('project') ->inject('dbForConsole') @@ -588,62 +632,76 @@ $project return $console; } - $project = $authorization->skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $project = $authorization->skip(fn() => $dbForConsole->getDocument('projects', $projectId)); return $project; }); -$container->set($project); -$pools = new Dependency(); $pools ->setName('pools') ->inject('registry') ->setCallback(function (Registry $registry) { return $registry->get('pools'); }); -$container->set($pools); -$dbForProject = new Dependency(); $dbForProject ->setName('dbForProject') + ->inject('cache') ->inject('pools') ->inject('project') - ->inject('cache') ->inject('dbForConsole') - ->inject('connections') ->inject('authorization') - ->setCallback(function (array $pools, Document $project, Cache $cache, Database $dbForConsole, Connections $connections, Authorization $authorization) { + ->inject('connections') + ->setCallback(function (Cache $cache, array $pools, Document $project, Database $dbForConsole, Authorization $authorization, Connections $connections) { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForConsole; } - $pool = $pools['pools-database-'.$project->getAttribute('database')]['pool']; - $dsn = $pools['pools-database-'.$project->getAttribute('database')]['dsn']; + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } + + $pool = $pools['pools-database-' . $dsn->getHost()]['pool']; + $connectionDsn = $pools['pools-database-' . $dsn->getHost()]['dsn']; $connection = $pool->get(); $connections->add($connection, $pool); - $adapter = match ($dsn->getScheme()) { + $adapter = match ($connectionDsn->getScheme()) { 'mariadb' => new MariaDB($connection), 'mysql' => new MySQL($connection), default => null }; - $adapter->setDatabase($dsn->getPath()); + $adapter->setDatabase($connectionDsn->getPath()); $database = new Database($adapter, $cache); + + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { + $database + ->setSharedTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + $database->setAuthorization($authorization); - - $database - ->setNamespace('_' . $project->getInternalId()) - ->setMetadata('host', \gethostname()) - ->setMetadata('project', $project->getId()) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - return $database; }); -$container->set($dbForProject); -$dbForConsole = new Dependency(); $dbForConsole ->setName('dbForConsole') ->inject('pools') @@ -675,79 +733,59 @@ $dbForConsole return $database; }); -$container->set($dbForConsole); -$cache = new Dependency(); $cache ->setName('cache') ->setCallback(function (): Cache { return new Cache(new None()); }); -$container->set($cache); -$authorization = new Dependency(); $authorization ->setName('authorization') ->setCallback(function (): Authorization { return new Authorization(); }); -$container->set($authorization); -$registry = new Dependency(); $registry ->setName('registry') ->setCallback(function () use (&$global): Registry { return $global; }); -$container->set($registry); -$pools = new Dependency(); $pools ->setName('pools') ->inject('registry') ->setCallback(function (Registry $registry) { return $registry->get('pools'); }); -$container->set($pools); -$logger = new Dependency(); $logger ->setName('logger') ->inject('registry') ->setCallback(function (Registry $registry) { return $registry->get('logger'); }); -$container->set($logger); -$log = new Dependency(); $log ->setName('log') ->setCallback(function () { return new Log(); }); -$container->set($log); -$connections = new Dependency(); $connections ->setName('connections') ->setCallback(function () { return new Connections(); }); -$container->set($connections); -$locale = new Dependency(); $locale ->setName('locale') - ->setCallback(fn () => new Locale(System::getEnv('_APP_LOCALE', 'en'))); -$container->set($locale); + ->setCallback(fn() => new Locale(System::getEnv('_APP_LOCALE', 'en'))); -$localeCodes = new Dependency(); $localeCodes ->setName('localeCodes') - ->setCallback(fn () => array_map(fn ($locale) => $locale['code'], Config::getParam('locale-codes', []))); -$container->set($localeCodes); + ->setCallback(fn() => array_map(fn($locale) => $locale['code'], Config::getParam('locale-codes', []))); -$queue = new Dependency(); $queue ->setName('queue') ->inject('pools') @@ -760,143 +798,111 @@ $queue return new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort()); }); -$container->set($queue); -$queueForMessaging = new Dependency(); $queueForMessaging ->setName('queueForMessaging') ->inject('queue') ->setCallback(function (Connection $queue) { return new Messaging($queue); }); -$container->set($queueForMessaging); -$queueForMails = new Dependency(); $queueForMails ->setName('queueForMails') ->inject('queue') ->setCallback(function (Connection $queue) { return new Mail($queue); }); -$container->set($queueForMails); -$queueForBuilds = new Dependency(); $queueForBuilds ->setName('queueForBuilds') ->inject('queue') ->setCallback(function (Connection $queue) { return new Build($queue); }); -$container->set($queueForBuilds); -$queueForDatabase = new Dependency(); $queueForDatabase ->setName('queueForDatabase') ->inject('queue') ->setCallback(function (Connection $queue) { return new EventDatabase($queue); }); -$container->set($queueForDatabase); -$queueForDeletes = new Dependency(); $queueForDeletes ->setName('queueForDeletes') ->inject('queue') ->setCallback(function (Connection $queue) { return new Delete($queue); }); -$container->set($queueForDeletes); -$queueForEvents = new Dependency(); $queueForEvents ->setName('queueForEvents') ->inject('queue') ->setCallback(function (Connection $queue) { return new Event($queue); }); -$container->set($queueForEvents); -$queueForAudits = new Dependency(); $queueForAudits ->setName('queueForAudits') ->inject('queue') ->setCallback(function (Connection $queue) { return new Audit($queue); }); -$container->set($queueForAudits); -$queueForFunctions = new Dependency(); $queueForFunctions ->setName('queueForFunctions') ->inject('queue') ->setCallback(function (Connection $queue) { return new Func($queue); }); -$container->set($queueForFunctions); -$queueForUsage = new Dependency(); $queueForUsage ->setName('queueForUsage') ->inject('queue') ->setCallback(function (Connection $queue) { return new Usage($queue); }); -$container->set($queueForUsage); -$queueForCertificates = new Dependency(); $queueForCertificates ->setName('queueForCertificates') ->inject('queue') ->setCallback(function (Connection $queue) { return new Certificate($queue); }); -$container->set($queueForCertificates); -$queueForMigrations = new Dependency(); $queueForMigrations ->setName('queueForMigrations') ->inject('queue') ->setCallback(function (Connection $queue) { return new Migration($queue); }); -$container->set($queueForMigrations); -$deviceForLocal = new Dependency(); $deviceForLocal ->setName('deviceForLocal') ->setCallback(function () { return new Local(); }); -$container->set($deviceForLocal); -$deviceForFiles = new Dependency(); $deviceForFiles ->setName('deviceForFiles') ->inject('project') ->setCallback(function ($project) { return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); }); -$container->set($deviceForFiles); -$deviceForFunctions = new Dependency(); $deviceForFunctions ->setName('deviceForFunctions') ->inject('project') ->setCallback(function ($project) { return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); }); -$container->set($deviceForFunctions); -$deviceForBuilds = new Dependency(); $deviceForBuilds ->setName('deviceForBuilds') ->inject('project') ->setCallback(function ($project) { return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); }); -$container->set($deviceForBuilds); -$clients = new Dependency(); $clients ->setName('clients') ->inject('request') @@ -930,10 +936,10 @@ $clients * + Filter for duplicated entries */ $clientsConsole = \array_map( - fn ($node) => $node['hostname'], + fn($node) => $node['hostname'], \array_filter( $console->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname'])) + fn($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname'])) ) ); @@ -941,10 +947,10 @@ $clients \array_merge( $clientsConsole, \array_map( - fn ($node) => $node['hostname'], + fn($node) => $node['hostname'], \array_filter( $project->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname'])) + fn($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname'])) ) ) ) @@ -952,9 +958,7 @@ $clients return $clients; }); -$container->set($clients); -$servers = new Dependency(); $servers ->setName('servers') ->setCallback(function () { @@ -967,18 +971,14 @@ $servers return $languages; }); -$container->set($servers); -$geodb = new Dependency(); $geodb ->setName('geodb') ->inject('registry') ->setCallback(function (Registry $register) { return $register->get('geodb'); }); -$container->set($geodb); -$passwordsDictionary = new Dependency(); $passwordsDictionary ->setName('passwordsDictionary') ->setCallback(function () { @@ -988,27 +988,20 @@ $passwordsDictionary return $content; }); -$container->set($passwordsDictionary); - -$hooks = new Dependency(); $hooks ->setName('hooks') ->inject('registry') ->setCallback(function (Registry $registry) { return $registry->get('hooks'); }); -$container->set($hooks); -$github = new Dependency(); $github ->setName('gitHub') ->inject('cache') ->setCallback(function (Cache $cache) { return new GitHub($cache); }); -$container->set($github); -$requestTimestamp = new Dependency(); $requestTimestamp ->setName('requestTimestamp') ->inject('request') @@ -1024,9 +1017,7 @@ $requestTimestamp } return $requestTimestamp; }); -$container->set($requestTimestamp); -$getProjectDB = new Dependency(); $getProjectDB ->setName('getProjectDB') ->inject('pools') @@ -1034,51 +1025,85 @@ $getProjectDB ->inject('cache') ->inject('authorization') ->inject('connections') - ->setCallback(function (array $pools, Database $dbForConsole, $cache, Authorization $authorization, Connections $connections) { + ->setCallback(function (array $pools, Database $dbForConsole, Cache $cache, Authorization $authorization, Connections $connections) { + $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools + return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases, $authorization, $connections): Database { if ($project->isEmpty() || $project->getId() === 'console') { return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + try { + $dsn = new DSN($project->getAttribute('database')); + } catch (\InvalidArgumentException) { + // TODO: Temporary until all projects are using shared tables + $dsn = new DSN('mysql://' . $project->getAttribute('database')); + } - $pool = $pools['pools-database-'.$databaseName]['pool']; - $dsn = $pools['pools-database-'.$databaseName]['dsn']; + if (isset($databases[$dsn->getHost()])) { + $database = $databases[$dsn->getHost()]; + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { + $database + ->setSharedTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + + return $database; + } + + $pool = $pools['pools-database-' . $dsn->getHost()]['pool']; + $connectionDsn = $pools['pools-database-' . $dsn->getHost()]['dsn']; $connection = $pool->get(); $connections->add($connection, $pool); - $adapter = match ($dsn->getScheme()) { + $adapter = match ($connectionDsn->getScheme()) { 'mariadb' => new MariaDB($connection), 'mysql' => new MySQL($connection), default => null }; - $adapter->setDatabase($dsn->getPath()); + $adapter->setDatabase($connectionDsn->getPath()); $database = new Database($adapter, $cache); $database->setAuthorization($authorization); - $database->setNamespace('_' . $project->getInternalId()); + + $databases[$dsn->getHost()] = $database; + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { + $database + ->setSharedTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } return $database; }; }); -$container->set($getProjectDB); -$promiseAdapter = new Dependency(); $promiseAdapter ->setName('promiseAdapter') ->inject('register') ->setCallback(function ($register) { return $register->get('promiseAdapter'); }); -$container->set($promiseAdapter); -$schema = new Dependency(); $schema ->setName('schema') ->inject('utopia') ->inject('dbForProject') - ->inject('auth') - ->setCallback(function (Http $utopia, Database $dbForProject, Authorization $auth) { + ->inject('authorization') + ->setCallback(function (Http $utopia, Database $dbForProject, Authorization $authorization) { $complexity = function (int $complexity, array $args) { $queries = Query::parseQueries($args['queries'] ?? []); $query = Query::getByType($queries, [Query::TYPE_LIMIT])[0] ?? null; @@ -1087,8 +1112,8 @@ $schema return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject, $auth) { - $attrs = $auth->skip(fn () => $dbForProject->find('attributes', [ + $attributes = function (int $limit, int $offset) use ($dbForProject, $authorization) { + $attrs = $authorization->skip(fn() => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -1118,7 +1143,7 @@ $schema $params = [ 'list' => function (string $databaseId, string $collectionId, array $args) { - return [ 'queries' => $args['queries']]; + return ['queries' => $args['queries']]; }, 'create' => function (string $databaseId, string $collectionId, array $args) { $id = $args['id'] ?? 'unique()'; @@ -1160,4 +1185,46 @@ $schema $params, ); }); +$container->set($log); +$container->set($mode); +$container->set($user); +$container->set($pools); +$container->set($cache); +$container->set($pools); +$container->set($queue); +$container->set($geodb); +$container->set($hooks); +$container->set($locale); $container->set($schema); +$container->set($github); +$container->set($logger); +$container->set($session); +$container->set($console); +$container->set($project); +$container->set($clients); +$container->set($servers); +$container->set($registry); +$container->set($connections); +$container->set($localeCodes); +$container->set($dbForProject); +$container->set($dbForConsole); +$container->set($getProjectDB); +$container->set($authorization); +$container->set($queueForUsage); +$container->set($queueForMails); +$container->set($queueForBuilds); +$container->set($queueForEvents); +$container->set($queueForAudits); +$container->set($deviceForLocal); +$container->set($deviceForFiles); +$container->set($promiseAdapter); +$container->set($queueForDeletes); +$container->set($deviceForBuilds); +$container->set($queueForDatabase); +$container->set($requestTimestamp); +$container->set($queueForMessaging); +$container->set($queueForFunctions); +$container->set($queueForMigrations); +$container->set($deviceForFunctions); +$container->set($passwordsDictionary); +$container->set($queueForCertificates); diff --git a/app/worker.php b/app/worker.php index d3a59cff84..7a62931a49 100644 --- a/app/worker.php +++ b/app/worker.php @@ -44,120 +44,20 @@ global $global, $container; Runtime::enableCoroutine(SWOOLE_HOOK_ALL); +$project = new Dependency(); $register = new Dependency(); +$dbForProject = new Dependency(); +$abuseRetention = new Dependency(); +$deviceForCache = new Dependency(); +$auditRetention = new Dependency(); +$queueForUsageDump = new Dependency(); +$executionRetention = new Dependency(); +$deviceForLocalFiles = new Dependency(); + $register ->setName('register') - ->setCallback(fn () => $global); -$container->set($register); + ->setCallback(fn() => $global); -$connections = new Dependency(); -$connections - ->setName('connections') - ->setCallback(function () { - return new Connections(); - }); -$container->set($connections); - -$pools = new Dependency(); -$pools - ->setName('pools') - ->inject('register') - ->setCallback(function ($register) { - return $register->get('pools'); - }); -$container->set($pools); - -$dbForConsole = new Dependency(); -$dbForConsole - ->setName('dbForConsole') - ->inject('cache') - ->inject('pools') - ->inject('auth') - ->inject('connections') - ->setCallback(function (Cache $cache, array $pools, Authorization $auth, Connections $connections) { - $pool = $pools['pools-console-main']['pool']; - $dsn = $pools['pools-console-main']['dsn']; - $connection = $pool->get(); - $connections->add($connection, $pool); - - $adapter = match ($dsn->getScheme()) { - 'mariadb' => new MariaDB($connection), - 'mysql' => new MySQL($connection), - default => null - }; - - $adapter->setDatabase($dsn->getPath()); - - $database = new Database($adapter, $cache); - $database->setAuthorization($auth); - $database->setNamespace('_console'); - - return $database; - }); -$container->set($dbForConsole); - -$dbForProject = new Dependency(); -$dbForProject - ->setName('dbForProject') - ->inject('cache') - ->inject('pools') - ->inject('message') - ->inject('project') - ->inject('dbForConsole') - ->inject('auth') - ->inject('connections') - ->setCallback(function (Cache $cache, array $pools, Message $message, Document $project, Database $dbForConsole, Authorization $auth, Connections $connections) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; - } - - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - - $pool = $pools['pools-database-' . $dsn->getHost()]['pool']; - $connectionDsn = $pools['pools-database-' . $dsn->getHost()]['dsn']; - - $connection = $pool->get(); - $connections->add($connection, $pool); - $adapter = match ($connectionDsn->getScheme()) { - 'mariadb' => new MariaDB($connection), - 'mysql' => new MySQL($connection), - default => null - }; - - $adapter->setDatabase($connectionDsn->getPath()); - - $database = new Database($adapter, $cache); - - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - - if ($dsn->getHost() === DATABASE_SHARED_TABLES) { - $database - ->setSharedTables(true) - ->setTenant($project->getInternalId()) - ->setNamespace($dsn->getParam('namespace')); - } else { - $database - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } - - $database->setAuthorization($auth); - return $database; - }); -$container->set($dbForProject); - -$project = new Dependency(); $project ->setName('project') ->inject('message') @@ -172,218 +72,25 @@ $project return $dbForConsole->getDocument('projects', $project->getId()); }); -$container->set($project); -$getProjectDB = new Dependency(); -$getProjectDB - ->setName('getProjectDB') - ->inject('pools') - ->inject('dbForConsole') - ->inject('cache') - ->inject('auth') - ->inject('connections') - ->setCallback(function (array $pools, Database $dbForConsole, Cache $cache, Authorization $auth, Connections $connections) { - $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases, $auth, $connections): Database { - if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; - } - - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - - if (isset($databases[$dsn->getHost()])) { - $database = $databases[$dsn->getHost()]; - - if ($dsn->getHost() === DATABASE_SHARED_TABLES) { - $database - ->setSharedTables(true) - ->setTenant($project->getInternalId()) - ->setNamespace($dsn->getParam('namespace')); - } else { - $database - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } - - return $database; - } - - $pool = $pools['pools-database-'.$dsn->getHost()]['pool']; - $connectionDsn = $pools['pools-database-'.$dsn->getHost()]['dsn']; - - $connection = $pool->get(); - $connections->add($connection, $pool); - $adapter = match ($connectionDsn->getScheme()) { - 'mariadb' => new MariaDB($connection), - 'mysql' => new MySQL($connection), - default => null - }; - $adapter->setDatabase($connectionDsn->getPath()); - - $database = new Database($adapter, $cache); - $database->setAuthorization($auth); - - $databases[$dsn->getHost()] = $database; - - if ($dsn->getHost() === DATABASE_SHARED_TABLES) { - $database - ->setSharedTables(true) - ->setTenant($project->getInternalId()) - ->setNamespace($dsn->getParam('namespace')); - } else { - $database - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } - - return $database; - }; - }); -$container->set($getProjectDB); - -$abuseRetention = new Dependency(); $abuseRetention ->setName('abuseRetention') ->setCallback(function () { return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400)); }); -$container->set($abuseRetention); -$auditRetention = new Dependency(); $auditRetention ->setName('auditRetention') ->setCallback(function () { return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600)); }); -$container->set($auditRetention); -$executionRetention = new Dependency(); $executionRetention ->setName('executionRetention') ->setCallback(function () { return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600)); }); -$container->set($executionRetention); -$cache = new Dependency(); -$cache - ->setName('cache') - ->setCallback(function () { - return new Cache(new None()); - }); -$container->set($cache); - -$log = new Dependency(); -$log - ->setName('log') - ->setCallback(fn () => new Log()); -$container->set($log); - -$queue = new Dependency(); -$queue - ->setName('queue') - ->inject('pools') - ->inject('connections') - ->setCallback(function (array $pools, Connections $connections) { - $pool = $pools['pools-queue-main']['pool']; - $dsn = $pools['pools-queue-main']['dsn']; - $connection = $pool->get(); - $connections->add($connection, $pool); - - return new Redis($dsn->getHost(), $dsn->getPort()); - }); -$container->set($queue); - -$queueForMessaging = new Dependency(); -$queueForMessaging - ->setName('queueForMessaging') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Messaging($queue); - }); -$container->set($queueForMessaging); - -$queueForMails = new Dependency(); -$queueForMails - ->setName('queueForMails') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Mail($queue); - }); -$container->set($queueForMails); - -$queueForBuilds = new Dependency(); -$queueForBuilds - ->setName('queueForBuilds') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Build($queue); - }); -$container->set($queueForBuilds); - -$queueForDatabase = new Dependency(); -$queueForDatabase - ->setName('queueForDatabase') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new EventDatabase($queue); - }); -$container->set($queueForDatabase); - -$queueForDeletes = new Dependency(); -$queueForDeletes - ->setName('queueForDeletes') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Delete($queue); - }); -$container->set($queueForDeletes); - -$queueForEvents = new Dependency(); -$queueForEvents - ->setName('queueForEvents') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Event($queue); - }); -$container->set($queueForEvents); - -$queueForAudits = new Dependency(); -$queueForAudits - ->setName('queueForAudits') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Audit($queue); - }); -$container->set($queueForAudits); - -$queueForFunctions = new Dependency(); -$queueForFunctions - ->setName('queueForFunctions') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Func($queue); - }); -$container->set($queueForFunctions); - -$queueForUsage = new Dependency(); -$queueForUsage - ->setName('queueForUsage') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Usage($queue); - }); -$container->set($queueForUsage); - -$queueForUsageDump = new Dependency(); $queueForUsageDump ->setName('queueForUsageDump') ->inject('queue') @@ -391,74 +98,13 @@ $queueForUsageDump return new UsageDump($queue); }); -$container->set($queueForUsageDump); - -$queueForCertificates = new Dependency(); -$queueForCertificates - ->setName('queueForCertificates') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Certificate($queue); - }); -$container->set($queueForCertificates); - -$queueForMigrations = new Dependency(); -$queueForMigrations - ->setName('queueForMigrations') - ->inject('queue') - ->setCallback(function (Connection $queue) { - return new Migration($queue); - }); -$container->set($queueForMigrations); - - - -$logger = new Dependency(); -$logger - ->setName('logger') - ->inject('register') - ->setCallback(function (Registry $register) { - return $register->get('logger'); - }); -$container->set($logger); - -$deviceForFunctions = new Dependency(); -$deviceForFunctions - ->setName('deviceForFunctions') - ->inject('project') - ->setCallback(function (Document $project) { - return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); - }); -$container->set($deviceForFunctions); - -$deviceForFiles = new Dependency(); -$deviceForFiles - ->setName('deviceForFiles') - ->inject('project') - ->setCallback(function (Document $project) { - return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); - }); -$container->set($deviceForFiles); - -$deviceForBuilds = new Dependency(); -$deviceForBuilds - ->setName('deviceForBuilds') - ->inject('project') - ->setCallback(function (Document $project) { - return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); - }); -$container->set($deviceForBuilds); - -$deviceForCache = new Dependency(); $deviceForCache ->setName('deviceForCache') ->inject('project') ->setCallback(function (Document $project) { return getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId()); }); -$container->set($deviceForCache); -$deviceForLocalFiles = new Dependency(); $deviceForLocalFiles ->setName('deviceForLocalFiles') ->inject('project') @@ -466,16 +112,18 @@ $deviceForLocalFiles return new Local(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); }); +$container->set($project); +$container->set($register); +$container->set($dbForProject); +$container->set($abuseRetention); +$container->set($auditRetention); +$container->set($deviceForCache); +$container->set($queueForUsageDump); +$container->set($executionRetention); $container->set($deviceForLocalFiles); -$auth = new Dependency(); -$auth - ->setName('auth') - ->setCallback(fn () => new Authorization()); -$container->set($auth); - $platform = new Appwrite(); -$args = $platform->getEnv('argv'); +$args = $_SERVER['argv']; if (!isset($args[1])) { Console::error('Missing worker name'); @@ -497,7 +145,6 @@ if (\str_starts_with($workerName, 'databases')) { } try { - $connection = new Connection\Redis( System::getEnv('_APP_REDIS_HOST', 'redis'), System::getEnv('_APP_REDIS_PORT', '6379'), @@ -518,13 +165,13 @@ try { 'queueName' => $queueName ]); } catch (\Throwable $e) { - Console::error($e->getMessage() . ', File: ' . $e->getFile() . ', Line: ' . $e->getLine()); + Console::error($e->getMessage() . ', File: ' . $e->getFile() . ', Line: ' . $e->getLine()); } Worker::init() - ->inject('auth') - ->action(function (Authorization $auth) { - $auth->disable(); + ->inject('authorization') + ->action(function (Authorization $authorization) { + $authorization->disable(); }); Worker::shutdown() @@ -539,8 +186,8 @@ Worker::error() ->inject('log') ->inject('connections') ->inject('project') - ->inject('auth') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Connections $connections, Document $project, Authorization $auth) use ($queueName) { + ->inject('authorization') + ->action(function (Throwable $error, ?Logger $logger, Log $log, Connections $connections, Document $project, Authorization $authorization) use ($queueName) { $connections->reclaim(); $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); @@ -558,7 +205,7 @@ Worker::error() $log->addExtra('line', $error->getLine()); $log->addExtra('trace', $error->getTraceAsString()); $log->addExtra('detailedTrace', $error->getTrace()); - $log->addExtra('roles', $auth->getRoles()); + $log->addExtra('roles', $authorization->getRoles()); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); diff --git a/composer.json b/composer.json index c51e90d46b..2ac000424f 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ "utopia-php/abuse": "dev-feat-framework-v2 as 0.37.99", "utopia-php/analytics": "dev-feat-framework-v2 as 0.10.99", "utopia-php/audit": "dev-feat-framework-v2 as 0.39.99", - "utopia-php/cache": "0.9.*", + "utopia-php/cache": "0.10.*", "utopia-php/cli": "dev-dev-coroutines as 0.17.99", "utopia-php/config": "0.2.*", "utopia-php/database": "dev-feat-framework-v2 as 0.49.99", diff --git a/composer.lock b/composer.lock index 249eb1fbf2..e65142d1f1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7778579de897a3e077914bd37686a62b", + "content-hash": "cea93b7a5d3b401c01b535df70df0b35", "packages": [ { "name": "adhocore/jwt", @@ -479,6 +479,89 @@ ], "time": "2022-09-10T18:51:20+00:00" }, + { + "name": "giggsey/libphonenumber-for-php-lite", + "version": "8.13.36", + "source": { + "type": "git", + "url": "https://github.com/giggsey/libphonenumber-for-php-lite.git", + "reference": "144bbe70d67664b5245910a475c7190ff140ab4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/144bbe70d67664b5245910a475c7190ff140ab4b", + "reference": "144bbe70d67664b5245910a475c7190ff140ab4b", + "shasum": "" + }, + "require": { + "php": "^8.1", + "symfony/polyfill-mbstring": "^1.17" + }, + "conflict": { + "giggsey/libphonenumber-for-php": "*" + }, + "require-dev": { + "ext-dom": "*", + "friendsofphp/php-cs-fixer": "^3.12", + "infection/infection": "^0.28", + "pear/pear-core-minimal": "^1.10.11", + "pear/pear_exception": "^1.0.2", + "pear/versioncontrol_git": "^0.7", + "phing/phing": "^2.17.4", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.2", + "phpunit/phpunit": "^10.5", + "symfony/console": "^6.0", + "symfony/var-exporter": "^6.0" + }, + "suggest": { + "giggsey/libphonenumber-for-php": "Use libphonenumber-for-php for geocoding, carriers, timezones and matching" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "libphonenumber\\": "src/" + }, + "exclude-from-classmap": [ + "/src/data/", + "/src/carrier/data/", + "/src/geocoding/data/", + "/src/timezone/data/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Joshua Gigg", + "email": "giggsey@gmail.com", + "homepage": "https://giggsey.com/" + } + ], + "description": "A lite version of giggsey/libphonenumber-for-php, which is a PHP Port of Google's libphonenumber", + "homepage": "https://github.com/giggsey/libphonenumber-for-php-lite", + "keywords": [ + "geocoding", + "geolocation", + "libphonenumber", + "mobile", + "phonenumber", + "validation" + ], + "support": { + "issues": "https://github.com/giggsey/libphonenumber-for-php-lite/issues", + "source": "https://github.com/giggsey/libphonenumber-for-php-lite" + }, + "time": "2024-05-03T06:31:11+00:00" + }, { "name": "jean85/pretty-package-versions", "version": "2.x-dev", @@ -1044,6 +1127,87 @@ }, "time": "2022-03-17T08:00:35+00:00" }, + { + "name": "symfony/polyfill-mbstring", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "098e36a5b73de12beeb5ac17e80abf3696f7ad5f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/098e36a5b73de12beeb5ac17e80abf3696f7ad5f", + "reference": "098e36a5b73de12beeb5ac17e80abf3696f7ad5f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/1.x" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, { "name": "symfony/polyfill-php80", "version": "1.x-dev", @@ -1408,16 +1572,16 @@ }, { "name": "utopia-php/cache", - "version": "0.9.1", + "version": "0.10.0", "source": { "type": "git", "url": "https://github.com/utopia-php/cache.git", - "reference": "552b4c554bb14d0c529631ce304cdf4a2b9d06a6" + "reference": "313bcdfbb166f75c2c205a59d1467cead63a9626" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cache/zipball/552b4c554bb14d0c529631ce304cdf4a2b9d06a6", - "reference": "552b4c554bb14d0c529631ce304cdf4a2b9d06a6", + "url": "https://api.github.com/repos/utopia-php/cache/zipball/313bcdfbb166f75c2c205a59d1467cead63a9626", + "reference": "313bcdfbb166f75c2c205a59d1467cead63a9626", "shasum": "" }, "require": { @@ -1452,9 +1616,9 @@ ], "support": { "issues": "https://github.com/utopia-php/cache/issues", - "source": "https://github.com/utopia-php/cache/tree/0.9.1" + "source": "https://github.com/utopia-php/cache/tree/0.10.0" }, - "time": "2024-03-19T17:07:20+00:00" + "time": "2024-06-05T16:40:43+00:00" }, { "name": "utopia-php/cli", @@ -1564,19 +1728,19 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "f53d63bc5903ea6d6ff8f61293a20235e912b242" + "reference": "5b0d6ba40141dd9d4983d3aac018782f8ecdfc8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/f53d63bc5903ea6d6ff8f61293a20235e912b242", - "reference": "f53d63bc5903ea6d6ff8f61293a20235e912b242", + "url": "https://api.github.com/repos/utopia-php/database/zipball/5b0d6ba40141dd9d4983d3aac018782f8ecdfc8a", + "reference": "5b0d6ba40141dd9d4983d3aac018782f8ecdfc8a", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/cache": "0.9.*", + "utopia-php/cache": "0.10.*", "utopia-php/framework": "0.34.*", "utopia-php/mongo": "0.3.*" }, @@ -1610,9 +1774,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/feat-framework-v2-1" + "source": "https://github.com/utopia-php/database/tree/feat-framework-v2" }, - "time": "2024-05-09T18:33:47+00:00" + "time": "2024-06-06T00:07:47+00:00" }, { "name": "utopia-php/di", @@ -1783,6 +1947,45 @@ }, "time": "2024-05-07T02:01:25+00:00" }, + { + "name": "utopia-php/fetch", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/fetch.git", + "reference": "1423c0ee3eef944d816ca6e31706895b585aea82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/fetch/zipball/1423c0ee3eef944d816ca6e31706895b585aea82", + "reference": "1423c0ee3eef944d816ca6e31706895b585aea82", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "laravel/pint": "^1.5.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Fetch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A simple library that provides an interface for making HTTP Requests.", + "support": { + "issues": "https://github.com/utopia-php/fetch/issues", + "source": "https://github.com/utopia-php/fetch/tree/0.2.1" + }, + "time": "2024-03-18T11:50:59+00:00" + }, { "name": "utopia-php/framework", "version": "dev-feat-di-upgrade", @@ -1934,22 +2137,23 @@ }, { "name": "utopia-php/logger", - "version": "0.3.x-dev", + "version": "0.5.2", "source": { "type": "git", "url": "https://github.com/utopia-php/logger.git", - "reference": "ba763c10688fe2ed715ad2bed3f13d18dfec6253" + "reference": "c6dfdb672e41364c309b0c30dc03bc6d45446dba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/logger/zipball/ba763c10688fe2ed715ad2bed3f13d18dfec6253", - "reference": "ba763c10688fe2ed715ad2bed3f13d18dfec6253", + "url": "https://api.github.com/repos/utopia-php/logger/zipball/c6dfdb672e41364c309b0c30dc03bc6d45446dba", + "reference": "c6dfdb672e41364c309b0c30dc03bc6d45446dba", "shasum": "" }, "require": { "php": ">=8.0" }, "require-dev": { + "laravel/pint": "1.2.*", "phpstan/phpstan": "1.9.x-dev", "phpunit/phpunit": "^9.3", "vimeo/psalm": "4.0.1" @@ -1981,27 +2185,28 @@ ], "support": { "issues": "https://github.com/utopia-php/logger/issues", - "source": "https://github.com/utopia-php/logger/tree/0.3.x" + "source": "https://github.com/utopia-php/logger/tree/0.5.2" }, - "time": "2023-11-22T14:45:43+00:00" + "time": "2024-05-17T09:32:59+00:00" }, { "name": "utopia-php/messaging", - "version": "0.10.0", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "71dce00ad43eb278a877cb2c329f7b8d677adfeb" + "reference": "b499c3ad11af711c28252c62d83f24e6106a2154" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/71dce00ad43eb278a877cb2c329f7b8d677adfeb", - "reference": "71dce00ad43eb278a877cb2c329f7b8d677adfeb", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/b499c3ad11af711c28252c62d83f24e6106a2154", + "reference": "b499c3ad11af711c28252c62d83f24e6106a2154", "shasum": "" }, "require": { "ext-curl": "*", "ext-openssl": "*", + "giggsey/libphonenumber-for-php-lite": "8.13.36", "php": ">=8.0.0", "phpmailer/phpmailer": "6.9.1" }, @@ -2031,9 +2236,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.10.0" + "source": "https://github.com/utopia-php/messaging/tree/0.11.0" }, - "time": "2024-02-20T07:30:15+00:00" + "time": "2024-05-08T17:10:02+00:00" }, { "name": "utopia-php/migration", @@ -2242,6 +2447,110 @@ }, "time": "2024-06-03T18:01:18+00:00" }, + { + "name": "utopia-php/pools", + "version": "0.5.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/pools.git", + "reference": "6f716a213a08db95eda1b5dddfa90983c1834817" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/6f716a213a08db95eda1b5dddfa90983c1834817", + "reference": "6f716a213a08db95eda1b5dddfa90983c1834817", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpstan/phpstan": "1.8.*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Pools\\": "src/Pools" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Team Appwrite", + "email": "team@appwrite.io" + } + ], + "description": "A simple library to manage connection pools", + "keywords": [ + "framework", + "php", + "pools", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/pools/issues", + "source": "https://github.com/utopia-php/pools/tree/0.5.0" + }, + "time": "2024-04-19T11:11:54+00:00" + }, + { + "name": "utopia-php/preloader", + "version": "0.2.4", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/preloader.git", + "reference": "65ef48392e72172f584b0baa2e224f9a1cebcce0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/preloader/zipball/65ef48392e72172f584b0baa2e224f9a1cebcce0", + "reference": "65ef48392e72172f584b0baa2e224f9a1cebcce0", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "vimeo/psalm": "4.0.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Preloader\\": "src/Preloader" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eldad Fux", + "email": "team@appwrite.io" + } + ], + "description": "Utopia Preloader library is simple and lite library for managing PHP preloading configuration", + "keywords": [ + "framework", + "php", + "preload", + "preloader", + "preloading", + "upf", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/preloader/issues", + "source": "https://github.com/utopia-php/preloader/tree/0.2.4" + }, + "time": "2020-10-24T07:04:59+00:00" + }, { "name": "utopia-php/queue", "version": "dev-feat-coroutine-and-di", @@ -2541,22 +2850,22 @@ }, { "name": "utopia-php/vcs", - "version": "0.6.6", + "version": "0.6.7", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "e538264cfee5e3efdfe1771efba04750cf20b2c4" + "reference": "8d8ff1ac68e991b95adb6f91fcde8f9bb8f24974" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/e538264cfee5e3efdfe1771efba04750cf20b2c4", - "reference": "e538264cfee5e3efdfe1771efba04750cf20b2c4", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/8d8ff1ac68e991b95adb6f91fcde8f9bb8f24974", + "reference": "8d8ff1ac68e991b95adb6f91fcde8f9bb8f24974", "shasum": "" }, "require": { "adhocore/jwt": "^1.1", "php": ">=8.0", - "utopia-php/cache": "^0.9.0", + "utopia-php/cache": "^0.10.0", "utopia-php/framework": "0.*.*" }, "require-dev": { @@ -2584,9 +2893,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.6.6" + "source": "https://github.com/utopia-php/vcs/tree/0.6.7" }, - "time": "2024-05-17T09:36:30+00:00" + "time": "2024-06-05T17:38:29+00:00" }, { "name": "utopia-php/view", @@ -5204,16 +5513,16 @@ }, { "name": "swoole/ide-helper", - "version": "5.0.2", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/swoole/ide-helper.git", - "reference": "16cfee44a6ec92254228c39bcab2fb8ae74cc2ea" + "reference": "33ec7af9111b76d06a70dd31191cc74793551112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swoole/ide-helper/zipball/16cfee44a6ec92254228c39bcab2fb8ae74cc2ea", - "reference": "16cfee44a6ec92254228c39bcab2fb8ae74cc2ea", + "url": "https://api.github.com/repos/swoole/ide-helper/zipball/33ec7af9111b76d06a70dd31191cc74793551112", + "reference": "33ec7af9111b76d06a70dd31191cc74793551112", "shasum": "" }, "type": "library", @@ -5230,9 +5539,9 @@ "description": "IDE help files for Swoole.", "support": { "issues": "https://github.com/swoole/ide-helper/issues", - "source": "https://github.com/swoole/ide-helper/tree/5.0.2" + "source": "https://github.com/swoole/ide-helper/tree/5.1.2" }, - "time": "2023-03-20T06:05:55+00:00" + "time": "2024-02-01T22:28:11+00:00" }, { "name": "symfony/polyfill-ctype", @@ -5314,87 +5623,6 @@ ], "time": "2024-05-31T15:07:36+00:00" }, - { - "name": "symfony/polyfill-mbstring", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "098e36a5b73de12beeb5ac17e80abf3696f7ad5f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/098e36a5b73de12beeb5ac17e80abf3696f7ad5f", - "reference": "098e36a5b73de12beeb5ac17e80abf3696f7ad5f", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/1.x" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T15:07:36+00:00" - }, { "name": "textalk/websocket", "version": "1.5.7", @@ -5565,45 +5793,6 @@ } ], "time": "2023-11-21T18:54:41+00:00" - }, - { - "name": "utopia-php/fetch", - "version": "0.1.0", - "source": { - "type": "git", - "url": "https://github.com/utopia-php/fetch.git", - "reference": "2fa214b9262acd1a3583515a364da4f35929d5c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/utopia-php/fetch/zipball/2fa214b9262acd1a3583515a364da4f35929d5c5", - "reference": "2fa214b9262acd1a3583515a364da4f35929d5c5", - "shasum": "" - }, - "require": { - "php": ">=8.0" - }, - "require-dev": { - "laravel/pint": "^1.5.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Utopia\\Fetch\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A simple library that provides an interface for making HTTP Requests.", - "support": { - "issues": "https://github.com/utopia-php/fetch/issues", - "source": "https://github.com/utopia-php/fetch/tree/0.1.0" - }, - "time": "2023-10-10T11:58:32+00:00" } ], "aliases": [ diff --git a/docker-compose.yml b/docker-compose.yml index b1e30a1e07..454df05b67 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,6 +40,7 @@ services: networks: - gateway - appwrite + - runtimes appwrite: container_name: appwrite @@ -48,10 +49,10 @@ services: build: context: . args: - DEBUG: false + DEBUG: true TESTING: true VERSION: dev - ports: + ports: - 9501:80 networks: - appwrite @@ -75,9 +76,11 @@ services: - appwrite-config:/storage/config:rw - appwrite-certificates:/storage/certificates:rw - appwrite-functions:/storage/functions:rw + - appwrite-builds:/storage/builds:rw - ./phpunit.xml:/usr/src/code/phpunit.xml - ./tests:/usr/src/code/tests - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./docs:/usr/src/code/docs - ./public:/usr/src/code/public - ./src:/usr/src/code/src @@ -91,8 +94,8 @@ services: - -e - app/http.php environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - - _APP_EDITION - _APP_WORKER_PER_CORE - _APP_LOCALE - _APP_CONSOLE_WHITELIST_ROOT @@ -216,11 +219,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - mariadb - redis environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPTIONS_ABUSE @@ -248,11 +253,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -277,12 +284,14 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb - request-catcher environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -317,8 +326,10 @@ services: - appwrite-builds:/storage/builds:rw - appwrite-certificates:/storage/certificates:rw - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -366,11 +377,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -399,11 +412,13 @@ services: - appwrite-functions:/storage/functions:rw - appwrite-builds:/storage/builds:rw - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -467,8 +482,10 @@ services: - appwrite-config:/storage/config:rw - appwrite-certificates:/storage/certificates:rw - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -497,12 +514,14 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb - openruntimes-executor environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -536,12 +555,14 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - maildev # - smtp environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -570,12 +591,13 @@ services: networks: - appwrite volumes: - - appwrite-uploads:/storage/uploads:rw - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -625,11 +647,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src - ./tests:/usr/src/code/tests depends_on: - mariadb environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -659,10 +683,12 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_DOMAIN @@ -696,11 +722,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -727,11 +755,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - redis - mariadb environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -758,11 +788,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - mariadb - redis environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -785,11 +817,13 @@ services: - appwrite volumes: - ./app:/usr/src/code/app + - ./vendor:/usr/src/code/vendor - ./src:/usr/src/code/src depends_on: - mariadb - redis environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 @@ -809,6 +843,7 @@ services: networks: - appwrite environment: + - PHP_IDE_CONFIG=serverName=Appwrite - _APP_ASSISTANT_OPENAI_API_KEY openruntimes-executor: @@ -829,6 +864,7 @@ services: # It's not possible to share mount file between 2 containers without host mount (copying is too slow) - /tmp:/tmp:rw environment: + - PHP_IDE_CONFIG=serverName=Appwrite - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL - OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK @@ -872,6 +908,7 @@ services: - appwrite - runtimes environment: + - PHP_IDE_CONFIG=serverName=Appwrite - OPR_PROXY_WORKER_PER_CORE=$_APP_WORKER_PER_CORE - OPR_PROXY_ENV=$_APP_ENV - OPR_PROXY_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET @@ -985,6 +1022,7 @@ services: networks: - appwrite environment: + - PHP_IDE_CONFIG=serverName=Appwrite - REDIS_HOSTS=redis ports: - "8081:5540" @@ -998,6 +1036,7 @@ services: ports: - "9509:3000" environment: + - PHP_IDE_CONFIG=serverName=Appwrite - SERVER_URL=http://localhost/v1/graphql # Dev Tools End ------------------------------------------------------------------------------------------ diff --git a/src/Appwrite/Platform/Tasks/QueueRetry.php b/src/Appwrite/Platform/Tasks/QueueRetry.php index aeed4305ee..634147ec9c 100644 --- a/src/Appwrite/Platform/Tasks/QueueRetry.php +++ b/src/Appwrite/Platform/Tasks/QueueRetry.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Tasks; use Utopia\CLI\Console; +use Utopia\Http\Validator\Text; use Utopia\Http\Validator\WhiteList; use Utopia\Http\Validator\Wildcard; use Utopia\Platform\Action; diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 4712e58cbe..d21f1c267d 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -29,8 +29,8 @@ class Audits extends Action ->desc('Audits worker') ->inject('message') ->inject('dbForProject') - ->inject('auth') - ->callback(fn ($message, $dbForProject, ValidatorAuthorization $auth) => $this->action($message, $dbForProject, $auth)); + ->inject('authorization') + ->callback(fn ($message, $dbForProject, ValidatorAuthorization $authorization) => $this->action($message, $dbForProject, $authorization)); } diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 3e7992ed19..4199fe0268 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -52,8 +52,8 @@ class Builds extends Action ->inject('dbForProject') ->inject('deviceForFunctions') ->inject('log') - ->inject('auth') - ->callback(fn ($message, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log, Authorization $auth) => $this->action($message, $dbForConsole, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log, $auth)); + ->inject('authorization') + ->callback(fn ($message, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log, Authorization $authorization) => $this->action($message, $dbForConsole, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log, $authorization)); } /** diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 9e0ac558c6..45df3e924f 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -55,8 +55,8 @@ class Deletes extends Action ->inject('executionRetention') ->inject('auditRetention') ->inject('log') - ->inject('auth') - ->callback(fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log, ValidatorAuthorization $auth) => $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $abuseRetention, $executionRetention, $auditRetention, $log, $auth)); + ->inject('authorization') + ->callback(fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log, ValidatorAuthorization $authorization) => $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $abuseRetention, $executionRetention, $auditRetention, $log, $authorization)); } /**