mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
First commit
This commit is contained in:
@@ -2,15 +2,11 @@
|
||||
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\JSON;
|
||||
// use Utopia\Locale\Locale;
|
||||
// use Utopia\Audit\Audit;
|
||||
// use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Database\Document;
|
||||
use Appwrite\Database\Validator\UID;
|
||||
@@ -20,11 +16,12 @@ use Appwrite\Database\Validator\Collection;
|
||||
use Appwrite\Database\Validator\Authorization;
|
||||
use Appwrite\Database\Exception\Authorization as AuthorizationException;
|
||||
use Appwrite\Database\Exception\Structure as StructureException;
|
||||
use Appwrite\Utopia\Response;
|
||||
|
||||
App::post('/v1/database/collections')
|
||||
->desc('Create Collection')
|
||||
->groups(['api', 'database'])
|
||||
->label('webhook', 'database.collections.create')
|
||||
->label('event', 'database.collections.create')
|
||||
->label('scope', 'collections.write')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
@@ -34,10 +31,9 @@ App::post('/v1/database/collections')
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', false, ['projectDB'])
|
||||
->action(function ($name, $read, $write, $rules, $response, $projectDB, $webhooks, $audits) {
|
||||
->action(function ($name, $read, $write, $rules, $response, $projectDB, $audits) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $webhooks */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$parsedRules = [];
|
||||
@@ -77,26 +73,15 @@ App::post('/v1/database/collections')
|
||||
throw new Exception('Failed saving collection to DB', 500);
|
||||
}
|
||||
|
||||
$data = $data->getArrayCopy();
|
||||
|
||||
$webhooks
|
||||
->setParam('payload', $data)
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.collections.create')
|
||||
->setParam('resource', 'database/collection/'.$data['$id'])
|
||||
->setParam('data', $data)
|
||||
->setParam('resource', 'database/collection/'.$data->getId())
|
||||
->setParam('data', $data->getArrayCopy())
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->json($data)
|
||||
;
|
||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||
$response->dynamic($data, Response::MODEL_COLLECTION);
|
||||
}, ['response', 'projectDB', 'audits']);
|
||||
|
||||
App::get('/v1/database/collections')
|
||||
->desc('List Collections')
|
||||
@@ -126,7 +111,10 @@ App::get('/v1/database/collections')
|
||||
],
|
||||
]);
|
||||
|
||||
$response->json(['sum' => $projectDB->getSum(), 'collections' => $results]);
|
||||
$response->dynamic(new Document([
|
||||
'sum' => $projectDB->getSum(),
|
||||
'collections' => $results
|
||||
]), Response::MODEL_COLLECTION_LIST);
|
||||
}, ['response', 'projectDB']);
|
||||
|
||||
App::get('/v1/database/collections/:collectionId')
|
||||
@@ -148,79 +136,14 @@ App::get('/v1/database/collections/:collectionId')
|
||||
throw new Exception('Collection not found', 404);
|
||||
}
|
||||
|
||||
$response->json($collection->getArrayCopy());
|
||||
$response->dynamic($collection, Response::MODEL_COLLECTION);
|
||||
}, ['response', 'projectDB']);
|
||||
|
||||
// App::get('/v1/database/collections/:collectionId/logs')
|
||||
// ->desc('Get Collection Logs')
|
||||
// ->groups(['api', 'database'])
|
||||
// ->label('scope', 'collections.read')
|
||||
// ->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
// ->label('sdk.namespace', 'database')
|
||||
// ->label('sdk.method', 'getCollectionLogs')
|
||||
// ->label('sdk.description', '/docs/references/database/get-collection-logs.md')
|
||||
// ->param('collectionId', '', new UID(), 'Collection unique ID.')
|
||||
// ->action(
|
||||
// function ($collectionId) use ($response, $register, $projectDB, $project) {
|
||||
// $collection = $projectDB->getDocument($collectionId, false);
|
||||
|
||||
// if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
||||
// throw new Exception('Collection not found', 404);
|
||||
// }
|
||||
|
||||
// $adapter = new AuditAdapter($register->get('db'));
|
||||
// $adapter->setNamespace('app_'.$project->getId());
|
||||
|
||||
// $audit = new Audit($adapter);
|
||||
|
||||
// $countries = Locale::getText('countries');
|
||||
|
||||
// $logs = $audit->getLogsByResource('database/collection/'.$collection->getId());
|
||||
|
||||
// $reader = new Reader(__DIR__.'/../../db/DBIP/dbip-country-lite-2020-01.mmdb');
|
||||
// $output = [];
|
||||
|
||||
// foreach ($logs as $i => &$log) {
|
||||
// $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
|
||||
|
||||
// $dd = new DeviceDetector($log['userAgent']);
|
||||
|
||||
// $dd->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
|
||||
|
||||
// $dd->parse();
|
||||
|
||||
// $output[$i] = [
|
||||
// 'event' => $log['event'],
|
||||
// 'ip' => $log['ip'],
|
||||
// 'time' => strtotime($log['time']),
|
||||
// 'OS' => $dd->getOs(),
|
||||
// 'client' => $dd->getClient(),
|
||||
// 'device' => $dd->getDevice(),
|
||||
// 'brand' => $dd->getBrand(),
|
||||
// 'model' => $dd->getModel(),
|
||||
// 'geo' => [],
|
||||
// ];
|
||||
|
||||
// try {
|
||||
// $record = $reader->country($log['ip']);
|
||||
// $output[$i]['geo']['isoCode'] = strtolower($record->country->isoCode);
|
||||
// $output[$i]['geo']['country'] = $record->country->name;
|
||||
// $output[$i]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : Locale::getText('locale.country.unknown');
|
||||
// } catch (\Exception $e) {
|
||||
// $output[$i]['geo']['isoCode'] = '--';
|
||||
// $output[$i]['geo']['country'] = Locale::getText('locale.country.unknown');
|
||||
// }
|
||||
// }
|
||||
|
||||
// $response->json($output);
|
||||
// }
|
||||
// );
|
||||
|
||||
App::put('/v1/database/collections/:collectionId')
|
||||
->desc('Update Collection')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'collections.write')
|
||||
->label('webhook', 'database.collections.update')
|
||||
->label('event', 'database.collections.update')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.method', 'updateCollection')
|
||||
@@ -230,10 +153,9 @@ App::put('/v1/database/collections/:collectionId')
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions(/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true, ['projectDB'])
|
||||
->action(function ($collectionId, $name, $read, $write, $rules, $response, $projectDB, $webhooks, $audits) {
|
||||
->action(function ($collectionId, $name, $read, $write, $rules, $response, $projectDB, $audits) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $webhooks */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$collection = $projectDB->getDocument($collectionId, false);
|
||||
@@ -277,26 +199,20 @@ App::put('/v1/database/collections/:collectionId')
|
||||
throw new Exception('Failed saving collection to DB', 500);
|
||||
}
|
||||
|
||||
$data = $collection->getArrayCopy();
|
||||
|
||||
$webhooks
|
||||
->setParam('payload', $data)
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.collections.update')
|
||||
->setParam('resource', 'database/collections/'.$data['$id'])
|
||||
->setParam('data', $data)
|
||||
->setParam('resource', 'database/collections/'.$collection->getId())
|
||||
->setParam('data', $collection->getArrayCopy())
|
||||
;
|
||||
|
||||
$response->json($collection->getArrayCopy());
|
||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
||||
$response->dynamic($collection, Response::MODEL_COLLECTION);
|
||||
}, ['response', 'projectDB', 'audits']);
|
||||
|
||||
App::delete('/v1/database/collections/:collectionId')
|
||||
->desc('Delete Collection')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'collections.write')
|
||||
->label('webhook', 'database.collections.delete')
|
||||
->label('event', 'database.collections.delete')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.method', 'deleteCollection')
|
||||
@@ -318,16 +234,14 @@ App::delete('/v1/database/collections/:collectionId')
|
||||
throw new Exception('Failed to remove collection from DB', 500);
|
||||
}
|
||||
|
||||
$data = $collection->getArrayCopy();
|
||||
|
||||
$webhooks
|
||||
->setParam('payload', $data)
|
||||
->setParam('payload', $response->output($collection, Response::MODEL_COLLECTION))
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.collections.delete')
|
||||
->setParam('resource', 'database/collections/'.$data['$id'])
|
||||
->setParam('data', $data)
|
||||
->setParam('resource', 'database/collections/'.$collection->getId())
|
||||
->setParam('data', $collection->getArrayCopy())
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
@@ -336,7 +250,7 @@ App::delete('/v1/database/collections/:collectionId')
|
||||
App::post('/v1/database/collections/:collectionId/documents')
|
||||
->desc('Create Document')
|
||||
->groups(['api', 'database'])
|
||||
->label('webhook', 'database.documents.create')
|
||||
->label('event', 'database.documents.create')
|
||||
->label('scope', 'documents.write')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
@@ -349,10 +263,9 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||
->param('parentDocument', '', new UID(), 'Parent document unique ID. Use when you want your new document to be a child of a parent document.', true)
|
||||
->param('parentProperty', '', new Key(), 'Parent document property name. Use when you want your new document to be a child of a parent document.', true)
|
||||
->param('parentPropertyType', Document::SET_TYPE_ASSIGN, new WhiteList([Document::SET_TYPE_ASSIGN, Document::SET_TYPE_APPEND, Document::SET_TYPE_PREPEND], true), 'Parent document property connection type. You can set this value to **assign**, **append** or **prepend**, default value is assign. Use when you want your new document to be a child of a parent document.', true)
|
||||
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $webhooks, $audits) {
|
||||
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $audits) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $webhooks */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
@@ -387,11 +300,11 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Check child has valid structure,
|
||||
* 2. Check user have write permission for parent document
|
||||
* 3. Assign parent data (including child) to $data
|
||||
* 4. Validate the combined result has valid structure (inside $projectDB->createDocument method)
|
||||
*/
|
||||
* 1. Check child has valid structure,
|
||||
* 2. Check user have write permission for parent document
|
||||
* 3. Assign parent data (including child) to $data
|
||||
* 4. Validate the combined result has valid structure (inside $projectDB->createDocument method)
|
||||
*/
|
||||
|
||||
$new = new Document($data);
|
||||
|
||||
@@ -436,26 +349,18 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||
throw new Exception('Failed saving document to DB'.$exception->getMessage(), 500);
|
||||
}
|
||||
|
||||
$data = $data->getArrayCopy();
|
||||
|
||||
$webhooks
|
||||
->setParam('payload', $data)
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.documents.create')
|
||||
->setParam('resource', 'database/document/'.$data['$id'])
|
||||
->setParam('data', $data)
|
||||
->setParam('data', $data->getArrayCopy())
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->json($data)
|
||||
;
|
||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
||||
|
||||
$response->dynamic($data, Response::MODEL_ANY);
|
||||
}, ['response', 'projectDB', 'audits']);
|
||||
|
||||
App::get('/v1/database/collections/:collectionId/documents')
|
||||
->desc('List Documents')
|
||||
@@ -495,27 +400,24 @@ App::get('/v1/database/collections/:collectionId/documents')
|
||||
]),
|
||||
]);
|
||||
|
||||
if (App::isDevelopment()) {
|
||||
$collection
|
||||
->setAttribute('debug', $projectDB->getDebug())
|
||||
->setAttribute('limit', $limit)
|
||||
->setAttribute('offset', $offset)
|
||||
->setAttribute('orderField', $orderField)
|
||||
->setAttribute('orderType', $orderType)
|
||||
->setAttribute('orderCast', $orderCast)
|
||||
->setAttribute('filters', $filters)
|
||||
;
|
||||
}
|
||||
// if (App::isDevelopment()) {
|
||||
// $collection
|
||||
// ->setAttribute('debug', $projectDB->getDebug())
|
||||
// ->setAttribute('limit', $limit)
|
||||
// ->setAttribute('offset', $offset)
|
||||
// ->setAttribute('orderField', $orderField)
|
||||
// ->setAttribute('orderType', $orderType)
|
||||
// ->setAttribute('orderCast', $orderCast)
|
||||
// ->setAttribute('filters', $filters)
|
||||
// ;
|
||||
// }
|
||||
|
||||
$collection
|
||||
->setAttribute('sum', $projectDB->getSum())
|
||||
->setAttribute('documents', $list)
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
|
||||
$response->dynamic($collection, Response::MODEL_DOCUMENT_LIST);
|
||||
}, ['response', 'projectDB']);
|
||||
|
||||
App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
@@ -540,36 +442,13 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
throw new Exception('No document found', 404);
|
||||
}
|
||||
|
||||
$output = $document->getArrayCopy();
|
||||
|
||||
$paths = \explode('/', $request->getParam('q', ''));
|
||||
$paths = \array_slice($paths, 7, \count($paths));
|
||||
|
||||
if (\count($paths) > 0) {
|
||||
if (\count($paths) % 2 == 1) {
|
||||
$output = $document->getAttribute(\implode('.', $paths));
|
||||
} else {
|
||||
$id = (int) \array_pop($paths);
|
||||
$output = $document->search('$id', $id, $document->getAttribute(\implode('.', $paths)));
|
||||
}
|
||||
|
||||
$output = ($output instanceof Document) ? $output->getArrayCopy() : $output;
|
||||
|
||||
if (!\is_array($output)) {
|
||||
throw new Exception('No document found', 404);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($output);
|
||||
$response->dynamic($document, Response::MODEL_ANY);
|
||||
}, ['request', 'response', 'projectDB']);
|
||||
|
||||
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->desc('Update Document')
|
||||
->groups(['api', 'database'])
|
||||
->label('webhook', 'database.documents.update')
|
||||
->label('event', 'database.documents.update')
|
||||
->label('scope', 'documents.write')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
@@ -580,10 +459,9 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->action(function ($collectionId, $documentId, $data, $read, $write, $response, $projectDB, $webhooks, $audits) {
|
||||
->action(function ($collectionId, $documentId, $data, $read, $write, $response, $projectDB, $audits) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $webhooks */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$collection = $projectDB->getDocument($collectionId, false);
|
||||
@@ -592,7 +470,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
if (!\is_array($data)) {
|
||||
throw new Exception('Data param should be a valid JSON', 400);
|
||||
throw new Exception('Data param should be a valid JSON object', 400);
|
||||
}
|
||||
|
||||
if (\is_null($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
||||
@@ -621,6 +499,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
if (empty($data)) {
|
||||
throw new Exception('Missing payload', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $projectDB->updateDocument($data);
|
||||
} catch (AuthorizationException $exception) {
|
||||
@@ -631,29 +510,20 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
throw new Exception('Failed saving document to DB', 500);
|
||||
}
|
||||
|
||||
$data = $data->getArrayCopy();
|
||||
|
||||
$webhooks
|
||||
->setParam('payload', $data)
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.documents.update')
|
||||
->setParam('resource', 'database/document/'.$data['$id'])
|
||||
->setParam('data', $data)
|
||||
->setParam('resource', 'database/document/'.$data->getId())
|
||||
->setParam('data', $data->getArrayCopy())
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($data);
|
||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
||||
$response->dynamic($data, Response::MODEL_ANY);
|
||||
}, ['response', 'projectDB', 'audits']);
|
||||
|
||||
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->desc('Delete Document')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'documents.write')
|
||||
->label('webhook', 'database.documents.delete')
|
||||
->label('event', 'database.documents.delete')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.method', 'deleteDocument')
|
||||
@@ -687,16 +557,14 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
throw new Exception('Failed to remove document from DB', 500);
|
||||
}
|
||||
|
||||
$data = $document->getArrayCopy();
|
||||
|
||||
$webhooks
|
||||
->setParam('payload', $data)
|
||||
->setParam('payload', $response->output($document, Response::MODEL_ANY))
|
||||
;
|
||||
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.documents.delete')
|
||||
->setParam('resource', 'database/document/'.$data['$id'])
|
||||
->setParam('data', $data) // Audit document in case of malicious or disastrous action
|
||||
->setParam('resource', 'database/document/'.$document->getId())
|
||||
->setParam('data', $document->getArrayCopy()) // Audit document in case of malicious or disastrous action
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
|
||||
Reference in New Issue
Block a user