diff --git a/app/config/events.php b/app/config/events.php index 601b502163..ed4b6da2b9 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -84,17 +84,17 @@ return [ ], 'database.documents.create' => [ 'description' => 'This event triggers when a database document is created.', - 'model' => Response::MODEL_ANY, + 'model' => Response::MODEL_DOCUMENT, 'note' => '', ], 'database.documents.update' => [ 'description' => 'This event triggers when a database document is updated.', - 'model' => Response::MODEL_ANY, + 'model' => Response::MODEL_DOCUMENT, 'note' => '', ], 'database.documents.delete' => [ 'description' => 'This event triggers when a database document is deleted.', - 'model' => Response::MODEL_ANY, + 'model' => Response::MODEL_DOCUMENT, 'note' => '', ], 'storage.files.create' => [ diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 2c32ae981e..f33b2e1351 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -294,7 +294,7 @@ App::post('/v1/database/collections/:collectionId/documents') ->label('sdk.description', '/docs/references/database/create-document.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk.response.model', Response::MODEL_DOCUMENT) ->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).') ->param('data', [], new JSON(), 'Document data as JSON object.') ->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true) @@ -401,7 +401,7 @@ App::post('/v1/database/collections/:collectionId/documents') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($data, Response::MODEL_ANY) + ->dynamic($data, Response::MODEL_DOCUMENT) ; }); @@ -478,7 +478,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') ->label('sdk.description', '/docs/references/database/get-document.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk.response.model', Response::MODEL_DOCUMENT) ->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).') ->param('documentId', null, new UID(), 'Document unique ID.') ->inject('response') @@ -494,7 +494,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') throw new Exception('No document found', 404); } - $response->dynamic($document, Response::MODEL_ANY); + $response->dynamic($document, Response::MODEL_DOCUMENT); }); App::patch('/v1/database/collections/:collectionId/documents/:documentId') @@ -508,7 +508,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') ->label('sdk.description', '/docs/references/database/update-document.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk.response.model', Response::MODEL_DOCUMENT) ->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).') ->param('documentId', null, new UID(), 'Document unique ID.') ->param('data', [], new JSON(), 'Document data as JSON object.') @@ -566,7 +566,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') ->setParam('data', $data->getArrayCopy()) ; - $response->dynamic($data, Response::MODEL_ANY); + $response->dynamic($data, Response::MODEL_DOCUMENT); }); App::delete('/v1/database/collections/:collectionId/documents/:documentId') @@ -614,7 +614,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') } $events - ->setParam('payload', $response->output($document, Response::MODEL_ANY)) + ->setParam('payload', $response->output($document, Response::MODEL_DOCUMENT)) ; $audits diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 3c62daf5f7..f01673d3a5 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -83,7 +83,9 @@ class OpenAPI3 extends Format $output['components']['securitySchemes']['Mode']['x-appwrite'] = ['demo' => '']; } - foreach ($this->routes as $route) { /* @var $route \Utopia\Route */ + $usedModels = []; + + foreach ($this->routes as $route) { /** @var \Utopia\Route $route */ $url = \str_replace('/v1', '', $route->getURL()); $scope = $route->getLabel('scope', ''); $hide = $route->getLabel('sdk.hide', false); @@ -146,6 +148,7 @@ class OpenAPI3 extends Format // ], ]; } else { + $usedModels[] = $model->getType(); $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'content' => [ @@ -236,7 +239,7 @@ class OpenAPI3 extends Format $node['schema']['format'] = 'format'; $node['schema']['x-example'] = 'password'; break; - case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */ + case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */ $node['schema']['type'] = 'integer'; $node['schema']['format'] = 'int32'; $node['schema']['x-example'] = $validator->getMin(); @@ -253,7 +256,7 @@ class OpenAPI3 extends Format $node['schema']['format'] = 'url'; $node['schema']['x-example'] = 'https://example.com'; break; - case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */ + case 'Utopia\Validator\WhiteList': /** @var \Utopia\Validator\WhiteList $validator */ $node['schema']['type'] = 'string'; $node['schema']['x-example'] = $validator->getList()[0]; break; @@ -307,8 +310,18 @@ class OpenAPI3 extends Format $output['paths'][$url][\strtolower($route->getMethod())] = $temp; } - foreach ($this->models as $model) { + foreach ($model->getRules() as $rule) { + if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) { + $usedModels[] = $rule['type']; + } + } + } + foreach ($this->models as $model) { + if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') { + continue; + } + $required = $model->getRequired(); $rules = $model->getRules(); diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 4dd0406088..1d92a0ea3c 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -4,6 +4,7 @@ namespace Appwrite\Specification\Format; use Appwrite\Specification\Format; use Appwrite\Template\Template; +use Appwrite\Utopia\Response\Model; use stdClass; class Swagger2 extends Format @@ -81,7 +82,9 @@ class Swagger2 extends Format $output['securityDefinitions']['Mode']['x-appwrite'] = ['demo' => '']; } - foreach ($this->routes as $route) { /* @var $route \Utopia\Route */ + $usedModels = []; + + foreach ($this->routes as $route) { /** @var \Utopia\Route $route */ $url = \str_replace('/v1', '', $route->getURL()); $scope = $route->getLabel('scope', ''); $hide = $route->getLabel('sdk.hide', false); @@ -148,6 +151,7 @@ class Swagger2 extends Format ], ]; } else { + $usedModels[] = $model->getType(); $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'schema' => [ @@ -232,7 +236,7 @@ class Swagger2 extends Format $node['format'] = 'format'; $node['x-example'] = 'password'; break; - case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */ + case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */ $node['type'] = 'integer'; $node['format'] = 'int32'; $node['x-example'] = $validator->getMin(); @@ -249,7 +253,7 @@ class Swagger2 extends Format $node['format'] = 'url'; $node['x-example'] = 'https://example.com'; break; - case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */ + case 'Utopia\Validator\WhiteList': /** @var \Utopia\Validator\WhiteList $validator */ $node['type'] = 'string'; $node['x-example'] = $validator->getList()[0]; break; @@ -308,8 +312,18 @@ class Swagger2 extends Format $output['paths'][$url][\strtolower($route->getMethod())] = $temp; } - foreach ($this->models as $model) { + foreach ($model->getRules() as $rule) { + if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) { + $usedModels[] = $rule['type']; + } + } + } + foreach ($this->models as $model) { + if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') { + continue; + } + $required = $model->getRequired(); $rules = $model->getRules(); diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index e7f7e4e84e..0bed14e45c 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -15,6 +15,7 @@ use Appwrite\Utopia\Response\Model\Collection; use Appwrite\Utopia\Response\Model\Continent; use Appwrite\Utopia\Response\Model\Country; use Appwrite\Utopia\Response\Model\Currency; +use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Domain; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; @@ -61,6 +62,7 @@ class Response extends SwooleResponse const MODEL_COLLECTION = 'collection'; const MODEL_COLLECTION_LIST = 'collectionList'; const MODEL_RULE = 'rule'; + const MODEL_DOCUMENT = 'document'; const MODEL_DOCUMENT_LIST = 'documentList'; // Users @@ -145,7 +147,7 @@ class Response extends SwooleResponse ->setModel(new ErrorDev()) // Lists ->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION)) - ->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_ANY)) + ->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT)) ->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER)) ->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION)) ->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG, false)) @@ -169,6 +171,7 @@ class Response extends SwooleResponse // Entities ->setModel(new Permissions()) ->setModel(new Collection()) + ->setModel(new ModelDocument()) ->setModel(new Rule()) ->setModel(new Log()) ->setModel(new User()) diff --git a/src/Appwrite/Utopia/Response/Filters/V06.php b/src/Appwrite/Utopia/Response/Filters/V06.php index 137ecbfb5a..13ee89cbb7 100644 --- a/src/Appwrite/Utopia/Response/Filters/V06.php +++ b/src/Appwrite/Utopia/Response/Filters/V06.php @@ -108,6 +108,7 @@ class V06 extends Filter { break; case Response::MODEL_ANY : + case Response::MODEL_DOCUMENT : $parsedResponse = $content; break; diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php new file mode 100644 index 0000000000..a8a9f80970 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -0,0 +1,52 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Document ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('$collection', [ + 'type' => self::TYPE_STRING, + 'description' => 'Collection ID.', + 'default' => '', + 'example' => '5e5ea5c15117e', + ]) + ->addRule('$permissions', [ + 'type' => Response::MODEL_PERMISSIONS, + 'description' => 'Document permissions.', + 'default' => new \stdClass, + 'example' => new \stdClass, + 'array' => false, + ]); + } +}