appwrite/app/controllers/api/databases.php

2231 lines
97 KiB
PHP
Raw Normal View History

2019-05-09 06:54:39 +00:00
<?php
2023-06-15 05:29:03 +00:00
use Appwrite\Auth\Auth;
use Appwrite\Detector\Detector;
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Event;
2025-01-30 04:53:53 +00:00
use Appwrite\Event\StatsUsage;
use Appwrite\Extend\Exception;
2025-01-17 04:31:39 +00:00
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
2023-06-15 05:29:03 +00:00
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Collections;
2023-07-21 11:10:44 +00:00
use Appwrite\Utopia\Database\Validator\Queries\Indexes;
2023-06-15 05:29:03 +00:00
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\App;
2021-08-15 21:09:40 +00:00
use Utopia\Audit\Audit;
2023-06-15 05:29:03 +00:00
use Utopia\Config\Config;
2021-08-16 23:21:00 +00:00
use Utopia\Database\Database;
2025-02-25 05:51:11 +00:00
use Utopia\Database\DateTime;
2021-08-16 23:21:00 +00:00
use Utopia\Database\Document;
2023-06-15 05:29:03 +00:00
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Limit as LimitException;
2024-11-04 07:57:08 +00:00
use Utopia\Database\Exception\NotFound as NotFoundException;
use Utopia\Database\Exception\Order as OrderException;
2024-09-09 07:17:47 +00:00
use Utopia\Database\Exception\Query as QueryException;
2023-06-15 05:29:03 +00:00
use Utopia\Database\Exception\Structure as StructureException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
2021-08-16 23:21:00 +00:00
use Utopia\Database\Query;
2021-08-12 01:05:19 +00:00
use Utopia\Database\Validator\Authorization;
2023-06-15 05:29:03 +00:00
use Utopia\Database\Validator\Index as IndexValidator;
2021-06-22 19:34:42 +00:00
use Utopia\Database\Validator\Key;
2021-07-05 20:27:20 +00:00
use Utopia\Database\Validator\Permissions;
2023-06-15 05:29:03 +00:00
use Utopia\Database\Validator\Queries;
2024-05-09 16:54:28 +00:00
use Utopia\Database\Validator\Query\Cursor;
2023-06-15 05:29:03 +00:00
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
2021-07-05 20:27:20 +00:00
use Utopia\Database\Validator\UID;
2022-05-25 12:10:10 +00:00
use Utopia\Locale\Locale;
2023-06-15 05:29:03 +00:00
use Utopia\Validator\ArrayList;
use Utopia\Validator\Boolean;
use Utopia\Validator\JSON;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
2021-07-27 01:00:36 +00:00
App::post('/v1/databases/:databaseId/tables')
->alias('/v1/databases/:databaseId/collections')
->desc('Create table')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].tables.[tableId].create')
->label('scope', 'collections.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'table.create')
->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}')
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'tables',
name: 'createTable',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/create-collection.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_CREATED,
model: Response::MODEL_COLLECTION,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('name', '', new Text(128), 'Table name. Max length: 128 chars.')
2023-10-13 13:43:23 +00:00
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true)
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
->inject('mode')
2022-12-20 16:11:30 +00:00
->inject('queueForEvents')
->action(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) {
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
$tableId = $tableId == 'unique()' ? ID::unique() : $tableId;
2021-07-05 20:27:20 +00:00
2022-08-23 01:42:25 +00:00
// Map aggregate permissions into the multiple permissions they represent.
2024-11-06 07:36:27 +00:00
$permissions = Permission::aggregate($permissions) ?? [];
2022-08-16 08:33:06 +00:00
2021-08-16 17:28:33 +00:00
try {
$table = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([
'$id' => $tableId,
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
'databaseInternalId' => $database->getInternalId(),
'databaseId' => $databaseId,
2024-11-06 07:36:27 +00:00
'$permissions' => $permissions,
'documentSecurity' => $documentSecurity,
'enabled' => $enabled,
2021-08-16 17:28:33 +00:00
'name' => $name,
'search' => implode(' ', [$tableId, $name]),
2021-08-16 17:28:33 +00:00
]));
2022-01-24 08:20:02 +00:00
$dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity);
} catch (DuplicateException) {
throw new Exception(Exception::COLLECTION_ALREADY_EXISTS);
} catch (LimitException) {
throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED);
2021-08-16 17:28:33 +00:00
}
2019-05-09 06:54:39 +00:00
2022-12-20 16:11:30 +00:00
$queueForEvents
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setContext('database', $database)
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId());
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2022-09-07 11:11:10 +00:00
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($table, Response::MODEL_COLLECTION);
2020-12-26 15:05:04 +00:00
});
2019-05-09 06:54:39 +00:00
App::get('/v1/databases/:databaseId/tables')
->alias('/v1/databases/:databaseId/collections')
->desc('List tables')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
2020-01-31 22:34:07 +00:00
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'tables',
name: 'listTables',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/list-collections.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_COLLECTION_LIST,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
2023-03-29 19:38:39 +00:00
->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true)
2021-07-05 19:19:18 +00:00
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
2023-05-26 11:38:09 +00:00
->inject('mode')
->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) {
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2020-06-29 21:43:34 +00:00
2024-11-04 07:57:08 +00:00
$queries = Query::parseQueries($queries);
2021-08-16 17:28:33 +00:00
2022-08-11 23:53:52 +00:00
if (!empty($search)) {
2022-08-23 12:30:28 +00:00
$queries[] = Query::search('search', $search);
2021-08-16 17:28:33 +00:00
}
2020-06-29 21:43:34 +00:00
2024-02-12 09:55:45 +00:00
/**
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
*/
2023-08-22 03:25:55 +00:00
$cursor = \array_filter($queries, function ($query) {
2023-12-06 14:10:40 +00:00
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
2023-08-22 03:25:55 +00:00
});
$cursor = reset($cursor);
2022-08-30 11:55:23 +00:00
if ($cursor) {
2022-08-23 12:30:28 +00:00
/** @var Query $cursor */
$validator = new Cursor();
if (!$validator->isValid($cursor)) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
}
$tableId = $cursor->getValue();
$cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
2021-08-06 12:35:57 +00:00
2022-08-11 23:53:52 +00:00
if ($cursorDocument->isEmpty()) {
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Table '{$tableId}' for the 'cursor' value not found.");
2022-08-11 23:53:52 +00:00
}
2022-08-23 12:30:28 +00:00
$cursor->setValue($cursorDocument);
2021-08-06 12:35:57 +00:00
}
2022-08-23 12:30:28 +00:00
$filterQueries = Query::groupByType($queries)['filters'];
try {
$tables = $dbForProject->find('database_' . $database->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
}
// TODO: collections > tables
2021-07-25 14:47:18 +00:00
$response->dynamic(new Document([
'collections' => $tables,
'total' => $total,
]), Response::MODEL_COLLECTION_LIST);
});
App::get('/v1/databases/:databaseId/tables/:tableId')
->alias('/v1/databases/:databaseId/collections/:tableId')
->desc('Get table')
->groups(['api', 'database'])
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'tables',
name: 'getTable',
description: '/docs/references/databases/get-collection.md',
2025-01-17 04:31:39 +00:00
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_COLLECTION,
2025-01-17 04:31:39 +00:00
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID.')
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $tableId, Response $response, Database $dbForProject) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
2023-03-10 13:06:34 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
2023-03-10 13:06:34 +00:00
}
$table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$response->dynamic($table, Response::MODEL_COLLECTION);
});
App::get('/v1/databases/:databaseId/tables/:tableId/logs')
->alias('/v1/databases/:databaseId/collections/:tableId/logs')
->desc('List table logs')
->groups(['api', 'database'])
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'tables',
name: 'listTableLogs',
description: '/docs/references/databases/get-collection-logs.md',
auth: [AuthType::ADMIN],
2025-01-17 04:31:39 +00:00
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_LOG_LIST,
2025-01-17 04:31:39 +00:00
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID.')
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
$table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId());
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
// Temp fix for logs
$queries[] = Query::or([
Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))),
Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))),
]);
$audit = new Audit($dbForProject);
$resource = 'database/' . $databaseId . '/table/' . $tableId;
$logs = $audit->getLogsByResource($resource, $queries);
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$detector = new Detector($log['userAgent']);
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector->getOS();
$client = $detector->getClient();
$device = $detector->getDevice();
$output[$i] = new Document([
'event' => $log['event'],
'userId' => $log['data']['userId'],
'userEmail' => $log['data']['userEmail'] ?? null,
'userName' => $log['data']['userName'] ?? null,
'mode' => $log['data']['mode'] ?? null,
'ip' => $log['ip'],
'time' => $log['time'],
'osCode' => $os['osCode'],
'osName' => $os['osName'],
'osVersion' => $os['osVersion'],
'clientType' => $client['clientType'],
'clientCode' => $client['clientCode'],
'clientName' => $client['clientName'],
'clientVersion' => $client['clientVersion'],
'clientEngine' => $client['clientEngine'],
'clientEngineVersion' => $client['clientEngineVersion'],
'deviceName' => $device['deviceName'],
'deviceBrand' => $device['deviceBrand'],
'deviceModel' => $device['deviceModel']
]);
$record = $geodb->get($log['ip']);
if ($record) {
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--';
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
} else {
$output[$i]['countryCode'] = '--';
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
$response->dynamic(new Document([
'total' => $audit->countLogsByResource($resource, $queries),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::put('/v1/databases/:databaseId/tables/:tableId')
->alias('/v1/databases/:databaseId/collections/:tableId')
->desc('Update table')
2023-03-23 03:58:41 +00:00
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].tables.[tableId].update')
->label('audits.event', 'table.update')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'tables',
name: 'updateTable',
description: '/docs/references/databases/update-collection.md',
2025-01-17 04:31:39 +00:00
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_COLLECTION,
2025-01-17 04:31:39 +00:00
)
],
contentType: ContentType::JSON
))
2023-03-23 03:58:41 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID.')
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true)
2023-03-23 03:58:41 +00:00
->inject('response')
->inject('dbForProject')
->inject('mode')
2023-10-03 18:56:36 +00:00
->inject('queueForEvents')
->action(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$permissions ??= $table->getPermissions() ?? [];
// Map aggregate permissions into the multiple permissions they represent.
$permissions = Permission::aggregate($permissions);
$enabled ??= $table->getAttribute('enabled', true);
$table = $dbForProject->updateDocument(
'database_' . $database->getInternalId(),
$tableId,
$table
->setAttribute('name', $name)
->setAttribute('$permissions', $permissions)
->setAttribute('documentSecurity', $documentSecurity)
->setAttribute('enabled', $enabled)
->setAttribute('search', \implode(' ', [$tableId, $name]))
2023-03-23 03:58:41 +00:00
);
$dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $permissions, $documentSecurity);
2023-03-23 03:58:41 +00:00
$queueForEvents
->setContext('database', $database)
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId());
2023-03-23 03:58:41 +00:00
$response->dynamic($table, Response::MODEL_COLLECTION);
2023-03-23 03:58:41 +00:00
});
App::delete('/v1/databases/:databaseId/tables/:tableId')
->alias('/v1/databases/:databaseId/collections/:tableId')
->desc('Delete table')
->groups(['api', 'database', 'schema'])
->label('scope', 'collections.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].tables.[tableId].delete')
->label('audits.event', 'table.delete')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'tables',
name: 'deleteTable',
description: '/docs/references/databases/delete-collection.md',
2025-01-17 04:31:39 +00:00
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_NOCONTENT,
model: Response::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID.')
2021-03-24 15:40:33 +00:00
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('mode')
->action(function (string $databaseId, string $tableId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, string $mode) {
2021-03-24 15:40:33 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
$table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
2021-03-24 15:40:33 +00:00
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-06-10 13:15:00 +00:00
}
if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $tableId)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
}
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId());
2023-03-30 17:36:24 +00:00
2022-12-20 16:11:30 +00:00
$queueForDatabase
->setType(DATABASE_TYPE_DELETE_COLLECTION)
->setDatabase($database)
->setTable($table);
2022-12-20 16:11:30 +00:00
$queueForEvents
->setContext('database', $database)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId())
->setPayload($response->output($table, Response::MODEL_COLLECTION));
2021-03-24 15:40:33 +00:00
$response->noContent();
});
App::post('/v1/databases/:databaseId/tables/:tableId/indexes')
->alias('/v1/databases/:databaseId/collections/:tableId/indexes')
2023-10-02 14:02:48 +00:00
->desc('Create index')
2021-03-23 21:19:19 +00:00
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create')
->label('scope', 'collections.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2022-09-05 08:00:08 +00:00
->label('audits.event', 'index.create')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
2025-03-31 09:32:47 +00:00
namespace: 'databases',
group: 'tables',
2025-01-17 04:31:39 +00:00
name: 'createIndex',
description: '/docs/references/databases/create-index.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_ACCEPTED,
model: Response::MODEL_INDEX,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', null, new Key(), 'Index Key.')
2024-02-26 02:38:58 +00:00
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.')
->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.')
2022-05-01 07:54:58 +00:00
->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true)
2021-03-23 21:19:19 +00:00
->inject('response')
->inject('dbForProject')
2022-12-20 16:11:30 +00:00
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
2021-03-23 21:19:19 +00:00
2024-03-06 17:34:21 +00:00
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($db->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2023-06-15 05:29:03 +00:00
$table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId);
2021-06-10 13:15:00 +00:00
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-06-10 13:15:00 +00:00
}
$count = $dbForProject->count('indexes', [
Query::equal('collectionInternalId', [$table->getInternalId()]),
2022-08-11 23:53:52 +00:00
Query::equal('databaseInternalId', [$db->getInternalId()])
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
], 61);
2021-08-24 23:35:32 +00:00
2022-11-03 20:24:03 +00:00
$limit = $dbForProject->getLimitForIndexes();
2021-08-24 23:35:32 +00:00
if ($count >= $limit) {
2022-08-14 08:05:11 +00:00
throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded');
2021-08-24 23:35:32 +00:00
}
// Convert Document[] to array of attribute metadata
$oldColumns = \array_map(fn ($a) => $a->getArrayCopy(), $table->getAttribute('attributes'));
2021-07-02 22:23:58 +00:00
$oldColumns[] = [
2022-06-20 14:22:27 +00:00
'key' => '$id',
'type' => Database::VAR_STRING,
2022-06-20 14:22:27 +00:00
'status' => 'available',
'required' => true,
'array' => false,
'default' => null,
2024-07-10 07:00:10 +00:00
'size' => Database::LENGTH_KEY
2022-06-20 14:22:27 +00:00
];
2022-06-22 09:46:37 +00:00
$oldColumns[] = [
2022-06-22 09:46:37 +00:00
'key' => '$createdAt',
'type' => Database::VAR_DATETIME,
2022-06-22 09:46:37 +00:00
'status' => 'available',
'signed' => false,
'required' => false,
'array' => false,
'default' => null,
'size' => 0
];
$oldColumns[] = [
2022-06-22 09:46:37 +00:00
'key' => '$updatedAt',
'type' => Database::VAR_DATETIME,
2022-06-22 09:46:37 +00:00
'status' => 'available',
'signed' => false,
'required' => false,
'array' => false,
'default' => null,
'size' => 0
];
2021-07-02 22:23:58 +00:00
// lengths hidden by default
$lengths = [];
foreach ($columns as $i => $column) {
2021-07-02 22:23:58 +00:00
// find attribute metadata in collection document
$columnIndex = \array_search($column, array_column($oldColumns, 'key'));
2021-07-02 22:23:58 +00:00
if ($columnIndex === false) {
throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.');
2021-07-02 22:23:58 +00:00
}
$columnStatus = $oldColumns[$columnIndex]['status'];
$columnType = $oldColumns[$columnIndex]['type'];
$columnArray = $oldColumns[$columnIndex]['array'] ?? false;
2021-07-02 22:23:58 +00:00
if ($columnType === Database::VAR_RELATIONSHIP) {
throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']);
}
// ensure attribute is available
if ($columnStatus !== 'available') {
throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']);
}
2024-02-08 13:01:20 +00:00
$lengths[$i] = null;
if ($columnArray === true) {
2024-02-08 13:01:20 +00:00
$lengths[$i] = Database::ARRAY_INDEX_LENGTH;
$orders[$i] = null;
}
2021-07-02 22:23:58 +00:00
}
2023-06-15 05:29:03 +00:00
$index = new Document([
'$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key),
2023-06-15 05:29:03 +00:00
'key' => $key,
'status' => 'processing', // processing, available, failed, deleting, stuck
'databaseInternalId' => $db->getInternalId(),
'databaseId' => $databaseId,
'collectionInternalId' => $table->getInternalId(),
'collectionId' => $tableId,
2023-06-15 05:29:03 +00:00
'type' => $type,
'attributes' => $columns,
2023-06-15 05:29:03 +00:00
'lengths' => $lengths,
'orders' => $orders,
]);
2023-10-19 01:26:44 +00:00
$validator = new IndexValidator(
$table->getAttribute('attributes'),
$dbForProject->getAdapter()->getMaxIndexLength(),
$dbForProject->getAdapter()->getInternalIndexesKeys(),
2023-10-19 01:26:44 +00:00
);
if (!$validator->isValid($index)) {
2023-06-15 05:29:03 +00:00
throw new Exception(Exception::INDEX_INVALID, $validator->getDescription());
}
2021-08-22 15:00:00 +00:00
try {
2023-06-15 05:29:03 +00:00
$index = $dbForProject->createDocument('indexes', $index);
} catch (DuplicateException) {
throw new Exception(Exception::INDEX_ALREADY_EXISTS);
2021-08-22 15:00:00 +00:00
}
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId);
2021-03-23 21:19:19 +00:00
2022-12-20 16:11:30 +00:00
$queueForDatabase
->setType(DATABASE_TYPE_CREATE_INDEX)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setDatabase($db)
2025-04-27 05:03:44 +00:00
->setTable($table)
->setRow($index);
2022-12-20 16:11:30 +00:00
$queueForEvents
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId())
->setParam('indexId', $index->getId())
->setContext('table', $table)
2023-05-24 10:09:08 +00:00
->setContext('database', $db);
2022-09-07 11:11:10 +00:00
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
->dynamic($index, Response::MODEL_INDEX);
2021-03-23 21:19:19 +00:00
});
App::get('/v1/databases/:databaseId/tables/:tableId/indexes')
->alias('/v1/databases/:databaseId/collections/:tableId/indexes')
2023-10-02 14:02:48 +00:00
->desc('List indexes')
2021-03-24 15:40:33 +00:00
->groups(['api', 'database'])
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
2025-03-31 05:48:17 +00:00
group: 'indexes',
2025-01-17 04:31:39 +00:00
name: 'listIndexes',
description: '/docs/references/databases/list-indexes.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_INDEX_LIST,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
2023-07-21 11:10:44 +00:00
->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true)
2021-03-24 15:40:33 +00:00
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject) {
2024-02-12 09:55:45 +00:00
/** @var Document $database */
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
$table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
2021-03-24 15:40:33 +00:00
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-06-10 13:15:00 +00:00
}
2024-11-04 07:57:08 +00:00
$queries = Query::parseQueries($queries);
2024-02-12 16:02:04 +00:00
2024-11-04 07:57:08 +00:00
\array_push(
$queries,
Query::equal('databaseId', [$databaseId]),
Query::equal('collectionId', [$tableId]),
2024-11-04 07:57:08 +00:00
);
2021-03-24 15:40:33 +00:00
2024-02-12 09:55:45 +00:00
/**
2024-02-12 10:03:31 +00:00
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
2024-02-12 09:55:45 +00:00
*/
2024-03-06 17:34:21 +00:00
$cursor = \array_filter($queries, function ($query) {
2023-12-06 14:10:40 +00:00
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
2024-03-06 17:34:21 +00:00
});
$cursor = reset($cursor);
2023-07-21 11:10:44 +00:00
if ($cursor) {
$validator = new Cursor();
if (!$validator->isValid($cursor)) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
}
2023-07-21 11:10:44 +00:00
$indexId = $cursor->getValue();
2024-03-06 17:34:21 +00:00
$cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [
Query::equal('collectionInternalId', [$table->getInternalId()]),
2024-02-12 09:55:45 +00:00
Query::equal('databaseInternalId', [$database->getInternalId()]),
Query::equal('key', [$indexId]),
Query::limit(1)
]));
2021-06-10 13:15:00 +00:00
2023-07-21 11:10:44 +00:00
if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) {
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Index '{$indexId}' for the 'cursor' value not found.");
}
2021-03-24 15:40:33 +00:00
2023-07-21 11:10:44 +00:00
$cursor->setValue($cursorDocument[0]);
}
2021-03-24 15:40:33 +00:00
2023-07-21 11:10:44 +00:00
$filterQueries = Query::groupByType($queries)['filters'];
try {
$total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT);
$indexes = $dbForProject->find('indexes', $queries);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null.");
}
2021-07-25 14:47:18 +00:00
$response->dynamic(new Document([
'total' => $total,
'indexes' => $indexes,
]), Response::MODEL_INDEX_LIST);
2021-03-24 15:40:33 +00:00
});
App::get('/v1/databases/:databaseId/tables/:tableId/indexes/:key')
->alias('/v1/databases/:databaseId/collections/:tableId/indexes/:key')
2023-10-02 14:02:48 +00:00
->desc('Get index')
2021-03-25 19:52:57 +00:00
->groups(['api', 'database'])
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
2025-03-31 05:48:17 +00:00
group: 'indexes',
2025-01-17 04:31:39 +00:00
name: 'getIndex',
description: '/docs/references/databases/get-index.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_INDEX,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', null, new Key(), 'Index Key.')
2021-03-25 19:52:57 +00:00
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject) {
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
2021-03-25 19:52:57 +00:00
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
$table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-06-10 13:15:00 +00:00
}
$index = $table->find('key', $key, 'indexes');
2023-07-20 09:22:05 +00:00
if (empty($index)) {
throw new Exception(Exception::INDEX_NOT_FOUND);
}
2021-07-25 14:47:18 +00:00
$response->dynamic($index, Response::MODEL_INDEX);
2021-03-25 19:52:57 +00:00
});
App::delete('/v1/databases/:databaseId/tables/:tableId/indexes/:key')
->alias('/v1/databases/:databaseId/collections/:tableId/indexes/:key')
2023-10-02 14:02:48 +00:00
->desc('Delete index')
2021-03-25 19:52:57 +00:00
->groups(['api', 'database'])
->label('scope', 'collections.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update')
2022-09-05 08:00:08 +00:00
->label('audits.event', 'index.delete')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
2025-03-31 05:48:17 +00:00
group: 'indexes',
2025-01-17 04:31:39 +00:00
name: 'deleteIndex',
description: '/docs/references/databases/delete-index.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_NOCONTENT,
model: Response::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Index Key.')
2021-03-25 19:52:57 +00:00
->inject('response')
->inject('dbForProject')
2022-12-20 16:11:30 +00:00
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
2021-03-25 19:52:57 +00:00
2024-03-06 17:34:21 +00:00
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($db->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
$table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId);
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-06-10 13:15:00 +00:00
}
$index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key);
2021-08-23 04:06:53 +00:00
if (empty($index->getId())) {
throw new Exception(Exception::INDEX_NOT_FOUND);
2021-03-25 19:52:57 +00:00
}
// Only update status if removing available index
if ($index->getAttribute('status') === 'available') {
$index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting'));
}
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId);
2021-08-23 04:06:53 +00:00
2022-12-20 16:11:30 +00:00
$queueForDatabase
->setType(DATABASE_TYPE_DELETE_INDEX)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setDatabase($db)
2025-04-27 05:03:44 +00:00
->setTable($table)
->setRow($index);
2021-03-25 19:52:57 +00:00
2022-12-20 16:11:30 +00:00
$queueForEvents
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId())
->setParam('indexId', $index->getId())
->setContext('table', $table)
2022-08-05 06:01:25 +00:00
->setContext('database', $db)
2023-05-24 10:09:08 +00:00
->setPayload($response->output($index, Response::MODEL_INDEX));
2021-03-25 19:52:57 +00:00
$response->noContent();
});
App::post('/v1/databases/:databaseId/tables/:tableId/rows')
->alias('/v1/databases/:databaseId/collections/:tableId/documents')
->desc('Create row')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create')
2020-01-31 22:34:07 +00:00
->label('scope', 'documents.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'row.create')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
2025-01-17 04:31:39 +00:00
->label(
'sdk',
[
new Method(
namespace: 'databases',
group: 'rows',
name: 'createRow',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/create-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_CREATED,
model: Response::MODEL_DOCUMENT,
)
],
contentType: ContentType::JSON
)
]
)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.')
->param('data', [], new JSON(), 'Row data as JSON object.')
2023-10-13 13:43:23 +00:00
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
2021-03-21 22:17:20 +00:00
->inject('user')
2022-12-20 16:11:30 +00:00
->inject('queueForEvents')
2025-01-30 04:53:53 +00:00
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
2020-06-29 21:43:34 +00:00
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data)) {
throw new Exception(Exception::DOCUMENT_MISSING_DATA);
2020-06-29 21:43:34 +00:00
}
2020-01-31 22:34:07 +00:00
2020-06-29 21:43:34 +00:00
if (isset($data['$id'])) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead');
2020-06-29 21:43:34 +00:00
}
2025-01-02 07:56:14 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
2022-08-08 10:58:28 +00:00
2023-08-08 19:46:01 +00:00
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
2023-08-16 21:58:25 +00:00
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
2022-08-08 10:58:28 +00:00
}
$table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId));
2020-01-31 22:34:07 +00:00
if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
2023-08-16 21:58:25 +00:00
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2022-08-08 10:58:28 +00:00
}
2022-08-23 01:42:25 +00:00
$allowedPermissions = [
Database::PERMISSION_READ,
Database::PERMISSION_UPDATE,
Database::PERMISSION_DELETE,
];
2022-08-23 01:42:25 +00:00
// Map aggregate permissions to into the set of individual permissions they represent.
$permissions = Permission::aggregate($permissions, $allowedPermissions);
// Add permissions for current the user if none were provided.
2022-08-15 12:56:19 +00:00
if (\is_null($permissions)) {
$permissions = [];
2022-08-15 13:16:20 +00:00
if (!empty($user->getId())) {
2022-08-15 12:56:19 +00:00
foreach ($allowedPermissions as $permission) {
2022-08-15 13:16:20 +00:00
$permissions[] = (new Permission($permission, 'user', $user->getId()))->toString();
2022-08-15 12:56:19 +00:00
}
}
}
2022-08-14 05:24:50 +00:00
2022-08-15 12:56:19 +00:00
// Users can only manage their own roles, API keys and Admin users can manage any
2023-08-16 21:58:25 +00:00
if (!$isAPIKey && !$isPrivilegedUser) {
2022-08-15 12:56:19 +00:00
foreach (Database::PERMISSIONS as $type) {
foreach ($permissions as $permission) {
2022-08-16 11:26:38 +00:00
$permission = Permission::parse($permission);
if ($permission->getPermission() != $type) {
2022-08-15 12:56:19 +00:00
continue;
}
2022-08-16 11:26:38 +00:00
$role = (new Role(
$permission->getRole(),
$permission->getIdentifier(),
$permission->getDimension()
))->toString();
2022-08-15 12:56:19 +00:00
if (!Authorization::isRole($role)) {
2023-08-22 03:25:55 +00:00
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')');
2022-08-15 12:56:19 +00:00
}
}
}
2022-08-08 10:58:28 +00:00
}
$data['$collection'] = $table->getId(); // Adding this param to make API easier for developers
$data['$id'] = $rowId == 'unique()' ? ID::unique() : $rowId;
$data['$permissions'] = $permissions;
$row = new Document($data);
2020-01-31 22:34:07 +00:00
2025-01-06 16:51:39 +00:00
$operations = 0;
$checkPermissions = function (Document $table, Document $row, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) {
2025-01-06 16:51:39 +00:00
$operations++;
$documentSecurity = $table->getAttribute('documentSecurity', false);
2023-03-28 09:02:49 +00:00
$validator = new Authorization($permission);
$valid = $validator->isValid($table->getPermissionsByType($permission));
2023-03-28 09:02:49 +00:00
if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if ($permission === Database::PERMISSION_UPDATE) {
$valid = $valid || $validator->isValid($row->getUpdate());
2023-03-28 09:02:49 +00:00
if ($documentSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
}
$relationships = \array_filter(
$table->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
2023-03-28 09:02:49 +00:00
);
foreach ($relationships as $relationship) {
$related = $row->getAttribute($relationship->getAttribute('key'));
2023-03-28 09:02:49 +00:00
if (empty($related)) {
continue;
}
2023-04-14 10:03:16 +00:00
$isList = \is_array($related) && \array_values($related) === $related;
if ($isList) {
$relations = $related;
} else {
$relations = [$related];
}
2023-03-28 09:02:49 +00:00
$relatedTableId = $relationship->getAttribute('relatedCollection');
$relatedTable = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)
2023-03-28 09:02:49 +00:00
);
foreach ($relations as &$relation) {
if (
2023-04-21 01:44:53 +00:00
\is_array($relation)
&& \array_values($relation) !== $relation
&& !isset($relation['$id'])
) {
$relation['$id'] = ID::unique();
$relation = new Document($relation);
}
2023-03-29 01:37:56 +00:00
if ($relation instanceof Document) {
2025-01-02 07:56:14 +00:00
$current = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId())
2023-03-28 09:02:49 +00:00
);
if ($current->isEmpty()) {
$type = Database::PERMISSION_CREATE;
if (isset($relation['$id']) && $relation['$id'] === 'unique()') {
$relation['$id'] = ID::unique();
}
} else {
$relation->removeAttribute('$collectionId');
$relation->removeAttribute('$databaseId');
$relation->setAttribute('$collection', $relatedTable->getId());
$type = Database::PERMISSION_UPDATE;
}
2023-03-28 09:02:49 +00:00
$checkPermissions($relatedTable, $relation, $type);
2023-03-28 09:02:49 +00:00
}
}
2023-04-14 10:03:16 +00:00
if ($isList) {
$row->setAttribute($relationship->getAttribute('key'), \array_values($relations));
} else {
$row->setAttribute($relationship->getAttribute('key'), \reset($relations));
}
2023-03-28 09:02:49 +00:00
}
};
$checkPermissions($table, $row, Database::PERMISSION_CREATE);
2023-03-28 09:02:49 +00:00
2024-03-06 17:34:21 +00:00
try {
$row = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $row);
2024-11-04 07:57:08 +00:00
} catch (StructureException $e) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage());
} catch (DuplicateException $e) {
2024-03-06 17:34:21 +00:00
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
2024-11-04 07:57:08 +00:00
} catch (NotFoundException $e) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2024-03-06 17:34:21 +00:00
}
2020-01-31 22:34:07 +00:00
2025-01-02 08:09:44 +00:00
// Add $tableId and $databaseId for all rows
$processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) {
$row->setAttribute('$databaseId', $database->getId());
$row->setAttribute('$collectionId', $table->getId());
$relationships = \array_filter(
$table->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
foreach ($relationships as $relationship) {
$related = $row->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
continue;
}
if (!\is_array($related)) {
$related = [$related];
}
$relatedTableId = $relationship->getAttribute('relatedCollection');
$relatedTable = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)
);
2023-03-29 01:37:56 +00:00
foreach ($related as $relation) {
2023-04-03 10:39:31 +00:00
if ($relation instanceof Document) {
$processRow($relatedTable, $relation);
2023-04-03 10:39:31 +00:00
}
}
}
};
$processRow($table, $row);
2020-01-31 22:34:07 +00:00
$queueForStatsUsage
2025-03-18 14:20:25 +00:00
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
2025-03-30 05:54:48 +00:00
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection
2025-01-02 14:45:21 +00:00
2025-01-06 15:19:39 +00:00
$response->addHeader('X-Debug-Operations', $operations);
2024-07-11 15:03:28 +00:00
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($row, Response::MODEL_DOCUMENT);
2024-07-11 15:03:28 +00:00
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
\array_filter(
$table->getAttribute('attributes', []),
2024-07-11 15:03:28 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
)
);
2022-12-20 16:11:30 +00:00
$queueForEvents
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId())
->setParam('rowId', $row->getId())
->setContext('table', $table)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setContext('database', $database)
2024-07-11 15:03:28 +00:00
->setPayload($response->getPayload(), sensitive: $relationships);
2020-12-26 15:05:04 +00:00
});
2020-01-31 22:34:07 +00:00
App::get('/v1/databases/:databaseId/tables/:tableId/rows')
->alias('/v1/databases/:databaseId/collections/:tableId/documents')
->desc('List rows')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
->label('scope', 'documents.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'rows',
name: 'listRows',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/list-documents.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_DOCUMENT_LIST,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
2023-03-29 19:38:39 +00:00
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
2025-01-30 04:53:53 +00:00
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) {
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
2023-08-08 19:46:01 +00:00
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
2019-05-09 06:54:39 +00:00
2023-08-16 21:58:25 +00:00
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2022-08-08 10:58:28 +00:00
$table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId));
2019-05-09 06:54:39 +00:00
if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
2021-12-28 17:57:24 +00:00
2024-02-08 16:10:25 +00:00
try {
2024-02-12 16:02:04 +00:00
$queries = Query::parseQueries($queries);
2024-02-08 16:10:25 +00:00
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
2020-06-29 21:43:34 +00:00
2024-02-12 09:55:45 +00:00
/**
2024-02-12 10:03:31 +00:00
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
2024-02-12 09:55:45 +00:00
*/
2023-08-22 03:25:55 +00:00
$cursor = \array_filter($queries, function ($query) {
2023-12-06 14:10:40 +00:00
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
2023-08-22 03:25:55 +00:00
});
$cursor = \reset($cursor);
2022-08-30 11:55:23 +00:00
if ($cursor) {
2024-05-09 16:54:28 +00:00
$validator = new Cursor();
if (!$validator->isValid($cursor)) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
}
$rowId = $cursor->getValue();
2021-07-05 20:27:20 +00:00
$cursorRow = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId));
2022-08-24 13:24:19 +00:00
if ($cursorRow->isEmpty()) {
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Row '{$rowId}' for the 'cursor' value not found.");
2021-08-05 19:01:00 +00:00
}
2022-08-11 23:53:52 +00:00
$cursor->setValue($cursorRow);
2022-08-11 23:53:52 +00:00
}
try {
$rows = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null.");
}
2025-01-06 16:01:44 +00:00
$operations = 0;
2025-01-02 08:09:44 +00:00
// Add $tableId and $databaseId for all rows
$processRow = (function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations): bool {
if ($row->isEmpty()) {
2023-03-28 09:02:49 +00:00
return false;
}
2025-01-06 16:01:44 +00:00
$operations++;
$row->removeAttribute('$collection');
$row->setAttribute('$databaseId', $database->getId());
$row->setAttribute('$collectionId', $table->getId());
$relationships = \array_filter(
$table->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
foreach ($relationships as $relationship) {
$related = $row->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
2025-01-06 16:51:39 +00:00
if (\in_array(\gettype($related), ['array', 'object'])) {
$operations++;
}
continue;
}
2025-01-06 16:01:44 +00:00
if (!\is_array($related)) {
2023-03-28 09:02:49 +00:00
$relations = [$related];
} else {
$relations = $related;
}
$relatedTableId = $relationship->getAttribute('relatedCollection');
2025-01-02 08:09:44 +00:00
// todo: Use local cache for this getDocument
$relatedTable = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId));
2023-03-28 09:02:49 +00:00
foreach ($relations as $index => $doc) {
2023-03-31 04:56:25 +00:00
if ($doc instanceof Document) {
if (!$processRow($relatedTable, $doc)) {
2023-03-31 04:56:25 +00:00
unset($relations[$index]);
}
2023-03-28 09:02:49 +00:00
}
}
if (\is_array($related)) {
$row->setAttribute($relationship->getAttribute('key'), \array_values($relations));
2023-03-28 09:02:49 +00:00
} elseif (empty($relations)) {
$row->setAttribute($relationship->getAttribute('key'), null);
}
}
2023-03-28 09:02:49 +00:00
return true;
2023-08-16 21:58:25 +00:00
});
foreach ($rows as $row) {
$processRow($table, $row);
2023-08-16 21:58:25 +00:00
}
2021-12-27 10:45:24 +00:00
$queueForStatsUsage
2025-03-18 14:20:25 +00:00
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
2025-01-06 09:28:26 +00:00
2025-01-06 15:19:39 +00:00
$response->addHeader('X-Debug-Operations', $operations);
2025-01-06 14:50:23 +00:00
2024-02-24 10:55:33 +00:00
$select = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT);
}, false);
// Check if the SELECT query includes $databaseId and $collectionId
$hasDatabaseId = false;
$hasTableId = false;
2024-02-24 10:55:33 +00:00
if ($select) {
$hasDatabaseId = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues()));
}, false);
$hasTableId = \array_reduce($queries, function ($result, $query) {
2024-02-24 10:55:33 +00:00
return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues()));
}, false);
}
if ($select) {
foreach ($rows as $row) {
2024-02-24 10:55:33 +00:00
if (!$hasDatabaseId) {
$row->removeAttribute('$databaseId');
2024-02-24 10:55:33 +00:00
}
if (!$hasTableId) {
$row->removeAttribute('$collectionId');
2024-02-24 10:55:33 +00:00
}
}
}
2021-07-25 14:47:18 +00:00
$response->dynamic(new Document([
2022-02-27 09:57:09 +00:00
'total' => $total,
'documents' => $rows,
2021-06-14 19:55:36 +00:00
]), Response::MODEL_DOCUMENT_LIST);
2020-12-26 15:05:04 +00:00
});
2019-05-09 06:54:39 +00:00
App::get('/v1/databases/:databaseId/tables/:tableId/rows/:rowId')
->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId')
->desc('Get row')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
->label('scope', 'documents.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'rows',
name: 'getRow',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/get-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_DOCUMENT,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('rowId', '', new UID(), 'Row ID.')
2024-02-02 10:54:34 +00:00
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
2025-01-30 04:53:53 +00:00
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $tableId, string $rowId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) {
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
2023-08-08 19:46:01 +00:00
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
2019-05-09 06:54:39 +00:00
2023-08-16 21:58:25 +00:00
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2022-08-08 10:58:28 +00:00
$table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId));
2019-05-09 06:54:39 +00:00
if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
2023-08-16 21:58:25 +00:00
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
2023-08-22 03:25:55 +00:00
try {
2024-02-12 16:02:04 +00:00
$queries = Query::parseQueries($queries);
$row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId, $queries);
2023-08-22 03:25:55 +00:00
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (QueryException $e) {
2024-02-12 16:02:04 +00:00
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
2022-08-08 10:58:28 +00:00
if ($row->isEmpty()) {
2022-08-16 09:07:30 +00:00
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
2022-08-08 10:58:28 +00:00
}
2025-01-06 16:01:44 +00:00
$operations = 0;
2025-01-02 08:09:44 +00:00
// Add $tableId and $databaseId for all rows
$processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations) {
if ($row->isEmpty()) {
return;
2023-03-28 09:02:49 +00:00
}
2025-01-06 16:01:44 +00:00
$operations++;
$row->setAttribute('$databaseId', $database->getId());
$row->setAttribute('$collectionId', $table->getId());
$relationships = \array_filter(
$table->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
foreach ($relationships as $relationship) {
$related = $row->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
2025-01-06 16:51:39 +00:00
if (\in_array(\gettype($related), ['array', 'object'])) {
$operations++;
}
continue;
}
2025-01-06 16:01:44 +00:00
if (!\is_array($related)) {
$related = [$related];
}
$relatedTableId = $relationship->getAttribute('relatedCollection');
$relatedTable = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)
);
2023-03-29 01:37:56 +00:00
foreach ($related as $relation) {
2023-04-03 10:39:31 +00:00
if ($relation instanceof Document) {
$processRow($relatedTable, $relation);
2023-04-03 10:39:31 +00:00
}
}
}
};
$processRow($table, $row);
2021-12-27 10:45:24 +00:00
$queueForStatsUsage
2025-03-18 14:20:25 +00:00
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
2025-01-02 07:56:14 +00:00
2025-01-06 15:19:39 +00:00
$response->addHeader('X-Debug-Operations', $operations);
$response->dynamic($row, Response::MODEL_DOCUMENT);
2020-12-26 15:05:04 +00:00
});
2019-05-09 06:54:39 +00:00
App::get('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs')
->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId/logs')
->desc('List row logs')
->groups(['api', 'database'])
->label('scope', 'documents.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
2025-03-31 05:48:17 +00:00
group: 'logs',
name: 'listRowLogs',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/get-document-logs.md',
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_LOG_LIST,
)
],
contentType: ContentType::JSON,
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Collection ID.')
->param('rowId', '', new UID(), 'Row ID.')
2023-05-16 12:56:20 +00:00
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $databaseId, string $tableId, string $rowId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
$table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId);
if ($row->isEmpty()) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
}
2024-02-12 16:02:04 +00:00
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
2025-02-25 08:03:37 +00:00
// Temp fix for logs
$queries[] = Query::or([
2025-02-26 01:00:16 +00:00
Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))),
2025-02-25 08:03:37 +00:00
Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))),
]);
2025-02-25 05:51:11 +00:00
$audit = new Audit($dbForProject);
$resource = 'database/' . $databaseId . '/table/' . $tableId . '/row/' . $row->getId();
2025-02-25 07:26:00 +00:00
$logs = $audit->getLogsByResource($resource, $queries);
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$detector = new Detector($log['userAgent']);
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector->getOS();
$client = $detector->getClient();
$device = $detector->getDevice();
$output[$i] = new Document([
'event' => $log['event'],
'userId' => $log['data']['userId'],
'userEmail' => $log['data']['userEmail'] ?? null,
'userName' => $log['data']['userName'] ?? null,
'mode' => $log['data']['mode'] ?? null,
'ip' => $log['ip'],
'time' => $log['time'],
'osCode' => $os['osCode'],
'osName' => $os['osName'],
'osVersion' => $os['osVersion'],
'clientType' => $client['clientType'],
'clientCode' => $client['clientCode'],
'clientName' => $client['clientName'],
'clientVersion' => $client['clientVersion'],
'clientEngine' => $client['clientEngine'],
'clientEngineVersion' => $client['clientEngineVersion'],
'deviceName' => $device['deviceName'],
'deviceBrand' => $device['deviceBrand'],
'deviceModel' => $device['deviceModel']
]);
$record = $geodb->get($log['ip']);
if ($record) {
2022-05-23 14:54:50 +00:00
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--';
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
} else {
$output[$i]['countryCode'] = '--';
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
2025-01-06 16:57:35 +00:00
2021-11-18 10:33:42 +00:00
$response->dynamic(new Document([
2025-02-25 07:26:00 +00:00
'total' => $audit->countLogsByResource($resource, $queries),
'logs' => $output,
2021-11-18 10:33:42 +00:00
]), Response::MODEL_LOG_LIST);
});
App::patch('/v1/databases/:databaseId/tables/:tableId/rows/:rowId')
->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId')
->desc('Update row')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update')
->label('scope', 'documents.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'row.update')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'rows',
name: 'updateRow',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/update-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_DOCUMENT,
)
],
contentType: ContentType::JSON
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Collection ID.')
->param('rowId', '', new UID(), 'Row ID.')
->param('data', [], new JSON(), 'Row data as JSON object. Include only columns and value pairs to be updated.', true)
2023-10-13 13:43:23 +00:00
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->inject('requestTimestamp')
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
2022-12-20 16:11:30 +00:00
->inject('queueForEvents')
2025-01-30 04:53:53 +00:00
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
2019-05-09 06:54:39 +00:00
2022-08-08 10:58:28 +00:00
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
2022-08-14 05:21:33 +00:00
if (empty($data) && \is_null($permissions)) {
2022-08-16 09:07:30 +00:00
throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD);
2022-08-08 10:58:28 +00:00
}
2025-01-02 07:56:14 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-08-08 19:46:01 +00:00
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
2023-08-16 21:58:25 +00:00
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2022-08-08 10:58:28 +00:00
$table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId));
2019-09-16 19:03:24 +00:00
if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
2023-08-16 21:58:25 +00:00
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-08-12 01:05:19 +00:00
}
// Read permission should not be required for update
/** @var Document $row */
$row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId));
if ($row->isEmpty()) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
2020-06-29 21:43:34 +00:00
}
2019-05-09 06:54:39 +00:00
2022-08-25 03:51:21 +00:00
// Map aggregate permissions into the multiple permissions they represent.
$permissions = Permission::aggregate($permissions, [
Database::PERMISSION_READ,
Database::PERMISSION_UPDATE,
Database::PERMISSION_DELETE,
]);
2022-08-15 12:56:19 +00:00
// Users can only manage their own roles, API keys and Admin users can manage any
2022-08-08 10:58:28 +00:00
$roles = Authorization::getRoles();
2023-08-16 21:58:25 +00:00
if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) {
2022-08-15 12:56:19 +00:00
foreach (Database::PERMISSIONS as $type) {
foreach ($permissions as $permission) {
2022-08-16 11:26:38 +00:00
$permission = Permission::parse($permission);
if ($permission->getPermission() != $type) {
2022-08-15 12:56:19 +00:00
continue;
}
2022-08-16 11:26:38 +00:00
$role = (new Role(
$permission->getRole(),
$permission->getIdentifier(),
$permission->getDimension()
))->toString();
2022-08-15 12:56:19 +00:00
if (!Authorization::isRole($role)) {
2022-08-25 03:51:21 +00:00
throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')');
2022-08-15 12:56:19 +00:00
}
2022-08-08 10:58:28 +00:00
}
}
}
if (\is_null($permissions)) {
$permissions = $row->getPermissions() ?? [];
}
$data['$id'] = $rowId;
$data['$permissions'] = $permissions;
$newRow = new Document($data);
2020-10-30 19:53:27 +00:00
2025-01-06 16:51:39 +00:00
$operations = 0;
2025-01-06 16:01:44 +00:00
$setTable = (function (Document $collection, Document $document) use (&$setTable, $dbForProject, $database, &$operations) {
2025-01-06 16:51:39 +00:00
$operations++;
2023-03-28 09:02:49 +00:00
$relationships = \array_filter(
$collection->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
2023-03-28 09:02:49 +00:00
);
foreach ($relationships as $relationship) {
$related = $document->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
continue;
}
2023-04-14 10:03:16 +00:00
$isList = \is_array($related) && \array_values($related) === $related;
if ($isList) {
$relations = $related;
} else {
$relations = [$related];
}
2023-03-28 09:02:49 +00:00
$relatedTableId = $relationship->getAttribute('relatedCollection');
$relatedTable = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)
2025-01-02 07:56:14 +00:00
);
2023-03-28 09:02:49 +00:00
foreach ($relations as &$relation) {
// If the relation is an array it can be either update or create a child document.
if (
\is_array($relation)
&& \array_values($relation) !== $relation
&& !isset($relation['$id'])
) {
$relation['$id'] = ID::unique();
$relation = new Document($relation);
}
2023-03-29 01:37:56 +00:00
if ($relation instanceof Document) {
$oldRow = Authorization::skip(fn () => $dbForProject->getDocument(
'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(),
2025-01-02 07:56:14 +00:00
$relation->getId()
));
2023-08-07 23:10:07 +00:00
$relation->removeAttribute('$collectionId');
$relation->removeAttribute('$databaseId');
// Attribute $collection is required for Utopia.
2025-01-02 07:56:14 +00:00
$relation->setAttribute(
'$collection',
'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId()
2025-01-02 07:56:14 +00:00
);
if ($oldRow->isEmpty()) {
if (isset($relation['$id']) && $relation['$id'] === 'unique()') {
$relation['$id'] = ID::unique();
}
}
$setTable($relatedTable, $relation);
2023-03-28 09:02:49 +00:00
}
}
2023-04-14 10:03:16 +00:00
if ($isList) {
$document->setAttribute($relationship->getAttribute('key'), \array_values($relations));
} else {
$document->setAttribute($relationship->getAttribute('key'), \reset($relations));
}
}
2023-08-17 13:34:41 +00:00
});
2023-03-28 09:02:49 +00:00
$setTable($table, $newRow);
2022-08-08 10:58:28 +00:00
$queueForStatsUsage
2025-03-18 14:20:25 +00:00
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations);
2025-01-06 09:28:26 +00:00
2025-01-06 15:19:39 +00:00
$response->addHeader('X-Debug-Operations', $operations);
2025-01-06 14:50:23 +00:00
2023-08-17 13:34:41 +00:00
try {
$row = $dbForProject->withRequestTimestamp(
2025-01-02 07:56:14 +00:00
$requestTimestamp,
fn () => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(),
$row->getId(),
$newRow
2025-01-02 07:56:14 +00:00
)
);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
2022-08-08 10:58:28 +00:00
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
2024-11-04 07:57:08 +00:00
} catch (StructureException $e) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage());
} catch (NotFoundException $e) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-08-15 21:09:40 +00:00
}
2021-12-16 18:12:06 +00:00
// Add $tableId and $databaseId for all rows
$processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) {
$row->setAttribute('$databaseId', $database->getId());
$row->setAttribute('$collectionId', $table->getId());
$relationships = \array_filter(
$table->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
foreach ($relationships as $relationship) {
$related = $row->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
2023-03-27 07:08:02 +00:00
continue;
}
if (!\is_array($related)) {
$related = [$related];
}
$relatedTableId = $relationship->getAttribute('relatedCollection');
$relatedTable = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)
2025-01-02 07:56:14 +00:00
);
2023-03-27 07:08:02 +00:00
2023-03-29 01:37:56 +00:00
foreach ($related as $relation) {
2023-04-03 10:39:31 +00:00
if ($relation instanceof Document) {
$processRow($relatedTable, $relation);
2023-04-03 10:39:31 +00:00
}
}
}
};
$processRow($table, $row);
$response->dynamic($row, Response::MODEL_DOCUMENT);
2024-07-11 15:03:28 +00:00
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
\array_filter(
$table->getAttribute('attributes', []),
2024-07-11 15:03:28 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
)
);
2022-12-20 16:11:30 +00:00
$queueForEvents
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId())
->setParam('rowId', $row->getId())
->setContext('table', $table)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setContext('database', $database)
2024-07-11 15:03:28 +00:00
->setPayload($response->getPayload(), sensitive: $relationships);
2020-12-26 15:05:04 +00:00
});
2019-05-09 06:54:39 +00:00
App::delete('/v1/databases/:databaseId/tables/:tableId/rows/:rowId')
->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId')
->desc('Delete row')
2020-06-25 18:32:12 +00:00
->groups(['api', 'database'])
->label('scope', 'documents.write')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].delete')
->label('audits.event', 'row.delete')
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{request.rowId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: 'rows',
name: 'deleteRow',
2025-01-17 04:31:39 +00:00
description: '/docs/references/databases/delete-document.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_NOCONTENT,
model: Response::MODEL_NONE,
)
],
contentType: ContentType::NONE
))
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('rowId', '', new UID(), 'Row ID.')
->inject('requestTimestamp')
2020-12-26 15:05:04 +00:00
->inject('response')
->inject('dbForProject')
2022-12-20 16:11:30 +00:00
->inject('queueForEvents')
2025-01-30 04:53:53 +00:00
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
2024-03-06 17:34:21 +00:00
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-08-08 19:46:01 +00:00
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
2019-05-09 06:54:39 +00:00
2023-08-16 21:58:25 +00:00
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2022-08-08 10:58:28 +00:00
$table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId));
2019-05-09 06:54:39 +00:00
if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
2023-08-16 21:58:25 +00:00
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2021-08-12 01:05:19 +00:00
}
// Read permission should not be required for delete
$row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId));
if ($row->isEmpty()) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
2020-06-29 21:43:34 +00:00
}
2019-05-09 06:54:39 +00:00
2024-11-04 07:57:08 +00:00
try {
$dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $table, $rowId) {
2025-01-02 07:56:14 +00:00
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(),
$rowId
2025-01-02 07:56:14 +00:00
);
2024-11-04 07:57:08 +00:00
});
} catch (NotFoundException $e) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
2022-08-08 10:58:28 +00:00
// Add $tableId and $databaseId for all rows
$processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) {
$row->setAttribute('$databaseId', $database->getId());
$row->setAttribute('$collectionId', $table->getId());
$relationships = \array_filter(
$table->getAttribute('attributes', []),
2024-03-06 17:34:21 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
foreach ($relationships as $relationship) {
$related = $row->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
continue;
}
if (!\is_array($related)) {
$related = [$related];
}
$relatedTableId = $relationship->getAttribute('relatedCollection');
$relatedTable = Authorization::skip(
fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)
2025-01-02 07:56:14 +00:00
);
2023-03-29 03:30:47 +00:00
foreach ($related as $relation) {
2023-04-03 10:39:31 +00:00
if ($relation instanceof Document) {
$processRow($relatedTable, $relation);
2023-04-03 10:39:31 +00:00
}
}
}
};
$processRow($table, $row);
2021-12-27 10:45:24 +00:00
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1)
2025-03-30 05:54:48 +00:00
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection
2025-01-06 09:28:26 +00:00
2025-01-06 17:07:18 +00:00
$response->addHeader('X-Debug-Operations', 1);
2025-01-06 16:57:35 +00:00
2024-07-11 15:03:28 +00:00
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
\array_filter(
$table->getAttribute('attributes', []),
2024-07-11 15:03:28 +00:00
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
)
);
2022-12-20 16:11:30 +00:00
$queueForEvents
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setParam('databaseId', $databaseId)
->setParam('tableId', $table->getId())
->setParam('rowId', $row->getId())
->setContext('table', $table)
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
->setContext('database', $database)
->setPayload($response->output($row, Response::MODEL_DOCUMENT), sensitive: $relationships);
2020-06-29 21:43:34 +00:00
$response->noContent();
});
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
App::get('/v1/databases/usage')
2024-02-26 02:44:20 +00:00
->desc('Get databases usage stats')
->groups(['api', 'database', 'usage'])
2022-06-23 08:50:11 +00:00
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: null,
2025-01-17 04:31:39 +00:00
name: 'getUsage',
description: '/docs/references/databases/get-usage.md',
2025-01-17 04:31:39 +00:00
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_USAGE_DATABASES,
)
],
contentType: ContentType::JSON
))
2023-11-08 09:09:32 +00:00
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true)
2022-06-23 08:50:11 +00:00
->inject('response')
->inject('dbForProject')
->action(function (string $range, Response $response, Database $dbForProject) {
2023-10-25 07:39:59 +00:00
$periods = Config::getParam('usage', []);
$stats = $usage = [];
$days = $periods[$range];
$metrics = [
METRIC_DATABASES,
METRIC_COLLECTIONS,
METRIC_DOCUMENTS,
2025-01-23 13:24:02 +00:00
METRIC_DATABASES_STORAGE,
METRIC_DATABASES_OPERATIONS_READS,
METRIC_DATABASES_OPERATIONS_WRITES,
2023-10-25 07:39:59 +00:00
];
2022-06-23 08:50:11 +00:00
2023-11-08 09:09:32 +00:00
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
$result = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
]);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-11-08 09:09:32 +00:00
$stats[$metric]['total'] = $result['value'] ?? 0;
2023-10-25 07:39:59 +00:00
$limit = $days['limit'];
$period = $days['period'];
2024-02-01 10:21:50 +00:00
$results = $dbForProject->find('stats', [
2023-10-25 07:39:59 +00:00
Query::equal('metric', [$metric]),
2023-10-25 12:06:54 +00:00
Query::equal('period', [$period]),
2023-10-25 07:39:59 +00:00
Query::limit($limit),
Query::orderDesc('time'),
]);
2023-11-08 09:09:32 +00:00
$stats[$metric]['data'] = [];
2023-10-25 07:39:59 +00:00
foreach ($results as $result) {
2023-11-08 09:09:32 +00:00
$stats[$metric]['data'][$result->getAttribute('time')] = [
'value' => $result->getAttribute('value'),
2023-10-25 07:39:59 +00:00
];
2023-10-15 17:41:09 +00:00
}
2023-10-25 07:39:59 +00:00
}
});
2023-10-15 17:41:09 +00:00
2023-10-25 07:39:59 +00:00
$format = match ($days['period']) {
'1h' => 'Y-m-d\TH:00:00.000P',
'1d' => 'Y-m-d\T00:00:00.000P',
};
2023-10-15 17:41:09 +00:00
2024-03-06 17:34:21 +00:00
foreach ($metrics as $metric) {
$usage[$metric]['total'] = $stats[$metric]['total'];
2024-03-06 17:34:21 +00:00
$usage[$metric]['data'] = [];
$leap = time() - ($days['limit'] * $days['factor']);
while ($leap < time()) {
$leap += $days['factor'];
$formatDate = date($format, $leap);
$usage[$metric]['data'][] = [
'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0,
'date' => $formatDate,
];
}
2022-06-23 08:50:11 +00:00
}
2023-10-25 07:39:59 +00:00
$response->dynamic(new Document([
'range' => $range,
'databasesTotal' => $usage[$metrics[0]]['total'],
2023-11-08 09:09:32 +00:00
'collectionsTotal' => $usage[$metrics[1]]['total'],
'documentsTotal' => $usage[$metrics[2]]['total'],
'storageTotal' => $usage[$metrics[3]]['total'],
2025-01-23 13:24:02 +00:00
'databasesReadsTotal' => $usage[$metrics[4]]['total'],
'databasesWritesTotal' => $usage[$metrics[5]]['total'],
'databases' => $usage[$metrics[0]]['data'],
2023-11-08 09:09:32 +00:00
'collections' => $usage[$metrics[1]]['data'],
'documents' => $usage[$metrics[2]]['data'],
'storage' => $usage[$metrics[3]]['data'],
2025-01-23 13:24:02 +00:00
'databasesReads' => $usage[$metrics[4]]['data'],
'databasesWrites' => $usage[$metrics[5]]['data'],
2023-10-25 07:39:59 +00:00
]), Response::MODEL_USAGE_DATABASES);
2022-06-23 08:50:11 +00:00
});
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
App::get('/v1/databases/:databaseId/usage')
2024-02-26 02:44:20 +00:00
->desc('Get database usage stats')
->groups(['api', 'database', 'usage'])
2022-06-23 08:50:11 +00:00
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: null,
2025-01-17 04:31:39 +00:00
name: 'getDatabaseUsage',
description: '/docs/references/databases/get-database-usage.md',
2025-01-17 04:31:39 +00:00
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_USAGE_DATABASE,
)
],
contentType: ContentType::JSON,
))
2022-06-23 08:50:11 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
2023-11-08 09:09:32 +00:00
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true)
2022-06-23 08:50:11 +00:00
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) {
$database = $dbForProject->getDocument('databases', $databaseId);
2022-06-23 08:50:11 +00:00
2023-10-25 07:39:59 +00:00
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
2022-06-23 08:50:11 +00:00
2023-10-25 07:39:59 +00:00
$periods = Config::getParam('usage', []);
$stats = $usage = [];
$days = $periods[$range];
$metrics = [
str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS),
str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS),
2025-01-23 13:24:02 +00:00
str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE),
str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_READS),
str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES)
2023-10-25 07:39:59 +00:00
];
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-11-08 09:09:32 +00:00
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
$result = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
]);
2023-11-08 09:09:32 +00:00
$stats[$metric]['total'] = $result['value'] ?? 0;
2023-10-25 07:39:59 +00:00
$limit = $days['limit'];
$period = $days['period'];
2024-02-01 10:21:50 +00:00
$results = $dbForProject->find('stats', [
2023-10-25 07:39:59 +00:00
Query::equal('metric', [$metric]),
2023-10-25 12:06:54 +00:00
Query::equal('period', [$period]),
2023-10-25 07:39:59 +00:00
Query::limit($limit),
Query::orderDesc('time'),
]);
2023-11-08 09:09:32 +00:00
$stats[$metric]['data'] = [];
2023-10-25 07:39:59 +00:00
foreach ($results as $result) {
2023-11-08 09:09:32 +00:00
$stats[$metric]['data'][$result->getAttribute('time')] = [
'value' => $result->getAttribute('value'),
2023-10-25 07:39:59 +00:00
];
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
}
2023-10-25 07:39:59 +00:00
}
});
$format = match ($days['period']) {
'1h' => 'Y-m-d\TH:00:00.000P',
'1d' => 'Y-m-d\T00:00:00.000P',
};
2024-03-06 17:34:21 +00:00
foreach ($metrics as $metric) {
$usage[$metric]['total'] = $stats[$metric]['total'];
2024-03-06 17:34:21 +00:00
$usage[$metric]['data'] = [];
$leap = time() - ($days['limit'] * $days['factor']);
while ($leap < time()) {
$leap += $days['factor'];
$formatDate = date($format, $leap);
$usage[$metric]['data'][] = [
'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0,
'date' => $formatDate,
];
}
2022-06-23 08:50:11 +00:00
}
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-10-25 07:39:59 +00:00
$response->dynamic(new Document([
'range' => $range,
'collectionsTotal' => $usage[$metrics[0]]['total'],
'documentsTotal' => $usage[$metrics[1]]['total'],
'storageTotal' => $usage[$metrics[2]]['total'],
2025-01-23 13:24:02 +00:00
'databaseReadsTotal' => $usage[$metrics[3]]['total'],
'databaseWritesTotal' => $usage[$metrics[4]]['total'],
'collections' => $usage[$metrics[0]]['data'],
'documents' => $usage[$metrics[1]]['data'],
'storage' => $usage[$metrics[2]]['data'],
'databaseReads' => $usage[$metrics[3]]['data'],
'databaseWrites' => $usage[$metrics[4]]['data'],
2023-10-25 07:39:59 +00:00
]), Response::MODEL_USAGE_DATABASE);
2022-06-23 08:50:11 +00:00
});
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
App::get('/v1/databases/:databaseId/tables/:tableId/usage')
->alias('/v1/databases/:databaseId/collections/:tableId/usage')
->desc('Get table usage stats')
->groups(['api', 'database', 'usage'])
2022-06-23 08:50:11 +00:00
->label('scope', 'collections.read')
2024-10-29 15:07:12 +00:00
->label('resourceType', RESOURCE_TYPE_DATABASES)
2025-01-17 04:31:39 +00:00
->label('sdk', new Method(
namespace: 'databases',
group: null,
name: 'getTableUsage',
description: '/docs/references/databases/get-collection-usage.md',
2025-01-17 04:31:39 +00:00
auth: [AuthType::ADMIN],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_USAGE_COLLECTION,
)
],
contentType: ContentType::JSON,
))
2022-06-23 08:50:11 +00:00
->param('databaseId', '', new UID(), 'Database ID.')
2023-11-08 09:09:32 +00:00
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
->param('tableId', '', new UID(), 'Collection ID.')
2022-06-23 08:50:11 +00:00
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, string $tableId, Response $response, Database $dbForProject) {
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2024-03-06 17:34:21 +00:00
$database = $dbForProject->getDocument('databases', $databaseId);
$tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId);
$table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId());
2022-06-23 08:50:11 +00:00
if ($table->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
2022-06-23 08:50:11 +00:00
}
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-10-25 07:39:59 +00:00
$periods = Config::getParam('usage', []);
$stats = $usage = [];
$days = $periods[$range];
$metrics = [
str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $tableDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS),
2023-10-25 07:39:59 +00:00
];
2022-06-23 08:50:11 +00:00
2023-11-08 09:09:32 +00:00
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
$result = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
]);
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-11-08 09:09:32 +00:00
$stats[$metric]['total'] = $result['value'] ?? 0;
2023-10-25 07:39:59 +00:00
$limit = $days['limit'];
$period = $days['period'];
2024-02-01 10:21:50 +00:00
$results = $dbForProject->find('stats', [
2023-10-25 07:39:59 +00:00
Query::equal('metric', [$metric]),
2023-10-25 12:06:54 +00:00
Query::equal('period', [$period]),
2023-10-25 07:39:59 +00:00
Query::limit($limit),
Query::orderDesc('time'),
]);
2023-11-08 09:09:32 +00:00
$stats[$metric]['data'] = [];
2023-10-25 07:39:59 +00:00
foreach ($results as $result) {
2023-11-08 09:09:32 +00:00
$stats[$metric]['data'][$result->getAttribute('time')] = [
'value' => $result->getAttribute('value'),
2023-10-25 07:39:59 +00:00
];
2023-10-15 17:41:09 +00:00
}
2023-10-25 07:39:59 +00:00
}
});
2022-06-23 08:50:11 +00:00
2023-10-25 07:39:59 +00:00
$format = match ($days['period']) {
'1h' => 'Y-m-d\TH:00:00.000P',
'1d' => 'Y-m-d\T00:00:00.000P',
};
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2024-03-06 17:34:21 +00:00
foreach ($metrics as $metric) {
$usage[$metric]['total'] = $stats[$metric]['total'];
2024-03-06 17:34:21 +00:00
$usage[$metric]['data'] = [];
$leap = time() - ($days['limit'] * $days['factor']);
while ($leap < time()) {
$leap += $days['factor'];
$formatDate = date($format, $leap);
$usage[$metric]['data'][] = [
'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0,
'date' => $formatDate,
];
}
2022-06-23 08:50:11 +00:00
}
Database layer (#3338) * database response model * database collection config * new database scopes * database service update * database execption codes * remove read write permission from database model * updating tests and fixing some bugs * server side tests are now passing * databases api * tests for database endpoint * composer update * fix error * formatting * formatting fixes * get database test * more updates to events and usage * more usage updates * fix delete type * fix test * delete database * more fixes * databaseId in attributes and indexes * more fixes * fix issues * fix index subquery * fix console scope and index query * updating tests as required * fix phpcs errors and warnings * updates to review suggestions * UI progress * ui updates and cleaning up * fix type * rework database events * update tests * update types * event generation fixed * events config updated * updating context to support multiple * realtime updates * fix ids * update context * validator updates * fix naming conflict * fix tests * fix lint errors * fix wprler and realtime tests * fix webhooks test * fix event validator and other tests * formatting fixes * removing leftover var_dumps * remove leftover comment * update usage params * usage metrics updates * update database usage * fix usage * specs update * updates to usage * fix UI and usage * fix lints * internal id fixes * fixes for internal Id * renaming services and related files * rename tests * rename doc link * rename readme * fix test name * tests: fixes for 0.15.x sync Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2022-06-22 10:51:49 +00:00
2023-10-25 07:39:59 +00:00
$response->dynamic(new Document([
'range' => $range,
'documentsTotal' => $usage[$metrics[0]]['total'],
'documents' => $usage[$metrics[0]]['data'],
2023-10-25 07:39:59 +00:00
]), Response::MODEL_USAGE_COLLECTION);
2022-06-23 08:50:11 +00:00
});