From fd2410d2ae5baa74c14c7e42c2bed72a87940a73 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sun, 14 Apr 2024 22:42:31 +0200 Subject: [PATCH] Fixed bootstrap --- app/controllers/api/projects.php | 1 - app/controllers/api/storage.php | 160 +++++++++++++++---------------- app/controllers/general.php | 2 +- app/http.php | 7 +- app/init2.php | 123 ++++++++++++++++++++++++ phpunit.xml | 2 +- 6 files changed, 207 insertions(+), 88 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 77052aba2..c1889a569 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -42,7 +42,6 @@ use Utopia\Http\Validator\Text; use Utopia\Http\Validator\URL; use Utopia\Http\Validator\WhiteList; use Utopia\Locale\Locale; -use Utopia\Pools\Group; use Utopia\System\System; Http::init() diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 12be11726..cec4c115a 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -365,19 +365,19 @@ Http::post('/v1/storage/buckets/:bucketId/files') ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $auth) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $authorization) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$auth->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -401,7 +401,7 @@ Http::post('/v1/storage/buckets/:bucketId/files') } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $auth->getRoles(); + $roles = $authorization->getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -414,7 +414,7 @@ Http::post('/v1/storage/buckets/:bucketId/files') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$auth->isRole($role)) { + if (!$authorization->isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -635,10 +635,10 @@ Http::post('/v1/storage/buckets/:bucketId/files') * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - if (!$auth->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = $auth->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); @@ -681,10 +681,10 @@ Http::post('/v1/storage/buckets/:bucketId/files') * However as with chunk upload even if we are updating, we are essentially creating a file * adding it's new chunk so we validate create permission instead of update */ - if (!$auth->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = $auth->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); @@ -726,19 +726,19 @@ Http::get('/v1/storage/buckets/:bucketId/files') ->inject('response') ->inject('dbForProject') ->inject('mode') - ->inject('auth') - ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode, Authorization $auth) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -767,7 +767,7 @@ Http::get('/v1/storage/buckets/:bucketId/files') if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $cursorDocument = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -783,8 +783,8 @@ Http::get('/v1/storage/buckets/:bucketId/files') $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = $auth->skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); - $total = $auth->skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); + $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); + $total = $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); } $response->dynamic(new Document([ @@ -810,19 +810,19 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('response') ->inject('dbForProject') ->inject('mode') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode, Authorization $auth) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -830,7 +830,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId') if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -875,24 +875,24 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $auth) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $authorization) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -900,7 +900,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -1035,20 +1035,20 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->inject('dbForProject') ->inject('mode') ->inject('deviceForFiles') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceForFiles, Authorization $auth) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceForFiles, Authorization $authorization) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1056,7 +1056,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/download') if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -1175,19 +1175,19 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->inject('dbForProject') ->inject('mode') ->inject('deviceForFiles') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceForFiles, Authorization $auth) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceForFiles, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1195,7 +1195,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/view') if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -1324,9 +1324,9 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->inject('project') ->inject('mode') ->inject('deviceForFiles') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Document $project, string $mode, Device $deviceForFiles, Authorization $auth) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Document $project, string $mode, Device $deviceForFiles, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1')); @@ -1345,14 +1345,14 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/push') throw new Exception(Exception::USER_UNAUTHORIZED); } - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1490,26 +1490,26 @@ Http::put('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('user') ->inject('mode') ->inject('queueForEvents') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents, Authorization $auth) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents, Authorization $authorization) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for update - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1523,7 +1523,7 @@ Http::put('/v1/storage/buckets/:bucketId/files/:fileId') ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $auth->getRoles(); + $roles = $authorization->getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -1536,7 +1536,7 @@ Http::put('/v1/storage/buckets/:bucketId/files/:fileId') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$auth->isRole($role)) { + if (!$authorization->isRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -1560,7 +1560,7 @@ Http::put('/v1/storage/buckets/:bucketId/files/:fileId') throw new Exception(Exception::USER_UNAUTHORIZED); } } else { - $file = $auth->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } $queueForEvents @@ -1596,32 +1596,32 @@ Http::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('mode') ->inject('deviceForFiles') ->inject('queueForDeletes') - ->inject('auth') - ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes, Authorization $auth) { - $bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($auth->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $auth->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for delete - $file = $auth->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } // Make sure we don't delete the file before the document permission check occurs - if ($fileSecurity && !$valid && !$auth->isValid($file->getDelete())) { + if ($fileSecurity && !$valid && !$authorization->isValid($file->getDelete())) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1649,7 +1649,7 @@ Http::delete('/v1/storage/buckets/:bucketId/files/:fileId') throw new Exception(Exception::USER_UNAUTHORIZED); } } else { - $deleted = $auth->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $deleted = $authorization->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if (!$deleted) { @@ -1682,8 +1682,8 @@ Http::get('/v1/storage/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('auth') - ->action(function (string $range, Response $response, Database $dbForProject, Authorization $auth) { + ->inject('authorization') + ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -1695,7 +1695,7 @@ Http::get('/v1/storage/usage') ]; $total = []; - $auth->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -1763,8 +1763,8 @@ Http::get('/v1/storage/:bucketId/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->inject('auth') - ->action(function (string $bucketId, string $range, Response $response, Database $dbForProject, Authorization $auth) { + ->inject('authorization') + ->action(function (string $bucketId, string $range, Response $response, Database $dbForProject, Authorization $authorization) { $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -1780,7 +1780,7 @@ Http::get('/v1/storage/:bucketId/usage') str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE), ]; - $auth->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), diff --git a/app/controllers/general.php b/app/controllers/general.php index 3855791ba..b81238a19 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -902,7 +902,7 @@ include_once 'api/locale.php'; //include_once 'api/migrations.php'; include_once 'api/projects.php'; //include_once 'api/proxy.php'; -//include_once 'api/storage.php'; +include_once 'api/storage.php'; include_once 'api/teams.php'; include_once 'api/users.php'; //include_once 'api/vcs.php'; diff --git a/app/http.php b/app/http.php index 2fe80777f..2d7a677ae 100644 --- a/app/http.php +++ b/app/http.php @@ -36,6 +36,8 @@ $server = new Server('0.0.0.0', '80', [ 'open_http2_protocol' => true, // 'http_compression' => true, // 'http_compression_level' => 6, + 'package_max_length' => $payloadSize, + 'buffer_output_size' => $payloadSize, // Server // 'log_level' => 0, @@ -57,11 +59,6 @@ $http->setRequestClass(Request::class); $http->setResponseClass(Response::class); //require_once __DIR__ . '/init.php'; -require_once __DIR__ . '/init/constants.php'; -require_once __DIR__ . '/init/config.php'; -require_once __DIR__ . '/init/locale.php'; -require_once __DIR__ . '/init/database/filters.php'; -require_once __DIR__ . '/init/database/formats.php'; require_once __DIR__ . '/init2.php'; require_once __DIR__ . '/controllers/general.php'; diff --git a/app/init2.php b/app/init2.php index af0f0d0a3..2d71d9f0f 100644 --- a/app/init2.php +++ b/app/init2.php @@ -1,5 +1,11 @@ getScheme(); + $accessKey = $dsn->getUser() ?? ''; + $accessSecret = $dsn->getPassword() ?? ''; + $bucket = $dsn->getPath() ?? ''; + $region = $dsn->getParam('region'); + } catch (\Throwable $e) { + Console::warning($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); + } + + switch ($device) { + case Storage::DEVICE_S3: + return new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case STORAGE::DEVICE_DO_SPACES: + return new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_BACKBLAZE: + return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_LINODE: + return new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_WASABI: + return new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_LOCAL: + default: + return new Local($root); + } + } else { + switch (strtolower(System::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) { + case Storage::DEVICE_LOCAL: + default: + return new Local($root); + case Storage::DEVICE_S3: + $s3AccessKey = System::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); + $s3SecretKey = System::getEnv('_APP_STORAGE_S3_SECRET', ''); + $s3Region = System::getEnv('_APP_STORAGE_S3_REGION', ''); + $s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', ''); + $s3Acl = 'private'; + return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); + case Storage::DEVICE_DO_SPACES: + $doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); + $doSpacesSecretKey = System::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); + $doSpacesRegion = System::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); + $doSpacesBucket = System::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); + $doSpacesAcl = 'private'; + return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); + case Storage::DEVICE_BACKBLAZE: + $backblazeAccessKey = System::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); + $backblazeSecretKey = System::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); + $backblazeRegion = System::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); + $backblazeBucket = System::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); + $backblazeAcl = 'private'; + return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); + case Storage::DEVICE_LINODE: + $linodeAccessKey = System::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); + $linodeSecretKey = System::getEnv('_APP_STORAGE_LINODE_SECRET', ''); + $linodeRegion = System::getEnv('_APP_STORAGE_LINODE_REGION', ''); + $linodeBucket = System::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); + $linodeAcl = 'private'; + return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); + case Storage::DEVICE_WASABI: + $wasabiAccessKey = System::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); + $wasabiSecretKey = System::getEnv('_APP_STORAGE_WASABI_SECRET', ''); + $wasabiRegion = System::getEnv('_APP_STORAGE_WASABI_REGION', ''); + $wasabiBucket = System::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); + $wasabiAcl = 'private'; + return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); + } + } +} + $global = new Registry(); $global->set('logger', function () { @@ -742,6 +830,41 @@ $queueForMigrations }); $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') diff --git a/phpunit.xml b/phpunit.xml index 90ebd4225..d2bc4610c 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,6 +1,6 @@