diff --git a/app/config/errors.php b/app/config/errors.php index cf407f7816..28220072a5 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -18,6 +18,16 @@ return [ 'description' => 'The requested service is disabled. You can enable/disable a service from the Appwrite console or by contacting the project owner.', 'statusCode' => 503, ], + Exception::INVALID_READ_PERMISSIONS => [ + 'name' => Exception::INVALID_READ_PERMISSIONS, + 'description' => 'Invalid format for read permissions. Please check the documentation.', + 'statusCode' => 400, + ], + Exception::INVALID_WRITE_PERMISSIONS => [ + 'name' => Exception::INVALID_WRITE_PERMISSIONS, + 'description' => 'Invalid format for write permissions. Please check the documentation.', + 'statusCode' => 400, + ], Exception::UNAUTHORIZED_SCOPE => [ 'name' => Exception::UNAUTHORIZED_SCOPE, 'description' => 'The current user or API key does not have the required scopes to access the requested resource.', @@ -293,16 +303,6 @@ return [ 'description' => 'There was an error reading the file from disk.', 'statusCode' => 500, ], - Exception::STORAGE_INVALID_READ_PERMISSIONS => [ - 'name' => Exception::STORAGE_INVALID_READ_PERMISSIONS, - 'description' => 'Invalid format for read permissions. Please check the documentation.', - 'statusCode' => 400, - ], - Exception::STORAGE_INVALID_WRITE_PERMISSIONS => [ - 'name' => Exception::STORAGE_INVALID_WRITE_PERMISSIONS, - 'description' => 'Invalid format for write permissions. Please check the documentation.', - 'statusCode' => 400, - ], Exception::STORAGE_INVALID_FILE_SIZE => [ 'name' => Exception::STORAGE_INVALID_FILE_SIZE, 'description' => 'The file size is either not valid or exceeds the maximum allowed size.', diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index da3cfc68b0..a2710e9ae4 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -1,7 +1,7 @@ getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } if (!empty($format)) { if (!Structure::hasFormat($format, $type)) { - throw new Exception("Format {$format} not available for {$type} attributes.", 400); + throw new Exception("Format {$format} not available for {$type} attributes.", 400, Exception::ATTRIBUTE_FORMAT_UNSUPPORTED); } } // Must throw here since dbForProject->createAttribute is performed by db worker if ($required && $default) { - throw new Exception('Cannot set default value for required attribute', 400); + throw new Exception('Cannot set default value for required attribute', 400, Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED); } if ($array && $default) { - throw new Exception('Cannot set default value for array attributes', 400); + throw new Exception('Cannot set default value for array attributes', 400, Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED); } try { @@ -104,10 +104,10 @@ function createAttribute(string $collectionId, Document $attribute, Response $re $attribute = $dbForProject->createDocument('attributes', $attribute); } catch (DuplicateException $exception) { - throw new Exception('Attribute already exists', 409); + throw new Exception('Attribute already exists', 409, Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException $exception) { - throw new Exception('Attribute limit exceeded', 400); + throw new Exception('Attribute limit exceeded', 400, Exception::ATTRIBUTE_LIMIT_EXCEEDED); } $dbForProject->deleteCachedDocument('collections', $collectionId); @@ -180,9 +180,9 @@ App::post('/v1/database/collections') $dbForProject->createCollection('collection_' . $collectionId); } catch (DuplicateException $th) { - throw new Exception('Collection already exists', 409); + throw new Exception('Collection already exists', 409, Exception::COLLECTION_ALREADY_EXISTS); } catch (LimitException $th) { - throw new Exception('Collection limit exceeded', 400); + throw new Exception('Collection limit exceeded', 400, Exception::COLLECTION_LIMIT_EXCEEDED); } $audits @@ -225,7 +225,7 @@ App::get('/v1/database/collections') $cursorCollection = $dbForProject->getDocument('collections', $cursor); if ($cursorCollection->isEmpty()) { - throw new Exception("Collection '{$cursor}' for the 'cursor' value not found.", 400); + throw new Exception("Collection '{$cursor}' for the 'cursor' value not found.", 400, Exception::COLLECTION_NOT_FOUND); } } @@ -265,7 +265,7 @@ App::get('/v1/database/collections/:collectionId') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $usage->setParam('database.collections.read', 1); @@ -405,7 +405,7 @@ App::get('/v1/database/:collectionId/usage') $collection = $dbForProject->getCollection('collection_' . $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $usage = []; @@ -516,7 +516,7 @@ App::get('/v1/database/collections/:collectionId/logs') $collection = $dbForProject->getCollection('collection_' . $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $audit = new Audit($dbForProject); @@ -605,7 +605,7 @@ App::put('/v1/database/collections/:collectionId') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $read ??= $collection->getRead() ?? []; // By default inherit read permissions @@ -624,10 +624,10 @@ App::put('/v1/database/collections/:collectionId') ); } catch (AuthorizationException $exception) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } catch (StructureException $exception) { - throw new Exception('Bad structure. '.$exception->getMessage(), 400); + throw new Exception('Bad structure. '.$exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } $usage->setParam('database.collections.update', 1); @@ -669,11 +669,11 @@ App::delete('/v1/database/collections/:collectionId') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } if (!$dbForProject->deleteDocument('collections', $collectionId)) { - throw new Exception('Failed to remove collection from DB', 500); + throw new Exception('Failed to remove collection from DB', 500, Exception::COLLECTION_DELETION_FAILED); } $dbForProject->deleteCachedCollection('collection_' . $collectionId); @@ -731,7 +731,7 @@ App::post('/v1/database/collections/:collectionId/attributes/string') // Ensure attribute default is within required size $validator = new Text($size); if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception($validator->getDescription(), 400); + throw new Exception($validator->getDescription(), 400, Exception::ATTRIBUTE_VALUE_INVALID); } $attribute = createAttribute($collectionId, new Document([ @@ -823,14 +823,14 @@ App::post('/v1/database/collections/:collectionId/attributes/enum') foreach ($elements as $element) { $length = \strlen($element); if ($length === 0) { - throw new Exception('Each enum element must not be empty', 400); + throw new Exception('Each enum element must not be empty', 400, Exception::ATTRIBUTE_VALUE_INVALID); } $size = ($length > $size) ? $length : $size; } if (!is_null($default) && !in_array($default, $elements)) { - throw new Exception('Default value not found in elements', 400); + throw new Exception('Default value not found in elements', 400, Exception::ATTRIBUTE_VALUE_INVALID); } $attribute = createAttribute($collectionId, new Document([ @@ -966,13 +966,13 @@ App::post('/v1/database/collections/:collectionId/attributes/integer') $max = (is_null($max)) ? PHP_INT_MAX : \intval($max); if ($min > $max) { - throw new Exception('Minimum value must be lesser than maximum value', 400); + throw new Exception('Minimum value must be lesser than maximum value', 400, Exception::ATTRIBUTE_VALUE_INVALID); } $validator = new Range($min, $max, Database::VAR_INTEGER); if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception($validator->getDescription(), 400); + throw new Exception($validator->getDescription(), 400, Exception::ATTRIBUTE_VALUE_INVALID); } $size = $max > 2147483647 ? 8 : 4; // Automatically create BigInt depending on max value @@ -1037,7 +1037,7 @@ App::post('/v1/database/collections/:collectionId/attributes/float') $max = (is_null($max)) ? PHP_FLOAT_MAX : \floatval($max); if ($min > $max) { - throw new Exception('Minimum value must be lesser than maximum value', 400); + throw new Exception('Minimum value must be lesser than maximum value', 400, Exception::ATTRIBUTE_VALUE_INVALID); } // Ensure default value is a float @@ -1048,7 +1048,7 @@ App::post('/v1/database/collections/:collectionId/attributes/float') $validator = new Range($min, $max, Database::VAR_FLOAT); if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception($validator->getDescription(), 400); + throw new Exception($validator->getDescription(), 400, Exception::ATTRIBUTE_VALUE_INVALID); } $attribute = createAttribute($collectionId, new Document([ @@ -1138,7 +1138,7 @@ App::get('/v1/database/collections/:collectionId/attributes') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $attributes = $collection->getAttribute('attributes'); @@ -1182,13 +1182,13 @@ App::get('/v1/database/collections/:collectionId/attributes/:key') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $attribute = $dbForProject->getDocument('attributes', $collectionId.'_'.$key); if ($attribute->isEmpty()) { - throw new Exception('Attribute not found', 404); + throw new Exception('Attribute not found', 404, Exception::ATTRIBUTE_NOT_FOUND); } // Select response model based on type and format @@ -1244,13 +1244,13 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $attribute = $dbForProject->getDocument('attributes', $collectionId.'_'.$key); if ($attribute->isEmpty()) { - throw new Exception('Attribute not found', 404); + throw new Exception('Attribute not found', 404, Exception::ATTRIBUTE_NOT_FOUND); } // Only update status if removing available attribute @@ -1332,7 +1332,7 @@ App::post('/v1/database/collections/:collectionId/indexes') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $count = $dbForProject->count('indexes', [ @@ -1342,7 +1342,7 @@ App::post('/v1/database/collections/:collectionId/indexes') $limit = 64 - MariaDB::getNumberOfDefaultIndexes(); if ($count >= $limit) { - throw new Exception('Index limit exceeded', 400); + throw new Exception('Index limit exceeded', 400, Exception::INDEX_LIMIT_EXCEEDED); } // Convert Document[] to array of attribute metadata @@ -1356,7 +1356,7 @@ App::post('/v1/database/collections/:collectionId/indexes') $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key')); if ($attributeIndex === false) { - throw new Exception('Unknown attribute: ' . $attribute, 400); + throw new Exception('Unknown attribute: ' . $attribute, 400, Exception::ATTRIBUTE_UNKNOWN); } $attributeStatus = $oldAttributes[$attributeIndex]['status']; @@ -1365,7 +1365,7 @@ App::post('/v1/database/collections/:collectionId/indexes') // ensure attribute is available if ($attributeStatus !== 'available') { - throw new Exception ('Attribute not available: ' . $oldAttributes[$attributeIndex]['key'], 400); + throw new Exception ('Attribute not available: ' . $oldAttributes[$attributeIndex]['key'], 400, Exception::ATTRIBUTE_NOT_AVAILABLE); } // set attribute size as index length only for strings @@ -1384,7 +1384,7 @@ App::post('/v1/database/collections/:collectionId/indexes') 'orders' => $orders, ])); } catch (DuplicateException $th) { - throw new Exception('Index already exists', 409); + throw new Exception('Index already exists', 409, Exception::INDEX_ALREADY_EXISTS); } $dbForProject->deleteCachedDocument('collections', $collectionId); @@ -1429,7 +1429,7 @@ App::get('/v1/database/collections/:collectionId/indexes') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $indexes = $collection->getAttribute('indexes'); @@ -1465,7 +1465,7 @@ App::get('/v1/database/collections/:collectionId/indexes/:key') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $indexes = $collection->getAttribute('indexes'); @@ -1474,7 +1474,7 @@ App::get('/v1/database/collections/:collectionId/indexes/:key') $indexIndex = array_search($key, array_column($indexes, 'key')); if ($indexIndex === false) { - throw new Exception('Index not found', 404); + throw new Exception('Index not found', 404, Exception::INDEX_NOT_FOUND); } $index = new Document([\array_merge($indexes[$indexIndex], [ @@ -1516,13 +1516,13 @@ App::delete('/v1/database/collections/:collectionId/indexes/:key') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $index = $dbForProject->getDocument('indexes', $collectionId.'_'.$key); if (empty($index->getId())) { - throw new Exception('Index not found', 404); + throw new Exception('Index not found', 404, Exception::INDEX_NOT_FOUND); } // Only update status if removing available index @@ -1589,11 +1589,11 @@ App::post('/v1/database/collections/:collectionId/documents') $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data)) { - throw new Exception('Missing payload', 400); + throw new Exception('Missing payload', 400, Exception::DOCUMENT_MISSING_PAYLOAD); } if (isset($data['$id'])) { - throw new Exception('$id is not allowed for creating new documents, try update instead', 400); + throw new Exception('$id is not allowed for creating new documents, try update instead', 400, Exception::DOCUMENT_INVALID_STRUCTURE); } /** @@ -1605,7 +1605,7 @@ App::post('/v1/database/collections/:collectionId/documents') if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } } @@ -1613,7 +1613,7 @@ App::post('/v1/database/collections/:collectionId/documents') if ($collection->getAttribute('permission') === 'collection') { $validator = new Authorization('write'); if (!$validator->isValid($collection->getWrite())) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } } @@ -1628,12 +1628,12 @@ App::post('/v1/database/collections/:collectionId/documents') if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach ($data['$read'] as $read) { if (!Authorization::isRole($read)) { - throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400); + throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_READ_PERMISSIONS); } } foreach ($data['$write'] as $write) { if (!Authorization::isRole($write)) { - throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400); + throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_WRITE_PERMISSIONS); } } } @@ -1648,10 +1648,10 @@ App::post('/v1/database/collections/:collectionId/documents') $document->setAttribute('$collection', $collectionId); } catch (StructureException $exception) { - throw new Exception($exception->getMessage(), 400); + throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } catch (DuplicateException $exception) { - throw new Exception('Document already exists', 409); + throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS); } $events->setParam('collection', $collection->getArrayCopy()); @@ -1709,7 +1709,7 @@ App::get('/v1/database/collections/:collectionId/documents') if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } } @@ -1717,7 +1717,7 @@ App::get('/v1/database/collections/:collectionId/documents') if ($collection->getAttribute('permission') === 'collection') { $validator = new Authorization('read'); if (!$validator->isValid($collection->getRead())) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } } @@ -1725,7 +1725,7 @@ App::get('/v1/database/collections/:collectionId/documents') $query = Query::parse($query); if (\count($query->getValues()) > 100) { - throw new Exception("You cannot use more than 100 query values on attribute '{$query->getAttribute()}'", 400); + throw new Exception("You cannot use more than 100 query values on attribute '{$query->getAttribute()}'", 400, Exception::QUERY_LIMIT_EXCEEDED); } return $query; @@ -1734,7 +1734,7 @@ App::get('/v1/database/collections/:collectionId/documents') if (!empty($queries)) { $validator = new QueriesValidator(new QueryValidator($collection->getAttribute('attributes', [])), $collection->getAttribute('indexes', []), true); if (!$validator->isValid($queries)) { - throw new Exception($validator->getDescription(), 400); + throw new Exception($validator->getDescription(), 400, Exception::QUERY_INVALID); } } @@ -1745,7 +1745,7 @@ App::get('/v1/database/collections/:collectionId/documents') : $dbForProject->getDocument('collection_' . $collectionId, $cursor); if ($cursorDocument->isEmpty()) { - throw new Exception("Document '{$cursor}' for the 'cursor' value not found.", 400); + throw new Exception("Document '{$cursor}' for the 'cursor' value not found.", 400, Exception::DOCUMENT_NOT_FOUND); } } @@ -1803,7 +1803,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } } @@ -1811,7 +1811,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->getAttribute('permission') === 'collection') { $validator = new Authorization('read'); if (!$validator->isValid($collection->getRead())) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } } @@ -1828,7 +1828,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') $document->setAttribute('$collection', $collectionId); if ($document->isEmpty()) { - throw new Exception('No document found', 404); + throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND); } $usage @@ -1868,13 +1868,13 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId/logs') $collection = $dbForProject->getDocument('collections', $collectionId); if ($collection->isEmpty()) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } $document = $dbForProject->getDocument('collection_' . $collectionId, $documentId); if ($document->isEmpty()) { - throw new Exception('No document found', 404); + throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND); } $audit = new Audit($dbForProject); @@ -1969,7 +1969,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } } @@ -1977,7 +1977,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->getAttribute('permission') === 'collection') { $validator = new Authorization('write'); if (!$validator->isValid($collection->getWrite())) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } $document = Authorization::skip(fn() => $dbForProject->getDocument('collection_' . $collectionId, $documentId)); @@ -1987,17 +1987,17 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') if ($document->isEmpty()) { - throw new Exception('Document not found', 404); + throw new Exception('Document not found', 404, Exception::DOCUMENT_NOT_FOUND); } $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data)) { - throw new Exception('Missing payload', 400); + throw new Exception('Missing payload', 400, Exception::DOCUMENT_MISSING_PAYLOAD); } if (!\is_array($data)) { - throw new Exception('Data param should be a valid JSON object', 400); + throw new Exception('Data param should be a valid JSON object', 400, Exception::DOCUMENT_INVALID_STRUCTURE); } $data = \array_merge($document->getArrayCopy(), $data); @@ -2013,12 +2013,12 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach ($data['$read'] as $read) { if (!Authorization::isRole($read)) { - throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400); + throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_READ_PERMISSIONS); } } foreach ($data['$write'] as $write) { if (!Authorization::isRole($write)) { - throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400); + throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_WRITE_PERMISSIONS); } } } @@ -2036,13 +2036,13 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') $document->setAttribute('$collection', $collectionId); } catch (AuthorizationException $exception) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } catch (DuplicateException $exception) { - throw new Exception('Document already exists', 409); + throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS); } catch (StructureException $exception) { - throw new Exception($exception->getMessage(), 400); + throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } $events->setParam('collection', $collection->getArrayCopy()); @@ -2097,7 +2097,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { - throw new Exception('Collection not found', 404); + throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } } @@ -2105,7 +2105,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') if ($collection->getAttribute('permission') === 'collection') { $validator = new Authorization('write'); if (!$validator->isValid($collection->getWrite())) { - throw new Exception('Unauthorized permissions', 401); + throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); } } @@ -2117,7 +2117,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') } if ($document->isEmpty()) { - throw new Exception('No document found', 404); + throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND); } if ($collection->getAttribute('permission') === 'collection') { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index bfb014b68f..0dbadb6aa8 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -68,12 +68,12 @@ App::post('/v1/storage/files') if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach ($read as $role) { if (!Authorization::isRole($role)) { - throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::STORAGE_INVALID_READ_PERMISSIONS); + throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_READ_PERMISSIONS); } } foreach ($write as $role) { if (!Authorization::isRole($role)) { - throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::STORAGE_INVALID_WRITE_PERMISSIONS); + throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_WRITE_PERMISSIONS); } } } @@ -602,12 +602,12 @@ App::put('/v1/storage/files/:fileId') if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach ($read as $role) { if (!Authorization::isRole($role)) { - throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::STORAGE_INVALID_READ_PERMISSIONS); + throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_READ_PERMISSIONS); } } foreach ($write as $role) { if (!Authorization::isRole($role)) { - throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::STORAGE_INVALID_WRITE_PERMISSIONS); + throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::INVALID_WRITE_PERMISSIONS); } } } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index cb2863e0c7..fd0b678793 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -81,8 +81,6 @@ class Exception extends \Exception const STORAGE_FILE_NOT_READABLE = 'storage_file_not_readable'; const STORAGE_FILE_EMPTY = 'storage_file_empty'; const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; - const STORAGE_INVALID_READ_PERMISSIONS = 'storage_invalid_read_permissions'; - const STORAGE_INVALID_WRITE_PERMISSIONS = 'storage_invalid_write_permissions'; const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; const STORAGE_INVALID_FILE = 'storage_invalid_file'; const STORAGE_FAILED_TO_MOVE_FILE = 'storage_failed_to_move_file'; @@ -99,23 +97,56 @@ class Exception extends \Exception /** Execution */ const EXECUTION_NOT_FOUND = 'execution_not_found'; + /** Collections */ + const COLLECTION_NOT_FOUND = 'collection_not_found'; + const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; + const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + const COLLECTION_DELETION_FAILED = 'collection_deletion_failed'; + + /** Documents */ + const DOCUMENT_NOT_FOUND = 'document_not_found'; + const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; + const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; + const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; + + /** Attribute */ + const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; + const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; + const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; + const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; + const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; + const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; + const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; + const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; + + /** Indexes */ + const INDEX_NOT_FOUND = 'index_not_found'; + const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; + const INDEX_ALREADY_EXISTS = 'index_already_exists'; + + /** Query limit exceeded */ + const QUERY_LIMIT_EXCEEDED = 'query_limit_exceeded'; + const QUERY_INVALID = 'query_invalid'; + /** Projects */ const PROJECT_NOT_FOUND = 'project_not_found'; const PROJECT_UNKNOWN = 'project_unknown'; /** API */ - const UNKNOWN = 'unknown'; - const UNKNOWN_ORIGIN = 'unknown_origin'; - const SERVICE_DISABLED = 'service_disabled'; - const UNAUTHORIZED_SCOPE = 'unauthorized_scope'; - const STORAGE_ERROR = 'storage_error'; - const RATE_LIMIT_EXCEEDED = 'rate_limit_exceeded'; - const SMTP_DISABLED = 'smtp_disabled'; + const DEFAULT = 'default'; + const UNKNOWN_ORIGIN = 'unknown_origin'; + const SERVICE_DISABLED = 'service_disabled'; + const INVALID_READ_PERMISSIONS = 'invalid_read_permissions'; + const INVALID_WRITE_PERMISSIONS = 'invalid_write_permissions'; + const UNAUTHORIZED_SCOPE = 'unauthorized_scope'; + const STORAGE_ERROR = 'storage_error'; + const RATE_LIMIT_EXCEEDED = 'rate_limit_exceeded'; + const SMTP_DISABLED = 'smtp_disabled'; private $errorCode = ''; - public function __construct(string $message, int $code = 0, string $errorCode = Exception::UNKNOWN, \Throwable $previous = null) + public function __construct(string $message, int $code = 0, string $errorCode = Exception::DEFAULT, \Throwable $previous = null) { $this->errorCode = $errorCode;