Wrap all db exceptions in error handler

This commit is contained in:
Jake Barnby
2024-03-11 12:54:42 +01:00
parent f482d96225
commit cea4e0d8b6
4 changed files with 124 additions and 172 deletions
+23 -56
View File
@@ -662,8 +662,6 @@ App::put('/v1/databases/:databaseId')
->setAttribute('name', $name)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$databaseId, $name])));
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
}
@@ -1015,19 +1013,14 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
$enabled ??= $collection->getAttribute('enabled', true);
try {
$collection = $dbForProject->updateDocument('database_' . $database->getInternalId(), $collectionId, $collection
->setAttribute('name', $name)
->setAttribute('$permissions', $permissions)
->setAttribute('documentSecurity', $documentSecurity)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$collectionId, $name])));
$dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
}
$collection = $dbForProject->updateDocument('database_' . $database->getInternalId(), $collectionId, $collection
->setAttribute('name', $name)
->setAttribute('$permissions', $permissions)
->setAttribute('documentSecurity', $documentSecurity)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$collectionId, $name])));
$dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity);
$queueForEvents
->setContext('database', $database)
@@ -2936,14 +2929,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$filters = Query::groupByType($queries)['filters'];
try {
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filters, APP_LIMIT_COUNT);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $e->getMessage());
}
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filters, APP_LIMIT_COUNT);
// Add $collectionId and $databaseId for all documents
$processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool {
@@ -3069,13 +3056,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$queries = Query::parseQueries($queries);
try {
$document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $e->getMessage());
}
$document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries);
if ($document->isEmpty()) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
@@ -3387,22 +3368,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$setCollection($collection, $newDocument);
try {
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
fn() => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(),
$newDocument
)
);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
}
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
fn() => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(),
$newDocument
)
);
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
@@ -3502,16 +3475,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
}
$dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) {
try {
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documentId
);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (RestrictedException) {
throw new Exception(Exception::DOCUMENT_DELETE_RESTRICTED);
}
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documentId
);
});
// Add $collectionId and $databaseId for all documents
+83 -107
View File
@@ -581,111 +581,95 @@ App::post('/v1/storage/buckets/:bucketId/files')
$openSSLIV = \bin2hex($iv);
}
try {
if ($file->isEmpty()) {
$doc = new Document([
'$id' => $fileId,
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => $fileHash,
'mimeType' => $mimeType,
'sizeOriginal' => $fileSize,
'sizeActual' => $sizeActual,
'algorithm' => $algorithm,
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'openSSLVersion' => $openSSLVersion,
'openSSLCipher' => $openSSLCipher,
'openSSLTag' => $openSSLTag,
'openSSLIV' => $openSSLIV,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
if ($file->isEmpty()) {
$doc = new Document([
'$id' => $fileId,
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => $fileHash,
'mimeType' => $mimeType,
'sizeOriginal' => $fileSize,
'sizeActual' => $sizeActual,
'algorithm' => $algorithm,
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'openSSLVersion' => $openSSLVersion,
'openSSLCipher' => $openSSLCipher,
'openSSLTag' => $openSSLTag,
'openSSLIV' => $openSSLIV,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('$permissions', $permissions)
->setAttribute('signature', $fileHash)
->setAttribute('mimeType', $mimeType)
->setAttribute('sizeActual', $sizeActual)
->setAttribute('algorithm', $algorithm)
->setAttribute('openSSLVersion', $openSSLVersion)
->setAttribute('openSSLCipher', $openSSLCipher)
->setAttribute('openSSLTag', $openSSLTag)
->setAttribute('openSSLIV', $openSSLIV)
->setAttribute('metadata', $metadata)
->setAttribute('chunksUploaded', $chunksUploaded);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('$permissions', $permissions)
->setAttribute('signature', $fileHash)
->setAttribute('mimeType', $mimeType)
->setAttribute('sizeActual', $sizeActual)
->setAttribute('algorithm', $algorithm)
->setAttribute('openSSLVersion', $openSSLVersion)
->setAttribute('openSSLCipher', $openSSLCipher)
->setAttribute('openSSLTag', $openSSLTag)
->setAttribute('openSSLIV', $openSSLIV)
->setAttribute('metadata', $metadata)
->setAttribute('chunksUploaded', $chunksUploaded);
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* 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
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* 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
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
}
} else {
try {
if ($file->isEmpty()) {
$doc = new Document([
'$id' => ID::custom($fileId),
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => '',
'mimeType' => '',
'sizeOriginal' => $fileSize,
'sizeActual' => 0,
'algorithm' => '',
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
if ($file->isEmpty()) {
$doc = new Document([
'$id' => ID::custom($fileId),
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => '',
'mimeType' => '',
'sizeOriginal' => $fileSize,
'sizeActual' => 0,
'algorithm' => '',
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('chunksUploaded', $chunksUploaded)
->setAttribute('metadata', $metadata);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('chunksUploaded', $chunksUploaded)
->setAttribute('metadata', $metadata);
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* 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
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* 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
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
}
}
@@ -1383,11 +1367,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
}
if ($fileSecurity && !$valid) {
try {
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
} else {
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
}
@@ -1471,11 +1451,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
;
if ($fileSecurity && !$valid) {
try {
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
} else {
$deleted = Authorization::skip(fn() => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId));
}
+1 -8
View File
@@ -1036,14 +1036,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception(Exception::TEAM_NOT_FOUND);
}
try {
$dbForProject->deleteDocument('memberships', $membership->getId());
} catch (AuthorizationException $exception) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (\Exception $exception) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB');
}
$dbForProject->deleteDocument('memberships', $membership->getId());
$dbForProject->deleteCachedDocument('users', $user->getId());
if ($membership->getAttribute('confirm')) { // Count only confirmed members
+17 -1
View File
@@ -810,7 +810,7 @@ App::error()
}
}
if ($logger && ($publish || $error->getCode() === 0)) {
if ($logger && $publish) {
try {
/** @var Utopia\Database\Document $user */
$user = $utopia->getResource('user');
@@ -892,6 +892,22 @@ App::error()
$error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error);
$code = $error->getCode();
$message = $error->getMessage();
} elseif ($error instanceof Utopia\Database\Exception\Query) {
$error = new AppwriteException(AppwriteException::GENERAL_QUERY_INVALID, previous: $error);
$code = $error->getCode();
$message = $error->getMessage();
} elseif ($error instanceof Utopia\Database\Exception\Structure) {
$error = new AppwriteException(AppwriteException::DOCUMENT_INVALID_STRUCTURE, $error->getMessage(), previous: $error);
$code = $error->getCode();
$message = $error->getMessage();
} elseif ($error instanceof Utopia\Database\Exception\Duplicate) {
$error = new AppwriteException(AppwriteException::DOCUMENT_ALREADY_EXISTS);
$code = $error->getCode();
$message = $error->getMessage();
} elseif ($error instanceof Utopia\Database\Exception\Restricted) {
$error = new AppwriteException(AppwriteException::DOCUMENT_DELETE_RESTRICTED);
$code = $error->getCode();
$message = $error->getMessage();
}
/** Wrap all exceptions inside Appwrite\Extend\Exception */