1
0
Fork 0
mirror of synced 2024-06-03 03:14:50 +12:00

Merge branch 'dev' of https://github.com/appwrite/appwrite into refactor-whitelist-type

This commit is contained in:
Torsten Dittmann 2021-04-13 09:57:26 +02:00
commit 7d08c30672
11 changed files with 122 additions and 25 deletions

View file

@ -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' => [

View file

@ -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

View file

@ -520,7 +520,7 @@ $maxCells = 10;
<div data-ls-loop="project-collections.collections" data-ls-as="project" data-ls-key="$index2" class="tiles cell-3 margin-bottom-negative">
<div class="margin-bottom" data-ls-if="{{project.$id}} != {{router.params.id}}">
<input type="radio" name="list" data-ls-attrs="value={{project.$id}},id={{project.$id}}" data-ls-bind="{{rule.list|firstElement}}" data-cast-to="array" required />
<input type="radio" data-ls-attrs="value={{project.$id}},id=[{{rule.$id}}].{{project.$id}},name=[{{rule.$id}}].list" data-ls-bind="{{rule.list|firstElement}}" data-cast-to="array" required />
<label data-ls-attrs="for={{project.$id}}"data-ls-bind="{{project.name}}"></label>
</div>
</div>

View file

@ -2211,9 +2211,11 @@ match=text.match(new RegExp(regex,'gi'))
if(!match){return fail}
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
return(date.getTime()/1000)}
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,to));return value;}
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
return value;}
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if(name.startsWith('[')){let splitName=name.split('.');if(splitName.length>1&&splitName[0].endsWith(']')){name=splitName[splitName.length-1];}}
if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
ref=json[name];}
else{if(!Array.isArray(json[name])){json[name]=[];}
json[name].push({});ref=json[name][json[name].length-1];}}

View file

@ -256,9 +256,11 @@ match=text.match(new RegExp(regex,'gi'))
if(!match){return fail}
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
return(date.getTime()/1000)}
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,to));return value;}
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
return value;}
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if(name.startsWith('[')){let splitName=name.split('.');if(splitName.length>1&&splitName[0].endsWith(']')){name=splitName[splitName.length-1];}}
if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
ref=json[name];}
else{if(!Array.isArray(json[name])){json[name]=[];}
json[name].push({});ref=json[name][json[name].length-1];}}

View file

@ -4,6 +4,10 @@
window.ls.container.set('form', function () {
function cast(value, to) {
if (value && Array.isArray(value) && to !== 'array') {
value = value.map(element => cast(element, to));
return value;
}
switch (to) {
case 'int':
case 'integer':
@ -42,6 +46,12 @@
let ref = json;
if (name && 'FORM' !== element.tagName) {
if (name.startsWith('[')) { // Check for array names
let splitName = name.split('.');
if (splitName.length > 1 && splitName[0].endsWith(']')) {
name = splitName[splitName.length-1];
}
}
if ('FIELDSET' === element.tagName) { // Fieldset Array / Object
if (castTo === 'object') {
@ -118,4 +128,4 @@
}
}, true, false);
})(window);
})(window);

View file

@ -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();

View file

@ -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();

View file

@ -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())

View file

@ -108,6 +108,7 @@ class V06 extends Filter {
break;
case Response::MODEL_ANY :
case Response::MODEL_DOCUMENT :
$parsedResponse = $content;
break;

View file

@ -0,0 +1,52 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
class Document extends Any
{
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Document';
}
/**
* Get Collection
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_DOCUMENT;
}
public function __construct()
{
$this
->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,
]);
}
}