1
0
Fork 0
mirror of synced 2024-06-02 19:04:49 +12:00
appwrite/app/controllers/api/database.php

944 lines
43 KiB
PHP
Raw Normal View History

2019-05-09 18:54:39 +12:00
<?php
2021-07-19 21:25:53 +12:00
use Appwrite\Database\Validator\CustomId;
2019-05-09 18:54:39 +12:00
use Utopia\App;
use Utopia\Exception;
use Utopia\Validator\Boolean;
2021-07-06 08:27:20 +12:00
use Utopia\Validator\Integer;
use Utopia\Validator\Numeric;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\Range;
use Utopia\Validator\WhiteList;
2021-07-03 05:29:03 +12:00
use Utopia\Validator\Wildcard;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\Text;
use Utopia\Validator\ArrayList;
use Utopia\Validator\JSON;
2021-06-23 07:34:42 +12:00
use Utopia\Database\Validator\Key;
2021-07-06 08:27:20 +12:00
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\QueryValidator;
use Utopia\Database\Validator\Queries as QueriesValidator;
use Utopia\Database\Validator\UID;
2021-06-16 02:24:51 +12:00
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Exception\Structure as StructureException;
2020-10-31 08:53:27 +13:00
use Appwrite\Utopia\Response;
2021-06-18 05:03:24 +12:00
use Utopia\Database\Database;
use Utopia\Database\Document;
2021-06-09 08:12:14 +12:00
use Utopia\Database\Query;
2020-06-29 05:31:21 +12:00
App::post('/v1/database/collections')
2019-05-09 18:54:39 +12:00
->desc('Create Collection')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
2020-10-31 08:53:27 +13:00
->label('event', 'database.collections.create')
->label('scope', 'collections.write')
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.method', 'createCollection')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/create-collection.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
2021-07-19 21:25:53 +12:00
->param('collectionId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
2021-07-06 08:27:20 +12:00
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
2020-12-27 04:05:04 +13:00
->inject('audits')
2021-07-22 17:12:01 +12:00
->action(function ($collectionId, $read, $write, $response, $dbForExternal, $audits) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal*/
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2021-07-19 21:25:53 +12:00
$collectionId = $collectionId == 'unique()' ? $dbForExternal->getId() : $collectionId;
2021-07-06 08:27:20 +12:00
2021-07-19 21:25:53 +12:00
$collection = $dbForExternal->createCollection($collectionId);
2021-06-17 08:36:18 +12:00
// TODO@kodumbeats what should the default permissions be?
$read = (is_null($read)) ? ($collection->getRead() ?? []) : $read; // By default inherit read permissions
$write = (is_null($write)) ? ($collection->getWrite() ?? []) : $write; // By default inherit write permissions
2021-07-06 07:15:39 +12:00
$collection->setAttribute('$read', $read);
$collection->setAttribute('$write', $write);
2021-07-19 21:25:53 +12:00
$dbForExternal->updateDocument(Database::COLLECTIONS, $collectionId, $collection);
2019-05-09 18:54:39 +12:00
2020-07-06 02:19:59 +12:00
$audits
2020-06-30 09:43:34 +12:00
->setParam('event', 'database.collections.create')
->setParam('resource', 'database/collection/'.$collection->getId())
->setParam('data', $collection->getArrayCopy())
2020-06-30 09:43:34 +12:00
;
2021-05-27 22:09:14 +12:00
$response->setStatusCode(Response::STATUS_CODE_CREATED);
2021-07-26 02:47:18 +12:00
$response->dynamic($collection, Response::MODEL_COLLECTION);
2020-12-27 04:05:04 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/database/collections')
2020-02-01 11:34:07 +13:00
->desc('List Collections')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
2020-02-01 11:34:07 +13:00
->label('scope', 'collections.read')
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2020-02-01 11:34:07 +13:00
->label('sdk.method', 'listCollections')
->label('sdk.description', '/docs/references/database/list-collections.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION_LIST)
2021-07-06 07:19:18 +12:00
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
2020-09-11 02:40:14 +12:00
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 40000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
2021-07-06 07:19:18 +12:00
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
2021-07-06 07:19:18 +12:00
->action(function ($search, $limit, $offset, $orderType, $response, $dbForExternal) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2020-06-30 09:43:34 +12:00
2021-07-06 07:19:18 +12:00
$queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : [];
2020-06-30 09:43:34 +12:00
2021-07-26 02:47:18 +12:00
$response->dynamic(new Document([
2021-07-06 08:27:20 +12:00
'collections' => $dbForExternal->find(Database::COLLECTIONS, $queries, $limit, $offset, ['_id'], [$orderType]),
'sum' => $dbForExternal->count(Database::COLLECTIONS, $queries, APP_LIMIT_COUNT),
2020-10-31 08:53:27 +13:00
]), Response::MODEL_COLLECTION_LIST);
2020-12-27 04:05:04 +13:00
});
2020-02-01 11:34:07 +13:00
2020-06-29 05:31:21 +12:00
App::get('/v1/database/collections/:collectionId')
2020-02-01 11:34:07 +13:00
->desc('Get Collection')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
2020-02-01 11:34:07 +13:00
->label('scope', 'collections.read')
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2020-02-01 11:34:07 +13:00
->label('sdk.method', 'getCollection')
->label('sdk.description', '/docs/references/database/get-collection.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
2020-09-11 02:40:14 +12:00
->param('collectionId', '', new UID(), 'Collection unique ID.')
2020-12-27 04:05:04 +13:00
->inject('response')
2021-06-12 06:07:05 +12:00
->inject('dbForExternal')
->action(function ($collectionId, $response, $dbForExternal) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2021-06-12 06:07:05 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2020-06-30 09:43:34 +12:00
if ($collection->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('Collection not found', 404);
2020-02-01 11:34:07 +13:00
}
2020-06-30 09:43:34 +12:00
2021-07-26 02:47:18 +12:00
$response->dynamic($collection, Response::MODEL_COLLECTION);
2020-12-27 04:05:04 +13:00
});
2020-02-01 11:34:07 +13:00
2020-06-29 05:31:21 +12:00
App::put('/v1/database/collections/:collectionId')
2019-06-09 23:44:58 +12:00
->desc('Update Collection')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
->label('scope', 'collections.write')
2020-10-31 08:53:27 +13:00
->label('event', 'database.collections.update')
2019-06-09 23:44:58 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'updateCollection')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/update-collection.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
2020-09-11 02:40:14 +12:00
->param('collectionId', '', new UID(), 'Collection unique ID.')
2021-07-06 08:27:20 +12:00
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
2020-12-27 04:05:04 +13:00
->inject('response')
2021-06-17 08:36:18 +12:00
->inject('dbForExternal')
2020-12-27 04:05:04 +13:00
->inject('audits')
2021-07-22 18:09:57 +12:00
->action(function ($collectionId, $read, $write, $response, $dbForExternal, $audits) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-06-17 08:36:18 +12:00
/** @var Utopia\Database\Database $dbForExternal */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2019-05-09 18:54:39 +12:00
2021-06-17 08:36:18 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2019-10-01 17:57:41 +13:00
2021-06-17 08:36:18 +12:00
if ($collection->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('Collection not found', 404);
}
2019-10-01 17:57:41 +13:00
2021-06-17 08:36:18 +12:00
$read = (is_null($read)) ? ($collection->getRead() ?? []) : $read; // By default inherit read permissions
$write = (is_null($write)) ? ($collection->getWrite() ?? []) : $write; // By default inherit write permissions
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
try {
2021-06-18 05:03:24 +12:00
$collection = $dbForExternal->updateDocument(Database::COLLECTIONS, $collection->getId(), new Document(\array_merge($collection->getArrayCopy(), [
2021-06-17 08:36:18 +12:00
'$read' => $read,
'$write' => $write
])));
2020-06-30 09:43:34 +12:00
} catch (AuthorizationException $exception) {
2020-08-30 16:49:24 +12:00
throw new Exception('Unauthorized permissions', 401);
2020-06-30 09:43:34 +12:00
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
2021-06-17 08:36:18 +12:00
}
2020-07-06 02:19:59 +12:00
$audits
2020-06-30 09:43:34 +12:00
->setParam('event', 'database.collections.update')
2020-10-31 08:53:27 +13:00
->setParam('resource', 'database/collections/'.$collection->getId())
->setParam('data', $collection->getArrayCopy())
2020-06-30 09:43:34 +12:00
;
2021-07-26 02:47:18 +12:00
$response->dynamic($collection, Response::MODEL_COLLECTION);
2020-12-27 04:05:04 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::delete('/v1/database/collections/:collectionId')
2019-05-09 18:54:39 +12:00
->desc('Delete Collection')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
->label('scope', 'collections.write')
2020-10-31 08:53:27 +13:00
->label('event', 'database.collections.delete')
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
2019-05-09 18:54:39 +12:00
->label('sdk.method', 'deleteCollection')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/delete-collection.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
2020-09-11 02:40:14 +12:00
->param('collectionId', '', new UID(), 'Collection unique ID.')
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
2020-12-27 04:05:04 +13:00
->inject('events')
->inject('audits')
->inject('deletes')
->action(function ($collectionId, $response, $dbForExternal, $events, $audits, $deletes) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2019-05-09 18:54:39 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2019-05-09 18:54:39 +12:00
if ($collection->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('Collection not found', 404);
}
$dbForExternal->deleteCollection($collectionId);
2020-12-07 11:14:57 +13:00
$events
2021-07-26 02:47:18 +12:00
->setParam('eventData', $response->output($collection, Response::MODEL_COLLECTION))
2020-06-30 09:43:34 +12:00
;
2019-05-09 18:54:39 +12:00
2020-07-06 02:19:59 +12:00
$audits
2020-06-30 09:43:34 +12:00
->setParam('event', 'database.collections.delete')
2020-10-31 08:53:27 +13:00
->setParam('resource', 'database/collections/'.$collection->getId())
->setParam('data', $collection->getArrayCopy())
2020-06-30 09:43:34 +12:00
;
$response->noContent();
2020-12-27 04:05:04 +13:00
});
2019-05-09 18:54:39 +12:00
2021-03-25 04:40:33 +13:00
App::post('/v1/database/collections/:collectionId/attributes')
->desc('Create Attribute')
->groups(['api', 'database'])
->label('event', 'database.attributes.create')
->label('scope', 'attributes.write')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'createAttribute')
->label('sdk.description', '/docs/references/database/create-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-07-17 01:53:55 +12:00
// TODO@kodumbeats attributeId
2021-06-23 07:34:42 +12:00
->param('id', '', new Key(), 'Attribute ID.')
2021-07-17 01:53:55 +12:00
// TODO@kodumbeats whitelist (allowlist)
2021-07-06 08:27:20 +12:00
->param('type', null, new Text(8), 'Attribute type.')
2021-07-17 01:53:55 +12:00
// TODO@kodumbeats hide size for ints/floats/bools
2021-07-06 08:27:20 +12:00
->param('size', null, new Integer(), 'Attribute size for text attributes, in number of characters. For integers, floats, or bools, use 0.')
->param('required', null, new Boolean(), 'Is attribute required?')
2021-07-03 05:29:03 +12:00
->param('default', null, new Wildcard(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
2021-06-12 06:07:05 +12:00
->param('array', false, new Boolean(), 'Is attribute an array?', true)
2021-03-25 04:40:33 +13:00
->inject('response')
->inject('dbForExternal')
->inject('database')
2021-06-09 08:12:14 +12:00
->inject('audits')
2021-07-03 05:29:03 +12:00
->action(function ($collectionId, $id, $type, $size, $required, $default, $array, $response, $dbForExternal, $database, $audits) {
2021-03-25 04:40:33 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal*/
/** @var Appwrite\Event\Event $database */
2021-03-25 04:40:33 +13:00
/** @var Appwrite\Event\Event $audits */
2021-06-11 01:15:00 +12:00
$collection = $dbForExternal->getCollection($collectionId);
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
// integers are signed by default, and filters are hidden from the endpoint.
$signed = true;
$filters = [];
2021-07-03 05:29:03 +12:00
$success = $dbForExternal->addAttributeInQueue($collectionId, $id, $type, $size, $required, $default, $signed, $array, $filters);
// Database->addAttributeInQueue() does not return a document
// So we need to create one for the response
//
// TODO@kodumbeats should $signed and $filters be part of the response model?
2021-06-18 05:03:24 +12:00
$attribute = new Document([
'$collection' => $collectionId,
'$id' => $id,
'type' => $type,
'size' => $size,
'required' => $required,
2021-07-03 05:29:03 +12:00
'default' => $default,
'signed' => $signed,
'array' => $array,
'filters' => $filters
]);
2021-03-25 04:40:33 +13:00
$database
->setParam('type', CREATE_TYPE_ATTRIBUTE)
->setParam('document', $attribute)
;
2021-03-25 04:40:33 +13:00
$audits
->setParam('event', 'database.attributes.create')
->setParam('resource', 'database/attributes/'.$attribute->getId())
->setParam('data', $attribute)
2021-03-25 04:40:33 +13:00
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
2021-07-26 02:47:18 +12:00
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE);
2021-03-25 04:40:33 +13:00
});
2021-07-18 20:19:23 +12:00
App::get('/v1/database/collections/:collectionId/attributes')
2021-03-26 08:52:57 +13:00
->desc('List Attributes')
->groups(['api', 'database'])
->label('scope', 'attributes.read')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'listAttributes')
->label('sdk.description', '/docs/references/database/list-attributes.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-03-26 08:52:57 +13:00
->inject('response')
->inject('dbForExternal')
->action(function ($collectionId, $response, $dbForExternal) {
2021-03-26 08:52:57 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2021-06-09 08:12:14 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2021-03-26 08:52:57 +13:00
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
2021-06-09 08:12:14 +12:00
$attributes = $collection->getAttributes();
2021-03-26 08:52:57 +13:00
$attributes = array_map(function ($attribute) use ($collection) {
2021-06-18 05:03:24 +12:00
return new Document([\array_merge($attribute, [
'collectionId' => $collection->getId(),
])]);
}, $attributes);
2021-07-26 02:47:18 +12:00
$response->dynamic(new Document([
'sum' => \count($attributes),
2021-06-09 08:12:14 +12:00
'attributes' => $attributes
]), Response::MODEL_ATTRIBUTE_LIST);
2021-03-26 08:52:57 +13:00
});
2021-07-18 20:19:23 +12:00
App::get('/v1/database/collections/:collectionId/attributes/:attributeId')
2021-03-26 08:52:57 +13:00
->desc('Get Attribute')
->groups(['api', 'database'])
->label('scope', 'attributes.read')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
2021-07-18 20:19:23 +12:00
->label('sdk.method', 'getAttribute')
2021-03-26 08:52:57 +13:00
->label('sdk.description', '/docs/references/database/get-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-06-23 07:34:42 +12:00
->param('attributeId', '', new Key(), 'Attribute ID.')
2021-03-26 08:52:57 +13:00
->inject('response')
->inject('dbForExternal')
->action(function ($collectionId, $attributeId, $response, $dbForExternal) {
2021-03-26 08:52:57 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2021-06-09 08:12:14 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2021-03-26 08:52:57 +13:00
2021-06-11 01:15:00 +12:00
if (empty($collection)) {
throw new Exception('Collection not found', 404);
}
2021-06-09 08:12:14 +12:00
$attributes = $collection->getAttributes();
2021-03-26 08:52:57 +13:00
// Search for attribute
$attributeIndex = array_search($attributeId, array_column($attributes, '$id'));
if ($attributeIndex === false) {
throw new Exception('Attribute not found', 404);
}
2021-06-18 05:03:24 +12:00
$attribute = new Document([\array_merge($attributes[$attributeIndex], [
'collectionId' => $collectionId,
])]);
2021-07-26 02:47:18 +12:00
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE);
2021-03-26 08:52:57 +13:00
});
2021-03-25 04:40:33 +13:00
App::delete('/v1/database/collections/:collectionId/attributes/:attributeId')
->desc('Delete Attribute')
->groups(['api', 'database'])
->label('scope', 'attributes.write')
->label('event', 'database.attributes.delete')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'deleteAttribute')
->label('sdk.description', '/docs/references/database/delete-attribute.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-06-23 07:34:42 +12:00
->param('attributeId', '', new Key(), 'Attribute ID.')
2021-03-25 04:40:33 +13:00
->inject('response')
->inject('dbForExternal')
->inject('database')
2021-03-25 04:40:33 +13:00
->inject('events')
->inject('audits')
->action(function ($collectionId, $attributeId, $response, $dbForExternal, $database, $events, $audits) {
2021-03-25 04:40:33 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
/** @var Appwrite\Event\Event $database */
2021-03-25 04:40:33 +13:00
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
$collection = $dbForExternal->getCollection($collectionId);
2021-03-25 04:40:33 +13:00
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
2021-06-09 08:12:14 +12:00
$attributes = $collection->getAttributes();
2021-03-25 04:40:33 +13:00
// Search for attribute
$attributeIndex = array_search($attributeId, array_column($attributes, '$id'));
2021-03-25 04:40:33 +13:00
if ($attributeIndex === false) {
throw new Exception('Attribute not found', 404);
}
2021-06-18 05:03:24 +12:00
$attribute = new Document([\array_merge($attributes[$attributeIndex], [
'collectionId' => $collectionId,
])]);
2021-06-09 08:12:14 +12:00
$database
->setParam('type', DELETE_TYPE_ATTRIBUTE)
->setParam('document', $attribute)
;
2021-06-09 08:12:14 +12:00
$events
2021-07-26 02:47:18 +12:00
->setParam('payload', $response->output($attribute, Response::MODEL_ATTRIBUTE))
;
2021-03-25 04:40:33 +13:00
$audits
->setParam('event', 'database.attributes.delete')
->setParam('resource', 'database/attributes/'.$attribute->getId())
->setParam('data', $attribute->getArrayCopy())
;
$response->noContent();
});
2021-03-24 10:19:19 +13:00
App::post('/v1/database/collections/:collectionId/indexes')
->desc('Create Index')
->groups(['api', 'database'])
->label('event', 'database.indexes.create')
->label('scope', 'indexes.write')
->label('sdk.namespace', 'database')
2021-03-25 04:40:33 +13:00
->label('sdk.platform', [APP_PLATFORM_SERVER])
2021-03-24 10:19:19 +13:00
->label('sdk.method', 'createIndex')
->label('sdk.description', '/docs/references/database/create-index.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-06-23 07:34:42 +12:00
->param('id', null, new Key(), 'Index ID.')
2021-06-18 05:03:24 +12:00
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL, Database::INDEX_ARRAY]), 'Index type.')
2021-06-23 07:34:42 +12:00
->param('attributes', null, new ArrayList(new Key()), 'Array of attributes to index.')
// TODO@kodumbeats debug below
2021-07-06 08:27:20 +12:00
->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING)), 'Array of index orders.', true)
// ->param('orders', [], new ArrayList(new Text(4)), 'Array of index orders.', true)
2021-03-24 10:19:19 +13:00
->inject('response')
->inject('dbForExternal')
->inject('database')
->inject('audits')
->action(function ($collectionId, $id, $type, $attributes, $orders, $response, $dbForExternal, $database, $audits) {
2021-03-24 10:19:19 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2021-07-03 10:22:49 +12:00
/** @var Appwrite\Event\Event $database */
2021-03-24 10:19:19 +13:00
/** @var Appwrite\Event\Event $audits */
2021-06-11 01:15:00 +12:00
$collection = $dbForExternal->getCollection($collectionId);
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
// Convert Document[] to array of attribute metadata
$oldAttributes = \array_map(function ($a) {
return $a->getArrayCopy();
}, $collection->getAttribute('attributes'));
2021-07-03 10:23:58 +12:00
// lengths hidden by default
$lengths = [];
2021-07-03 10:23:58 +12:00
// set attribute size as length for strings, null otherwise
foreach ($attributes as $key => $attribute) {
2021-07-03 10:23:58 +12:00
// find attribute metadata in collection document
$attributeIndex = \array_search($attribute, array_column($oldAttributes, '$id'));
if ($attributeIndex === false) {
throw new Exception('Unknown attribute: ' . $attribute, 400);
}
$attributeType = $oldAttributes[$attributeIndex]['type'];
$attributeSize = $oldAttributes[$attributeIndex]['size'];
2021-07-03 10:23:58 +12:00
// Only set length for indexes on strings
$lengths[$key] = ($attributeType === Database::VAR_STRING) ? $attributeSize : null;
2021-07-03 10:23:58 +12:00
}
$success = $dbForExternal->addIndexInQueue($collectionId, $id, $type, $attributes, $lengths, $orders);
// Database->createIndex() does not return a document
// So we need to create one for the response
//
// TODO@kodumbeats should $lengths be a part of the response model?
2021-06-18 05:03:24 +12:00
$index = new Document([
'$collection' => $collectionId,
'$id' => $id,
'type' => $type,
'attributes' => $attributes,
'lengths' => $lengths,
'orders' => $orders,
]);
2021-03-24 10:19:19 +13:00
$database
->setParam('type', CREATE_TYPE_INDEX)
->setParam('document', $index)
;
2021-03-24 10:19:19 +13:00
$audits
->setParam('event', 'database.indexes.create')
->setParam('resource', 'database/indexes/'.$index->getId())
->setParam('data', $index->getArrayCopy())
2021-03-24 10:19:19 +13:00
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
2021-07-26 02:47:18 +12:00
$response->dynamic($index, Response::MODEL_INDEX);
2021-03-24 10:19:19 +13:00
});
2021-07-18 20:19:23 +12:00
App::get('/v1/database/collections/:collectionId/indexes')
2021-03-25 04:40:33 +13:00
->desc('List Indexes')
->groups(['api', 'database'])
->label('scope', 'indexes.read')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'listIndexes')
->label('sdk.description', '/docs/references/database/list-indexes.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX_LIST)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-03-25 04:40:33 +13:00
->inject('response')
->inject('dbForExternal')
->action(function ($collectionId, $response, $dbForExternal) {
2021-03-25 04:40:33 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
$collection = $dbForExternal->getCollection($collectionId);
2021-03-25 04:40:33 +13:00
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
$indexes = $collection->getAttribute('indexes');
2021-03-25 04:40:33 +13:00
$indexes = array_map(function ($index) use ($collection) {
2021-06-18 05:03:24 +12:00
return new Document([\array_merge($index, [
'collectionId' => $collection->getId(),
])]);
}, $indexes);
2021-07-26 02:47:18 +12:00
$response->dynamic(new Document([
'sum' => \count($indexes),
'attributes' => $indexes,
]), Response::MODEL_INDEX_LIST);
2021-03-25 04:40:33 +13:00
});
2021-07-18 20:19:23 +12:00
App::get('/v1/database/collections/:collectionId/indexes/:indexId')
2021-03-26 08:52:57 +13:00
->desc('Get Index')
->groups(['api', 'database'])
->label('scope', 'indexes.read')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
2021-07-18 20:19:23 +12:00
->label('sdk.method', 'getIndex')
2021-03-26 08:52:57 +13:00
->label('sdk.description', '/docs/references/database/get-index.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-06-23 07:34:42 +12:00
->param('indexId', null, new Key(), 'Index ID.')
2021-03-26 08:52:57 +13:00
->inject('response')
2021-06-17 08:36:18 +12:00
->inject('dbForExternal')
->action(function ($collectionId, $indexId, $response, $dbForExternal) {
2021-03-26 08:52:57 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2021-03-26 08:52:57 +13:00
$collection = $dbForExternal->getCollection($collectionId);
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
$indexes = $collection->getAttribute('indexes');
2021-03-26 08:52:57 +13:00
// // Search for index
$indexIndex = array_search($indexId, array_column($indexes, '$id'));
if ($indexIndex === false) {
throw new Exception('Index not found', 404);
}
2021-06-18 05:03:24 +12:00
$index = new Document([\array_merge($indexes[$indexIndex], [
'collectionId' => $collectionId,
])]);
2021-07-26 02:47:18 +12:00
$response->dynamic($index, Response::MODEL_INDEX);
2021-03-26 08:52:57 +13:00
});
App::delete('/v1/database/collections/:collectionId/indexes/:indexId')
->desc('Delete Index')
->groups(['api', 'database'])
->label('scope', 'indexes.write')
->label('event', 'database.indexes.delete')
->label('sdk.namespace', 'database')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'deleteIndex')
->label('sdk.description', '/docs/references/database/delete-index.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-06-23 07:34:42 +12:00
->param('indexId', '', new Key(), 'Index ID.')
2021-03-26 08:52:57 +13:00
->inject('response')
->inject('dbForExternal')
->inject('database')
2021-03-26 08:52:57 +13:00
->inject('events')
->inject('audits')
->action(function ($collectionId, $indexId, $response, $dbForExternal, $database, $events, $audits) {
2021-03-26 08:52:57 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
/** @var Appwrite\Event\Event $database */
2021-03-26 08:52:57 +13:00
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
$collection = $dbForExternal->getCollection($collectionId);
2021-06-12 06:07:05 +12:00
if ($collection->isEmpty()) {
2021-06-11 01:15:00 +12:00
throw new Exception('Collection not found', 404);
}
$indexes = $collection->getAttribute('indexes');
2021-03-26 08:52:57 +13:00
// // Search for index
$indexIndex = array_search($indexId, array_column($indexes, '$id'));
if ($indexIndex === false) {
throw new Exception('Index not found', 404);
2021-03-26 08:52:57 +13:00
}
2021-06-18 05:03:24 +12:00
$index = new Document([\array_merge($indexes[$indexIndex], [
'collectionId' => $collectionId,
])]);
$database
->setParam('type', DELETE_TYPE_INDEX)
->setParam('document', $index)
;
2021-03-26 08:52:57 +13:00
$events
2021-07-26 02:47:18 +12:00
->setParam('payload', $response->output($index, Response::MODEL_INDEX))
2021-03-26 08:52:57 +13:00
;
$audits
->setParam('event', 'database.indexes.delete')
->setParam('resource', 'database/indexes/'.$index->getId())
2021-03-26 08:52:57 +13:00
->setParam('data', $index->getArrayCopy())
;
$response->noContent();
});
2020-06-29 05:31:21 +12:00
App::post('/v1/database/collections/:collectionId/documents')
2020-02-01 11:34:07 +13:00
->desc('Create Document')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
2020-10-31 08:53:27 +13:00
->label('event', 'database.documents.create')
2020-02-01 11:34:07 +13:00
->label('scope', 'documents.write')
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2020-02-01 11:34:07 +13:00
->label('sdk.method', 'createDocument')
->label('sdk.description', '/docs/references/database/create-document.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT)
2021-07-19 21:25:53 +12:00
->param('documentId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
2020-09-11 02:40:14 +12:00
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
->param('data', [], new JSON(), 'Document data as JSON object.')
2021-07-06 08:27:20 +12:00
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
2021-03-22 11:17:20 +13:00
->inject('user')
2020-12-27 04:05:04 +13:00
->inject('audits')
2021-07-19 21:25:53 +12:00
->action(function ($documentId, $collectionId, $data, $read, $write, $response, $dbForExternal, $user, $audits) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
/** @var Utopia\Database\Document $user */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2020-06-30 09:43:34 +12:00
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data)) {
throw new Exception('Missing payload', 400);
}
2020-02-01 11:34:07 +13:00
2020-06-30 09:43:34 +12:00
if (isset($data['$id'])) {
throw new Exception('$id is not allowed for creating new documents, try update instead', 400);
}
$collection = $dbForExternal->getCollection($collectionId);
2020-02-01 11:34:07 +13:00
2021-06-12 06:07:05 +12:00
if ($collection->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('Collection not found', 404);
}
2020-02-01 11:34:07 +13:00
$data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers
2021-07-19 21:25:53 +12:00
$data['$id'] = $documentId == 'unique()' ? $dbForExternal->getId() : $documentId;
$data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? []; // By default set read permissions for user
$data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? []; // By default set write permissions for user
2020-02-01 11:34:07 +13:00
try {
2021-06-18 05:03:24 +12:00
$document = $dbForExternal->createDocument($collectionId, new Document($data));
} catch (StructureException $exception) {
throw new Exception($exception->getMessage(), 400);
}
2020-02-01 11:34:07 +13:00
2020-07-06 02:19:59 +12:00
$audits
2020-06-30 09:43:34 +12:00
->setParam('event', 'database.documents.create')
->setParam('resource', 'database/document/'.$document->getId())
->setParam('data', $document->getArrayCopy())
2020-06-30 09:43:34 +12:00
;
2020-02-01 11:34:07 +13:00
2021-05-27 22:09:14 +12:00
$response->setStatusCode(Response::STATUS_CODE_CREATED);
2021-07-26 02:47:18 +12:00
$response->dynamic($document, Response::MODEL_DOCUMENT);
2020-12-27 04:05:04 +13:00
});
2020-02-01 11:34:07 +13:00
2020-06-29 05:31:21 +12:00
App::get('/v1/database/collections/:collectionId/documents')
2019-05-09 18:54:39 +12:00
->desc('List Documents')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
->label('scope', 'documents.read')
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.method', 'listDocuments')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/list-documents.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2021-06-15 07:55:36 +12:00
->param('queries', [], new ArrayList(new Text(128)), 'Array of query strings.', true)
2020-11-06 05:02:25 +13:00
->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true)
2021-07-17 01:53:55 +12:00
// TODO@kodumbeats 'after' param for pagination
2021-06-15 07:55:36 +12:00
->param('orderAttributes', [], new ArrayList(new Text(128)), 'Array of attributes used to sort results.', true)
->param('orderTypes', [], new ArrayList(new WhiteList(['DESC', 'ASC'], true)), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order.', true)
2020-12-27 04:05:04 +13:00
->inject('response')
2021-06-15 07:55:36 +12:00
->inject('dbForExternal')
->action(function ($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $response, $dbForExternal) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-06-15 07:55:36 +12:00
/** @var Utopia\Database\Database $dbForExternal */
2019-05-09 18:54:39 +12:00
2021-06-15 07:55:36 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2019-05-09 18:54:39 +12:00
2021-06-15 07:55:36 +12:00
if ($collection->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('Collection not found', 404);
}
2020-06-22 00:12:13 +12:00
2021-06-15 07:55:36 +12:00
$queries = \array_map(function ($query) {
return Query::parse($query);
}, $queries);
2020-06-30 09:43:34 +12:00
2021-07-06 08:27:20 +12:00
// TODO@kodumbeats find a more efficient alternative to this
$schema = $collection->getArrayCopy()['attributes'];
$indexes = $collection->getArrayCopy()['indexes'];
$indexesInQueue = $collection->getArrayCopy()['indexesInQueue'];
// TODO@kodumbeats use strict query validation
$validator = new QueriesValidator(new QueryValidator($schema), $indexes, $indexesInQueue, false);
if (!$validator->isValid($queries)) {
throw new Exception($validator->getDescription(), 400);
}
2021-06-15 07:55:36 +12:00
$documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes);
2020-06-30 09:43:34 +12:00
2021-07-26 02:47:18 +12:00
$response->dynamic(new Document([
2021-06-15 07:55:36 +12:00
'sum' => \count($documents),
'documents' => $documents,
]), Response::MODEL_DOCUMENT_LIST);
2020-12-27 04:05:04 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/database/collections/:collectionId/documents/:documentId')
2019-05-09 18:54:39 +12:00
->desc('Get Document')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
->label('scope', 'documents.read')
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.method', 'getDocument')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/get-document.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT)
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2020-09-11 02:40:14 +12:00
->param('documentId', null, new UID(), 'Document unique ID.')
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
->action(function ($collectionId, $documentId, $response, $dbForExternal) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2019-05-09 18:54:39 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2019-05-09 18:54:39 +12:00
2021-06-12 06:07:05 +12:00
if ($collection->isEmpty()) {
throw new Exception('Collection not found', 404);
}
$document = $dbForExternal->getDocument($collectionId, $documentId);
if ($document->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('No document found', 404);
}
2019-05-09 18:54:39 +12:00
2021-07-26 02:47:18 +12:00
$response->dynamic($document, Response::MODEL_DOCUMENT);
2020-12-27 04:05:04 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
2019-05-09 18:54:39 +12:00
->desc('Update Document')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
2020-10-31 08:53:27 +13:00
->label('event', 'database.documents.update')
->label('scope', 'documents.write')
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.method', 'updateDocument')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/update-document.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT)
2020-09-11 02:40:14 +12:00
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
->param('documentId', null, new UID(), 'Document unique ID.')
->param('data', [], new JSON(), 'Document data as JSON object.')
2021-07-06 08:27:20 +12:00
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
2020-12-27 04:05:04 +13:00
->inject('audits')
->action(function ($collectionId, $documentId, $data, $read, $write, $response, $dbForExternal, $audits) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2019-05-09 18:54:39 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2019-09-17 07:03:24 +12:00
if ($collection->isEmpty()) {
throw new Exception('Collection not found', 404);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
$document = $dbForExternal->getDocument($collectionId, $documentId);
if ($document->isEmpty()) {
throw new Exception('Document not found', 404);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data)) {
throw new Exception('Missing payload', 400);
}
if (!\is_array($data)) {
throw new Exception('Data param should be a valid JSON object', 400);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$data = \array_merge($document->getArrayCopy(), $data);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$data['$collection'] = $collection->getId(); // Make sure user don't switch collectionID
$data['$id'] = $document->getId(); // Make sure user don't switch document unique ID
$data['$read'] = (is_null($read)) ? ($document->getRead() ?? []) : $read; // By default inherit read permissions
$data['$write'] = (is_null($write)) ? ($document->getWrite() ?? []) : $write; // By default inherit write permissions
2020-10-31 08:53:27 +13:00
2020-06-30 09:43:34 +12:00
try {
2021-06-18 05:03:24 +12:00
$document = $dbForExternal->updateDocument($collection->getId(), $document->getId(), new Document($data));
2020-06-30 09:43:34 +12:00
} catch (AuthorizationException $exception) {
2020-08-30 16:49:24 +12:00
throw new Exception('Unauthorized permissions', 401);
2020-06-30 09:43:34 +12:00
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
2021-06-16 02:24:51 +12:00
}
2019-05-09 18:54:39 +12:00
2020-07-06 02:19:59 +12:00
$audits
2020-06-30 09:43:34 +12:00
->setParam('event', 'database.documents.update')
->setParam('resource', 'database/document/'.$document->getId())
->setParam('data', $document->getArrayCopy())
2020-06-30 09:43:34 +12:00
;
2019-05-09 18:54:39 +12:00
2021-07-26 02:47:18 +12:00
$response->dynamic($document, Response::MODEL_DOCUMENT);
2020-12-27 04:05:04 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
2019-05-09 18:54:39 +12:00
->desc('Delete Document')
2020-06-26 06:32:12 +12:00
->groups(['api', 'database'])
->label('scope', 'documents.write')
2020-10-31 08:53:27 +13:00
->label('event', 'database.documents.delete')
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'database')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.method', 'deleteDocument')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/database/delete-document.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
2020-09-11 02:40:14 +12:00
->param('documentId', null, new UID(), 'Document unique ID.')
2020-12-27 04:05:04 +13:00
->inject('response')
->inject('dbForExternal')
2020-12-27 04:05:04 +13:00
->inject('events')
->inject('audits')
->action(function ($collectionId, $documentId, $response, $dbForExternal, $events, $audits) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2020-07-06 02:19:59 +12:00
/** @var Appwrite\Event\Event $audits */
2019-05-09 18:54:39 +12:00
$collection = $dbForExternal->getCollection($collectionId);
2019-05-09 18:54:39 +12:00
2021-06-12 06:07:05 +12:00
if ($collection->isEmpty()) {
2020-06-30 09:43:34 +12:00
throw new Exception('Collection not found', 404);
}
$document = $dbForExternal->getDocument($collectionId, $documentId);
if ($document->isEmpty()) {
throw new Exception('No document found', 404);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
$success = $dbForExternal->deleteDocument($collectionId, $documentId);
2020-12-07 11:14:57 +13:00
$events
2021-07-26 02:47:18 +12:00
->setParam('eventData', $response->output($document, Response::MODEL_DOCUMENT))
2020-06-30 09:43:34 +12:00
;
2020-07-06 02:19:59 +12:00
$audits
2020-06-30 09:43:34 +12:00
->setParam('event', 'database.documents.delete')
2020-10-31 08:53:27 +13:00
->setParam('resource', 'database/document/'.$document->getId())
->setParam('data', $document->getArrayCopy()) // Audit document in case of malicious or disastrous action
2020-06-30 09:43:34 +12:00
;
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$response->noContent();
2021-03-26 08:52:57 +13:00
});