Storage permission check fixes
This commit is contained in:
parent
20f621d05c
commit
69a79f660f
|
@ -104,7 +104,7 @@ App::post('/v1/storage/buckets')
|
|||
]);
|
||||
}
|
||||
|
||||
$bucket = $dbForProject->createDocument('buckets', new Document([
|
||||
$dbForProject->createDocument('buckets', new Document([
|
||||
'$id' => $bucketId,
|
||||
'$collection' => 'buckets',
|
||||
'$permissions' => $permissions,
|
||||
|
@ -121,7 +121,7 @@ App::post('/v1/storage/buckets')
|
|||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||
|
||||
$dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes);
|
||||
} catch (Duplicate $th) {
|
||||
} catch (Duplicate) {
|
||||
throw new Exception('Bucket already exists', 409, Exception::STORAGE_BUCKET_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
|
@ -350,37 +350,27 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
->inject('deviceFiles')
|
||||
->inject('deviceLocal')
|
||||
->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Audit $audits, Stats $usage, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal) {
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$permissions = PermissionsProcessor::addDefaultsIfNeeded($permissions, $user->getId());
|
||||
$permissions = PermissionsProcessor::handleAggregates($permissions);
|
||||
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($bucket->getWrite())) {
|
||||
$validator = new Authorization('create');
|
||||
$valid = $validator->isValid($bucket->getCreate());
|
||||
if ($bucket->getAttribute('fileSecurity', false)) {
|
||||
$valid |= $validator->isValid($permissions);
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// Users can only add their roles to files, API keys and Admin users can add any
|
||||
$roles = Authorization::getRoles();
|
||||
|
||||
if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) {
|
||||
foreach ($permissions as $permission) {
|
||||
$matches = [];
|
||||
if (\preg_match('/^create\((.+)(?:,(.+))*\)$/', $permission, $matches)) {
|
||||
\array_shift($matches);
|
||||
foreach ($matches as $match) {
|
||||
if (!Authorization::isRole($match)) {
|
||||
throw new Exception('Permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!PermissionsProcessor::allowedForUserType($permissions)) {
|
||||
throw new Exception('Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$file = $request->getFiles('file');
|
||||
|
@ -456,13 +446,9 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
$path = $deviceFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION));
|
||||
$path = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root
|
||||
|
||||
if ($permissionBucket) {
|
||||
$file = Authorization::skip(function () use ($dbForProject, $bucket, $fileId) {
|
||||
return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
});
|
||||
} else {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
}
|
||||
$file = Authorization::skip(function () use ($dbForProject, $bucket, $fileId) {
|
||||
return $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
});
|
||||
|
||||
$metadata = ['content_type' => $deviceLocal->getFileMimeType($fileTmpName)];
|
||||
if (!$file->isEmpty()) {
|
||||
|
@ -478,8 +464,6 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
throw new Exception('Failed uploading file', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$read = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? [];
|
||||
$write = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? [];
|
||||
if ($chunksUploaded === $chunks) {
|
||||
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled' && $bucket->getAttribute('antivirus', true) && $fileSize <= APP_LIMIT_ANTIVIRUS && App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) === Storage::DEVICE_LOCAL) {
|
||||
$antivirus = new Network(
|
||||
|
@ -552,11 +536,8 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
'search' => implode(' ', [$fileId, $fileName]),
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
if ($permissionBucket) {
|
||||
$file = Authorization::skip(fn () => $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc));
|
||||
} else {
|
||||
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
|
||||
}
|
||||
|
||||
$file = Authorization::skip(fn () => $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc));
|
||||
} else {
|
||||
$file = $file
|
||||
->setAttribute('$permissions', $permissions)
|
||||
|
@ -571,15 +552,11 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
->setAttribute('metadata', $metadata)
|
||||
->setAttribute('chunksUploaded', $chunksUploaded);
|
||||
|
||||
if ($permissionBucket) {
|
||||
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
|
||||
} else {
|
||||
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
|
||||
}
|
||||
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
|
||||
}
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
} catch (DuplicateException $exception) {
|
||||
} catch (DuplicateException) {
|
||||
throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
|
@ -612,25 +589,18 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
'search' => implode(' ', [$fileId, $fileName]),
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
if ($permissionBucket) {
|
||||
$file = Authorization::skip(fn () => $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc));
|
||||
} else {
|
||||
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
|
||||
}
|
||||
|
||||
$file = Authorization::skip(fn () => $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc));
|
||||
} else {
|
||||
$file = $file
|
||||
->setAttribute('chunksUploaded', $chunksUploaded)
|
||||
->setAttribute('metadata', $metadata);
|
||||
|
||||
if ($permissionBucket) {
|
||||
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
|
||||
} else {
|
||||
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
|
||||
}
|
||||
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
|
||||
}
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
} catch (DuplicateException $exception) {
|
||||
} catch (DuplicateException) {
|
||||
throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
|
@ -674,10 +644,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
|||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
@ -693,10 +660,10 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
|||
}
|
||||
|
||||
if (!empty($cursor)) {
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$cursorFile = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor));
|
||||
} else {
|
||||
if ($bucket->getAttribute('fileSecurity', false)) {
|
||||
$cursorFile = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor);
|
||||
} else {
|
||||
$cursorFile = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor));
|
||||
}
|
||||
|
||||
if ($cursorFile->isEmpty()) {
|
||||
|
@ -710,7 +677,11 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
|||
$queries[] = new Query('search', Query::TYPE_SEARCH, [$search]);
|
||||
}
|
||||
|
||||
$files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection));
|
||||
if ($bucket->getAttribute('fileSecurity', false)) {
|
||||
$files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection);
|
||||
} else {
|
||||
$files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection));
|
||||
}
|
||||
|
||||
$usage
|
||||
->setParam('storage.files.read', 1)
|
||||
|
@ -745,27 +716,30 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization('read');
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$valid && !$fileSecurity) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($fileSecurity) {
|
||||
$valid |= $validator->isValid($file->getRead());
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$usage
|
||||
->setParam('storage.files.read', 1)
|
||||
->setParam('bucketId', $bucketId)
|
||||
|
@ -815,19 +789,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization('read');
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$valid && !$fileSecurity) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ((\strpos($request->getAccept(), 'image/webp') === false) && ('webp' === $output)) { // Fallback webp to jpeg when no browser support
|
||||
|
@ -841,12 +811,19 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
|
||||
$key = \md5($fileId . $width . $height . $gravity . $quality . $borderWidth . $borderColor . $borderRadius . $opacity . $rotation . $background . $output);
|
||||
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($fileSecurity) {
|
||||
$valid |= $validator->isValid($file->getRead());
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$path = $file->getAttribute('path');
|
||||
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
|
||||
$algorithm = $file->getAttribute('algorithm');
|
||||
|
@ -978,27 +955,30 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization('read');
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$valid && !$fileSecurity) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($bucket->getAttribute('fileSecurity', false)) {
|
||||
$valid |= $validator->isValid($file->getRead());
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$path = $file->getAttribute('path', '');
|
||||
|
||||
if (!$deviceFiles->exists($path)) {
|
||||
|
@ -1113,41 +1093,38 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization('read');
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$valid && !$fileSecurity) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
} else {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
}
|
||||
|
||||
$mimes = Config::getParam('storage-mimes');
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($fileSecurity) {
|
||||
$valid |= $validator->isValid($file->getRead());
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$mimes = Config::getParam('storage-mimes');
|
||||
|
||||
$path = $file->getAttribute('path', '');
|
||||
|
||||
if (!$deviceFiles->exists($path)) {
|
||||
throw new Exception('File not found in ' . $path, 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$compressor = new GZIP();
|
||||
|
||||
$contentType = 'text/plain';
|
||||
|
||||
if (\in_array($file->getAttribute('mimeType'), $mimes)) {
|
||||
|
@ -1265,75 +1242,42 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
->inject('mode')
|
||||
->inject('events')
|
||||
->action(function (string $bucketId, string $fileId, ?array $permissions, Response $response, Database $dbForProject, Document $user, Audit $audits, Stats $usage, string $mode, Event $events) {
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (\is_null($permissions)) {
|
||||
$permissions = [];
|
||||
if (!$user->isEmpty()) {
|
||||
$permissions = [
|
||||
'read(user:' . $user->getId() . ') ',
|
||||
'write(user:' . $user->getId() . ') ',
|
||||
];
|
||||
}
|
||||
} elseif (empty(\preg_grep('#^read\(.+\)$#', $permissions))) {
|
||||
if (!$user->isEmpty()) {
|
||||
$permissions[] = 'read(user:' . $user->getId() . ')';
|
||||
}
|
||||
} elseif (empty(\preg_grep('#^write\(.+\)$#', $permissions))) {
|
||||
if (!$user->isEmpty()) {
|
||||
$permissions[] = 'write(user:' . $user->getId() . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Users can only add their roles to files, API keys and Admin users can add any
|
||||
$roles = Authorization::getRoles();
|
||||
|
||||
if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) {
|
||||
foreach ($permissions as $permission) {
|
||||
$matches = [];
|
||||
if (\preg_match('/^(update|write)\((.+)(?:,(.+))*\)$/', $permission, $matches)) {
|
||||
\array_shift($matches);
|
||||
foreach ($matches as $match) {
|
||||
if (!Authorization::isRole($match)) {
|
||||
throw new Exception('Permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($bucket->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
$fileSecurity = $bucket->getAttributes('fileSecurity', false);
|
||||
$validator = new Authorization('update');
|
||||
$valid = $validator->isValid($bucket->getUpdate());
|
||||
if (!$valid && !$fileSecurity) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
} else {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
}
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($fileSecurity) {
|
||||
$valid |= $validator->isValid($file->getUpdate());
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$permissions = PermissionsProcessor::handleAggregates($permissions);
|
||||
|
||||
if (!PermissionsProcessor::allowedForUserType($permissions)) {
|
||||
throw new Exception('Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$file->setAttribute('$permissions', $permissions);
|
||||
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
|
||||
} else {
|
||||
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
|
||||
}
|
||||
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
|
||||
|
||||
$events
|
||||
->setParam('bucketId', $bucket->getId())
|
||||
|
@ -1376,31 +1320,30 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $events, Audit $audits, Stats $usage, string $mode, Device $deviceFiles, Document $project) {
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if (
|
||||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($bucket->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
$fileSecurity = $bucket->getAttributes('fileSecurity', false);
|
||||
$validator = new Authorization('delete');
|
||||
$valid = $validator->isValid($bucket->getDelete());
|
||||
if (!$valid && !$fileSecurity) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
} else {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
}
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($fileSecurity) {
|
||||
$valid |= $validator->isValid($file->getDelete());
|
||||
}
|
||||
if (!$valid) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$deviceDeleted = false;
|
||||
if ($file->getAttribute('chunksTotal') !== $file->getAttribute('chunksUploaded')) {
|
||||
$deviceDeleted = $deviceFiles->abort(
|
||||
|
@ -1417,11 +1360,8 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
$deviceLocal = new Local($cacheDir);
|
||||
$deviceLocal->delete($cacheDir, true);
|
||||
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
} else {
|
||||
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
}
|
||||
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
|
||||
if (!$deleted) {
|
||||
throw new Exception('Failed to remove file from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue