1
0
Fork 0
mirror of synced 2024-09-28 15:31:43 +12:00

Merge branch '0.7.x' of github.com:appwrite/appwrite into swoole-and-functions

This commit is contained in:
Eldad Fux 2020-11-21 08:15:55 +02:00
commit 31884d17b2
79 changed files with 2360 additions and 894 deletions

View file

@ -32,7 +32,7 @@ before_install:
install: install:
- docker --version - docker --version
- docker-compose up -d - docker-compose up -d
- sleep 60 - sleep 90
script: script:
- docker ps - docker ps

View file

@ -11,4 +11,4 @@
## Reporting a Vulnerability ## Reporting a Vulnerability
For security issues, kindly email us at security@appwrite.io instead of posting a public issue in GitHub. For security issues, kindly email us at security@appwrite.io instead of posting a public issue in GitHub.

View file

@ -172,6 +172,14 @@ $collections = [
'required' => false, 'required' => false,
'array' => true, 'array' => true,
], ],
[
'$collection' => Database::SYSTEM_COLLECTION_RULES,
'label' => 'Filter',
'key' => 'filter',
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
'required' => false,
'array' => true,
],
], ],
], ],
Database::SYSTEM_COLLECTION_USERS => [ Database::SYSTEM_COLLECTION_USERS => [

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -37,6 +37,9 @@ App::post('/v1/account')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'create') ->label('sdk.method', 'create')
->label('sdk.description', '/docs/references/account/create.md') ->label('sdk.description', '/docs/references/account/create.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->label('abuse-limit', 10) ->label('abuse-limit', 10)
->param('email', '', new Email(), 'User email.') ->param('email', '', new Email(), 'User email.')
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.') ->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
@ -131,6 +134,9 @@ App::post('/v1/account/sessions')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'createSession') ->label('sdk.method', 'createSession')
->label('sdk.description', '/docs/references/account/create-session.md') ->label('sdk.description', '/docs/references/account/create-session.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_SESSION)
->label('abuse-limit', 10) ->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}') ->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', new Email(), 'User email.') ->param('email', '', new Email(), 'User email.')
@ -185,7 +191,7 @@ App::post('/v1/account/sessions')
'$collection' => Database::SYSTEM_COLLECTION_TOKENS, '$collection' => Database::SYSTEM_COLLECTION_TOKENS,
'$permissions' => ['read' => ['user:'.$profile->getId()], 'write' => ['user:'.$profile->getId()]], '$permissions' => ['read' => ['user:'.$profile->getId()], 'write' => ['user:'.$profile->getId()]],
'type' => Auth::TOKEN_TYPE_LOGIN, 'type' => Auth::TOKEN_TYPE_LOGIN,
'secret' => Auth::hash($secret), // On way hash encryption to protect DB leak 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'expire' => $expiry, 'expire' => $expiry,
'userAgent' => $request->getUserAgent('UNKNOWN'), 'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(), 'ip' => $request->getIP(),
@ -523,7 +529,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
'$collection' => Database::SYSTEM_COLLECTION_TOKENS, '$collection' => Database::SYSTEM_COLLECTION_TOKENS,
'$permissions' => ['read' => ['user:'.$user['$id']], 'write' => ['user:'.$user['$id']]], '$permissions' => ['read' => ['user:'.$user['$id']], 'write' => ['user:'.$user['$id']]],
'type' => Auth::TOKEN_TYPE_LOGIN, 'type' => Auth::TOKEN_TYPE_LOGIN,
'secret' => Auth::hash($secret), // On way hash encryption to protect DB leak 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'expire' => $expiry, 'expire' => $expiry,
'userAgent' => $request->getUserAgent('UNKNOWN'), 'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(), 'ip' => $request->getIP(),
@ -611,7 +617,9 @@ App::get('/v1/account')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'get') ->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/account/get.md') ->label('sdk.description', '/docs/references/account/get.md')
->label('sdk.response', ['200' => 'user']) ->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->action(function ($response, $user) { ->action(function ($response, $user) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Document $user */
@ -631,13 +639,16 @@ App::get('/v1/account/prefs')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'getPrefs') ->label('sdk.method', 'getPrefs')
->label('sdk.description', '/docs/references/account/get-prefs.md') ->label('sdk.description', '/docs/references/account/get-prefs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ANY)
->action(function ($response, $user) { ->action(function ($response, $user) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Document $user */
$prefs = $user->getAttribute('prefs', new \stdClass); $prefs = $user->getAttribute('prefs', new \stdClass);
$response->json($prefs); $response->dynamic(new Document($prefs), Response::MODEL_ANY);
}, ['response', 'user']); }, ['response', 'user']);
App::get('/v1/account/sessions') App::get('/v1/account/sessions')
@ -648,6 +659,9 @@ App::get('/v1/account/sessions')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'getSessions') ->label('sdk.method', 'getSessions')
->label('sdk.description', '/docs/references/account/get-sessions.md') ->label('sdk.description', '/docs/references/account/get-sessions.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_SESSION_LIST)
->action(function ($response, $user, $locale) { ->action(function ($response, $user, $locale) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Document $user */
@ -685,6 +699,9 @@ App::get('/v1/account/logs')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'getLogs') ->label('sdk.method', 'getLogs')
->label('sdk.description', '/docs/references/account/get-logs.md') ->label('sdk.description', '/docs/references/account/get-logs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->action(function ($response, $register, $project, $user, $locale, $geodb) { ->action(function ($response, $register, $project, $user, $locale, $geodb) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $project */
@ -783,6 +800,9 @@ App::patch('/v1/account/name')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'updateName') ->label('sdk.method', 'updateName')
->label('sdk.description', '/docs/references/account/update-name.md') ->label('sdk.description', '/docs/references/account/update-name.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('name', '', new Text(128), 'User name. Max length: 128 chars.') ->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
->action(function ($name, $response, $user, $projectDB, $audits) { ->action(function ($name, $response, $user, $projectDB, $audits) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -818,6 +838,9 @@ App::patch('/v1/account/password')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePassword') ->label('sdk.method', 'updatePassword')
->label('sdk.description', '/docs/references/account/update-password.md') ->label('sdk.description', '/docs/references/account/update-password.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('password', '', new Password(), 'New user password. Must be between 6 to 32 chars.') ->param('password', '', new Password(), 'New user password. Must be between 6 to 32 chars.')
->param('oldPassword', '', new Password(), 'Old user password. Must be between 6 to 32 chars.') ->param('oldPassword', '', new Password(), 'Old user password. Must be between 6 to 32 chars.')
->action(function ($password, $oldPassword, $response, $user, $projectDB, $audits) { ->action(function ($password, $oldPassword, $response, $user, $projectDB, $audits) {
@ -858,6 +881,9 @@ App::patch('/v1/account/email')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'updateEmail') ->label('sdk.method', 'updateEmail')
->label('sdk.description', '/docs/references/account/update-email.md') ->label('sdk.description', '/docs/references/account/update-email.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('email', '', new Email(), 'User email.') ->param('email', '', new Email(), 'User email.')
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.') ->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
->action(function ($email, $password, $response, $user, $projectDB, $audits) { ->action(function ($email, $password, $response, $user, $projectDB, $audits) {
@ -913,6 +939,9 @@ App::patch('/v1/account/prefs')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePrefs') ->label('sdk.method', 'updatePrefs')
->label('sdk.description', '/docs/references/account/update-prefs.md') ->label('sdk.description', '/docs/references/account/update-prefs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ANY)
->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.') ->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.')
->action(function ($prefs, $response, $user, $projectDB, $audits) { ->action(function ($prefs, $response, $user, $projectDB, $audits) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -935,7 +964,7 @@ App::patch('/v1/account/prefs')
$prefs = $user->getAttribute('prefs', new \stdClass); $prefs = $user->getAttribute('prefs', new \stdClass);
$response->json($prefs); $response->dynamic(new Document($prefs), Response::MODEL_ANY);
}, ['response', 'user', 'projectDB', 'audits']); }, ['response', 'user', 'projectDB', 'audits']);
App::delete('/v1/account') App::delete('/v1/account')
@ -947,6 +976,9 @@ App::delete('/v1/account')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'delete') ->label('sdk.method', 'delete')
->label('sdk.description', '/docs/references/account/delete.md') ->label('sdk.description', '/docs/references/account/delete.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->action(function ($request, $response, $user, $projectDB, $audits, $webhooks) { ->action(function ($request, $response, $user, $projectDB, $audits, $webhooks) {
/** @var Utopia\Swoole\Request $request */ /** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -1005,6 +1037,9 @@ App::delete('/v1/account/sessions/:sessionId')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'deleteSession') ->label('sdk.method', 'deleteSession')
->label('sdk.description', '/docs/references/account/delete-session.md') ->label('sdk.description', '/docs/references/account/delete-session.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->label('abuse-limit', 100) ->label('abuse-limit', 100)
->param('sessionId', null, new UID(), 'Session unique ID. Use the string \'current\' to delete the current device session.') ->param('sessionId', null, new UID(), 'Session unique ID. Use the string \'current\' to delete the current device session.')
->action(function ($sessionId, $request, $response, $user, $projectDB, $audits, $webhooks) { ->action(function ($sessionId, $request, $response, $user, $projectDB, $audits, $webhooks) {
@ -1067,6 +1102,9 @@ App::delete('/v1/account/sessions')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'deleteSessions') ->label('sdk.method', 'deleteSessions')
->label('sdk.description', '/docs/references/account/delete-sessions.md') ->label('sdk.description', '/docs/references/account/delete-sessions.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->label('abuse-limit', 100) ->label('abuse-limit', 100)
->action(function ($request, $response, $user, $projectDB, $audits, $webhooks) { ->action(function ($request, $response, $user, $projectDB, $audits, $webhooks) {
/** @var Utopia\Swoole\Request $request */ /** @var Utopia\Swoole\Request $request */
@ -1119,6 +1157,9 @@ App::post('/v1/account/recovery')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'createRecovery') ->label('sdk.method', 'createRecovery')
->label('sdk.description', '/docs/references/account/create-recovery.md') ->label('sdk.description', '/docs/references/account/create-recovery.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TOKEN)
->label('abuse-limit', 10) ->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}') ->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', new Email(), 'User email.') ->param('email', '', new Email(), 'User email.')
@ -1149,7 +1190,7 @@ App::post('/v1/account/recovery')
'$collection' => Database::SYSTEM_COLLECTION_TOKENS, '$collection' => Database::SYSTEM_COLLECTION_TOKENS,
'$permissions' => ['read' => ['user:'.$profile->getId()], 'write' => ['user:'.$profile->getId()]], '$permissions' => ['read' => ['user:'.$profile->getId()], 'write' => ['user:'.$profile->getId()]],
'type' => Auth::TOKEN_TYPE_RECOVERY, 'type' => Auth::TOKEN_TYPE_RECOVERY,
'secret' => Auth::hash($secret), // On way hash encryption to protect DB leak 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'expire' => \time() + Auth::TOKEN_EXPIRATION_RECOVERY, 'expire' => \time() + Auth::TOKEN_EXPIRATION_RECOVERY,
'userAgent' => $request->getUserAgent('UNKNOWN'), 'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(), 'ip' => $request->getIP(),
@ -1213,7 +1254,7 @@ App::post('/v1/account/recovery')
$response $response
->setStatusCode(Response::STATUS_CODE_CREATED) ->setStatusCode(Response::STATUS_CODE_CREATED)
->json($recovery->getArrayCopy(['$id', 'type', 'expire'])) ->dynamic($recovery, Response::MODEL_TOKEN)
; ;
}, ['request', 'response', 'projectDB', 'project', 'locale', 'mails', 'audits']); }, ['request', 'response', 'projectDB', 'project', 'locale', 'mails', 'audits']);
@ -1225,6 +1266,9 @@ App::put('/v1/account/recovery')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'updateRecovery') ->label('sdk.method', 'updateRecovery')
->label('sdk.description', '/docs/references/account/update-recovery.md') ->label('sdk.description', '/docs/references/account/update-recovery.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TOKEN)
->label('abuse-limit', 10) ->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}') ->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', new UID(), 'User account UID address.') ->param('userId', '', new UID(), 'User account UID address.')
@ -1286,7 +1330,7 @@ App::put('/v1/account/recovery')
$recovery = $profile->search('$id', $recovery, $profile->getAttribute('tokens', [])); $recovery = $profile->search('$id', $recovery, $profile->getAttribute('tokens', []));
$response->json($recovery->getArrayCopy(['$id', 'type', 'expire'])); $response->dynamic($recovery, Response::MODEL_TOKEN);
}, ['response', 'projectDB', 'audits']); }, ['response', 'projectDB', 'audits']);
App::post('/v1/account/verification') App::post('/v1/account/verification')
@ -1297,6 +1341,9 @@ App::post('/v1/account/verification')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'createVerification') ->label('sdk.method', 'createVerification')
->label('sdk.description', '/docs/references/account/create-verification.md') ->label('sdk.description', '/docs/references/account/create-verification.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TOKEN)
->label('abuse-limit', 10) ->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}') ->label('abuse-key', 'url:{url},email:{param-email}')
->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page
@ -1316,7 +1363,7 @@ App::post('/v1/account/verification')
'$collection' => Database::SYSTEM_COLLECTION_TOKENS, '$collection' => Database::SYSTEM_COLLECTION_TOKENS,
'$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]], '$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]],
'type' => Auth::TOKEN_TYPE_VERIFICATION, 'type' => Auth::TOKEN_TYPE_VERIFICATION,
'secret' => Auth::hash($verificationSecret), // On way hash encryption to protect DB leak 'secret' => Auth::hash($verificationSecret), // One way hash encryption to protect DB leak
'expire' => \time() + Auth::TOKEN_EXPIRATION_CONFIRM, 'expire' => \time() + Auth::TOKEN_EXPIRATION_CONFIRM,
'userAgent' => $request->getUserAgent('UNKNOWN'), 'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(), 'ip' => $request->getIP(),
@ -1380,7 +1427,7 @@ App::post('/v1/account/verification')
$response $response
->setStatusCode(Response::STATUS_CODE_CREATED) ->setStatusCode(Response::STATUS_CODE_CREATED)
->json($verification->getArrayCopy(['$id', 'type', 'expire'])) ->dynamic($verification, Response::MODEL_TOKEN)
; ;
}, ['request', 'response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails']); }, ['request', 'response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails']);
@ -1392,6 +1439,9 @@ App::put('/v1/account/verification')
->label('sdk.namespace', 'account') ->label('sdk.namespace', 'account')
->label('sdk.method', 'updateVerification') ->label('sdk.method', 'updateVerification')
->label('sdk.description', '/docs/references/account/update-verification.md') ->label('sdk.description', '/docs/references/account/update-verification.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TOKEN)
->label('abuse-limit', 10) ->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}') ->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
@ -1446,5 +1496,5 @@ App::put('/v1/account/verification')
$verification = $profile->search('$id', $verification, $profile->getAttribute('tokens', [])); $verification = $profile->search('$id', $verification, $profile->getAttribute('tokens', []));
$response->json($verification->getArrayCopy(['$id', 'type', 'expire'])); $response->dynamic($verification, Response::MODEL_TOKEN);
}, ['response', 'user', 'projectDB', 'audits']); }, ['response', 'user', 'projectDB', 'audits']);

View file

@ -11,6 +11,7 @@ use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Adapter\Filesystem;
use Appwrite\Resize\Resize; use Appwrite\Resize\Resize;
use Appwrite\URL\URL as URLParse; use Appwrite\URL\URL as URLParse;
use Appwrite\Utopia\Response;
use Utopia\Config\Config; use Utopia\Config\Config;
use Utopia\Validator\HexColor; use Utopia\Validator\HexColor;
use chillerlan\QRCode\QRCode; use chillerlan\QRCode\QRCode;
@ -88,6 +89,8 @@ App::get('/v1/avatars/credit-cards/:code')
->label('sdk.method', 'getCreditCard') ->label('sdk.method', 'getCreditCard')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-credit-card.md') ->label('sdk.description', '/docs/references/avatars/get-credit-card.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.') ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
@ -105,6 +108,8 @@ App::get('/v1/avatars/browsers/:code')
->label('sdk.method', 'getBrowser') ->label('sdk.method', 'getBrowser')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-browser.md') ->label('sdk.description', '/docs/references/avatars/get-browser.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-browsers'))), 'Browser Code.') ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-browsers'))), 'Browser Code.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
@ -122,6 +127,8 @@ App::get('/v1/avatars/flags/:code')
->label('sdk.method', 'getFlag') ->label('sdk.method', 'getFlag')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-flag.md') ->label('sdk.description', '/docs/references/avatars/get-flag.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-flags'))), 'Country Code. ISO Alpha-2 country code format.') ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-flags'))), 'Country Code. ISO Alpha-2 country code format.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
@ -139,6 +146,8 @@ App::get('/v1/avatars/image')
->label('sdk.method', 'getImage') ->label('sdk.method', 'getImage')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-image.md') ->label('sdk.description', '/docs/references/avatars/get-image.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE)
->param('url', '', new URL(), 'Image URL which you want to crop.') ->param('url', '', new URL(), 'Image URL which you want to crop.')
->param('width', 400, new Range(0, 2000), 'Resize preview image width, Pass an integer between 0 to 2000.', true) ->param('width', 400, new Range(0, 2000), 'Resize preview image width, Pass an integer between 0 to 2000.', true)
->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000.', true) ->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000.', true)
@ -205,6 +214,8 @@ App::get('/v1/avatars/favicon')
->label('sdk.method', 'getFavicon') ->label('sdk.method', 'getFavicon')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-favicon.md') ->label('sdk.description', '/docs/references/avatars/get-favicon.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE)
->param('url', '', new URL(), 'Website URL which you want to fetch the favicon from.') ->param('url', '', new URL(), 'Website URL which you want to fetch the favicon from.')
->action(function ($url, $response) { ->action(function ($url, $response) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -355,6 +366,8 @@ App::get('/v1/avatars/qr')
->label('sdk.method', 'getQR') ->label('sdk.method', 'getQR')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-qr.md') ->label('sdk.description', '/docs/references/avatars/get-qr.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('text', '', new Text(512), 'Plain text to be converted to QR code image.') ->param('text', '', new Text(512), 'Plain text to be converted to QR code image.')
->param('size', 400, new Range(0, 1000), 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true) ->param('size', 400, new Range(0, 1000), 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
->param('margin', 1, new Range(0, 10), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true) ->param('margin', 1, new Range(0, 10), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
@ -390,6 +403,8 @@ App::get('/v1/avatars/initials')
->label('sdk.method', 'getInitials') ->label('sdk.method', 'getInitials')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-initials.md') ->label('sdk.description', '/docs/references/avatars/get-initials.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('name', '', new Text(128), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.', true) ->param('name', '', new Text(128), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.', true)
->param('width', 500, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('width', 500, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 500, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 500, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)

View file

@ -27,6 +27,9 @@ App::post('/v1/database/collections')
->label('sdk.platform', [APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'createCollection') ->label('sdk.method', 'createCollection')
->label('sdk.description', '/docs/references/database/create-collection.md') ->label('sdk.description', '/docs/references/database/create-collection.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
->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('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('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.')
@ -93,6 +96,9 @@ App::get('/v1/database/collections')
->label('sdk.platform', [APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'listCollections') ->label('sdk.method', 'listCollections')
->label('sdk.description', '/docs/references/database/list-collections.md') ->label('sdk.description', '/docs/references/database/list-collections.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION_LIST)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 40000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('offset', 0, new Range(0, 40000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
@ -127,6 +133,9 @@ App::get('/v1/database/collections/:collectionId')
->label('sdk.platform', [APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'getCollection') ->label('sdk.method', 'getCollection')
->label('sdk.description', '/docs/references/database/get-collection.md') ->label('sdk.description', '/docs/references/database/get-collection.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
->param('collectionId', '', new UID(), 'Collection unique ID.') ->param('collectionId', '', new UID(), 'Collection unique ID.')
->action(function ($collectionId, $response, $projectDB) { ->action(function ($collectionId, $response, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -150,6 +159,9 @@ App::put('/v1/database/collections/:collectionId')
->label('sdk.platform', [APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'updateCollection') ->label('sdk.method', 'updateCollection')
->label('sdk.description', '/docs/references/database/update-collection.md') ->label('sdk.description', '/docs/references/database/update-collection.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
->param('collectionId', '', new UID(), 'Collection unique ID.') ->param('collectionId', '', new UID(), 'Collection unique ID.')
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
->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('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.')
@ -219,6 +231,9 @@ App::delete('/v1/database/collections/:collectionId')
->label('sdk.platform', [APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.method', 'deleteCollection') ->label('sdk.method', 'deleteCollection')
->label('sdk.description', '/docs/references/database/delete-collection.md') ->label('sdk.description', '/docs/references/database/delete-collection.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('collectionId', '', new UID(), 'Collection unique ID.') ->param('collectionId', '', new UID(), 'Collection unique ID.')
->action(function ($collectionId, $response, $projectDB, $webhooks, $audits) { ->action(function ($collectionId, $response, $projectDB, $webhooks, $audits) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -258,6 +273,9 @@ App::post('/v1/database/collections/:collectionId/documents')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.method', 'createDocument') ->label('sdk.method', 'createDocument')
->label('sdk.description', '/docs/references/database/create-document.md') ->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)
->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('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('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('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.')
@ -371,10 +389,13 @@ App::get('/v1/database/collections/:collectionId/documents')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.method', 'listDocuments') ->label('sdk.method', 'listDocuments')
->label('sdk.description', '/docs/references/database/list-documents.md') ->label('sdk.description', '/docs/references/database/list-documents.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST)
->param('collectionId', 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('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('filters', [], new ArrayList(new Text(128)), 'Array of filter strings. Each filter is constructed from a key name, comparison operator (=, !=, >, <, <=, >=) and a value. You can also use a dot (.) separator in attribute names to filter by child document attributes. Examples: \'name=John Doe\' or \'category.$id>=5bed2d152c362\'.', true) ->param('filters', [], new ArrayList(new Text(128)), 'Array of filter strings. Each filter is constructed from a key name, comparison operator (=, !=, >, <, <=, >=) and a value. You can also use a dot (.) separator in attribute names to filter by child document attributes. Examples: \'name=John Doe\' or \'category.$id>=5bed2d152c362\'.', true)
->param('limit', 25, new Range(0, 1000), 'Maximum number of documents to return in response. Use this value to manage pagination.', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 900000000), 'Offset value. Use this value to manage pagination.', true) ->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true)
->param('orderField', '$id', new Text(128), 'Document field that results will be sorted by.', true) ->param('orderField', '$id', new Text(128), 'Document field that results will be sorted by.', true)
->param('orderType', 'ASC', new WhiteList(['DESC', 'ASC'], true), 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true) ->param('orderType', 'ASC', new WhiteList(['DESC', 'ASC'], true), 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true)
->param('orderCast', 'string', new WhiteList(['int', 'string', 'date', 'time', 'datetime'], true), 'Order field type casting. Possible values are int, string, date, time or datetime. The database will attempt to cast the order field to the value you pass here. The default value is a string.', true) ->param('orderCast', 'string', new WhiteList(['int', 'string', 'date', 'time', 'datetime'], true), 'Order field type casting. Possible values are int, string, date, time or datetime. The database will attempt to cast the order field to the value you pass here. The default value is a string.', true)
@ -429,6 +450,9 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.method', 'getDocument') ->label('sdk.method', 'getDocument')
->label('sdk.description', '/docs/references/database/get-document.md') ->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)
->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('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('documentId', null, new UID(), 'Document unique ID.')
->action(function ($collectionId, $documentId, $request, $response, $projectDB) { ->action(function ($collectionId, $documentId, $request, $response, $projectDB) {
@ -455,6 +479,9 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.method', 'updateDocument') ->label('sdk.method', 'updateDocument')
->label('sdk.description', '/docs/references/database/update-document.md') ->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)
->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('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('documentId', null, new UID(), 'Document unique ID.')
->param('data', [], new JSON(), 'Document data as JSON object.') ->param('data', [], new JSON(), 'Document data as JSON object.')
@ -529,6 +556,9 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER]) ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.method', 'deleteDocument') ->label('sdk.method', 'deleteDocument')
->label('sdk.description', '/docs/references/database/delete-document.md') ->label('sdk.description', '/docs/references/database/delete-document.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->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('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('documentId', null, new UID(), 'Document unique ID.')
->action(function ($collectionId, $documentId, $response, $projectDB, $webhooks, $audits) { ->action(function ($collectionId, $documentId, $response, $projectDB, $webhooks, $audits) {

View file

@ -29,6 +29,9 @@ App::post('/v1/functions')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'create') ->label('sdk.method', 'create')
->label('sdk.description', '/docs/references/functions/create-function.md') ->label('sdk.description', '/docs/references/functions/create-function.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
->param('env', '', new WhiteList(array_keys(Config::getParam('environments')), true), 'Execution enviornment.') ->param('env', '', new WhiteList(array_keys(Config::getParam('environments')), true), 'Execution enviornment.')
->param('vars', [], new Assoc(), 'Key-value JSON object.', true) ->param('vars', [], new Assoc(), 'Key-value JSON object.', true)
@ -74,6 +77,9 @@ App::get('/v1/functions')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'list') ->label('sdk.method', 'list')
->label('sdk.description', '/docs/references/functions/list-functions.md') ->label('sdk.description', '/docs/references/functions/list-functions.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FUNCTION_LIST)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
@ -105,6 +111,9 @@ App::get('/v1/functions/:functionId')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'get') ->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/functions/get-function.md') ->label('sdk.description', '/docs/references/functions/get-function.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->action(function ($functionId, $response, $projectDB) { ->action(function ($functionId, $response, $projectDB) {
$function = $projectDB->getDocument($functionId); $function = $projectDB->getDocument($functionId);
@ -237,6 +246,9 @@ App::put('/v1/functions/:functionId')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'update') ->label('sdk.method', 'update')
->label('sdk.description', '/docs/references/functions/update-function.md') ->label('sdk.description', '/docs/references/functions/update-function.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
->param('vars', [], new Assoc(), 'Key-value JSON object.', true) ->param('vars', [], new Assoc(), 'Key-value JSON object.', true)
@ -292,6 +304,9 @@ App::patch('/v1/functions/:functionId/tag')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'updateTag') ->label('sdk.method', 'updateTag')
->label('sdk.description', '/docs/references/functions/update-tag.md') ->label('sdk.description', '/docs/references/functions/update-tag.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('tag', '', new UID(), 'Tag unique ID.') ->param('tag', '', new UID(), 'Tag unique ID.')
->action(function ($functionId, $tag, $response, $projectDB) { ->action(function ($functionId, $tag, $response, $projectDB) {
@ -330,6 +345,9 @@ App::delete('/v1/functions/:functionId')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'delete') ->label('sdk.method', 'delete')
->label('sdk.description', '/docs/references/functions/delete-function.md') ->label('sdk.description', '/docs/references/functions/delete-function.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->action(function ($functionId, $response, $projectDB, $deletes) { ->action(function ($functionId, $response, $projectDB, $deletes) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -361,6 +379,10 @@ App::post('/v1/functions/:functionId/tags')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'createTag') ->label('sdk.method', 'createTag')
->label('sdk.description', '/docs/references/functions/create-tag.md') ->label('sdk.description', '/docs/references/functions/create-tag.md')
->label('sdk.request.type', 'multipart/form-data')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TAG)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('command', '', new Text('1028'), 'Code execution command.') ->param('command', '', new Text('1028'), 'Code execution command.')
->param('code', [], new File(), 'Gzip file containing your code.', false) ->param('code', [], new File(), 'Gzip file containing your code.', false)
@ -443,6 +465,9 @@ App::get('/v1/functions/:functionId/tags')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'listTags') ->label('sdk.method', 'listTags')
->label('sdk.description', '/docs/references/functions/list-tags.md') ->label('sdk.description', '/docs/references/functions/list-tags.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TAG_LIST)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
@ -482,6 +507,9 @@ App::get('/v1/functions/:functionId/tags/:tagId')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'getTag') ->label('sdk.method', 'getTag')
->label('sdk.description', '/docs/references/functions/get-tag.md') ->label('sdk.description', '/docs/references/functions/get-tag.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TAG)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('tagId', '', new UID(), 'Tag unique ID.') ->param('tagId', '', new UID(), 'Tag unique ID.')
->action(function ($functionId, $tagId, $response, $projectDB) { ->action(function ($functionId, $tagId, $response, $projectDB) {
@ -512,6 +540,9 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'deleteTag') ->label('sdk.method', 'deleteTag')
->label('sdk.description', '/docs/references/functions/delete-tag.md') ->label('sdk.description', '/docs/references/functions/delete-tag.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('tagId', '', new UID(), 'Tag unique ID.') ->param('tagId', '', new UID(), 'Tag unique ID.')
->action(function ($functionId, $tagId, $response, $projectDB, $usage) { ->action(function ($functionId, $tagId, $response, $projectDB, $usage) {
@ -564,6 +595,9 @@ App::post('/v1/functions/:functionId/executions')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'createExecution') ->label('sdk.method', 'createExecution')
->label('sdk.description', '/docs/references/functions/create-execution.md') ->label('sdk.description', '/docs/references/functions/create-execution.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_EXECUTION)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
// ->param('async', 1, new Range(0, 1), 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true) // ->param('async', 1, new Range(0, 1), 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
->action(function ($functionId, /*$async,*/ $response, $project, $projectDB) { ->action(function ($functionId, /*$async,*/ $response, $project, $projectDB) {
@ -629,6 +663,9 @@ App::get('/v1/functions/:functionId/executions')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'listExecutions') ->label('sdk.method', 'listExecutions')
->label('sdk.description', '/docs/references/functions/list-executions.md') ->label('sdk.description', '/docs/references/functions/list-executions.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_EXECUTION_LIST)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
@ -668,6 +705,9 @@ App::get('/v1/functions/:functionId/executions/:executionId')
->label('sdk.namespace', 'functions') ->label('sdk.namespace', 'functions')
->label('sdk.method', 'getExecution') ->label('sdk.method', 'getExecution')
->label('sdk.description', '/docs/references/functions/get-execution.md') ->label('sdk.description', '/docs/references/functions/get-execution.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_EXECUTION)
->param('functionId', '', new UID(), 'Function unique ID.') ->param('functionId', '', new UID(), 'Function unique ID.')
->param('executionId', '', new UID(), 'Execution unique ID.') ->param('executionId', '', new UID(), 'Execution unique ID.')
->action(function ($functionId, $executionId, $response, $projectDB) { ->action(function ($functionId, $executionId, $response, $projectDB) {

View file

@ -13,6 +13,9 @@ App::get('/v1/locale')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'get') ->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/locale/get-locale.md') ->label('sdk.description', '/docs/references/locale/get-locale.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOCALE)
->action(function ($request, $response, $locale, $geodb) { ->action(function ($request, $response, $locale, $geodb) {
/** @var Utopia\Swoole\Request $request */ /** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -71,6 +74,9 @@ App::get('/v1/locale/countries')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCountries') ->label('sdk.method', 'getCountries')
->label('sdk.description', '/docs/references/locale/get-countries.md') ->label('sdk.description', '/docs/references/locale/get-countries.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COUNTRY_LIST)
->action(function ($response, $locale) { ->action(function ($response, $locale) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */ /** @var Utopia\Locale\Locale $locale */
@ -98,6 +104,9 @@ App::get('/v1/locale/countries/eu')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCountriesEU') ->label('sdk.method', 'getCountriesEU')
->label('sdk.description', '/docs/references/locale/get-countries-eu.md') ->label('sdk.description', '/docs/references/locale/get-countries-eu.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COUNTRY_LIST)
->action(function ($response, $locale) { ->action(function ($response, $locale) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */ /** @var Utopia\Locale\Locale $locale */
@ -128,6 +137,9 @@ App::get('/v1/locale/countries/phones')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCountriesPhones') ->label('sdk.method', 'getCountriesPhones')
->label('sdk.description', '/docs/references/locale/get-countries-phones.md') ->label('sdk.description', '/docs/references/locale/get-countries-phones.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PHONE_LIST)
->action(function ($response, $locale) { ->action(function ($response, $locale) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */ /** @var Utopia\Locale\Locale $locale */
@ -159,6 +171,9 @@ App::get('/v1/locale/continents')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'getContinents') ->label('sdk.method', 'getContinents')
->label('sdk.description', '/docs/references/locale/get-continents.md') ->label('sdk.description', '/docs/references/locale/get-continents.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_CONTINENT_LIST)
->action(function ($response, $locale) { ->action(function ($response, $locale) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */ /** @var Utopia\Locale\Locale $locale */
@ -185,6 +200,9 @@ App::get('/v1/locale/currencies')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'getCurrencies') ->label('sdk.method', 'getCurrencies')
->label('sdk.description', '/docs/references/locale/get-currencies.md') ->label('sdk.description', '/docs/references/locale/get-currencies.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_CURRENCY_LIST)
->action(function ($response) { ->action(function ($response) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -206,6 +224,9 @@ App::get('/v1/locale/languages')
->label('sdk.namespace', 'locale') ->label('sdk.namespace', 'locale')
->label('sdk.method', 'getLanguages') ->label('sdk.method', 'getLanguages')
->label('sdk.description', '/docs/references/locale/get-languages.md') ->label('sdk.description', '/docs/references/locale/get-languages.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LANGUAGE_LIST)
->action(function ($response) { ->action(function ($response) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */

View file

@ -26,6 +26,9 @@ App::post('/v1/projects')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'create') ->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true)
@ -92,6 +95,9 @@ App::get('/v1/projects')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'list') ->label('sdk.method', 'list')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT_LIST)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
@ -124,6 +130,9 @@ App::get('/v1/projects/:projectId')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'get') ->label('sdk.method', 'get')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->action(function ($projectId, $response, $consoleDB) { ->action(function ($projectId, $response, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -332,6 +341,9 @@ App::patch('/v1/projects/:projectId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'update') ->label('sdk.method', 'update')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true)
@ -379,6 +391,9 @@ App::patch('/v1/projects/:projectId/oauth2')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateOAuth2') ->label('sdk.method', 'updateOAuth2')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'Provider Name', false) ->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'Provider Name', false)
->param('appId', '', new Text(256), 'Provider app ID. Max length: 256 chars.', true) ->param('appId', '', new Text(256), 'Provider app ID. Max length: 256 chars.', true)
@ -411,6 +426,9 @@ App::delete('/v1/projects/:projectId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'delete') ->label('sdk.method', 'delete')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->param('password', '', new UID(), 'Your user password for confirmation. Must be between 6 to 32 chars.') ->param('password', '', new UID(), 'Your user password for confirmation. Must be between 6 to 32 chars.')
->action(function ($projectId, $password, $response, $user, $consoleDB, $deletes) { ->action(function ($projectId, $password, $response, $user, $consoleDB, $deletes) {
@ -460,6 +478,9 @@ App::post('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'createWebhook') ->label('sdk.method', 'createWebhook')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_WEBHOOK)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
->param('events', null, new ArrayList(new WhiteList(array_keys(Config::getParam('events'), true), true)), 'Events list.') ->param('events', null, new ArrayList(new WhiteList(array_keys(Config::getParam('events'), true), true)), 'Events list.')
@ -517,6 +538,9 @@ App::get('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'listWebhooks') ->label('sdk.method', 'listWebhooks')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_WEBHOOK_LIST)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->action(function ($projectId, $response, $consoleDB) { ->action(function ($projectId, $response, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -542,6 +566,9 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'getWebhook') ->label('sdk.method', 'getWebhook')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_WEBHOOK)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('webhookId', null, new UID(), 'Webhook unique ID.') ->param('webhookId', null, new UID(), 'Webhook unique ID.')
->action(function ($projectId, $webhookId, $response, $consoleDB) { ->action(function ($projectId, $webhookId, $response, $consoleDB) {
@ -569,6 +596,9 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateWebhook') ->label('sdk.method', 'updateWebhook')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_WEBHOOK)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('webhookId', null, new UID(), 'Webhook unique ID.') ->param('webhookId', null, new UID(), 'Webhook unique ID.')
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
@ -617,6 +647,9 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteWebhook') ->label('sdk.method', 'deleteWebhook')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('webhookId', null, new UID(), 'Webhook unique ID.') ->param('webhookId', null, new UID(), 'Webhook unique ID.')
->action(function ($projectId, $webhookId, $response, $consoleDB) { ->action(function ($projectId, $webhookId, $response, $consoleDB) {
@ -650,6 +683,9 @@ App::post('/v1/projects/:projectId/keys')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'createKey') ->label('sdk.method', 'createKey')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_KEY)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
->param('scopes', null, new ArrayList(new WhiteList(Config::getParam('scopes'), true)), 'Key scopes list.') ->param('scopes', null, new ArrayList(new WhiteList(Config::getParam('scopes'), true)), 'Key scopes list.')
@ -698,6 +734,9 @@ App::get('/v1/projects/:projectId/keys')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'listKeys') ->label('sdk.method', 'listKeys')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_KEY_LIST)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->action(function ($projectId, $response, $consoleDB) { ->action(function ($projectId, $response, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -723,6 +762,9 @@ App::get('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'getKey') ->label('sdk.method', 'getKey')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_KEY)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('keyId', null, new UID(), 'Key unique ID.') ->param('keyId', null, new UID(), 'Key unique ID.')
->action(function ($projectId, $keyId, $response, $consoleDB) { ->action(function ($projectId, $keyId, $response, $consoleDB) {
@ -747,6 +789,9 @@ App::put('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateKey') ->label('sdk.method', 'updateKey')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_KEY)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('keyId', null, new UID(), 'Key unique ID.') ->param('keyId', null, new UID(), 'Key unique ID.')
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
@ -785,6 +830,9 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteKey') ->label('sdk.method', 'deleteKey')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('keyId', null, new UID(), 'Key unique ID.') ->param('keyId', null, new UID(), 'Key unique ID.')
->action(function ($projectId, $keyId, $response, $consoleDB) { ->action(function ($projectId, $keyId, $response, $consoleDB) {
@ -818,6 +866,9 @@ App::post('/v1/projects/:projectId/tasks')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'createTask') ->label('sdk.method', 'createTask')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TASK)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('name', null, new Text(128), 'Task name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Task name. Max length: 128 chars.')
->param('status', null, new WhiteList(['play', 'pause'], true), 'Task status.') ->param('status', null, new WhiteList(['play', 'pause'], true), 'Task status.')
@ -893,6 +944,9 @@ App::get('/v1/projects/:projectId/tasks')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'listTasks') ->label('sdk.method', 'listTasks')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TASK_LIST)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->action(function ($projectId, $response, $consoleDB) { ->action(function ($projectId, $response, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -919,6 +973,9 @@ App::get('/v1/projects/:projectId/tasks/:taskId')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'getTask') ->label('sdk.method', 'getTask')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TASK)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('taskId', null, new UID(), 'Task unique ID.') ->param('taskId', null, new UID(), 'Task unique ID.')
->action(function ($projectId, $taskId, $response, $consoleDB) { ->action(function ($projectId, $taskId, $response, $consoleDB) {
@ -946,6 +1003,9 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateTask') ->label('sdk.method', 'updateTask')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TASK)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('taskId', null, new UID(), 'Task unique ID.') ->param('taskId', null, new UID(), 'Task unique ID.')
->param('name', null, new Text(128), 'Task name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Task name. Max length: 128 chars.')
@ -1009,6 +1069,9 @@ App::delete('/v1/projects/:projectId/tasks/:taskId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteTask') ->label('sdk.method', 'deleteTask')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('taskId', null, new UID(), 'Task unique ID.') ->param('taskId', null, new UID(), 'Task unique ID.')
->action(function ($projectId, $taskId, $response, $consoleDB) { ->action(function ($projectId, $taskId, $response, $consoleDB) {
@ -1042,6 +1105,9 @@ App::post('/v1/projects/:projectId/platforms')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'createPlatform') ->label('sdk.method', 'createPlatform')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PLATFORM)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('type', null, new WhiteList(['web', 'flutter-ios', 'flutter-android', 'ios', 'android', 'unity'], true), 'Platform type.') ->param('type', null, new WhiteList(['web', 'flutter-ios', 'flutter-android', 'ios', 'android', 'unity'], true), 'Platform type.')
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
@ -1097,6 +1163,9 @@ App::get('/v1/projects/:projectId/platforms')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'listPlatforms') ->label('sdk.method', 'listPlatforms')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PLATFORM_LIST)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->action(function ($projectId, $response, $consoleDB) { ->action(function ($projectId, $response, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -1122,6 +1191,9 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'getPlatform') ->label('sdk.method', 'getPlatform')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PLATFORM)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('platformId', null, new UID(), 'Platform unique ID.') ->param('platformId', null, new UID(), 'Platform unique ID.')
->action(function ($projectId, $platformId, $response, $consoleDB) { ->action(function ($projectId, $platformId, $response, $consoleDB) {
@ -1149,6 +1221,9 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'updatePlatform') ->label('sdk.method', 'updatePlatform')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PLATFORM)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('platformId', null, new UID(), 'Platform unique ID.') ->param('platformId', null, new UID(), 'Platform unique ID.')
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
@ -1192,6 +1267,9 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'deletePlatform') ->label('sdk.method', 'deletePlatform')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('platformId', null, new UID(), 'Platform unique ID.') ->param('platformId', null, new UID(), 'Platform unique ID.')
->action(function ($projectId, $platformId, $response, $consoleDB) { ->action(function ($projectId, $platformId, $response, $consoleDB) {
@ -1225,6 +1303,9 @@ App::post('/v1/projects/:projectId/domains')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'createDomain') ->label('sdk.method', 'createDomain')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('domain', null, new DomainValidator(), 'Domain name.') ->param('domain', null, new DomainValidator(), 'Domain name.')
->action(function ($projectId, $domain, $response, $consoleDB) { ->action(function ($projectId, $domain, $response, $consoleDB) {
@ -1289,6 +1370,9 @@ App::get('/v1/projects/:projectId/domains')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'listDomains') ->label('sdk.method', 'listDomains')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN_LIST)
->param('projectId', '', new UID(), 'Project unique ID.') ->param('projectId', '', new UID(), 'Project unique ID.')
->action(function ($projectId, $response, $consoleDB) { ->action(function ($projectId, $response, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -1314,6 +1398,9 @@ App::get('/v1/projects/:projectId/domains/:domainId')
->label('scope', 'projects.read') ->label('scope', 'projects.read')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'getDomain') ->label('sdk.method', 'getDomain')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('domainId', null, new UID(), 'Domain unique ID.') ->param('domainId', null, new UID(), 'Domain unique ID.')
->action(function ($projectId, $domainId, $response, $consoleDB) { ->action(function ($projectId, $domainId, $response, $consoleDB) {
@ -1341,6 +1428,9 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateDomainVerification') ->label('sdk.method', 'updateDomainVerification')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('domainId', null, new UID(), 'Domain unique ID.') ->param('domainId', null, new UID(), 'Domain unique ID.')
->action(function ($projectId, $domainId, $response, $consoleDB) { ->action(function ($projectId, $domainId, $response, $consoleDB) {
@ -1399,6 +1489,9 @@ App::delete('/v1/projects/:projectId/domains/:domainId')
->label('scope', 'projects.write') ->label('scope', 'projects.write')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteDomain') ->label('sdk.method', 'deleteDomain')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('projectId', null, new UID(), 'Project unique ID.') ->param('projectId', null, new UID(), 'Project unique ID.')
->param('domainId', null, new UID(), 'Domain unique ID.') ->param('domainId', null, new UID(), 'Domain unique ID.')
->action(function ($projectId, $domainId, $response, $consoleDB) { ->action(function ($projectId, $domainId, $response, $consoleDB) {

View file

@ -32,8 +32,11 @@ App::post('/v1/storage/files')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'createFile') ->label('sdk.method', 'createFile')
->label('sdk.description', '/docs/references/storage/create-file.md') ->label('sdk.description', '/docs/references/storage/create-file.md')
->label('sdk.consumes', 'multipart/form-data') ->label('sdk.request.type', 'multipart/form-data')
->label('sdk.methodType', 'upload') ->label('sdk.methodType', 'upload')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FILE)
->param('file', [], new File(), 'Binary file.', false) ->param('file', [], new File(), 'Binary file.', false)
->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('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('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.')
@ -46,12 +49,10 @@ App::post('/v1/storage/files')
/** @var Appwrite\Event\Event $usage */ /** @var Appwrite\Event\Event $usage */
$file = $request->getFiles('file'); $file = $request->getFiles('file');
$read = (empty($read)) ? ['user:'.$user->getId()] : $read;
$write = (empty($write)) ? ['user:'.$user->getId()] : $write;
/* /*
* Validators * Validators
*/ */
//$fileType = new FileType(array(FileType::FILE_TYPE_PNG, FileType::FILE_TYPE_GIF, FileType::FILE_TYPE_JPEG)); //$fileType = new FileType(array(FileType::FILE_TYPE_PNG, FileType::FILE_TYPE_GIF, FileType::FILE_TYPE_JPEG));
$fileSize = new FileSize(App::getEnv('_APP_STORAGE_LIMIT', 0)); $fileSize = new FileSize(App::getEnv('_APP_STORAGE_LIMIT', 0));
$upload = new Upload(); $upload = new Upload();
@ -163,6 +164,9 @@ App::get('/v1/storage/files')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'listFiles') ->label('sdk.method', 'listFiles')
->label('sdk.description', '/docs/references/storage/list-files.md') ->label('sdk.description', '/docs/references/storage/list-files.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FILE_LIST)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
@ -197,6 +201,9 @@ App::get('/v1/storage/files/:fileId')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFile') ->label('sdk.method', 'getFile')
->label('sdk.description', '/docs/references/storage/get-file.md') ->label('sdk.description', '/docs/references/storage/get-file.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FILE)
->param('fileId', '', new UID(), 'File unique ID.') ->param('fileId', '', new UID(), 'File unique ID.')
->action(function ($fileId, $response, $projectDB) { ->action(function ($fileId, $response, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -219,7 +226,8 @@ App::get('/v1/storage/files/:fileId/preview')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFilePreview') ->label('sdk.method', 'getFilePreview')
->label('sdk.description', '/docs/references/storage/get-file-preview.md') ->label('sdk.description', '/docs/references/storage/get-file-preview.md')
->label('sdk.response.type', 'image/*') ->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE)
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->param('fileId', '', new UID(), 'File unique ID') ->param('fileId', '', new UID(), 'File unique ID')
->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true) ->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true)
@ -345,7 +353,8 @@ App::get('/v1/storage/files/:fileId/download')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFileDownload') ->label('sdk.method', 'getFileDownload')
->label('sdk.description', '/docs/references/storage/get-file-download.md') ->label('sdk.description', '/docs/references/storage/get-file-download.md')
->label('sdk.response.type', '*') ->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', '*/*')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->param('fileId', '', new UID(), 'File unique ID.') ->param('fileId', '', new UID(), 'File unique ID.')
->action(function ($fileId, $response, $projectDB) { ->action(function ($fileId, $response, $projectDB) {
@ -400,7 +409,8 @@ App::get('/v1/storage/files/:fileId/view')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'getFileView') ->label('sdk.method', 'getFileView')
->label('sdk.description', '/docs/references/storage/get-file-view.md') ->label('sdk.description', '/docs/references/storage/get-file-view.md')
->label('sdk.response.type', '*') ->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', '*/*')
->label('sdk.methodType', 'location') ->label('sdk.methodType', 'location')
->param('fileId', '', new UID(), 'File unique ID.') ->param('fileId', '', new UID(), 'File unique ID.')
->param('as', '', new WhiteList(['pdf', /*'html',*/ 'text'], true), 'Choose a file format to convert your file to. Currently you can only convert word and pdf files to pdf or txt. This option is currently experimental only, use at your own risk.', true) ->param('as', '', new WhiteList(['pdf', /*'html',*/ 'text'], true), 'Choose a file format to convert your file to. Currently you can only convert word and pdf files to pdf or txt. This option is currently experimental only, use at your own risk.', true)
@ -474,6 +484,9 @@ App::put('/v1/storage/files/:fileId')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'updateFile') ->label('sdk.method', 'updateFile')
->label('sdk.description', '/docs/references/storage/update-file.md') ->label('sdk.description', '/docs/references/storage/update-file.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FILE)
->param('fileId', '', new UID(), 'File unique ID.') ->param('fileId', '', new UID(), 'File unique ID.')
->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('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('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.')
@ -506,7 +519,7 @@ App::put('/v1/storage/files/:fileId')
; ;
$response->dynamic($file, Response::MODEL_FILE); $response->dynamic($file, Response::MODEL_FILE);
}, ['response', 'projectDB', 'webhooks', 'audits']); }, ['response', 'projectDB', 'audits']);
App::delete('/v1/storage/files/:fileId') App::delete('/v1/storage/files/:fileId')
->desc('Delete File') ->desc('Delete File')
@ -517,6 +530,9 @@ App::delete('/v1/storage/files/:fileId')
->label('sdk.namespace', 'storage') ->label('sdk.namespace', 'storage')
->label('sdk.method', 'deleteFile') ->label('sdk.method', 'deleteFile')
->label('sdk.description', '/docs/references/storage/delete-file.md') ->label('sdk.description', '/docs/references/storage/delete-file.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('fileId', '', new UID(), 'File unique ID.') ->param('fileId', '', new UID(), 'File unique ID.')
->action(function ($fileId, $response, $projectDB, $webhooks, $audits, $usage) { ->action(function ($fileId, $response, $projectDB, $webhooks, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */

View file

@ -28,16 +28,21 @@ App::post('/v1/teams')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'create') ->label('sdk.method', 'create')
->label('sdk.description', '/docs/references/teams/create-team.md') ->label('sdk.description', '/docs/references/teams/create-team.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TEAM)
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
->param('roles', ['owner'], new ArrayList(new Key()), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.', true) ->param('roles', ['owner'], new ArrayList(new Key()), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.', true)
->action(function ($name, $roles, $response, $user, $projectDB, $mode) { ->action(function ($name, $roles, $response, $user, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */ /** @var Appwrite\Database\Database $projectDB */
/** @var bool $mode */
Authorization::disable(); Authorization::disable();
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
$isAppUser = Auth::isAppUser(Authorization::$roles);
$team = $projectDB->createDocument([ $team = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_TEAMS, '$collection' => Database::SYSTEM_COLLECTION_TEAMS,
'$permissions' => [ '$permissions' => [
@ -45,7 +50,7 @@ App::post('/v1/teams')
'write' => ['team:{self}/owner'], 'write' => ['team:{self}/owner'],
], ],
'name' => $name, 'name' => $name,
'sum' => ($mode !== APP_MODE_ADMIN && $user->getId()) ? 1 : 0, 'sum' => ($isPreviliggedUser || $isAppUser) ? 0 : 1,
'dateCreated' => \time(), 'dateCreated' => \time(),
]); ]);
@ -55,7 +60,7 @@ App::post('/v1/teams')
throw new Exception('Failed saving team to DB', 500); throw new Exception('Failed saving team to DB', 500);
} }
if ($mode !== APP_MODE_ADMIN && $user->getId()) { // Don't add user on server mode if (!$isPreviliggedUser && !$isAppUser) { // Don't add user on server mode
$membership = new Document([ $membership = new Document([
'$collection' => Database::SYSTEM_COLLECTION_MEMBERSHIPS, '$collection' => Database::SYSTEM_COLLECTION_MEMBERSHIPS,
'$permissions' => [ '$permissions' => [
@ -85,7 +90,7 @@ App::post('/v1/teams')
->setStatusCode(Response::STATUS_CODE_CREATED) ->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($team, Response::MODEL_TEAM) ->dynamic($team, Response::MODEL_TEAM)
; ;
}, ['response', 'user', 'projectDB', 'mode']); }, ['response', 'user', 'projectDB']);
App::get('/v1/teams') App::get('/v1/teams')
->desc('List Teams') ->desc('List Teams')
@ -95,6 +100,9 @@ App::get('/v1/teams')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'list') ->label('sdk.method', 'list')
->label('sdk.description', '/docs/references/teams/list-teams.md') ->label('sdk.description', '/docs/references/teams/list-teams.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TEAM_LIST)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
@ -129,6 +137,9 @@ App::get('/v1/teams/:teamId')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'get') ->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/teams/get-team.md') ->label('sdk.description', '/docs/references/teams/get-team.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TEAM)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->action(function ($teamId, $response, $projectDB) { ->action(function ($teamId, $response, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -151,6 +162,9 @@ App::put('/v1/teams/:teamId')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'update') ->label('sdk.method', 'update')
->label('sdk.description', '/docs/references/teams/update-team.md') ->label('sdk.description', '/docs/references/teams/update-team.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TEAM)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
->action(function ($teamId, $name, $response, $projectDB) { ->action(function ($teamId, $name, $response, $projectDB) {
@ -182,6 +196,9 @@ App::delete('/v1/teams/:teamId')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'delete') ->label('sdk.method', 'delete')
->label('sdk.description', '/docs/references/teams/delete-team.md') ->label('sdk.description', '/docs/references/teams/delete-team.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->action(function ($teamId, $response, $projectDB) { ->action(function ($teamId, $response, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -223,19 +240,24 @@ App::post('/v1/teams/:teamId/memberships')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'createMembership') ->label('sdk.method', 'createMembership')
->label('sdk.description', '/docs/references/teams/create-team-membership.md') ->label('sdk.description', '/docs/references/teams/create-team-membership.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->param('email', '', new Email(), 'New team member email.') ->param('email', '', new Email(), 'New team member email.')
->param('name', '', new Text(128), 'New team member name. Max length: 128 chars.', true) ->param('name', '', new Text(128), 'New team member name. Max length: 128 chars.', true)
->param('roles', [], new ArrayList(new Key()), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.') ->param('roles', [], new ArrayList(new Key()), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.')
->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add our own built-in confirm page ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add our own built-in confirm page
->action(function ($teamId, $email, $name, $roles, $url, $response, $project, $user, $projectDB, $locale, $audits, $mails, $mode) { ->action(function ($teamId, $email, $name, $roles, $url, $response, $project, $user, $projectDB, $locale, $audits, $mails) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $project */
/** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Document $user */
/** @var Appwrite\Database\Database $projectDB */ /** @var Appwrite\Database\Database $projectDB */
/** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $mails */ /** @var Appwrite\Event\Event $mails */
/** @var bool $mode */
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
$isAppUser = Auth::isAppUser(Authorization::$roles);
$name = (empty($name)) ? $email : $name; $name = (empty($name)) ? $email : $name;
$team = $projectDB->getDocument($teamId); $team = $projectDB->getDocument($teamId);
@ -305,7 +327,7 @@ App::post('/v1/teams/:teamId/memberships')
} }
} }
if (!$isOwner && APP_MODE_ADMIN !== $mode && $user->getId()) { // Not owner, not admin, not app (server) if (!$isOwner && !$isPreviliggedUser && !$isAppUser) { // Not owner, not admin, not app (server)
throw new Exception('User is not allowed to send invitations for this team', 401); throw new Exception('User is not allowed to send invitations for this team', 401);
} }
@ -321,12 +343,12 @@ App::post('/v1/teams/:teamId/memberships')
'teamId' => $team->getId(), 'teamId' => $team->getId(),
'roles' => $roles, 'roles' => $roles,
'invited' => \time(), 'invited' => \time(),
'joined' => (APP_MODE_ADMIN === $mode || !$user->getId()) ? \time() : 0, 'joined' => ($isPreviliggedUser || $isAppUser) ? \time() : 0,
'confirm' => (APP_MODE_ADMIN === $mode || !$user->getId()), 'confirm' => ($isPreviliggedUser || $isAppUser),
'secret' => Auth::hash($secret), 'secret' => Auth::hash($secret),
]); ]);
if (APP_MODE_ADMIN === $mode || !$user->getId()) { // Allow admin to create membership if ($isPreviliggedUser || $isAppUser) { // Allow admin to create membership
Authorization::disable(); Authorization::disable();
$membership = $projectDB->createDocument($membership->getArrayCopy()); $membership = $projectDB->createDocument($membership->getArrayCopy());
@ -377,7 +399,7 @@ App::post('/v1/teams/:teamId/memberships')
->setParam('{{text-cta}}', '#ffffff') ->setParam('{{text-cta}}', '#ffffff')
; ;
if (APP_MODE_ADMIN !== $mode && $user->getId()) { // No need in comfirmation when in admin or app mode if (!$isPreviliggedUser && !$isAppUser) { // No need in comfirmation when in admin or app mode
$mails $mails
->setParam('event', 'teams.membership.create') ->setParam('event', 'teams.membership.create')
->setParam('from', ($project->getId() === 'console') ? '' : \sprintf($locale->getText('account.emails.team'), $project->getAttribute('name'))) ->setParam('from', ($project->getId() === 'console') ? '' : \sprintf($locale->getText('account.emails.team'), $project->getAttribute('name')))
@ -402,7 +424,7 @@ App::post('/v1/teams/:teamId/memberships')
'name' => $name, 'name' => $name,
])), Response::MODEL_MEMBERSHIP) ])), Response::MODEL_MEMBERSHIP)
; ;
}, ['response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails', 'mode']); }, ['response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails']);
App::get('/v1/teams/:teamId/memberships') App::get('/v1/teams/:teamId/memberships')
->desc('Get Team Memberships') ->desc('Get Team Memberships')
@ -412,6 +434,9 @@ App::get('/v1/teams/:teamId/memberships')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'getMemberships') ->label('sdk.method', 'getMemberships')
->label('sdk.description', '/docs/references/teams/get-team-members.md') ->label('sdk.description', '/docs/references/teams/get-team-members.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
@ -462,6 +487,9 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'updateMembershipStatus') ->label('sdk.method', 'updateMembershipStatus')
->label('sdk.description', '/docs/references/teams/update-team-membership-status.md') ->label('sdk.description', '/docs/references/teams/update-team-membership-status.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->param('inviteId', '', new UID(), 'Invite unique ID.') ->param('inviteId', '', new UID(), 'Invite unique ID.')
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
@ -553,7 +581,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
'$collection' => Database::SYSTEM_COLLECTION_TOKENS, '$collection' => Database::SYSTEM_COLLECTION_TOKENS,
'$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]], '$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]],
'type' => Auth::TOKEN_TYPE_LOGIN, 'type' => Auth::TOKEN_TYPE_LOGIN,
'secret' => Auth::hash($secret), // On way hash encryption to protect DB leak 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'expire' => $expiry, 'expire' => $expiry,
'userAgent' => $request->getUserAgent('UNKNOWN'), 'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(), 'ip' => $request->getIP(),
@ -637,6 +665,9 @@ App::delete('/v1/teams/:teamId/memberships/:inviteId')
->label('sdk.namespace', 'teams') ->label('sdk.namespace', 'teams')
->label('sdk.method', 'deleteMembership') ->label('sdk.method', 'deleteMembership')
->label('sdk.description', '/docs/references/teams/delete-team-membership.md') ->label('sdk.description', '/docs/references/teams/delete-team-membership.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->param('teamId', '', new UID(), 'Team unique ID.') ->param('teamId', '', new UID(), 'Team unique ID.')
->param('inviteId', '', new UID(), 'Invite unique ID.') ->param('inviteId', '', new UID(), 'Invite unique ID.')
->action(function ($teamId, $inviteId, $response, $projectDB, $audits) { ->action(function ($teamId, $inviteId, $response, $projectDB, $audits) {

View file

@ -27,6 +27,9 @@ App::post('/v1/users')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'create') ->label('sdk.method', 'create')
->label('sdk.description', '/docs/references/users/create-user.md') ->label('sdk.description', '/docs/references/users/create-user.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('email', '', new Email(), 'User email.') ->param('email', '', new Email(), 'User email.')
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.') ->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true) ->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@ -80,6 +83,9 @@ App::get('/v1/users')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'list') ->label('sdk.method', 'list')
->label('sdk.description', '/docs/references/users/list-users.md') ->label('sdk.description', '/docs/references/users/list-users.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER_LIST)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
@ -114,6 +120,9 @@ App::get('/v1/users/:userId')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'get') ->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/users/get-user.md') ->label('sdk.description', '/docs/references/users/get-user.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->action(function ($userId, $response, $projectDB) { ->action(function ($userId, $response, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -136,6 +145,9 @@ App::get('/v1/users/:userId/prefs')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'getPrefs') ->label('sdk.method', 'getPrefs')
->label('sdk.description', '/docs/references/users/get-user-prefs.md') ->label('sdk.description', '/docs/references/users/get-user-prefs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ANY)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->action(function ($userId, $response, $projectDB) { ->action(function ($userId, $response, $projectDB) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -149,7 +161,7 @@ App::get('/v1/users/:userId/prefs')
$prefs = $user->getAttribute('prefs', ''); $prefs = $user->getAttribute('prefs', '');
$response->json($prefs); $response->dynamic(new Document($prefs), Response::MODEL_ANY);
}, ['response', 'projectDB']); }, ['response', 'projectDB']);
App::get('/v1/users/:userId/sessions') App::get('/v1/users/:userId/sessions')
@ -160,6 +172,9 @@ App::get('/v1/users/:userId/sessions')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'getSessions') ->label('sdk.method', 'getSessions')
->label('sdk.description', '/docs/references/users/get-user-sessions.md') ->label('sdk.description', '/docs/references/users/get-user-sessions.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_SESSION_LIST)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->action(function ($userId, $response, $projectDB, $locale) { ->action(function ($userId, $response, $projectDB, $locale) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -203,6 +218,9 @@ App::get('/v1/users/:userId/logs')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'getLogs') ->label('sdk.method', 'getLogs')
->label('sdk.description', '/docs/references/users/get-user-logs.md') ->label('sdk.description', '/docs/references/users/get-user-logs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->action(function ($userId, $response, $register, $project, $projectDB, $locale, $geodb) { ->action(function ($userId, $response, $register, $project, $projectDB, $locale, $geodb) {
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
@ -309,6 +327,9 @@ App::patch('/v1/users/:userId/status')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'updateStatus') ->label('sdk.method', 'updateStatus')
->label('sdk.description', '/docs/references/users/update-user-status.md') ->label('sdk.description', '/docs/references/users/update-user-status.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->param('status', '', new WhiteList([Auth::USER_STATUS_ACTIVATED, Auth::USER_STATUS_BLOCKED, Auth::USER_STATUS_UNACTIVATED], true), 'User Status code. To activate the user pass '.Auth::USER_STATUS_ACTIVATED.', to block the user pass '.Auth::USER_STATUS_BLOCKED.' and for disabling the user pass '.Auth::USER_STATUS_UNACTIVATED) ->param('status', '', new WhiteList([Auth::USER_STATUS_ACTIVATED, Auth::USER_STATUS_BLOCKED, Auth::USER_STATUS_UNACTIVATED], true), 'User Status code. To activate the user pass '.Auth::USER_STATUS_ACTIVATED.', to block the user pass '.Auth::USER_STATUS_BLOCKED.' and for disabling the user pass '.Auth::USER_STATUS_UNACTIVATED)
->action(function ($userId, $status, $response, $projectDB) { ->action(function ($userId, $status, $response, $projectDB) {
@ -340,6 +361,9 @@ App::patch('/v1/users/:userId/prefs')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'updatePrefs') ->label('sdk.method', 'updatePrefs')
->label('sdk.description', '/docs/references/users/update-user-prefs.md') ->label('sdk.description', '/docs/references/users/update-user-prefs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ANY)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.') ->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
->action(function ($userId, $prefs, $response, $projectDB) { ->action(function ($userId, $prefs, $response, $projectDB) {
@ -360,7 +384,7 @@ App::patch('/v1/users/:userId/prefs')
throw new Exception('Failed saving user to DB', 500); throw new Exception('Failed saving user to DB', 500);
} }
$response->json($prefs); $response->dynamic(new Document($prefs), Response::MODEL_ANY);
}, ['response', 'projectDB']); }, ['response', 'projectDB']);
App::delete('/v1/users/:userId/sessions/:sessionId') App::delete('/v1/users/:userId/sessions/:sessionId')
@ -372,6 +396,9 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'deleteSession') ->label('sdk.method', 'deleteSession')
->label('sdk.description', '/docs/references/users/delete-user-session.md') ->label('sdk.description', '/docs/references/users/delete-user-session.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->label('abuse-limit', 100) ->label('abuse-limit', 100)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->param('sessionId', null, new UID(), 'User unique session ID.') ->param('sessionId', null, new UID(), 'User unique session ID.')
@ -412,6 +439,9 @@ App::delete('/v1/users/:userId/sessions')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'deleteSessions') ->label('sdk.method', 'deleteSessions')
->label('sdk.description', '/docs/references/users/delete-user-sessions.md') ->label('sdk.description', '/docs/references/users/delete-user-sessions.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->label('abuse-limit', 100) ->label('abuse-limit', 100)
->param('userId', '', new UID(), 'User unique ID.') ->param('userId', '', new UID(), 'User unique ID.')
->action(function ($userId, $response, $projectDB, $webhooks) { ->action(function ($userId, $response, $projectDB, $webhooks) {
@ -449,6 +479,9 @@ App::delete('/v1/users/:userId')
->label('sdk.namespace', 'users') ->label('sdk.namespace', 'users')
->label('sdk.method', 'deleteUser') ->label('sdk.method', 'deleteUser')
->label('sdk.description', '/docs/references/users/delete-user.md') ->label('sdk.description', '/docs/references/users/delete-user.md')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_NONE)
->label('abuse-limit', 100) ->label('abuse-limit', 100)
->param('userId', '', function () {return new UID();}, 'User unique ID.') ->param('userId', '', function () {return new UID();}, 'User unique ID.')
->action(function ($userId, $response, $projectDB, $webhooks, $deletes) { ->action(function ($userId, $response, $projectDB, $webhooks, $deletes) {

View file

@ -37,8 +37,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
/** @var bool $mode */ /** @var bool $mode */
/** @var array $clients */ /** @var array $clients */
Authorization::$roles = ['*'];
$localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); $localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));

View file

@ -157,7 +157,7 @@ App::post('/v1/mock/tests/general/upload')
->label('sdk.namespace', 'general') ->label('sdk.namespace', 'general')
->label('sdk.method', 'upload') ->label('sdk.method', 'upload')
->label('sdk.description', 'Mock a delete request for SDK tests') ->label('sdk.description', 'Mock a delete request for SDK tests')
->label('sdk.consumes', 'multipart/form-data') ->label('sdk.request.type', 'multipart/form-data')
->label('sdk.mock', true) ->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param') ->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param') ->param('y', '', new Numeric(), 'Sample numeric param')

View file

@ -1,11 +1,13 @@
<?php <?php
use Appwrite\Template\Template; use Appwrite\Specification\Format\OpenAPI3;
use Appwrite\Specification\Format\Swagger2;
use Appwrite\Specification\Specification;
use Utopia\App; use Utopia\App;
use Utopia\View; use Utopia\View;
use Utopia\Config\Config; use Utopia\Config\Config;
use Utopia\Exception;
use Utopia\Validator\WhiteList; use Utopia\Validator\WhiteList;
use Utopia\Validator\Range;
App::init(function ($layout) { App::init(function ($layout) {
/** @var Utopia\View $layout */ /** @var Utopia\View $layout */
@ -180,30 +182,26 @@ App::get('/error/:code')
->setParam('body', $page); ->setParam('body', $page);
}, ['layout']); }, ['layout']);
App::get('/open-api-2.json') App::get('/specs/:format')
->groups(['web', 'home']) ->groups(['web', 'home'])
->label('scope', 'public') ->label('scope', 'public')
->label('docs', false) ->label('docs', false)
->param('format', 'swagger2', new WhiteList(['swagger2', 'open-api3'], true), 'Spec format.', true)
->param('platform', APP_PLATFORM_CLIENT, new WhiteList([APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER, APP_PLATFORM_CONSOLE], true), 'Choose target platform.', true) ->param('platform', APP_PLATFORM_CLIENT, new WhiteList([APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER, APP_PLATFORM_CONSOLE], true), 'Choose target platform.', true)
->param('extensions', 0, new Range(0, 1), 'Show extra data.', true) ->action(function ($format, $platform, $utopia, $request, $response) {
->param('tests', 0, new Range(0, 1), 'Include only test services.', true)
->action(function ($platform, $extensions, $tests, $utopia, $request, $response) {
/** @var Utopia\App $utopia */ /** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */ /** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Utopia\Response $response */
$security = [
APP_PLATFORM_CLIENT => ['Project' => []],
APP_PLATFORM_SERVER => ['Project' => [], 'Key' => []],
APP_PLATFORM_CONSOLE => ['Project' => [], 'Key' => []],
];
$platforms = [ $platforms = [
'client' => APP_PLATFORM_CLIENT, 'client' => APP_PLATFORM_CLIENT,
'server' => APP_PLATFORM_SERVER, 'server' => APP_PLATFORM_SERVER,
'all' => APP_PLATFORM_CONSOLE, 'console' => APP_PLATFORM_CONSOLE,
]; ];
$routes = [];
$models = [];
$keys = [ $keys = [
APP_PLATFORM_CLIENT => [ APP_PLATFORM_CLIENT => [
'Project' => [ 'Project' => [
@ -267,98 +265,14 @@ App::get('/open-api-2.json')
], ],
]; ];
/* $security = [
* Specifications (v3.0.0): APP_PLATFORM_CLIENT => ['Project' => []],
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md APP_PLATFORM_SERVER => ['Project' => [], 'Key' => []],
*/ APP_PLATFORM_CONSOLE => ['Project' => [], 'Key' => []],
$output = [
'swagger' => '2.0',
'info' => [
'version' => APP_VERSION_STABLE,
'title' => APP_NAME,
'description' => 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)',
'termsOfService' => 'https://appwrite.io/policy/terms',
'contact' => [
'name' => 'Appwrite Team',
'url' => 'https://appwrite.io/support',
'email' => App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM),
],
'license' => [
'name' => 'BSD-3-Clause',
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
],
],
'host' => \parse_url(App::getEnv('_APP_HOME', $request->getHostname()), PHP_URL_HOST),
'basePath' => '/v1',
'schemes' => ['https'],
'consumes' => ['application/json', 'multipart/form-data'],
'produces' => ['application/json'],
'securityDefinitions' => $keys[$platform],
'paths' => [],
'definitions' => [
// 'Pet' => [
// 'required' => ['id', 'name'],
// 'properties' => [
// 'id' => [
// 'type' => 'integer',
// 'format' => 'int64',
// ],
// 'name' => [
// 'type' => 'string',
// ],
// 'tag' => [
// 'type' => 'string',
// ],
// ],
// ],
// 'Pets' => array(
// 'type' => 'array',
// 'items' => array(
// '$ref' => '#/definitions/Pet',
// ),
// ),
'Error' => array(
'required' => array(
0 => 'code',
1 => 'message',
),
'properties' => array(
'code' => array(
'type' => 'integer',
'format' => 'int32',
),
'message' => array(
'type' => 'string',
),
),
),
],
'externalDocs' => [
'description' => 'Full API docs, specs and tutorials',
'url' => $request->getProtocol().'://'.$request->getHostname().'/docs',
],
]; ];
if ($extensions) {
if (isset($output['securityDefinitions']['Project'])) {
$output['securityDefinitions']['Project']['extensions'] = ['demo' => '5df5acd0d48c2'];
}
if (isset($output['securityDefinitions']['Key'])) {
$output['securityDefinitions']['Key']['extensions'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
}
if (isset($output['securityDefinitions']['Locale'])) {
$output['securityDefinitions']['Locale']['extensions'] = ['demo' => 'en'];
}
if (isset($output['securityDefinitions']['Mode'])) {
$output['securityDefinitions']['Mode']['extensions'] = ['demo' => ''];
}
}
foreach ($utopia->getRoutes() as $key => $method) { foreach ($utopia->getRoutes() as $key => $method) {
foreach ($method as $route) { /* @var $route \Utopia\Route */ foreach ($method as $route) { /** @var \Utopia\Route $route */
if (!$route->getLabel('docs', true)) { if (!$route->getLabel('docs', true)) {
continue; continue;
} }
@ -375,184 +289,56 @@ App::get('/open-api-2.json')
continue; continue;
} }
$url = \str_replace('/v1', '', $route->getURL()); $routes[] = $route;
$scope = $route->getLabel('scope', ''); $model = $response->getModel($route->getLabel('sdk.response.model', 'none'));
$hide = $route->getLabel('sdk.hide', false);
$consumes = ['application/json']; if($model) {
$models[$model->getType()] = $model;
if ($hide) {
continue;
} }
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../'.$route->getLabel('sdk.description', '')) : null;
$temp = [
'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.method', \uniqid()),
'consumes' => [],
'tags' => [$route->getLabel('sdk.namespace', 'default')],
'description' => ($desc) ? \file_get_contents($desc) : '',
// 'responses' => [
// 200 => [
// 'description' => 'An paged array of pets',
// 'schema' => [
// '$ref' => '#/definitions/Pet',
// ],
// ],
// ],
];
if ($extensions) {
$platformList = $route->getLabel('sdk.platform', []);
$temp['extensions'] = [
'weight' => $route->getOrder(),
'cookies' => $route->getLabel('sdk.cookies', false),
'type' => $route->getLabel('sdk.methodType', ''),
'demo' => 'docs/examples/'. Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($temp['operationId']).'.md',
'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''),
'rate-limit' => $route->getLabel('abuse-limit', 0),
'rate-time' => $route->getLabel('abuse-time', 3600),
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
'scope' => $route->getLabel('scope', ''),
'platforms' => $platformList,
];
}
if ((!empty($scope))) { // && 'public' != $scope
$temp['security'][] = $route->getLabel('sdk.security', $security[$platform]);
}
$requestBody = [
'content' => [
'application/x-www-form-urlencoded' => [
'schema' => [
'type' => 'object',
'properties' => [],
],
'required' => [],
],
],
];
foreach ($route->getParams() as $name => $param) {
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $utopia->getResources($param['resources'])) : $param['validator']; /* @var $validator \Utopia\Validator */
$node = [
'name' => $name,
'description' => $param['description'],
'required' => !$param['optional'],
];
switch ((!empty($validator)) ? \get_class($validator) : '') {
case 'Utopia\Validator\Text':
$node['type'] = 'string';
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
break;
case 'Utopia\Validator\Boolean':
$node['type'] = 'boolean';
$node['x-example'] = false;
break;
case 'Appwrite\Database\Validator\UID':
$node['type'] = 'string';
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
break;
case 'Utopia\Validator\Email':
$node['type'] = 'string';
$node['format'] = 'email';
$node['x-example'] = 'email@example.com';
break;
case 'Utopia\Validator\URL':
$node['type'] = 'string';
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\JSON':
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$node['type'] = 'object';
$node['type'] = 'object';
$node['x-example'] = '{}';
//$node['format'] = 'json';
break;
case 'Appwrite\Storage\Validator\File':
$consumes = ['multipart/form-data'];
$node['type'] = 'file';
break;
case 'Utopia\Validator\ArrayList':
$node['type'] = 'array';
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => 'string',
];
break;
case 'Appwrite\Auth\Validator\Password':
$node['type'] = 'string';
$node['format'] = 'format';
$node['x-example'] = 'password';
break;
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
$node['type'] = 'integer';
$node['format'] = 'int32';
$node['x-example'] = $validator->getMin();
break;
case 'Utopia\Validator\Numeric':
$node['type'] = 'integer';
$node['format'] = 'int32';
break;
case 'Utopia\Validator\Length':
$node['type'] = 'string';
break;
case 'Utopia\Validator\Host':
$node['type'] = 'string';
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
$node['type'] = 'string';
$node['x-example'] = $validator->getList()[0];
break;
default:
$node['type'] = 'string';
break;
}
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
$node['default'] = $param['default'];
}
if (false !== \strpos($url, ':'.$name)) { // Param is in URL path
$node['in'] = 'path';
$temp['parameters'][] = $node;
} elseif ($key == 'GET') { // Param is in query
$node['in'] = 'query';
$temp['parameters'][] = $node;
} else { // Param is in payload
$node['in'] = 'formData';
$temp['parameters'][] = $node;
$requestBody['content']['application/x-www-form-urlencoded']['schema']['properties'][] = $node;
if (!$param['optional']) {
$requestBody['content']['application/x-www-form-urlencoded']['required'][] = $name;
}
}
$url = \str_replace(':'.$name, '{'.$name.'}', $url);
}
$temp['consumes'] = $consumes;
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
} }
} }
/*foreach ($consoleDB->getMocks() as $mock) { $models = $response->getModels();
var_dump($mock['name']);
}*/
\ksort($output['paths']); foreach ($models as $key => $value) {
if($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
unset($models[$key]);
}
}
switch ($format) {
case 'swagger2':
$format = new Swagger2($utopia, $routes, $models, $keys[$platform], $security[$platform]);
break;
case 'open-api3':
$format = new OpenAPI3($utopia, $routes, $models, $keys[$platform], $security[$platform]);
break;
default:
throw new Exception('Format not found', 404);
break;
}
$specs = new Specification($format);
$format
->setParam('name', APP_NAME)
->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)')
->setParam('endpoint', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/v1')
->setParam('version', APP_VERSION_STABLE)
->setParam('terms', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/policy/terms')
->setParam('support.email', App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM))
->setParam('support.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/support')
->setParam('contact.name', APP_NAME.' Team')
->setParam('contact.email', App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM))
->setParam('contact.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/support')
->setParam('license.name', 'BSD-3-Clause')
->setParam('license.url', 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE')
->setParam('docs.description', 'Full API docs, specs and tutorials')
->setParam('docs.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/docs')
;
$response $response
->json($output); ->json($specs->parse());
}, ['utopia', 'request', 'response']); }, ['utopia', 'request', 'response']);

View file

@ -2,6 +2,7 @@
require_once __DIR__.'/../vendor/autoload.php'; require_once __DIR__.'/../vendor/autoload.php';
use Appwrite\Database\Validator\Authorization;
use Utopia\Swoole\Files; use Utopia\Swoole\Files;
use Utopia\Swoole\Request; use Utopia\Swoole\Request;
use Appwrite\Utopia\Response; use Appwrite\Utopia\Response;
@ -19,8 +20,6 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
sleep(2);
$http = new Server("0.0.0.0", 80); $http = new Server("0.0.0.0", 80);
$payloadSize = max(4000000 /* 4mb */, App::getEnv('_APP_STORAGE_LIMIT', 10000000 /* 10mb */)); $payloadSize = max(4000000 /* 4mb */, App::getEnv('_APP_STORAGE_LIMIT', 10000000 /* 10mb */));
@ -96,6 +95,9 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo
$app = new App('America/New_York'); $app = new App('America/New_York');
try { try {
Authorization::cleanRoles();
Authorization::setRole('*');
$app->run($request, $response); $app->run($request, $response);
} catch (\Throwable $th) { } catch (\Throwable $th) {
Console::error('[Error] Type: '.get_class($th)); Console::error('[Error] Type: '.get_class($th));

View file

@ -34,9 +34,10 @@ const APP_DOMAIN = 'appwrite.io';
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
const APP_EMAIL_SECURITY = 'security@localhost.test'; // Default security email address const APP_EMAIL_SECURITY = 'security@localhost.test'; // Default security email address
const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s'; const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
const APP_MODE_DEFAULT = 'default';
const APP_MODE_ADMIN = 'admin'; const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 12; const APP_PAGING_LIMIT = 12;
const APP_CACHE_BUSTER = 138; const APP_CACHE_BUSTER = 140;
const APP_VERSION_STABLE = '0.7.0'; const APP_VERSION_STABLE = '0.7.0';
const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_FUNCTIONS = '/storage/functions'; const APP_STORAGE_FUNCTIONS = '/storage/functions';
@ -381,8 +382,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response
$session = Auth::decodeSession( $session = Auth::decodeSession(
$request->getCookie(Auth::$cookieName, // Get sessions $request->getCookie(Auth::$cookieName, // Get sessions
$request->getCookie(Auth::$cookieName.'_legacy', // Get fallback session from old clients (no SameSite support) $request->getCookie(Auth::$cookieName.'_legacy', '')));// Get fallback session from old clients (no SameSite support)
$request->getHeader('x-appwrite-key', '')))); // Get API Key
// Get fallback session from clients who block 3rd-party cookies // Get fallback session from clients who block 3rd-party cookies
$response->addHeader('X-Debug-Fallback', 'false'); $response->addHeader('X-Debug-Fallback', 'false');
@ -463,7 +463,7 @@ App::setResource('projectDB', function($register, $project) {
App::setResource('mode', function($request) { App::setResource('mode', function($request) {
/** @var Utopia\Swoole\Request $request */ /** @var Utopia\Swoole\Request $request */
return $request->getParam('mode', $request->getHeader('x-appwrite-mode', 'default')); return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT));
}, ['request']); }, ['request']);
App::setResource('geodb', function($register) { App::setResource('geodb', function($register) {

View file

@ -21,41 +21,41 @@ $cli
Console::log("\n".'👩‍⚕️ Running '.APP_NAME.' Doctor for version '.App::getEnv('_APP_VERSION', 'UNKNOWN').' ...'."\n"); Console::log("\n".'👩‍⚕️ Running '.APP_NAME.' Doctor for version '.App::getEnv('_APP_VERSION', 'UNKNOWN').' ...'."\n");
Console::log('Checking for production best practices...'); Console::log('Checking for production best practices...');
$domain = new Domain(App::getEnv('_APP_DOMAIN')); $domain = new Domain(App::getEnv('_APP_DOMAIN'));
if(!$domain->isKnown() || $domain->isTest()) { if(!$domain->isKnown() || $domain->isTest()) {
Console::log('🔴 Hostname has a public suffix'); Console::log('🔴 Hostname has no public suffix ('.$domain->get().')');
} }
else { else {
Console::log('🟢 Hostname has a public suffix'); Console::log('🟢 Hostname has a public suffix ('.$domain->get().')');
} }
$domain = new Domain(App::getEnv('_APP_DOMAIN_TARGET')); $domain = new Domain(App::getEnv('_APP_DOMAIN_TARGET'));
if(!$domain->isKnown() || $domain->isTest()) { if(!$domain->isKnown() || $domain->isTest()) {
Console::log('🔴 CNAME target has a public suffix'); Console::log('🔴 CNAME target has no public suffix ('.$domain->get().')');
} }
else { else {
Console::log('🟢 CNAME target has a public suffix'); Console::log('🟢 CNAME target has a public suffix ('.$domain->get().')');
} }
if(App::getEnv('_APP_OPENSSL_KEY_V1', 'your-secret-key') === 'your-secret-key') { if(App::getEnv('_APP_OPENSSL_KEY_V1') === 'your-secret-key' || empty(App::getEnv('_APP_OPENSSL_KEY_V1'))) {
Console::log('🔴 Using a unique secret key for encryption'); Console::log('🔴 Not using a unique secret key for encryption');
} }
else { else {
Console::log('🟢 Using a unique secret key for encryption'); Console::log('🟢 Using a unique secret key for encryption');
} }
if(App::getEnv('_APP_ENV', 'development') === 'development') { if(App::getEnv('_APP_ENV', 'development') !== 'production') {
Console::log('🔴 App enviornment is set for production'); Console::log('🔴 App environment is set for development');
} }
else { else {
Console::log('🟢 App enviornment is set for production'); Console::log('🟢 App environment is set for production');
} }
if(App::getEnv('_APP_OPTIONS_ABUSE', 'disabled') === 'disabled') { if('enabled' !== App::getEnv('_APP_OPTIONS_ABUSE', 'disabled')) {
Console::log('🔴 Abuse protection is enabled'); Console::log('🔴 Abuse protection is disabled');
} }
else { else {
Console::log('🟢 Abuse protection is enabled'); Console::log('🟢 Abuse protection is enabled');
@ -74,12 +74,12 @@ $cli
else { else {
Console::log('🟢 Console access limits are enabled'); Console::log('🟢 Console access limits are enabled');
} }
if(empty(App::getEnv('_APP_OPTIONS_FORCE_HTTPS', null))) { if('enabled' !== App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled')) {
Console::log('🔴 HTTP force option is disabled'); Console::log('🔴 HTTPS force option is disabled');
} }
else { else {
Console::log('🟢 HTTP force option is enabled'); Console::log('🟢 HTTPS force option is enabled');
} }
\sleep(0.2); \sleep(0.2);
@ -133,17 +133,18 @@ $cli
$mail->Subject = 'Test SMTP Connection'; $mail->Subject = 'Test SMTP Connection';
$mail->Body = 'Hello World'; $mail->Body = 'Hello World';
$mail->AltBody = 'Hello World'; $mail->AltBody = 'Hello World';
$mail->send(); $mail->send();
Console::success('SMTP................connected 👍'); Console::success('SMTP................connected 👍');
} catch (\Throwable $th) { } catch (\Throwable $th) {
Console::error('SMTP.............disconnected 👎'); Console::error('SMTP.............disconnected 👎');
var_dump($th);
} }
$host = App::getEnv('_APP_STATSD_HOST', 'telegraf'); $host = App::getEnv('_APP_STATSD_HOST', 'telegraf');
$port = App::getEnv('_APP_STATSD_PORT', 8125); $port = App::getEnv('_APP_STATSD_PORT', 8125);
if($fp = @\fsockopen('udp://'.$host, $port, $errCode, $errStr, 2)){ if($fp = @\fsockopen('udp://'.$host, $port, $errCode, $errStr, 2)){
Console::success('StatsD..............connected 👍'); Console::success('StatsD..............connected 👍');
\fclose($fp); \fclose($fp);
} else { } else {
@ -153,7 +154,7 @@ $cli
$host = App::getEnv('_APP_INFLUXDB_HOST', ''); $host = App::getEnv('_APP_INFLUXDB_HOST', '');
$port = App::getEnv('_APP_INFLUXDB_PORT', ''); $port = App::getEnv('_APP_INFLUXDB_PORT', '');
if($fp = @\fsockopen($host, $port, $errCode, $errStr, 2)){ if($fp = @\fsockopen($host, $port, $errCode, $errStr, 2)){
Console::success('InfluxDB............connected 👍'); Console::success('InfluxDB............connected 👍');
\fclose($fp); \fclose($fp);
} else { } else {
@ -179,7 +180,7 @@ $cli
else { else {
Console::error('🔴 '.$key.' Volume is unreadable'); Console::error('🔴 '.$key.' Volume is unreadable');
} }
if (\is_writable($device->getRoot())) { if (\is_writable($device->getRoot())) {
Console::success('🟢 '.$key.' Volume is writeable'); Console::success('🟢 '.$key.' Volume is writeable');
} }
@ -203,9 +204,9 @@ $cli
$percentage = (($device->getPartitionTotalSpace() - $device->getPartitionFreeSpace()) $percentage = (($device->getPartitionTotalSpace() - $device->getPartitionFreeSpace())
/ $device->getPartitionTotalSpace()) * 100; / $device->getPartitionTotalSpace()) * 100;
$message = $key.' Volume has '.Storage::human($device->getPartitionFreeSpace()) . ' free space ('.\round($percentage, 2).'% used)'; $message = $key.' Volume has '.Storage::human($device->getPartitionFreeSpace()) . ' free space ('.\round($percentage, 2).'% used)';
if ($percentage < 80) { if ($percentage < 80) {
Console::success('🟢 ' . $message); Console::success('🟢 ' . $message);
} }
@ -213,20 +214,22 @@ $cli
Console::error('🔴 ' . $message); Console::error('🔴 ' . $message);
} }
} }
try { try {
Console::log(''); if(App::isProduction()) {
$version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost').'/v1/health/version'), true); Console::log('');
$version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost').'/v1/health/version'), true);
if ($version && isset($version['version']) && App::isProduction()) {
if(\version_compare($version['version'], App::getEnv('_APP_VERSION', 'UNKNOWN')) === 0) { if ($version && isset($version['version'])) {
Console::info('You are running the latest version of '.APP_NAME.'! 🥳'); if(\version_compare($version['version'], App::getEnv('_APP_VERSION', 'UNKNOWN')) === 0) {
Console::info('You are running the latest version of '.APP_NAME.'! 🥳');
}
else {
Console::info('A new version ('.$version['version'].') is available! 🥳'."\n");
}
} else {
Console::error('Failed to check for a newer version'."\n");
} }
else {
Console::info('A new version ('.$version['version'].') is available! 🥳'."\n");
}
} else {
Console::error('Failed to check for a newer version'."\n");
} }
} catch (\Throwable $th) { } catch (\Throwable $th) {
Console::error('Failed to check for a newer version'."\n"); Console::error('Failed to check for a newer version'."\n");

View file

@ -67,6 +67,11 @@ services:
- _APP_DB_SCHEMA - _APP_DB_SCHEMA
- _APP_DB_USER - _APP_DB_USER
- _APP_DB_PASS - _APP_DB_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
- _APP_SMTP_USERNAME
- _APP_SMTP_PASSWORD
- _APP_INFLUXDB_HOST - _APP_INFLUXDB_HOST
- _APP_INFLUXDB_PORT - _APP_INFLUXDB_PORT
- _APP_STORAGE_LIMIT - _APP_STORAGE_LIMIT

View file

@ -34,7 +34,7 @@
"appwrite/php-clamav": "1.0.*", "appwrite/php-clamav": "1.0.*",
"utopia-php/framework": "0.9.7", "utopia-php/framework": "0.9.8",
"utopia-php/abuse": "0.2.*", "utopia-php/abuse": "0.2.*",
"utopia-php/audit": "0.3.*", "utopia-php/audit": "0.3.*",
"utopia-php/cache": "0.2.*", "utopia-php/cache": "0.2.*",
@ -47,18 +47,18 @@
"utopia-php/swoole": "0.2.*", "utopia-php/swoole": "0.2.*",
"resque/php-resque": "1.3.6", "resque/php-resque": "1.3.6",
"piwik/device-detector": "3.13.0", "matomo/device-detector": "3.13.0",
"dragonmantank/cron-expression": "3.0.1", "dragonmantank/cron-expression": "3.0.1",
"domnikl/statsd": "3.0.*", "domnikl/statsd": "3.0.2",
"influxdb/influxdb-php": "1.15.*", "influxdb/influxdb-php": "1.15.1",
"phpmailer/phpmailer": "6.1.7", "phpmailer/phpmailer": "6.1.7",
"chillerlan/php-qrcode": "^4.2" "chillerlan/php-qrcode": "4.2.0"
}, },
"require-dev": { "require-dev": {
"swoole/ide-helper": "4.5.5", "swoole/ide-helper": "4.5.5",
"appwrite/sdk-generator": "master", "appwrite/sdk-generator": "master",
"phpunit/phpunit": "^9.3", "phpunit/phpunit": "9.4.2",
"vimeo/psalm": "4.0.1" "vimeo/psalm": "4.1.1"
}, },
"repositories": [ "repositories": [
{ {

423
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "17cb743e6efae97f01129b2a4a5239cd", "content-hash": "18cec0afcb76ef57fa38386fe04fd87b",
"packages": [ "packages": [
{ {
"name": "appwrite/php-clamav", "name": "appwrite/php-clamav",
@ -178,16 +178,16 @@
}, },
{ {
"name": "colinmollenhour/credis", "name": "colinmollenhour/credis",
"version": "v1.11.4", "version": "v1.12.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/colinmollenhour/credis.git", "url": "https://github.com/colinmollenhour/credis.git",
"reference": "b458b7c65d156744f5f0c4667c0f8ce45d955435" "reference": "c27faa11724229986335c23f4b6d0f1d8d6547fb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/colinmollenhour/credis/zipball/b458b7c65d156744f5f0c4667c0f8ce45d955435", "url": "https://api.github.com/repos/colinmollenhour/credis/zipball/c27faa11724229986335c23f4b6d0f1d8d6547fb",
"reference": "b458b7c65d156744f5f0c4667c0f8ce45d955435", "reference": "c27faa11724229986335c23f4b6d0f1d8d6547fb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -214,7 +214,7 @@
], ],
"description": "Credis is a lightweight interface to the Redis key-value store which wraps the phpredis library when available for better performance.", "description": "Credis is a lightweight interface to the Redis key-value store which wraps the phpredis library when available for better performance.",
"homepage": "https://github.com/colinmollenhour/credis", "homepage": "https://github.com/colinmollenhour/credis",
"time": "2020-10-13T23:55:13+00:00" "time": "2020-11-06T16:09:14+00:00"
}, },
{ {
"name": "domnikl/statsd", "name": "domnikl/statsd",
@ -601,6 +601,61 @@
], ],
"time": "2020-09-18T13:24:03+00:00" "time": "2020-09-18T13:24:03+00:00"
}, },
{
"name": "matomo/device-detector",
"version": "3.13.0",
"source": {
"type": "git",
"url": "https://github.com/matomo-org/device-detector.git",
"reference": "75ca5b690e38c40d199ade93e677bc5d7c3bc498"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matomo-org/device-detector/zipball/75ca5b690e38c40d199ade93e677bc5d7c3bc498",
"reference": "75ca5b690e38c40d199ade93e677bc5d7c3bc498",
"shasum": ""
},
"require": {
"mustangostang/spyc": "*",
"php": ">=5.5"
},
"require-dev": {
"fabpot/php-cs-fixer": "~1.7",
"matthiasmullie/scrapbook": "@stable",
"phpunit/phpunit": "^4.8.36",
"psr/cache": "^1.0",
"psr/simple-cache": "^1.0"
},
"suggest": {
"doctrine/cache": "Can directly be used for caching purpose",
"ext-yaml": "Necessary for using the Pecl YAML parser"
},
"type": "library",
"autoload": {
"psr-4": {
"DeviceDetector\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-or-later"
],
"authors": [
{
"name": "The Matomo Team",
"email": "hello@matomo.org",
"homepage": "https://matomo.org/team/"
}
],
"description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, media players, mobile apps, feed readers, libraries, etc), operating systems, devices, brands and models.",
"homepage": "https://matomo.org",
"keywords": [
"devicedetection",
"parser",
"useragent"
],
"time": "2020-08-17T07:37:33+00:00"
},
{ {
"name": "mustangostang/spyc", "name": "mustangostang/spyc",
"version": "dev-master", "version": "dev-master",
@ -719,62 +774,6 @@
], ],
"time": "2020-07-14T18:50:27+00:00" "time": "2020-07-14T18:50:27+00:00"
}, },
{
"name": "piwik/device-detector",
"version": "3.13.0",
"source": {
"type": "git",
"url": "https://github.com/matomo-org/device-detector.git",
"reference": "75ca5b690e38c40d199ade93e677bc5d7c3bc498"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matomo-org/device-detector/zipball/75ca5b690e38c40d199ade93e677bc5d7c3bc498",
"reference": "75ca5b690e38c40d199ade93e677bc5d7c3bc498",
"shasum": ""
},
"require": {
"mustangostang/spyc": "*",
"php": ">=5.5"
},
"require-dev": {
"fabpot/php-cs-fixer": "~1.7",
"matthiasmullie/scrapbook": "@stable",
"phpunit/phpunit": "^4.8.36",
"psr/cache": "^1.0",
"psr/simple-cache": "^1.0"
},
"suggest": {
"doctrine/cache": "Can directly be used for caching purpose",
"ext-yaml": "Necessary for using the Pecl YAML parser"
},
"type": "library",
"autoload": {
"psr-4": {
"DeviceDetector\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-or-later"
],
"authors": [
{
"name": "The Matomo Team",
"email": "hello@matomo.org",
"homepage": "https://matomo.org/team/"
}
],
"description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, media players, mobile apps, feed readers, libraries, etc), operating systems, devices, brands and models.",
"homepage": "https://matomo.org",
"keywords": [
"devicedetection",
"parser",
"useragent"
],
"abandoned": "matomo/device-detector",
"time": "2020-08-17T07:37:33+00:00"
},
{ {
"name": "psr/http-client", "name": "psr/http-client",
"version": "dev-master", "version": "dev-master",
@ -1333,16 +1332,16 @@
}, },
{ {
"name": "utopia-php/framework", "name": "utopia-php/framework",
"version": "0.9.7", "version": "0.9.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/framework.git", "url": "https://github.com/utopia-php/framework.git",
"reference": "20568f1325b4e38a43ef422a00e2271d5695a561" "reference": "4caec144554f028b3ec710a0cdd4f75193f01285"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/20568f1325b4e38a43ef422a00e2271d5695a561", "url": "https://api.github.com/repos/utopia-php/framework/zipball/4caec144554f028b3ec710a0cdd4f75193f01285",
"reference": "20568f1325b4e38a43ef422a00e2271d5695a561", "reference": "4caec144554f028b3ec710a0cdd4f75193f01285",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1374,7 +1373,7 @@
"php", "php",
"upf" "upf"
], ],
"time": "2020-10-29T12:25:16+00:00" "time": "2020-11-11T20:34:58+00:00"
}, },
{ {
"name": "utopia-php/locale", "name": "utopia-php/locale",
@ -1580,12 +1579,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/amphp/amp.git", "url": "https://github.com/amphp/amp.git",
"reference": "eb2f325586bc6ebb12d27834fc779fa140c38a57" "reference": "ecdc3c476b3ccff02f8e5d5bcc04f7ccfd18751c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/eb2f325586bc6ebb12d27834fc779fa140c38a57", "url": "https://api.github.com/repos/amphp/amp/zipball/ecdc3c476b3ccff02f8e5d5bcc04f7ccfd18751c",
"reference": "eb2f325586bc6ebb12d27834fc779fa140c38a57", "reference": "ecdc3c476b3ccff02f8e5d5bcc04f7ccfd18751c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1656,7 +1655,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-10T13:54:50+00:00" "time": "2020-11-03T16:23:45+00:00"
}, },
{ {
"name": "amphp/byte-stream", "name": "amphp/byte-stream",
@ -1736,7 +1735,7 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/appwrite/sdk-generator", "url": "https://github.com/appwrite/sdk-generator",
"reference": "11789d2169109f182dbc9d7cca91aba925582cf3" "reference": "e78d94eb1bc538e988d7e45afca7304a98ffc3f1"
}, },
"require": { "require": {
"ext-curl": "*", "ext-curl": "*",
@ -1766,7 +1765,7 @@
} }
], ],
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"time": "2020-10-31T19:31:23+00:00" "time": "2020-11-11T09:53:31+00:00"
}, },
{ {
"name": "composer/package-versions-deprecated", "name": "composer/package-versions-deprecated",
@ -1774,12 +1773,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git", "url": "https://github.com/composer/package-versions-deprecated.git",
"reference": "c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855" "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855", "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/7413f0b55a051e89485c5cb9f765fe24bb02a7b6",
"reference": "c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855", "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1835,7 +1834,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-08-25T05:50:16+00:00" "time": "2020-11-11T10:22:58+00:00"
}, },
{ {
"name": "composer/semver", "name": "composer/semver",
@ -2006,36 +2005,31 @@
}, },
{ {
"name": "doctrine/instantiator", "name": "doctrine/instantiator",
"version": "dev-master", "version": "1.5.x-dev",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/instantiator.git", "url": "https://github.com/doctrine/instantiator.git",
"reference": "3e7a22aed197e9333cc929e7f6b4300bdae91fcc" "reference": "6410c4b8352cb64218641457cef64997e6b784fb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/3e7a22aed197e9333cc929e7f6b4300bdae91fcc", "url": "https://api.github.com/repos/doctrine/instantiator/zipball/6410c4b8352cb64218641457cef64997e6b784fb",
"reference": "3e7a22aed197e9333cc929e7f6b4300bdae91fcc", "reference": "6410c4b8352cb64218641457cef64997e6b784fb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.1 || ^8.0" "php": "^7.1 || ^8.0"
}, },
"require-dev": { "require-dev": {
"doctrine/coding-standard": "^6.0", "doctrine/coding-standard": "^8.0",
"ext-pdo": "*", "ext-pdo": "*",
"ext-phar": "*", "ext-phar": "*",
"phpbench/phpbench": "^0.13", "phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
"phpstan/phpstan-phpunit": "^0.11", "phpstan/phpstan": "^0.12",
"phpstan/phpstan-shim": "^0.11", "phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.0" "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
@ -2049,7 +2043,7 @@
{ {
"name": "Marco Pivetta", "name": "Marco Pivetta",
"email": "ocramius@gmail.com", "email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/" "homepage": "https://ocramius.github.io/"
} }
], ],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
@ -2072,7 +2066,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-06-15T18:51:04+00:00" "time": "2020-11-10T19:05:51+00:00"
}, },
{ {
"name": "felixfbecker/advanced-json-rpc", "name": "felixfbecker/advanced-json-rpc",
@ -2795,12 +2789,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "7c0684ac5818c3a5a79d9dd9d85aac2aebdadb05" "reference": "5d66bde3afba51e21c6eb7d1a3776bd3b88dfafc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7c0684ac5818c3a5a79d9dd9d85aac2aebdadb05", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5d66bde3afba51e21c6eb7d1a3776bd3b88dfafc",
"reference": "7c0684ac5818c3a5a79d9dd9d85aac2aebdadb05", "reference": "5d66bde3afba51e21c6eb7d1a3776bd3b88dfafc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2860,7 +2854,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:10:23+00:00" "time": "2020-11-09T10:25:30+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@ -2868,12 +2862,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "437553634c79817d89b412cf2e6711ef1ccf6418" "reference": "854c530d02bcc6b5b96942e6e4cfeead11b35aad"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/437553634c79817d89b412cf2e6711ef1ccf6418", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/854c530d02bcc6b5b96942e6e4cfeead11b35aad",
"reference": "437553634c79817d89b412cf2e6711ef1ccf6418", "reference": "854c530d02bcc6b5b96942e6e4cfeead11b35aad",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2916,7 +2910,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:12:04+00:00" "time": "2020-11-09T10:26:59+00:00"
}, },
{ {
"name": "phpunit/php-invoker", "name": "phpunit/php-invoker",
@ -2924,12 +2918,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git", "url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "27560ee0808c5ba9144ad228887e788c608c8f58" "reference": "0cd572c9935a3a8373416e733ad1566d7c602ff1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/27560ee0808c5ba9144ad228887e788c608c8f58", "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/0cd572c9935a3a8373416e733ad1566d7c602ff1",
"reference": "27560ee0808c5ba9144ad228887e788c608c8f58", "reference": "0cd572c9935a3a8373416e733ad1566d7c602ff1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2975,7 +2969,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:12:14+00:00" "time": "2020-11-09T10:27:08+00:00"
}, },
{ {
"name": "phpunit/php-text-template", "name": "phpunit/php-text-template",
@ -2983,12 +2977,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git", "url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "2d6aa395e3f5a69ba3a5449d090cf7b845552081" "reference": "0d0bdf563575ba6715c5a6754541c80a9aa6dde2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/2d6aa395e3f5a69ba3a5449d090cf7b845552081", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0d0bdf563575ba6715c5a6754541c80a9aa6dde2",
"reference": "2d6aa395e3f5a69ba3a5449d090cf7b845552081", "reference": "0d0bdf563575ba6715c5a6754541c80a9aa6dde2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3030,7 +3024,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:12:53+00:00" "time": "2020-11-09T10:27:42+00:00"
}, },
{ {
"name": "phpunit/php-timer", "name": "phpunit/php-timer",
@ -3038,12 +3032,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git", "url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "735b06b2ce91f813d4574d0671a4e8165c8ece9c" "reference": "16bcf8ca6821c270f22794c02e50b8107cb375d8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/735b06b2ce91f813d4574d0671a4e8165c8ece9c", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/16bcf8ca6821c270f22794c02e50b8107cb375d8",
"reference": "735b06b2ce91f813d4574d0671a4e8165c8ece9c", "reference": "16bcf8ca6821c270f22794c02e50b8107cb375d8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3085,20 +3079,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:12:23+00:00" "time": "2020-11-09T10:27:16+00:00"
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "dev-master", "version": "9.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "abbb373dfdc7be1c77a1a700da67f28a7013d2e7" "reference": "3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/abbb373dfdc7be1c77a1a700da67f28a7013d2e7", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa",
"reference": "abbb373dfdc7be1c77a1a700da67f28a7013d2e7", "reference": "3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3114,7 +3108,7 @@
"phar-io/version": "^3.0.2", "phar-io/version": "^3.0.2",
"php": ">=7.3", "php": ">=7.3",
"phpspec/prophecy": "^1.12.1", "phpspec/prophecy": "^1.12.1",
"phpunit/php-code-coverage": "^9.2.3", "phpunit/php-code-coverage": "^9.2",
"phpunit/php-file-iterator": "^3.0.5", "phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1", "phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3", "phpunit/php-text-template": "^2.0.3",
@ -3145,7 +3139,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "9.5-dev" "dev-master": "9.4-dev"
} }
}, },
"autoload": { "autoload": {
@ -3184,7 +3178,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:20:26+00:00" "time": "2020-10-19T09:23:29+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",
@ -3241,12 +3235,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git", "url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "a8a95d7ddcf625e12c9eca502af7a2f72d6e3e7a" "reference": "0810c53718aa9ea7e42f2de2865a049ce3f5122f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/a8a95d7ddcf625e12c9eca502af7a2f72d6e3e7a", "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/0810c53718aa9ea7e42f2de2865a049ce3f5122f",
"reference": "a8a95d7ddcf625e12c9eca502af7a2f72d6e3e7a", "reference": "0810c53718aa9ea7e42f2de2865a049ce3f5122f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3285,7 +3279,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:13:23+00:00" "time": "2020-11-09T10:28:10+00:00"
}, },
{ {
"name": "sebastian/code-unit", "name": "sebastian/code-unit",
@ -3293,12 +3287,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git", "url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "97d3d265ae9e0692bc19553d0a28d2e99c6a13dc" "reference": "2af9894d3d514c2ee6d6ad03cc23bb4625050649"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/97d3d265ae9e0692bc19553d0a28d2e99c6a13dc", "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/2af9894d3d514c2ee6d6ad03cc23bb4625050649",
"reference": "97d3d265ae9e0692bc19553d0a28d2e99c6a13dc", "reference": "2af9894d3d514c2ee6d6ad03cc23bb4625050649",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3337,7 +3331,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:10:33+00:00" "time": "2020-11-09T10:25:39+00:00"
}, },
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
@ -3345,12 +3339,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "b7b8338be2131558c2eaeb0ec0b62ee3885181a8" "reference": "2f9aa793a37d4f39b5cf5ee3c9a1bd506885d60c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/b7b8338be2131558c2eaeb0ec0b62ee3885181a8", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/2f9aa793a37d4f39b5cf5ee3c9a1bd506885d60c",
"reference": "b7b8338be2131558c2eaeb0ec0b62ee3885181a8", "reference": "2f9aa793a37d4f39b5cf5ee3c9a1bd506885d60c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3388,7 +3382,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:10:42+00:00" "time": "2020-11-09T10:25:48+00:00"
}, },
{ {
"name": "sebastian/comparator", "name": "sebastian/comparator",
@ -3396,12 +3390,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git", "url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "169f358f64962df247708bb7a2974f04cd44f836" "reference": "6d3dc38d8631941ca18c76cac3d7a15838071693"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/169f358f64962df247708bb7a2974f04cd44f836", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6d3dc38d8631941ca18c76cac3d7a15838071693",
"reference": "169f358f64962df247708bb7a2974f04cd44f836", "reference": "6d3dc38d8631941ca18c76cac3d7a15838071693",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3458,7 +3452,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-31T09:38:51+00:00" "time": "2020-11-09T10:25:57+00:00"
}, },
{ {
"name": "sebastian/complexity", "name": "sebastian/complexity",
@ -3466,12 +3460,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git", "url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "3bd69c610bb8e2958f3289d1a9583514471b62e6" "reference": "cf04d6dfa8f99e37a677bf67195c43fc30024282"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/3bd69c610bb8e2958f3289d1a9583514471b62e6", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/cf04d6dfa8f99e37a677bf67195c43fc30024282",
"reference": "3bd69c610bb8e2958f3289d1a9583514471b62e6", "reference": "cf04d6dfa8f99e37a677bf67195c43fc30024282",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3511,7 +3505,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:13:03+00:00" "time": "2020-11-09T10:27:51+00:00"
}, },
{ {
"name": "sebastian/diff", "name": "sebastian/diff",
@ -3519,12 +3513,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/diff.git", "url": "https://github.com/sebastianbergmann/diff.git",
"reference": "7b02596262b190492663ff4df9227100f70c7823" "reference": "2c921642f8495dbf50fdcb920c425f9ccbb6a843"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7b02596262b190492663ff4df9227100f70c7823", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/2c921642f8495dbf50fdcb920c425f9ccbb6a843",
"reference": "7b02596262b190492663ff4df9227100f70c7823", "reference": "2c921642f8495dbf50fdcb920c425f9ccbb6a843",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3573,7 +3567,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:11:04+00:00" "time": "2020-11-09T10:26:06+00:00"
}, },
{ {
"name": "sebastian/environment", "name": "sebastian/environment",
@ -3581,12 +3575,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/environment.git", "url": "https://github.com/sebastianbergmann/environment.git",
"reference": "7a613938b2aa9c873233f810e6300bf06c42ca17" "reference": "6fe240eca4c1230f6442747269ff94234674f30e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/7a613938b2aa9c873233f810e6300bf06c42ca17", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6fe240eca4c1230f6442747269ff94234674f30e",
"reference": "7a613938b2aa9c873233f810e6300bf06c42ca17", "reference": "6fe240eca4c1230f6442747269ff94234674f30e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3632,7 +3626,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:11:15+00:00" "time": "2020-11-09T10:26:15+00:00"
}, },
{ {
"name": "sebastian/exporter", "name": "sebastian/exporter",
@ -3640,12 +3634,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git", "url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "33fcbffef7131af7ee4ad12f52bf6a3d02124557" "reference": "04229817d2bb369fa6b25229316e7bbc53baece2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/33fcbffef7131af7ee4ad12f52bf6a3d02124557", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/04229817d2bb369fa6b25229316e7bbc53baece2",
"reference": "33fcbffef7131af7ee4ad12f52bf6a3d02124557", "reference": "04229817d2bb369fa6b25229316e7bbc53baece2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3705,7 +3699,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:11:24+00:00" "time": "2020-11-09T10:26:24+00:00"
}, },
{ {
"name": "sebastian/global-state", "name": "sebastian/global-state",
@ -3713,12 +3707,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git", "url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "e9696869db3ba851de7221f4d6997b4262b623d9" "reference": "bae2a2a7c5dac8eb4ab11e178fcd88242c1f8b17"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e9696869db3ba851de7221f4d6997b4262b623d9", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bae2a2a7c5dac8eb4ab11e178fcd88242c1f8b17",
"reference": "e9696869db3ba851de7221f4d6997b4262b623d9", "reference": "bae2a2a7c5dac8eb4ab11e178fcd88242c1f8b17",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3765,7 +3759,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:11:34+00:00" "time": "2020-11-09T10:26:33+00:00"
}, },
{ {
"name": "sebastian/lines-of-code", "name": "sebastian/lines-of-code",
@ -3773,12 +3767,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git", "url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "edc91041d25e5f667f5adf1deb0f96a11153575e" "reference": "62f65495957a0d4b39045a059bbf8d6d74db06f5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/edc91041d25e5f667f5adf1deb0f96a11153575e", "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/62f65495957a0d4b39045a059bbf8d6d74db06f5",
"reference": "edc91041d25e5f667f5adf1deb0f96a11153575e", "reference": "62f65495957a0d4b39045a059bbf8d6d74db06f5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3818,7 +3812,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:13:13+00:00" "time": "2020-11-09T10:28:00+00:00"
}, },
{ {
"name": "sebastian/object-enumerator", "name": "sebastian/object-enumerator",
@ -3826,12 +3820,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git", "url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "d913c474aa28f6646d5a899d18b546a9d8a94134" "reference": "bd926d4c9372e89f8eeff4d3e1d46886b3647959"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d913c474aa28f6646d5a899d18b546a9d8a94134", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/bd926d4c9372e89f8eeff4d3e1d46886b3647959",
"reference": "d913c474aa28f6646d5a899d18b546a9d8a94134", "reference": "bd926d4c9372e89f8eeff4d3e1d46886b3647959",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3871,7 +3865,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:11:44+00:00" "time": "2020-11-09T10:26:42+00:00"
}, },
{ {
"name": "sebastian/object-reflector", "name": "sebastian/object-reflector",
@ -3879,12 +3873,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git", "url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "4acdc9cb8f4eae4da631c414ece1fff21d3578b0" "reference": "2ae863c8667f2c149b20d13782d11ce23ab995f8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4acdc9cb8f4eae4da631c414ece1fff21d3578b0", "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/2ae863c8667f2c149b20d13782d11ce23ab995f8",
"reference": "4acdc9cb8f4eae4da631c414ece1fff21d3578b0", "reference": "2ae863c8667f2c149b20d13782d11ce23ab995f8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3922,7 +3916,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:11:55+00:00" "time": "2020-11-09T10:26:50+00:00"
}, },
{ {
"name": "sebastian/recursion-context", "name": "sebastian/recursion-context",
@ -3930,12 +3924,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git", "url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "d09a5073917f11f0b1e2dce2443d91acb50d0671" "reference": "4c073073e68e3d2d5dd7a50ebfc53a912116b498"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/d09a5073917f11f0b1e2dce2443d91acb50d0671", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/4c073073e68e3d2d5dd7a50ebfc53a912116b498",
"reference": "d09a5073917f11f0b1e2dce2443d91acb50d0671", "reference": "4c073073e68e3d2d5dd7a50ebfc53a912116b498",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3981,7 +3975,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:12:33+00:00" "time": "2020-11-09T10:27:25+00:00"
}, },
{ {
"name": "sebastian/resource-operations", "name": "sebastian/resource-operations",
@ -4040,12 +4034,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/type.git", "url": "https://github.com/sebastianbergmann/type.git",
"reference": "d6eb978632b7b77cad85a9a655e5c3dbb9c7100c" "reference": "dcac0d6b8489ed9975d01303f0903958ebad0ce4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/d6eb978632b7b77cad85a9a655e5c3dbb9c7100c", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/dcac0d6b8489ed9975d01303f0903958ebad0ce4",
"reference": "d6eb978632b7b77cad85a9a655e5c3dbb9c7100c", "reference": "dcac0d6b8489ed9975d01303f0903958ebad0ce4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4084,7 +4078,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-30T14:12:43+00:00" "time": "2020-11-09T10:27:33+00:00"
}, },
{ {
"name": "sebastian/version", "name": "sebastian/version",
@ -4175,12 +4169,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "5164210f240d580ce0f490a7f24827c6fbc7bc36" "reference": "d1d8b8fd9b605630aa73b1b384e246fee54e8ffa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5164210f240d580ce0f490a7f24827c6fbc7bc36", "url": "https://api.github.com/repos/symfony/console/zipball/d1d8b8fd9b605630aa73b1b384e246fee54e8ffa",
"reference": "5164210f240d580ce0f490a7f24827c6fbc7bc36", "reference": "d1d8b8fd9b605630aa73b1b384e246fee54e8ffa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4261,7 +4255,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-11-01T17:40:07+00:00" "time": "2020-11-05T20:05:54+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@ -4940,12 +4934,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "b163c7f71698165ccf13738ac77273b40d5776f8" "reference": "e133d1fd8c9f22dd9bc43d1b7fc46e0f35692226"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/b163c7f71698165ccf13738ac77273b40d5776f8", "url": "https://api.github.com/repos/twigphp/Twig/zipball/e133d1fd8c9f22dd9bc43d1b7fc46e0f35692226",
"reference": "b163c7f71698165ccf13738ac77273b40d5776f8", "reference": "e133d1fd8c9f22dd9bc43d1b7fc46e0f35692226",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5007,20 +5001,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-10-27T19:26:34+00:00" "time": "2020-11-09T13:33:24+00:00"
}, },
{ {
"name": "vimeo/psalm", "name": "vimeo/psalm",
"version": "4.0.1", "version": "4.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/vimeo/psalm.git", "url": "https://github.com/vimeo/psalm.git",
"reference": "b1e2e30026936ef8d5bf6a354d1c3959b6231f44" "reference": "16bfbd9224698bd738c665f33039fade2a1a3977"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/b1e2e30026936ef8d5bf6a354d1c3959b6231f44", "url": "https://api.github.com/repos/vimeo/psalm/zipball/16bfbd9224698bd738c665f33039fade2a1a3977",
"reference": "b1e2e30026936ef8d5bf6a354d1c3959b6231f44", "reference": "16bfbd9224698bd738c665f33039fade2a1a3977",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5041,10 +5035,9 @@
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0",
"nikic/php-parser": "^4.10.1", "nikic/php-parser": "^4.10.1",
"openlss/lib-array2xml": "^1.0", "openlss/lib-array2xml": "^1.0",
"php": "^7.3|^8", "php": "^7.1|^8",
"sebastian/diff": "^3.0 || ^4.0", "sebastian/diff": "^3.0 || ^4.0",
"symfony/console": "^3.4.17 || ^4.1.6 || ^5.0", "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0",
"webmozart/glob": "^4.1",
"webmozart/path-util": "^2.3" "webmozart/path-util": "^2.3"
}, },
"provide": { "provide": {
@ -5055,6 +5048,7 @@
"bamarni/composer-bin-plugin": "^1.2", "bamarni/composer-bin-plugin": "^1.2",
"brianium/paratest": "^4.0.0", "brianium/paratest": "^4.0.0",
"ext-curl": "*", "ext-curl": "*",
"php": "^7.3|^8",
"phpdocumentor/reflection-docblock": "^5", "phpdocumentor/reflection-docblock": "^5",
"phpmyadmin/sql-parser": "5.1.0", "phpmyadmin/sql-parser": "5.1.0",
"phpspec/prophecy": ">=1.9.0", "phpspec/prophecy": ">=1.9.0",
@ -5108,7 +5102,7 @@
"inspection", "inspection",
"php" "php"
], ],
"time": "2020-10-20T13:40:17+00:00" "time": "2020-11-02T05:54:12+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
@ -5159,53 +5153,6 @@
], ],
"time": "2020-07-08T17:02:28+00:00" "time": "2020-07-08T17:02:28+00:00"
}, },
{
"name": "webmozart/glob",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/webmozart/glob.git",
"reference": "8da14867b709e8776d9f6272faaf844aefc695e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/glob/zipball/8da14867b709e8776d9f6272faaf844aefc695e3",
"reference": "8da14867b709e8776d9f6272faaf844aefc695e3",
"shasum": ""
},
"require": {
"php": "^5.3.3|^7.0",
"webmozart/path-util": "^2.2"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1",
"symfony/filesystem": "^2.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Glob\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A PHP implementation of Ant's glob.",
"time": "2016-08-15T15:31:26+00:00"
},
{ {
"name": "webmozart/path-util", "name": "webmozart/path-util",
"version": "dev-master", "version": "dev-master",

View file

@ -82,6 +82,11 @@ services:
- _APP_DB_SCHEMA - _APP_DB_SCHEMA
- _APP_DB_USER - _APP_DB_USER
- _APP_DB_PASS - _APP_DB_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
- _APP_SMTP_USERNAME
- _APP_SMTP_PASSWORD
- _APP_INFLUXDB_HOST - _APP_INFLUXDB_HOST
- _APP_INFLUXDB_PORT - _APP_INFLUXDB_PORT
- _APP_STORAGE_LIMIT - _APP_STORAGE_LIMIT
@ -306,24 +311,6 @@ services:
command: 'mysqld --innodb-flush-method=fsync' # add ' --query_cache_size=0' for DB tests command: 'mysqld --innodb-flush-method=fsync' # add ' --query_cache_size=0' for DB tests
# command: mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bu && mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bu # command: mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bu && mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bu
maildev: # used mainly for dev tests
image: djfarrelly/maildev
container_name: appwrite-maildev
restart: unless-stopped
ports:
- '1080:80'
networks:
- appwrite
request-catcher: # used mainly for dev tests
image: smarterdm/http-request-catcher
container_name: appwrite-request-catcher
restart: unless-stopped
ports:
- '5000:5000'
networks:
- appwrite
# smtp: # smtp:
# image: appwrite/smtp:1.2.0 # image: appwrite/smtp:1.2.0
# container_name: appwrite-smtp # container_name: appwrite-smtp
@ -370,6 +357,24 @@ services:
networks: networks:
- appwrite - appwrite
maildev: # used mainly for dev tests
image: djfarrelly/maildev
container_name: appwrite-maildev
restart: unless-stopped
ports:
- '1080:80'
networks:
- appwrite
request-catcher: # used mainly for dev tests
image: smarterdm/http-request-catcher
container_name: appwrite-request-catcher
restart: unless-stopped
ports:
- '5000:5000'
networks:
- appwrite
# redis-commander: # redis-commander:
# image: rediscommander/redis-commander:latest # image: rediscommander/redis-commander:latest
# restart: unless-stopped # restart: unless-stopped

View file

@ -1 +1 @@
Use this endpoint to fetch the favorite icon (AKA favicon) of a any remote website URL. Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,25 +1,3 @@
<?xml version="1.0" standalone="no"?> <svg height="100" width="100">
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" <circle cx="50" cy="50" r="40" fill="#c9c9c9" />
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> </svg>
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,1024.000000) scale(0.100000,-0.100000)"
fill="#96b7eb" stroke="none">
<path d="M5000 10143 c-904 -20 -1805 -293 -2565 -776 -1163 -740 -1970 -1911
-2240 -3252 -68 -337 -96 -634 -96 -1000 0 -483 55 -896 180 -1350 268 -971
836 -1854 1609 -2501 868 -726 1911 -1129 3032 -1173 700 -27 1388 85 2020
331 1324 514 2364 1554 2878 2878 197 508 309 1052 331 1610 42 1074 -243
2099 -830 2983 -742 1118 -1887 1889 -3194 2152 -354 71 -756 106 -1125 98z
m375 -673 c778 -48 1359 -279 1826 -728 377 -361 594 -768 676 -1267 25 -156
25 -525 -1 -680 -36 -221 -88 -386 -182 -583 -175 -368 -480 -723 -1099 -1281
-310 -279 -556 -524 -649 -647 -84 -111 -194 -331 -235 -474 -51 -175 -81
-419 -97 -803 l-7 -157 -506 2 -506 3 1 300 c1 508 55 822 199 1160 175 408
417 696 1105 1316 645 582 814 806 890 1181 39 188 26 461 -31 653 -122 415
-477 811 -894 997 -252 113 -552 162 -849 138 -373 -29 -659 -142 -929 -368
-301 -253 -521 -690 -621 -1237 -19 -103 -25 -120 -42 -122 -10 -2 -253 26
-539 60 l-520 62 3 60 c3 73 43 289 83 447 98 390 273 757 497 1043 84 107
305 322 417 405 120 90 277 185 402 245 446 213 1020 311 1608 275z m355
-8130 l0 -600 -600 0 -600 0 0 600 0 600 600 0 600 0 0 -600z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 88 B

View file

@ -29,7 +29,7 @@
--config-color-success: #1bbf61; --config-color-success: #1bbf61;
--config-color-warning: #ffed4d; --config-color-warning: #ffed4d;
--config-color-info: #386fd2; --config-color-info: #386fd2;
--config-border-color: #f5f5f5; --config-border-color: #f3f3f3;
--config-border-fade: #e0e3e4; --config-border-fade: #e0e3e4;
--config-border-radius: 10px; --config-border-radius: 10px;
--config-prism-background: #373738; --config-prism-background: #373738;

View file

@ -23,7 +23,6 @@ class Auth
const USER_ROLE_OWNER = 4; const USER_ROLE_OWNER = 4;
const USER_ROLE_APP = 5; const USER_ROLE_APP = 5;
const USER_ROLE_SYSTEM = 6; const USER_ROLE_SYSTEM = 6;
const USER_ROLE_ALL = '*';
/** /**
* Token Types. * Token Types.
@ -49,9 +48,9 @@ class Auth
/** /**
* User Unique ID. * User Unique ID.
* *
* @var int * @var string
*/ */
public static $unique = 0; public static $unique = '';
/** /**
* User Secret Key. * User Secret Key.
@ -75,7 +74,7 @@ class Auth
/** /**
* Encode Session. * Encode Session.
* *
* @param int $id * @param string $id
* @param string $secret * @param string $secret
* *
* @return string * @return string
@ -206,4 +205,40 @@ class Auth
return false; return false;
} }
/**
* Is Previligged User?
*
* @param array $roles
*
* @return bool
*/
public static function isPreviliggedUser(array $roles): bool
{
if(
array_key_exists('role:'.self::USER_ROLE_OWNER, $roles) ||
array_key_exists('role:'.self::USER_ROLE_DEVELOPER, $roles) ||
array_key_exists('role:'.self::USER_ROLE_ADMIN, $roles)
) {
return true;
}
return false;
}
/**
* Is App User?
*
* @param array $roles
*
* @return bool
*/
public static function isAppUser(array $roles): bool
{
if(array_key_exists('role:'.self::USER_ROLE_APP, $roles)) {
return true;
}
return false;
}
} }

View file

@ -455,13 +455,28 @@ class Database
foreach ($rules as $key => $rule) { foreach ($rules as $key => $rule) {
$key = $rule->getAttribute('key', null); $key = $rule->getAttribute('key', null);
$filters = $rule->getAttribute('filter', null); $type = $rule->getAttribute('type', null);
$array = $rule->getAttribute('array', false);
$filters = $rule->getAttribute('filter', []);
$value = $document->getAttribute($key, null); $value = $document->getAttribute($key, null);
if (($value !== null) && is_array($filters)) { if (($value !== null)) {
foreach ($filters as $filter) { if ($type === self::SYSTEM_VAR_TYPE_DOCUMENT) {
$value = $this->encodeAttribute($filter, $value); if($array) {
$document->setAttribute($key, $value); $list = [];
foreach ($value as $child) {
$list[] = $this->encode($child);
}
$document->setAttribute($key, $list);
} else {
$document->setAttribute($key, $this->encode($value));
}
} else {
foreach ($filters as $filter) {
$value = $this->encodeAttribute($filter, $value);
$document->setAttribute($key, $value);
}
} }
} }
} }
@ -476,13 +491,28 @@ class Database
foreach ($rules as $key => $rule) { foreach ($rules as $key => $rule) {
$key = $rule->getAttribute('key', null); $key = $rule->getAttribute('key', null);
$filters = $rule->getAttribute('filter', null); $type = $rule->getAttribute('type', null);
$array = $rule->getAttribute('array', false);
$filters = $rule->getAttribute('filter', []);
$value = $document->getAttribute($key, null); $value = $document->getAttribute($key, null);
if (($value !== null) && is_array($filters)) { if (($value !== null)) {
foreach (array_reverse($filters) as $filter) { if ($type === self::SYSTEM_VAR_TYPE_DOCUMENT) {
$value = $this->decodeAttribute($filter, $value); if($array) {
$document->setAttribute($key, $value); $list = [];
foreach ($value as $child) {
$list[] = $this->decode($child);
}
$document->setAttribute($key, $list);
} else {
$document->setAttribute($key, $this->decode($value));
}
} else {
foreach (array_reverse($filters) as $filter) {
$value = $this->decodeAttribute($filter, $value);
$document->setAttribute($key, $value);
}
} }
} }
} }
@ -499,6 +529,7 @@ class Database
static protected function encodeAttribute(string $name, $value) static protected function encodeAttribute(string $name, $value)
{ {
if (!isset(self::$filters[$name])) { if (!isset(self::$filters[$name])) {
return $value;
throw new Exception('Filter not found'); throw new Exception('Filter not found');
} }
@ -520,6 +551,7 @@ class Database
static protected function decodeAttribute(string $name, $value) static protected function decodeAttribute(string $name, $value)
{ {
if (!isset(self::$filters[$name])) { if (!isset(self::$filters[$name])) {
return $value;
throw new Exception('Filter not found'); throw new Exception('Filter not found');
} }

View file

@ -10,7 +10,7 @@ class Authorization extends Validator
/** /**
* @var array * @var array
*/ */
static $roles = ['*']; static $roles = ['*' => true];
/** /**
* @var Document * @var Document
@ -77,7 +77,7 @@ class Authorization extends Validator
foreach ($permissions[$this->action] as $permission) { foreach ($permissions[$this->action] as $permission) {
$permission = \str_replace(':{self}', ':'.$this->document->getId(), $permission); $permission = \str_replace(':{self}', ':'.$this->document->getId(), $permission);
if (\in_array($permission, self::getRoles())) { if (\array_key_exists($permission, self::$roles)) {
return true; return true;
} }
} }
@ -92,17 +92,35 @@ class Authorization extends Validator
* *
* @return void * @return void
*/ */
public static function setRole($role): void public static function setRole(string $role): void
{ {
self::$roles[] = $role; self::$roles[$role] = true;
} }
/** /**
* @return array * @return array
*/ */
public static function getRoles() public static function getRoles(): array
{ {
return self::$roles; return \array_keys(self::$roles);
}
/**
* @return void
*/
public static function cleanRoles(): void
{
self::$roles = [];
}
/**
* @param string $role
*
* @return bool
*/
public static function isRole(string $role): bool
{
return (\array_key_exists($role, self::$roles));
} }
/** /**

View file

@ -0,0 +1,124 @@
<?php
namespace Appwrite\Specification;
use Utopia\App;
use Utopia\Route;
use Appwrite\Utopia\Response\Model;
abstract class Format
{
/**
* @var App
*/
protected $app;
/**
* @var Route[]
*/
protected $routes;
/**
* @var Model[]
*/
protected $models;
/**
* @var array
*/
protected $keys;
/**
* @var array
*/
protected $security;
/**
* @var array
*/
protected $params = [
'name' => '',
'description' => '',
'endpoint' => 'https://localhost',
'version' => '1.0.0',
'terms' => '',
'support.email' => '',
'support.url' => '',
'contact.name' => '',
'contact.email' => '',
'contact.url' => '',
'license.name' => '',
'license.url' => '',
];
/**
* @param App $app
* @param Route[] $routes
* @param Model[] $models
* @param array $keys
* @param array $security
*/
public function __construct(App $app, array $routes, array $models, array $keys, array $security)
{
$this->app = $app;
$this->routes = $routes;
$this->models = $models;
$this->keys = $keys;
$this->security = $security;
}
/**
* Get Name.
*
* Get format name
*
* @return string
*/
abstract public function getName(): string;
/**
* Parse
*
* Parses Appwrite App to given format
*
* @return array
*/
abstract public function parse(): array;
/**
* Set Param.
*
* Set param value
*
* @param string $key
* @param string $value
*
* @return self
*/
public function setParam(string $key, string $value): self
{
$this->params[$key] = $value;
return $this;
}
/**
* Get Param.
*
* Get param value
*
* @param string $key
* @param string $default
*
* @return string
*/
public function getParam(string $key, string $default = ''): string
{
if(!isset($this->params[$key])) {
return $default;
}
return $this->params[$key];
}
}

View file

@ -0,0 +1,403 @@
<?php
namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format;
use Appwrite\Template\Template;
class OpenAPI3 extends Format
{
/**
* Get Name.
*
* Get format name
*
* @return string
*/
public function getName():string
{
return 'Open API 3';
}
/**
* Parse
*
* Parses Appwrite App to given format
*
* @return array
*/
public function parse(): array
{
/*
* Specifications (v3.0.0):
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
*/
$output = [
'openapi' => '3.0.0',
'info' => [
'version' => $this->getParam('version'),
'title' => $this->getParam('name'),
'description' => $this->getParam('description'),
'termsOfService' => $this->getParam('terms'),
'contact' => [
'name' => $this->getParam('contact.name'),
'url' => $this->getParam('contact.url'),
'email' => $this->getParam('contact.email'),
],
'license' => [
'name' => 'BSD-3-Clause',
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
],
],
'servers' => [
[
'url' => $this->getParam('endpoint', ''),
],
],
'paths' => [],
'components' => [
'schemas' => [],
'securitySchemes' => $this->keys,
],
'externalDocs' => [
'description' => $this->getParam('docs.description'),
'url' => $this->getParam('docs.url'),
],
];
if (isset($output['components']['securitySchemes']['Project'])) {
$output['components']['securitySchemes']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
}
if (isset($output['components']['securitySchemes']['Key'])) {
$output['components']['securitySchemes']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
}
if (isset($output['components']['securitySchemes']['Locale'])) {
$output['components']['securitySchemes']['Locale']['x-appwrite'] = ['demo' => 'en'];
}
if (isset($output['components']['securitySchemes']['Mode'])) {
$output['components']['securitySchemes']['Mode']['x-appwrite'] = ['demo' => ''];
}
foreach ($this->routes as $route) { /* @var $route \Utopia\Route */
$url = \str_replace('/v1', '', $route->getURL());
$scope = $route->getLabel('scope', '');
$hide = $route->getLabel('sdk.hide', false);
$consumes = [$route->getLabel('sdk.request.type', 'application/json')];
if ($hide) {
continue;
}
$id = $route->getLabel('sdk.method', \uniqid());
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null;
$produces = $route->getLabel('sdk.response.type', 'application/json');
$model = $route->getLabel('sdk.response.model', 'none');
$temp = [
'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id),
// 'consumes' => [],
// 'produces' => [$produces],
'tags' => [$route->getLabel('sdk.namespace', 'default')],
'description' => ($desc) ? \file_get_contents($desc) : '',
'responses' => [],
'x-appwrite' => [ // Appwrite related metadata
'method' => $route->getLabel('sdk.method', \uniqid()),
'weight' => $route->getOrder(),
'cookies' => $route->getLabel('sdk.cookies', false),
'type' => $route->getLabel('sdk.methodType', ''),
'demo' => 'docs/examples/'. Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md',
'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''),
'rate-limit' => $route->getLabel('abuse-limit', 0),
'rate-time' => $route->getLabel('abuse-time', 3600),
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
'scope' => $route->getLabel('scope', ''),
'platforms' => $route->getLabel('sdk.platform', []),
],
];
foreach ($this->models as $key => $value) {
if($value->getType() === $model) {
$model = $value;
break;
}
}
if($model->isNone()) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => (in_array($produces, [
'image/*',
'image/jpeg',
'image/gif',
'image/png',
'image/webp',
'image/svg-x',
'image/x-icon',
'image/bmp',
])) ? 'Image' : 'File',
// 'schema' => [
// 'type' => 'file'
// ],
];
} else {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
'content' => [
$produces => [
'schema' => [
'$ref' => '#/components/schemas/'.$model->getType(),
],
],
],
];
}
if($route->getLabel('sdk.response.code', 500) === 204) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content';
unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']);
}
if ((!empty($scope))) { // && 'public' != $scope
$temp['security'][] = $route->getLabel('sdk.security', $this->security);
}
$body = [
'content' => [
$consumes[0] => [
'schema' => [
'type' => 'object',
'properties' => [],
],
],
],
];
$bodyRequired = [];
foreach ($route->getParams() as $name => $param) { // Set params
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['resources'])) : $param['validator']; /* @var $validator \Utopia\Validator */
$node = [
'name' => $name,
'description' => $param['description'],
'required' => !$param['optional'],
];
switch ((!empty($validator)) ? \get_class($validator) : '') {
case 'Utopia\Validator\Text':
$node['schema']['type'] = 'string';
$node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
break;
case 'Utopia\Validator\Boolean':
$node['schema']['type'] = 'boolean';
$node['schema']['x-example'] = false;
break;
case 'Appwrite\Database\Validator\UID':
$node['schema']['type'] = 'string';
$node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
break;
case 'Utopia\Validator\Email':
$node['schema']['type'] = 'string';
$node['schema']['format'] = 'email';
$node['schema']['x-example'] = 'email@example.com';
break;
case 'Utopia\Validator\URL':
$node['schema']['type'] = 'string';
$node['schema']['format'] = 'url';
$node['schema']['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\JSON':
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$node['schema']['type'] = 'object';
$node['schema']['type'] = 'object';
$node['schema']['x-example'] = '{}';
//$node['schema']['format'] = 'json';
break;
case 'Appwrite\Storage\Validator\File':
$consumes = ['multipart/form-data'];
$node['schema']['type'] = 'string';
$node['schema']['format'] = 'binary';
break;
case 'Utopia\Validator\ArrayList':
$node['schema']['type'] = 'array';
$node['schema']['items'] = [
'type' => 'string',
];
break;
case 'Appwrite\Auth\Validator\Password':
$node['schema']['type'] = 'string';
$node['schema']['format'] = 'format';
$node['schema']['x-example'] = 'password';
break;
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
$node['schema']['type'] = 'integer';
$node['schema']['format'] = 'int32';
$node['schema']['x-example'] = $validator->getMin();
break;
case 'Utopia\Validator\Numeric':
$node['schema']['type'] = 'integer';
$node['schema']['format'] = 'int32';
break;
case 'Utopia\Validator\Length':
$node['schema']['type'] = 'string';
break;
case 'Utopia\Validator\Host':
$node['schema']['type'] = 'string';
$node['schema']['format'] = 'url';
$node['schema']['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
$node['schema']['type'] = 'string';
$node['schema']['x-example'] = $validator->getList()[0];
break;
default:
$node['schema']['type'] = 'string';
break;
}
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
$node['schema']['default'] = $param['default'];
}
if (false !== \strpos($url, ':'.$name)) { // Param is in URL path
$node['in'] = 'path';
$temp['parameters'][] = $node;
} elseif ($route->getMethod() == 'GET') { // Param is in query
$node['in'] = 'query';
$temp['parameters'][] = $node;
} else { // Param is in payload
if(!$param['optional']) {
$bodyRequired[] = $name;
}
$body['content'][$consumes[0]]['schema']['properties'][$name] = [
'type' => $node['schema']['type'],
'description' => $node['description'],
'x-example' => $node['x-example'] ?? null,
];
if(isset($node['default'])) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['default'] = $node['default'];
}
if(\array_key_exists('items', $node['schema'])) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['items'] = $node['schema']['items'];
}
}
$url = \str_replace(':'.$name, '{'.$name.'}', $url);
}
if(!empty($bodyRequired)) {
$body['content'][$consumes[0]]['schema']['required'] = $bodyRequired;
}
if(!empty($body['content'][$consumes[0]]['schema']['properties'])) {
$temp['requestBody'] = $body;
}
//$temp['consumes'] = $consumes;
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
foreach ($this->models as $model) {
$required = $model->getRequired();
$rules = $model->getRules();
$output['components']['schemas'][$model->getType()] = [
'description' => $model->getName(),
'type' => 'object',
];
if(!empty($rules)) {
$output['components']['schemas'][$model->getType()]['properties'] = [];
}
if($model->isAny()) {
$output['components']['schemas'][$model->getType()]['additionalProperties'] = true;
}
if(!empty($required)) {
$output['components']['schemas'][$model->getType()]['required'] = $required;
}
foreach($model->getRules() as $name => $rule) {
$type = '';
$format = null;
$items = null;
switch ($rule['type']) {
case 'string':
case 'json':
$type = 'string';
break;
case 'integer':
$type = 'integer';
$format = 'int32';
break;
case 'float':
$type = 'number';
$format = 'float';
break;
case 'boolean':
$type = 'boolean';
break;
default:
$type = 'object';
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
$items = [
'$ref' => '#/components/schemas/'.$rule['type'],
];
break;
}
if($rule['array']) {
$output['components']['schemas'][$model->getType()]['properties'][$name] = [
'type' => 'array',
'description' => $rule['description'] ?? '',
'items' => [
'type' => $type,
]
];
if($format) {
$output['components']['schemas'][$model->getType()]['properties'][$name]['items']['format'] = $format;
}
if($items) {
$output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items;
}
} else {
$output['components']['schemas'][$model->getType()]['properties'][$name] = [
'type' => $type,
'description' => $rule['description'] ?? '',
//'default' => $rule['default'] ?? null,
'x-example' => $rule['example'] ?? null,
];
if($format) {
$output['components']['schemas'][$model->getType()]['properties'][$name]['format'] = $format;
}
if($items) {
$output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items;
}
}
}
}
\ksort($output['paths']);
return $output;
}
}

View file

@ -0,0 +1,401 @@
<?php
namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format;
use Appwrite\Template\Template;
class Swagger2 extends Format
{
/**
* Get Name.
*
* Get format name
*
* @return string
*/
public function getName():string
{
return 'Swagger 2';
}
/**
* Parse
*
* Parses Appwrite App to given format
*
* @return array
*/
public function parse(): array
{
/*
* Specifications (v3.0.0):
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
*/
$output = [
'swagger' => '2.0',
'info' => [
'version' => $this->getParam('version'),
'title' => $this->getParam('name'),
'description' => $this->getParam('description'),
'termsOfService' => $this->getParam('terms'),
'contact' => [
'name' => $this->getParam('contact.name'),
'url' => $this->getParam('contact.url'),
'email' => $this->getParam('contact.email'),
],
'license' => [
'name' => 'BSD-3-Clause',
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
],
],
'host' => \parse_url($this->getParam('endpoint', ''), PHP_URL_HOST),
'basePath' => \parse_url($this->getParam('endpoint', ''), PHP_URL_PATH),
'schemes' => [\parse_url($this->getParam('endpoint', ''), PHP_URL_SCHEME)],
'consumes' => ['application/json', 'multipart/form-data'],
'produces' => ['application/json'],
'securityDefinitions' => $this->keys,
'paths' => [],
'definitions' => [],
'externalDocs' => [
'description' => $this->getParam('docs.description'),
'url' => $this->getParam('docs.url'),
],
];
if (isset($output['securityDefinitions']['Project'])) {
$output['securityDefinitions']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
}
if (isset($output['securityDefinitions']['Key'])) {
$output['securityDefinitions']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
}
if (isset($output['securityDefinitions']['Locale'])) {
$output['securityDefinitions']['Locale']['x-appwrite'] = ['demo' => 'en'];
}
if (isset($output['securityDefinitions']['Mode'])) {
$output['securityDefinitions']['Mode']['x-appwrite'] = ['demo' => ''];
}
foreach ($this->routes as $route) { /* @var $route \Utopia\Route */
$url = \str_replace('/v1', '', $route->getURL());
$scope = $route->getLabel('scope', '');
$hide = $route->getLabel('sdk.hide', false);
$consumes = [$route->getLabel('sdk.request.type', 'application/json')];
if ($hide) {
continue;
}
$id = $route->getLabel('sdk.method', \uniqid());
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null;
$produces = $route->getLabel('sdk.response.type', 'application/json');
$model = $route->getLabel('sdk.response.model', 'none');
$temp = [
'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id),
'consumes' => [],
'produces' => [$produces],
'tags' => [$route->getLabel('sdk.namespace', 'default')],
'description' => ($desc) ? \file_get_contents($desc) : '',
'responses' => [],
'x-appwrite' => [ // Appwrite related metadata
'method' => $route->getLabel('sdk.method', \uniqid()),
'weight' => $route->getOrder(),
'cookies' => $route->getLabel('sdk.cookies', false),
'type' => $route->getLabel('sdk.methodType', ''),
'demo' => 'docs/examples/'. Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md',
'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''),
'rate-limit' => $route->getLabel('abuse-limit', 0),
'rate-time' => $route->getLabel('abuse-time', 3600),
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
'scope' => $route->getLabel('scope', ''),
'platforms' => $route->getLabel('sdk.platform', []),
],
];
foreach ($this->models as $key => $value) {
if($value->getType() === $model) {
$model = $value;
break;
}
}
if($model->isNone()) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => (in_array($produces, [
'image/*',
'image/jpeg',
'image/gif',
'image/png',
'image/webp',
'image/svg-x',
'image/x-icon',
'image/bmp',
])) ? 'Image' : 'File',
'schema' => [
'type' => 'file'
],
];
} else {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
'schema' => [
'$ref' => '#/definitions/'.$model->getType(),
],
];
}
if($route->getLabel('sdk.response.code', 500) === 204) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content';
unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']);
}
if ((!empty($scope))) { // && 'public' != $scope
$temp['security'][] = $route->getLabel('sdk.security', $this->security);
}
$body = [
'name' => 'payload',
'in' => 'body',
'schema' => [
'type' => 'object',
'properties' => [],
],
];
$bodyRequired = [];
foreach ($route->getParams() as $name => $param) { // Set params
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['resources'])) : $param['validator']; /* @var $validator \Utopia\Validator */
$node = [
'name' => $name,
'description' => $param['description'],
'required' => !$param['optional'],
];
switch ((!empty($validator)) ? \get_class($validator) : '') {
case 'Utopia\Validator\Text':
$node['type'] = 'string';
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
break;
case 'Utopia\Validator\Boolean':
$node['type'] = 'boolean';
$node['x-example'] = false;
break;
case 'Appwrite\Database\Validator\UID':
$node['type'] = 'string';
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
break;
case 'Utopia\Validator\Email':
$node['type'] = 'string';
$node['format'] = 'email';
$node['x-example'] = 'email@example.com';
break;
case 'Utopia\Validator\URL':
$node['type'] = 'string';
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\JSON':
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$node['type'] = 'object';
$node['type'] = 'object';
$node['x-example'] = '{}';
//$node['format'] = 'json';
break;
case 'Appwrite\Storage\Validator\File':
$consumes = ['multipart/form-data'];
$node['type'] = 'file';
break;
case 'Utopia\Validator\ArrayList':
$node['type'] = 'array';
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => 'string',
];
break;
case 'Appwrite\Auth\Validator\Password':
$node['type'] = 'string';
$node['format'] = 'format';
$node['x-example'] = 'password';
break;
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
$node['type'] = 'integer';
$node['format'] = 'int32';
$node['x-example'] = $validator->getMin();
break;
case 'Utopia\Validator\Numeric':
$node['type'] = 'integer';
$node['format'] = 'int32';
break;
case 'Utopia\Validator\Length':
$node['type'] = 'string';
break;
case 'Utopia\Validator\Host':
$node['type'] = 'string';
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
$node['type'] = 'string';
$node['x-example'] = $validator->getList()[0];
break;
default:
$node['type'] = 'string';
break;
}
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
$node['default'] = $param['default'];
}
if (false !== \strpos($url, ':'.$name)) { // Param is in URL path
$node['in'] = 'path';
$temp['parameters'][] = $node;
} elseif ($route->getMethod() == 'GET') { // Param is in query
$node['in'] = 'query';
$temp['parameters'][] = $node;
} else { // Param is in payload
if(\in_array('multipart/form-data', $consumes)) {
$node['in'] = 'formData';
$temp['parameters'][] = $node;
continue;
}
if(!$param['optional']) {
$bodyRequired[] = $name;
}
$body['schema']['properties'][$name] = [
'type' => $node['type'],
'description' => $node['description'],
'default' => $node['default'] ?? null,
'x-example' => $node['x-example'] ?? null,
];
if(\array_key_exists('items', $node)) {
$body['schema']['properties'][$name]['items'] = $node['items'];
}
}
$url = \str_replace(':'.$name, '{'.$name.'}', $url);
}
if(!empty($bodyRequired)) {
$body['schema']['required'] = $bodyRequired;
}
if(!empty($body['schema']['properties'])) {
$temp['parameters'][] = $body;
}
$temp['consumes'] = $consumes;
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
foreach ($this->models as $model) {
$required = $model->getRequired();
$rules = $model->getRules();
$output['definitions'][$model->getType()] = [
'description' => $model->getName(),
'type' => 'object',
];
if(!empty($rules)) {
$output['definitions'][$model->getType()]['properties'] = [];
}
if($model->isAny()) {
$output['definitions'][$model->getType()]['additionalProperties'] = true;
}
if(!empty($required)) {
$output['definitions'][$model->getType()]['required'] = $required;
}
foreach($model->getRules() as $name => $rule) {
$type = '';
$format = null;
$items = null;
switch ($rule['type']) {
case 'string':
case 'json':
$type = 'string';
break;
case 'integer':
$type = 'integer';
$format = 'int32';
break;
case 'float':
$type = 'number';
$format = 'float';
break;
case 'boolean':
$type = 'boolean';
break;
default:
$type = 'object';
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
$items = [
'type' => $type,
'$ref' => '#/definitions/'.$rule['type'],
];
break;
}
if($rule['array']) {
$output['definitions'][$model->getType()]['properties'][$name] = [
'type' => 'array',
'description' => $rule['description'] ?? '',
'items' => [
'type' => $type,
]
];
if($format) {
$output['definitions'][$model->getType()]['properties'][$name]['items']['format'] = $format;
}
if($items) {
$output['definitions'][$model->getType()]['properties'][$name]['items'] = $items;
}
} else {
$output['definitions'][$model->getType()]['properties'][$name] = [
'type' => $type,
'description' => $rule['description'] ?? '',
//'default' => $rule['default'] ?? null,
'x-example' => $rule['example'] ?? null,
];
if($format) {
$output['definitions'][$model->getType()]['properties'][$name]['format'] = $format;
}
if($items) {
$output['definitions'][$model->getType()]['properties'][$name]['items'] = $items;
}
}
}
}
\ksort($output['paths']);
return $output;
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Appwrite\Specification;
class Specification
{
/**
* @var Format
*/
protected $format;
/**
* @param Format $format
*/
public function __construct(Format $format)
{
$this->format = $format;
}
/**
* Get Name.
*
* Get format name
*
* @return string
*/
public function getName():string
{
return $this->format->getName();
}
/**
* Parse
*
* Parses Appwrite App to given format
*
* @return array
*/
public function parse(): array
{
return $this->format->parse();
}
}

View file

@ -7,6 +7,7 @@ use Utopia\Swoole\Response as SwooleResponse;
use Swoole\Http\Response as SwooleHTTPResponse; use Swoole\Http\Response as SwooleHTTPResponse;
use Appwrite\Database\Document; use Appwrite\Database\Document;
use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response\Model\None;
use Appwrite\Utopia\Response\Model\Any; use Appwrite\Utopia\Response\Model\Any;
use Appwrite\Utopia\Response\Model\BaseList; use Appwrite\Utopia\Response\Model\BaseList;
use Appwrite\Utopia\Response\Model\Collection; use Appwrite\Utopia\Response\Model\Collection;
@ -27,12 +28,14 @@ use Appwrite\Utopia\Response\Model\Team;
use Appwrite\Utopia\Response\Model\Locale; use Appwrite\Utopia\Response\Model\Locale;
use Appwrite\Utopia\Response\Model\Log; use Appwrite\Utopia\Response\Model\Log;
use Appwrite\Utopia\Response\Model\Membership; use Appwrite\Utopia\Response\Model\Membership;
use Appwrite\Utopia\Response\Model\Permissions;
use Appwrite\Utopia\Response\Model\Phone; use Appwrite\Utopia\Response\Model\Phone;
use Appwrite\Utopia\Response\Model\Platform; use Appwrite\Utopia\Response\Model\Platform;
use Appwrite\Utopia\Response\Model\Project; use Appwrite\Utopia\Response\Model\Project;
use Appwrite\Utopia\Response\Model\Rule; use Appwrite\Utopia\Response\Model\Rule;
use Appwrite\Utopia\Response\Model\Tag; use Appwrite\Utopia\Response\Model\Tag;
use Appwrite\Utopia\Response\Model\Task; use Appwrite\Utopia\Response\Model\Task;
use Appwrite\Utopia\Response\Model\Token;
use Appwrite\Utopia\Response\Model\Webhook; use Appwrite\Utopia\Response\Model\Webhook;
/** /**
@ -41,6 +44,7 @@ use Appwrite\Utopia\Response\Model\Webhook;
class Response extends SwooleResponse class Response extends SwooleResponse
{ {
// General // General
const MODEL_NONE = 'none';
const MODEL_ANY = 'any'; const MODEL_ANY = 'any';
const MODEL_LOG = 'log'; const MODEL_LOG = 'log';
const MODEL_LOG_LIST = 'logList'; const MODEL_LOG_LIST = 'logList';
@ -122,6 +126,8 @@ class Response extends SwooleResponse
{ {
$this $this
// General // General
->setModel(new None())
->setModel(new Any())
->setModel(new Error()) ->setModel(new Error())
->setModel(new ErrorDev()) ->setModel(new ErrorDev())
// Lists // Lists
@ -136,24 +142,25 @@ class Response extends SwooleResponse
->setModel(new BaseList('Functions List', self::MODEL_FUNCTION_LIST, 'functions', self::MODEL_FUNCTION)) ->setModel(new BaseList('Functions List', self::MODEL_FUNCTION_LIST, 'functions', self::MODEL_FUNCTION))
->setModel(new BaseList('Tags List', self::MODEL_TAG_LIST, 'tags', self::MODEL_TAG)) ->setModel(new BaseList('Tags List', self::MODEL_TAG_LIST, 'tags', self::MODEL_TAG))
->setModel(new BaseList('Executions List', self::MODEL_EXECUTION_LIST, 'executions', self::MODEL_EXECUTION)) ->setModel(new BaseList('Executions List', self::MODEL_EXECUTION_LIST, 'executions', self::MODEL_EXECUTION))
->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT)) ->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false))
->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK)) ->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false))
->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY)) ->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false))
->setModel(new BaseList('Tasks List', self::MODEL_TASK_LIST, 'tasks', self::MODEL_TASK)) ->setModel(new BaseList('Tasks List', self::MODEL_TASK_LIST, 'tasks', self::MODEL_TASK, true, false))
->setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM)) ->setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM, true, false))
->setModel(new BaseList('Domains List', self::MODEL_DOMAIN_LIST, 'domains', self::MODEL_DOMAIN)) ->setModel(new BaseList('Domains List', self::MODEL_DOMAIN_LIST, 'domains', self::MODEL_DOMAIN, true, false))
->setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY)) ->setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY))
->setModel(new BaseList('Continents List', self::MODEL_CONTINENT_LIST, 'continents', self::MODEL_CONTINENT)) ->setModel(new BaseList('Continents List', self::MODEL_CONTINENT_LIST, 'continents', self::MODEL_CONTINENT))
->setModel(new BaseList('Languages List', self::MODEL_LANGUAGE_LIST, 'languages', self::MODEL_LANGUAGE)) ->setModel(new BaseList('Languages List', self::MODEL_LANGUAGE_LIST, 'languages', self::MODEL_LANGUAGE))
->setModel(new BaseList('Currencies List', self::MODEL_CURRENCY_LIST, 'currencies', self::MODEL_CURRENCY)) ->setModel(new BaseList('Currencies List', self::MODEL_CURRENCY_LIST, 'currencies', self::MODEL_CURRENCY))
->setModel(new BaseList('Phones List', self::MODEL_PHONE_LIST, 'phones', self::MODEL_PHONE)) ->setModel(new BaseList('Phones List', self::MODEL_PHONE_LIST, 'phones', self::MODEL_PHONE))
// Entities // Entities
->setModel(new Any()) ->setModel(new Permissions())
->setModel(new Collection()) ->setModel(new Collection())
->setModel(new Rule()) ->setModel(new Rule())
->setModel(new Log()) ->setModel(new Log())
->setModel(new User()) ->setModel(new User())
->setModel(new Session()) ->setModel(new Session())
->setModel(new Token())
->setModel(new Locale()) ->setModel(new Locale())
->setModel(new File()) ->setModel(new File())
->setModel(new Team()) ->setModel(new Team())
@ -215,6 +222,16 @@ class Response extends SwooleResponse
return $this->models[$key]; return $this->models[$key];
} }
/**
* Get Models List
*
* @return Model[]
*/
public function getModels(): array
{
return $this->models;
}
/** /**
* Validate response objects and outputs * Validate response objects and outputs
* the response according to given format type * the response according to given format type

View file

@ -4,11 +4,27 @@ namespace Appwrite\Utopia\Response;
abstract class Model abstract class Model
{ {
const TYPE_STRING = 'string';
const TYPE_INTEGER = 'integer';
const TYPE_FLOAT = 'float';
const TYPE_BOOLEAN = 'boolean';
const TYPE_JSON = 'json';
/**
* @var bool
*/
protected $none = false;
/** /**
* @var bool * @var bool
*/ */
protected $any = false; protected $any = false;
/**
* @var bool
*/
protected $public = true;
/** /**
* @var array * @var array
*/ */
@ -44,6 +60,7 @@ abstract class Model
protected function addRule(string $key, array $options): self protected function addRule(string $key, array $options): self
{ {
$this->rules[$key] = array_merge([ $this->rules[$key] = array_merge([
'require' => true,
'type' => '', 'type' => '',
'description' => '', 'description' => '',
'default' => null, 'default' => null,
@ -54,8 +71,52 @@ abstract class Model
return $this; return $this;
} }
public function getRequired()
{
$list = [];
foreach($this->rules as $key => $rule) {
if(isset($rule['require']) || $rule['require']) {
$list[] = $key;
}
}
return $list;
}
/**
* Is None
*
* Use to check if response is empty
*
* @return bool
*/
public function isNone(): bool
{
return $this->none;
}
/**
* Is Any
*
* Use to check if response is a wildcard
*
* @return bool
*/
public function isAny(): bool public function isAny(): bool
{ {
return $this->any; return $this->any;
} }
/**
* Is Public
*
* Should this model be publicly available in docs and spec files?
*
* @return bool
*/
public function isPublic(): bool
{
return $this->public;
}
} }

View file

@ -17,22 +17,32 @@ class BaseList extends Model
*/ */
protected $type = ''; protected $type = '';
public function __construct(string $name, string $type, string $key, string $model, bool $paging = true) /**
* @param string $name
* @param string $type
* @param string $key
* @param string $model
* @param bool $paging
* @param bool $public
*/
public function __construct(string $name, string $type, string $key, string $model, bool $paging = true, bool $public = true)
{ {
$this->name = $name; $this->name = $name;
$this->type = $type; $this->type = $type;
$this->public = $public;
if ($paging) { if ($paging) {
$this->addRule('sum', [ $this->addRule('sum', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Total sum of items in the list.', 'description' => 'Total sum of items in the list.',
'example' => '5', 'default' => 0,
'example' => 5,
]); ]);
} }
$this->addRule($key, [ $this->addRule($key, [
'type' => $model, 'type' => $model,
'description' => 'List of '.$key.'.', 'description' => 'List of '.$key.'.',
'example' => [], 'default' => [],
'array' => true, 'array' => true,
]); ]);
} }

View file

@ -11,7 +11,7 @@ class Collection extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Collection ID.', 'description' => 'Collection ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
@ -22,24 +22,23 @@ class Collection extends Model
'array' => false, 'array' => false,
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Collection name.', 'description' => 'Collection name.',
'example' => 'Movies', 'example' => 'Movies',
]) ])
->addRule('dateCreated', [ ->addRule('dateCreated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Collection creation date in Unix timestamp.', 'description' => 'Collection creation date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('dateUpdated', [ ->addRule('dateUpdated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Collection creation date in Unix timestamp.', 'description' => 'Collection creation date in Unix timestamp.',
'example' => 1592981550, 'example' => 1592981550,
]) ])
->addRule('rules', [ ->addRule('rules', [
'type' => Response::MODEL_RULE, 'type' => Response::MODEL_RULE,
'description' => 'Collection rules.', 'description' => 'Collection rules.',
'example' => [],
'default' => [], 'default' => [],
'array' => true, 'array' => true,
]) ])

View file

@ -11,12 +11,12 @@ class Continent extends Model
{ {
$this $this
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Continent name.', 'description' => 'Continent name.',
'example' => 'Europe', 'example' => 'Europe',
]) ])
->addRule('code', [ ->addRule('code', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Continent two letter code.', 'description' => 'Continent two letter code.',
'example' => 'EU', 'example' => 'EU',
]) ])

View file

@ -11,12 +11,12 @@ class Country extends Model
{ {
$this $this
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country name.', 'description' => 'Country name.',
'example' => 'United States', 'example' => 'United States',
]) ])
->addRule('code', [ ->addRule('code', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country two-character ISO 3166-1 alpha code.', 'description' => 'Country two-character ISO 3166-1 alpha code.',
'example' => 'US', 'example' => 'US',
]) ])

View file

@ -11,42 +11,42 @@ class Currency extends Model
{ {
$this $this
->addRule('symbol', [ ->addRule('symbol', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Currency symbol.', 'description' => 'Currency symbol.',
'example' => '$', 'example' => '$',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Currency name.', 'description' => 'Currency name.',
'example' => 'US dollar', 'example' => 'US dollar',
]) ])
->addRule('symbolNative', [ ->addRule('symbolNative', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Currency native symbol.', 'description' => 'Currency native symbol.',
'example' => '$', 'example' => '$',
]) ])
->addRule('decimalDigits', [ ->addRule('decimalDigits', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Number of decimal digits.', 'description' => 'Number of decimal digits.',
'example' => 2, 'example' => 2,
]) ])
->addRule('rounding', [ ->addRule('rounding', [
'type' => 'float', 'type' => self::TYPE_FLOAT,
'description' => 'Currency digit rounding.', 'description' => 'Currency digit rounding.',
'example' => 0, 'example' => 0,
]) ])
->addRule('code', [ ->addRule('code', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format.', 'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format.',
'example' => 'USD', 'example' => 'USD',
]) ])
->addRule('namePlural', [ ->addRule('namePlural', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Currency plural name', 'description' => 'Currency plural name',
'example' => 'US dollars', 'example' => 'US dollars',
]) ])
// ->addRule('locations', [ // ->addRule('locations', [
// 'type' => 'string', // 'type' => self::TYPE_STRING,
// 'description' => 'Currency locations list. List of location in two-character ISO 3166-1 alpha code.', // 'description' => 'Currency locations list. List of location in two-character ISO 3166-1 alpha code.',
// 'example' => ['US'], // 'example' => ['US'],
// 'array' => true, // 'array' => true,

View file

@ -7,31 +7,36 @@ use Appwrite\Utopia\Response\Model;
class Domain extends Model class Domain extends Model
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Domain ID.', 'description' => 'Domain ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('domain', [ ->addRule('domain', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Domain name.', 'description' => 'Domain name.',
'example' => 'appwrite.company.com', 'example' => 'appwrite.company.com',
]) ])
->addRule('registerable', [ ->addRule('registerable', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Registerable domain name.', 'description' => 'Registerable domain name.',
'example' => 'company.com', 'example' => 'company.com',
]) ])
->addRule('tld', [ ->addRule('tld', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'TLD name.', 'description' => 'TLD name.',
'example' => 'com', 'example' => 'com',
]) ])
->addRule('verification', [ ->addRule('verification', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Verification process status.', 'description' => 'Verification process status.',
'example' => true, 'example' => true,
]) ])

View file

@ -11,17 +11,17 @@ class Error extends Model
{ {
$this $this
->addRule('message', [ ->addRule('message', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Error message.', 'description' => 'Error message.',
'example' => 'Not found', 'example' => 'Not found',
]) ])
->addRule('code', [ ->addRule('code', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Error code.', 'description' => 'Error code.',
'example' => '404', 'example' => '404',
]) ])
->addRule('version', [ ->addRule('version', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Server version number.', 'description' => 'Server version number.',
'example' => '1.0', 'example' => '1.0',
]) ])

View file

@ -6,23 +6,28 @@ use Appwrite\Utopia\Response;
class ErrorDev extends Error class ErrorDev extends Error
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this $this
->addRule('file', [ ->addRule('file', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'File path.', 'description' => 'File path.',
'example' => '/usr/code/vendor/utopia-php/framework/src/App.php', 'example' => '/usr/code/vendor/utopia-php/framework/src/App.php',
]) ])
->addRule('line', [ ->addRule('line', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Line number.', 'description' => 'Line number.',
'example' => 209, 'example' => 209,
]) ])
->addRule('trace', [ ->addRule('trace', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Error trace.', 'description' => 'Error trace.',
'example' => [ 'example' => [
'' ''

View file

@ -11,47 +11,47 @@ class Execution extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Execution ID.', 'description' => 'Execution ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('functionId', [ ->addRule('functionId', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function ID.', 'description' => 'Function ID.',
'example' => '5e5ea6g16897e', 'example' => '5e5ea6g16897e',
]) ])
->addRule('dateCreated', [ ->addRule('dateCreated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'The execution creation date in Unix timestamp.', 'description' => 'The execution creation date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('trigger', [ ->addRule('trigger', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.', 'description' => 'The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.',
'example' => 'http', 'example' => 'http',
]) ])
->addRule('status', [ ->addRule('status', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.', 'description' => 'The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.',
'example' => 'processing', 'example' => 'processing',
]) ])
->addRule('exitCode', [ ->addRule('exitCode', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'The script exit code.', 'description' => 'The script exit code.',
'example' => 0, 'example' => 0,
]) ])
->addRule('stdout', [ ->addRule('stdout', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'The script stdout output string.', 'description' => 'The script stdout output string.',
'example' => '', 'example' => '',
]) ])
->addRule('stderr', [ ->addRule('stderr', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'The script stderr output string.', 'description' => 'The script stderr output string.',
'example' => '', 'example' => '',
]) ])
->addRule('time', [ ->addRule('time', [
'type' => 'float', 'type' => self::TYPE_FLOAT,
'description' => 'The script execution time in seconds.', 'description' => 'The script execution time in seconds.',
'example' => 0.400, 'example' => 0.400,
]) ])

View file

@ -11,7 +11,7 @@ class File extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'File ID.', 'description' => 'File ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
@ -22,27 +22,27 @@ class File extends Model
'array' => false, 'array' => false,
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'File name.', 'description' => 'File name.',
'example' => 'Pink.png', 'example' => 'Pink.png',
]) ])
->addRule('dateCreated', [ ->addRule('dateCreated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'File creation date in Unix timestamp.', 'description' => 'File creation date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('signature', [ ->addRule('signature', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'File MD5 signature.', 'description' => 'File MD5 signature.',
'example' => '5d529fd02b544198ae075bd57c1762bb', 'example' => '5d529fd02b544198ae075bd57c1762bb',
]) ])
->addRule('mimeType', [ ->addRule('mimeType', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'File mime type.', 'description' => 'File mime type.',
'example' => 'image/png', 'example' => 'image/png',
]) ])
->addRule('sizeOriginal', [ ->addRule('sizeOriginal', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'File original size in bytes.', 'description' => 'File original size in bytes.',
'example' => 17890, 'example' => 17890,
]) ])

View file

@ -11,74 +11,74 @@ class Func extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function ID.', 'description' => 'Function ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function name.', 'description' => 'Function name.',
'example' => 'My Function', 'example' => 'My Function',
]) ])
->addRule('dateCreated', [ ->addRule('dateCreated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Function creation date in Unix timestamp.', 'description' => 'Function creation date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('dateUpdated', [ ->addRule('dateUpdated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Function update date in Unix timestamp.', 'description' => 'Function update date in Unix timestamp.',
'example' => 1592981257, 'example' => 1592981257,
]) ])
->addRule('status', [ ->addRule('status', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function status. Possible values: disabled, enabled', 'description' => 'Function status. Possible values: disabled, enabled',
'example' => 'enabled', 'example' => 'enabled',
]) ])
->addRule('env', [ ->addRule('env', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function execution environment.', 'description' => 'Function execution environment.',
'example' => 'python-3.8', 'example' => 'python-3.8',
]) ])
->addRule('tag', [ ->addRule('tag', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function active tag ID.', 'description' => 'Function active tag ID.',
'default' => '', 'default' => '',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('vars', [ ->addRule('vars', [
'type' => 'json', 'type' => self::TYPE_JSON,
'description' => 'Function environment variables.', 'description' => 'Function environment variables.',
'default' => new \stdClass, 'default' => new \stdClass,
'example' => ['key' => 'value'], 'example' => ['key' => 'value'],
]) ])
->addRule('events', [ ->addRule('events', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function trigger events.', 'description' => 'Function trigger events.',
'default' => [], 'default' => [],
'example' => ['account.create'], 'example' => ['account.create'],
'array' => true, 'array' => true,
]) ])
->addRule('schedule', [ ->addRule('schedule', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function execution schedult in CRON format.', 'description' => 'Function execution schedult in CRON format.',
'default' => '', 'default' => '',
'example' => '5 4 * * *', 'example' => '5 4 * * *',
]) ])
->addRule('scheduleNext', [ ->addRule('scheduleNext', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Function next scheduled execution date in Unix timestamp.', 'description' => 'Function next scheduled execution date in Unix timestamp.',
'example' => 1592981292, 'example' => 1592981292,
'default' => 0, 'default' => 0,
]) ])
->addRule('schedulePrevious', [ ->addRule('schedulePrevious', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Function next scheduled execution date in Unix timestamp.', 'description' => 'Function next scheduled execution date in Unix timestamp.',
'example' => 1592981237, 'example' => 1592981237,
'default' => 0, 'default' => 0,
]) ])
->addRule('timeout', [ ->addRule('timeout', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Function execution timeout in seconds.', 'description' => 'Function execution timeout in seconds.',
'default' => 15, 'default' => 15,
'example' => 1592981237, 'example' => 1592981237,

View file

@ -7,28 +7,33 @@ use Appwrite\Utopia\Response\Model;
class Key extends Model class Key extends Model
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Key ID.', 'description' => 'Key ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Key name.', 'description' => 'Key name.',
'example' => 'My API Key', 'example' => 'My API Key',
]) ])
->addRule('scopes', [ ->addRule('scopes', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Allowed permission scopes.', 'description' => 'Allowed permission scopes.',
'default' => [], 'default' => [],
'example' => ['users.read', 'documents.write'], 'example' => ['users.read', 'documents.write'],
'array' => true, 'array' => true,
]) ])
->addRule('secret', [ ->addRule('secret', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Secret key.', 'description' => 'Secret key.',
'example' => '919c2d18fb5d4...a2ae413da83346ad2', 'example' => '919c2d18fb5d4...a2ae413da83346ad2',
]) ])

View file

@ -11,17 +11,17 @@ class Language extends Model
{ {
$this $this
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Language name.', 'description' => 'Language name.',
'example' => 'Italian', 'example' => 'Italian',
]) ])
->addRule('code', [ ->addRule('code', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Language two-character ISO 639-1 codes.', 'description' => 'Language two-character ISO 639-1 codes.',
'example' => 'it', 'example' => 'it',
]) ])
->addRule('nativeName', [ ->addRule('nativeName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Language native name.', 'description' => 'Language native name.',
'example' => 'Italiano', 'example' => 'Italiano',
]) ])

View file

@ -11,38 +11,38 @@ class Locale extends Model
{ {
$this $this
->addRule('ip', [ ->addRule('ip', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User IP address.', 'description' => 'User IP address.',
'example' => '127.0.0.1', 'example' => '127.0.0.1',
]) ])
->addRule('countryCode', [ ->addRule('countryCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country code in [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) two-character format', 'description' => 'Country code in [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) two-character format',
'example' => 'US', 'example' => 'US',
]) ])
->addRule('country', [ ->addRule('country', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country name. This field support localization.', 'description' => 'Country name. This field support localization.',
'example' => 'United States', 'example' => 'United States',
]) ])
->addRule('continentCode', [ ->addRule('continentCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Continent code. A two character continent code "AF" for Africa, "AN" for Antarctica, "AS" for Asia, "EU" for Europe, "NA" for North America, "OC" for Oceania, and "SA" for South America.', 'description' => 'Continent code. A two character continent code "AF" for Africa, "AN" for Antarctica, "AS" for Asia, "EU" for Europe, "NA" for North America, "OC" for Oceania, and "SA" for South America.',
'example' => 'NA', 'example' => 'NA',
]) ])
->addRule('continent', [ ->addRule('continent', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Continent name. This field support localization.', 'description' => 'Continent name. This field support localization.',
'example' => 'North America', 'example' => 'North America',
]) ])
->addRule('eu', [ ->addRule('eu', [
'type' => 'Boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'True if country is part of the Europian Union.', 'description' => 'True if country is part of the Europian Union.',
'default' => false, 'default' => false,
'example' => false, 'example' => false,
]) ])
->addRule('currency', [ ->addRule('currency', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format', 'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format',
'example' => 'USD', 'example' => 'USD',
]) ])

View file

@ -11,100 +11,100 @@ class Log extends Model
{ {
$this $this
->addRule('event', [ ->addRule('event', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Event name.', 'description' => 'Event name.',
'example' => 'account.sessions.create', 'example' => 'account.sessions.create',
]) ])
->addRule('ip', [ ->addRule('ip', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'IP session in use when the session was created.', 'description' => 'IP session in use when the session was created.',
'example' => '127.0.0.1', 'example' => '127.0.0.1',
]) ])
->addRule('time', [ ->addRule('time', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Log creation time in Unix timestamp.', 'description' => 'Log creation time in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('osCode', [ ->addRule('osCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Operating system code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/os.json).', 'description' => 'Operating system code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/os.json).',
'default' => '', 'default' => '',
'example' => 'Mac', 'example' => 'Mac',
]) ])
->addRule('osName', [ ->addRule('osName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Operating system name.', 'description' => 'Operating system name.',
'default' => '', 'default' => '',
'example' => 'Mac', 'example' => 'Mac',
]) ])
->addRule('osVersion', [ ->addRule('osVersion', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Operating system version.', 'description' => 'Operating system version.',
'default' => '', 'default' => '',
'example' => 'Mac', 'example' => 'Mac',
]) ])
->addRule('clientType', [ ->addRule('clientType', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client type.', 'description' => 'Client type.',
'default' => '', 'default' => '',
'example' => 'browser', 'example' => 'browser',
]) ])
->addRule('clientCode', [ ->addRule('clientCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/clients.json).', 'description' => 'Client code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/clients.json).',
'default' => '', 'default' => '',
'example' => 'CM', 'example' => 'CM',
]) ])
->addRule('clientName', [ ->addRule('clientName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client name.', 'description' => 'Client name.',
'default' => '', 'default' => '',
'example' => 'Chrome Mobile iOS', 'example' => 'Chrome Mobile iOS',
]) ])
->addRule('clientVersion', [ ->addRule('clientVersion', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client version.', 'description' => 'Client version.',
'default' => '', 'default' => '',
'example' => '84.0', 'example' => '84.0',
]) ])
->addRule('clientEngine', [ ->addRule('clientEngine', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client engine name.', 'description' => 'Client engine name.',
'default' => '', 'default' => '',
'example' => 'WebKit', 'example' => 'WebKit',
]) ])
->addRule('clientEngineVersion', [ ->addRule('clientEngineVersion', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client engine name.', 'description' => 'Client engine name.',
'default' => '', 'default' => '',
'example' => '605.1.15', 'example' => '605.1.15',
]) ])
->addRule('deviceName', [ ->addRule('deviceName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Device name.', 'description' => 'Device name.',
'default' => '', 'default' => '',
'example' => 'smartphone', 'example' => 'smartphone',
]) ])
->addRule('deviceBrand', [ ->addRule('deviceBrand', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Device brand name.', 'description' => 'Device brand name.',
'default' => '', 'default' => '',
'example' => 'Google', 'example' => 'Google',
]) ])
->addRule('deviceModel', [ ->addRule('deviceModel', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Device model name.', 'description' => 'Device model name.',
'default' => '', 'default' => '',
'example' => 'Nexus 5', 'example' => 'Nexus 5',
]) ])
->addRule('countryCode', [ ->addRule('countryCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country two-character ISO 3166-1 alpha code.', 'description' => 'Country two-character ISO 3166-1 alpha code.',
'default' => '', 'default' => '',
'example' => 'US', 'example' => 'US',
]) ])
->addRule('countryName', [ ->addRule('countryName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country name.', 'description' => 'Country name.',
'default' => '', 'default' => '',
'example' => 'United States', 'example' => 'United States',

View file

@ -11,49 +11,49 @@ class Membership extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Membership ID.', 'description' => 'Membership ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('userId', [ ->addRule('userId', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User ID.', 'description' => 'User ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('teamId', [ ->addRule('teamId', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Team ID.', 'description' => 'Team ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User name.', 'description' => 'User name.',
'default' => '', 'default' => '',
'example' => 'VIP', 'example' => 'VIP',
]) ])
->addRule('email', [ ->addRule('email', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User email address.', 'description' => 'User email address.',
'default' => '', 'default' => '',
'example' => 'john@appwrite.io', 'example' => 'john@appwrite.io',
]) ])
->addRule('invited', [ ->addRule('invited', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Date, the user has been invited to join the team in Unix timestamp.', 'description' => 'Date, the user has been invited to join the team in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('joined', [ ->addRule('joined', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Date, the user has accepted the invitation to join the team in Unix timestamp.', 'description' => 'Date, the user has accepted the invitation to join the team in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('confirm', [ ->addRule('confirm', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'User confirmation status, true if the user has joined the team or false otherwise.', 'description' => 'User confirmation status, true if the user has joined the team or false otherwise.',
'example' => false, 'example' => false,
]) ])
->addRule('roles', [ ->addRule('roles', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User list of roles', 'description' => 'User list of roles',
'default' => [], 'default' => [],
'example' => [], 'example' => [],

View file

@ -0,0 +1,34 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class None extends Model
{
/**
* @var bool
*/
protected $none = true;
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'None';
}
/**
* Get Collection
*
* @return string
*/
public function getType():string
{
return Response::MODEL_NONE;
}
}

View file

@ -11,13 +11,13 @@ class Permissions extends Model
{ {
$this $this
->addRule('read', [ ->addRule('read', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Read permissions.', 'description' => 'Read permissions.',
'example' => ['*', 'user:5e5ea5c16897e'], 'example' => ['*', 'user:5e5ea5c16897e'],
'array' => true, 'array' => true,
]) ])
->addRule('write', [ ->addRule('write', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Write permissions.', 'description' => 'Write permissions.',
'example' => ['*', 'user:5e5ea5c16897e'], 'example' => ['*', 'user:5e5ea5c16897e'],
'array' => true, 'array' => true,

View file

@ -11,17 +11,17 @@ class Phone extends Model
{ {
$this $this
->addRule('code', [ ->addRule('code', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Phone code.', 'description' => 'Phone code.',
'example' => '+1', 'example' => '+1',
]) ])
->addRule('countryCode', [ ->addRule('countryCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country two-character ISO 3166-1 alpha code.', 'description' => 'Country two-character ISO 3166-1 alpha code.',
'example' => 'US', 'example' => 'US',
]) ])
->addRule('countryName', [ ->addRule('countryName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country name.', 'description' => 'Country name.',
'example' => 'United States', 'example' => 'United States',
]) ])

View file

@ -7,47 +7,52 @@ use Appwrite\Utopia\Response\Model;
class Platform extends Model class Platform extends Model
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Platform ID.', 'description' => 'Platform ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Platform name.', 'description' => 'Platform name.',
'example' => 'My Web App', 'example' => 'My Web App',
]) ])
->addRule('type', [ ->addRule('type', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Platform type. Possible values are: web, flutter-ios, flutter-android, ios, android, and unity.', 'description' => 'Platform type. Possible values are: web, flutter-ios, flutter-android, ios, android, and unity.',
'example' => 'My Web App', 'example' => 'My Web App',
]) ])
->addRule('key', [ ->addRule('key', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.', 'description' => 'Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.',
'example' => 'com.company.appname', 'example' => 'com.company.appname',
]) ])
// ->addRule('store', [ // ->addRule('store', [
// 'type' => 'string', // 'type' => self::TYPE_STRING,
// 'description' => 'Link to platform store.', // 'description' => 'Link to platform store.',
// 'example' => '', // 'example' => '',
// ]) // ])
->addRule('hostname', [ ->addRule('hostname', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Web app hostname. Empty string for other platforms.', 'description' => 'Web app hostname. Empty string for other platforms.',
'example' => true, 'example' => true,
]) ])
->addRule('httpUser', [ ->addRule('httpUser', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'HTTP basic authentication username.', 'description' => 'HTTP basic authentication username.',
'default' => '', 'default' => '',
'example' => 'username', 'example' => 'username',
]) ])
->addRule('httpPass', [ ->addRule('httpPass', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'HTTP basic authentication password.', 'description' => 'HTTP basic authentication password.',
'default' => '', 'default' => '',
'example' => 'password', 'example' => 'password',

View file

@ -8,75 +8,80 @@ use Utopia\Config\Config;
class Project extends Model class Project extends Model
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Project ID.', 'description' => 'Project ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Project name.', 'description' => 'Project name.',
'default' => '', 'default' => '',
'example' => 'New Project', 'example' => 'New Project',
]) ])
->addRule('description', [ ->addRule('description', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Project description.', 'description' => 'Project description.',
'default' => '', 'default' => '',
'example' => 'This is a new project.', 'example' => 'This is a new project.',
]) ])
->addRule('teamId', [ ->addRule('teamId', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Project team ID.', 'description' => 'Project team ID.',
'example' => '1592981250', 'example' => '1592981250',
]) ])
->addRule('logo', [ ->addRule('logo', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Project logo file ID.', 'description' => 'Project logo file ID.',
'default' => '', 'default' => '',
'example' => '5f5c451b403cb', 'example' => '5f5c451b403cb',
]) ])
->addRule('url', [ ->addRule('url', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Project website URL.', 'description' => 'Project website URL.',
'default' => '', 'default' => '',
'example' => '5f5c451b403cb', 'example' => '5f5c451b403cb',
]) ])
->addRule('legalName', [ ->addRule('legalName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Company legal name.', 'description' => 'Company legal name.',
'default' => '', 'default' => '',
'example' => 'Company LTD.', 'example' => 'Company LTD.',
]) ])
->addRule('legalCountry', [ ->addRule('legalCountry', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country code in [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) two-character format.', 'description' => 'Country code in [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) two-character format.',
'default' => '', 'default' => '',
'example' => 'US', 'example' => 'US',
]) ])
->addRule('legalState', [ ->addRule('legalState', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'State name.', 'description' => 'State name.',
'default' => '', 'default' => '',
'example' => 'New York', 'example' => 'New York',
]) ])
->addRule('legalCity', [ ->addRule('legalCity', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'City name.', 'description' => 'City name.',
'default' => '', 'default' => '',
'example' => 'New York City.', 'example' => 'New York City.',
]) ])
->addRule('legalAddress', [ ->addRule('legalAddress', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Company Address.', 'description' => 'Company Address.',
'default' => '', 'default' => '',
'example' => '620 Eighth Avenue, New York, NY 10018', 'example' => '620 Eighth Avenue, New York, NY 10018',
]) ])
->addRule('legalTaxId', [ ->addRule('legalTaxId', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Company Tax ID.', 'description' => 'Company Tax ID.',
'default' => '', 'default' => '',
'example' => '131102020', 'example' => '131102020',
@ -129,13 +134,13 @@ class Project extends Model
$this $this
->addRule('usersOauth2'.\ucfirst($index).'Appid', [ ->addRule('usersOauth2'.\ucfirst($index).'Appid', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => $name.' OAuth app ID.', 'description' => $name.' OAuth app ID.',
'example' => '123247283472834787438', 'example' => '123247283472834787438',
'default' => '', 'default' => '',
]) ])
->addRule('usersOauth2'.\ucfirst($index).'Secret', [ ->addRule('usersOauth2'.\ucfirst($index).'Secret', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => $name.' OAuth secret ID.', 'description' => $name.' OAuth secret ID.',
'example' => 'djsgudsdsewe43434343dd34...', 'example' => 'djsgudsdsewe43434343dd34...',
'default' => '', 'default' => '',

View file

@ -11,48 +11,48 @@ class Rule extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Rule ID.', 'description' => 'Rule ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('$collection', [ // TODO remove this from public response ->addRule('$collection', [ // TODO remove this from public response
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Rule Collection.', 'description' => 'Rule Collection.',
'example' => '5e5e66c16897e', 'example' => '5e5e66c16897e',
]) ])
->addRule('type', [ ->addRule('type', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Rule type. Possible values: ', 'description' => 'Rule type. Possible values: ',
'example' => 'title', 'example' => 'title',
]) ])
->addRule('key', [ ->addRule('key', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Rule key.', 'description' => 'Rule key.',
'example' => 'title', 'example' => 'title',
]) ])
->addRule('label', [ ->addRule('label', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Rule label.', 'description' => 'Rule label.',
'example' => 'Title', 'example' => 'Title',
]) ])
->addRule('default', [ // TODO should be of mixed types ->addRule('default', [ // TODO should be of mixed types
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Rule default value.', 'description' => 'Rule default value.',
'example' => 'Movie Name', 'example' => 'Movie Name',
'default' => '', 'default' => '',
]) ])
->addRule('array', [ ->addRule('array', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Is array?', 'description' => 'Is array?',
'example' => false, 'example' => false,
]) ])
->addRule('required', [ ->addRule('required', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Is required?', 'description' => 'Is required?',
'example' => true, 'example' => true,
]) ])
->addRule('list', [ ->addRule('list', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'List of allowed values', 'description' => 'List of allowed values',
'array' => true, 'array' => true,
'default' => [], 'default' => [],

View file

@ -11,108 +11,108 @@ class Session extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Session ID.', 'description' => 'Session ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('expire', [ ->addRule('expire', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Session expiration date in Unix timestamp.', 'description' => 'Session expiration date in Unix timestamp.',
'default' => 0, 'default' => 0,
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('ip', [ ->addRule('ip', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'IP in use when the session was created.', 'description' => 'IP in use when the session was created.',
'default' => '', 'default' => '',
'example' => '127.0.0.1', 'example' => '127.0.0.1',
]) ])
->addRule('osCode', [ ->addRule('osCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Operating system code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/os.json).', 'description' => 'Operating system code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/os.json).',
'default' => '', 'default' => '',
'example' => 'Mac', 'example' => 'Mac',
]) ])
->addRule('osName', [ ->addRule('osName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Operating system name.', 'description' => 'Operating system name.',
'default' => '', 'default' => '',
'example' => 'Mac', 'example' => 'Mac',
]) ])
->addRule('osVersion', [ ->addRule('osVersion', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Operating system version.', 'description' => 'Operating system version.',
'default' => '', 'default' => '',
'example' => 'Mac', 'example' => 'Mac',
]) ])
->addRule('clientType', [ ->addRule('clientType', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client type.', 'description' => 'Client type.',
'default' => '', 'default' => '',
'example' => 'browser', 'example' => 'browser',
]) ])
->addRule('clientCode', [ ->addRule('clientCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/clients.json).', 'description' => 'Client code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/clients.json).',
'default' => '', 'default' => '',
'example' => 'CM', 'example' => 'CM',
]) ])
->addRule('clientName', [ ->addRule('clientName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client name.', 'description' => 'Client name.',
'default' => '', 'default' => '',
'example' => 'Chrome Mobile iOS', 'example' => 'Chrome Mobile iOS',
]) ])
->addRule('clientVersion', [ ->addRule('clientVersion', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client version.', 'description' => 'Client version.',
'default' => '', 'default' => '',
'example' => '84.0', 'example' => '84.0',
]) ])
->addRule('clientEngine', [ ->addRule('clientEngine', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client engine name.', 'description' => 'Client engine name.',
'default' => '', 'default' => '',
'example' => 'WebKit', 'example' => 'WebKit',
]) ])
->addRule('clientEngineVersion', [ ->addRule('clientEngineVersion', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Client engine name.', 'description' => 'Client engine name.',
'default' => '', 'default' => '',
'example' => '605.1.15', 'example' => '605.1.15',
]) ])
->addRule('deviceName', [ ->addRule('deviceName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Device name.', 'description' => 'Device name.',
'default' => '', 'default' => '',
'example' => 'smartphone', 'example' => 'smartphone',
]) ])
->addRule('deviceBrand', [ ->addRule('deviceBrand', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Device brand name.', 'description' => 'Device brand name.',
'default' => '', 'default' => '',
'example' => 'Google', 'example' => 'Google',
]) ])
->addRule('deviceModel', [ ->addRule('deviceModel', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Device model name.', 'description' => 'Device model name.',
'default' => '', 'default' => '',
'example' => 'Nexus 5', 'example' => 'Nexus 5',
]) ])
->addRule('countryCode', [ ->addRule('countryCode', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country two-character ISO 3166-1 alpha code.', 'description' => 'Country two-character ISO 3166-1 alpha code.',
'default' => '', 'default' => '',
'example' => 'US', 'example' => 'US',
]) ])
->addRule('countryName', [ ->addRule('countryName', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Country name.', 'description' => 'Country name.',
'default' => '', 'default' => '',
'example' => 'United States', 'example' => 'United States',
]) ])
->addRule('current', [ ->addRule('current', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Returns true if this the current user session.', 'description' => 'Returns true if this the current user session.',
'default' => '', 'default' => '',
'example' => true, 'example' => true,

View file

@ -11,27 +11,27 @@ class Tag extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Tag ID.', 'description' => 'Tag ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('functionId', [ ->addRule('functionId', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Function ID.', 'description' => 'Function ID.',
'example' => '5e5ea6g16897e', 'example' => '5e5ea6g16897e',
]) ])
->addRule('dateCreated', [ ->addRule('dateCreated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'The tag creation date in Unix timestamp.', 'description' => 'The tag creation date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('command', [ ->addRule('command', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'The entrypoint command in use to execute the tag code.', 'description' => 'The entrypoint command in use to execute the tag code.',
'example' => 'enabled', 'example' => 'enabled',
]) ])
->addRule('size', [ ->addRule('size', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'The code size in bytes.', 'description' => 'The code size in bytes.',
'example' => 'python-3.8', 'example' => 'python-3.8',
]) ])

View file

@ -7,95 +7,100 @@ use Appwrite\Utopia\Response\Model;
class Task extends Model class Task extends Model
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task ID.', 'description' => 'Task ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task name.', 'description' => 'Task name.',
'example' => 'My Task', 'example' => 'My Task',
]) ])
->addRule('security', [ ->addRule('security', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Indicated if SSL / TLS Certificate verification is enabled.', 'description' => 'Indicated if SSL / TLS Certificate verification is enabled.',
'example' => true, 'example' => true,
]) ])
->addRule('httpMethod', [ ->addRule('httpMethod', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task HTTP Method.', 'description' => 'Task HTTP Method.',
'example' => 'POST', 'example' => 'POST',
]) ])
->addRule('httpUrl', [ ->addRule('httpUrl', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task HTTP URL.', 'description' => 'Task HTTP URL.',
'example' => 'https://example.com/task', 'example' => 'https://example.com/task',
]) ])
->addRule('httpHeaders', [ ->addRule('httpHeaders', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task HTTP headers.', 'description' => 'Task HTTP headers.',
'default' => [], 'default' => [],
'example' => ['key:value'], 'example' => ['key:value'],
'array' => true, 'array' => true,
]) ])
->addRule('httpUser', [ ->addRule('httpUser', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'HTTP basic authentication username.', 'description' => 'HTTP basic authentication username.',
'default' => '', 'default' => '',
'example' => 'username', 'example' => 'username',
]) ])
->addRule('httpPass', [ ->addRule('httpPass', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'HTTP basic authentication password.', 'description' => 'HTTP basic authentication password.',
'default' => '', 'default' => '',
'example' => 'password', 'example' => 'password',
]) ])
->addRule('duration', [ ->addRule('duration', [
'type' => 'float', 'type' => self::TYPE_FLOAT,
'description' => 'Task duration in seconds.', 'description' => 'Task duration in seconds.',
'default' => 0, 'default' => 0,
'example' => 1.2, 'example' => 1.2,
]) ])
->addRule('delay', [ ->addRule('delay', [
'type' => 'float', 'type' => self::TYPE_FLOAT,
'description' => 'Task delay time in seconds.', 'description' => 'Task delay time in seconds.',
'default' => 0, 'default' => 0,
'example' => 1.2, 'example' => 1.2,
]) ])
->addRule('failures', [ ->addRule('failures', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Number of recurring task failures.', 'description' => 'Number of recurring task failures.',
'default' => 0, 'default' => 0,
'example' => 0, 'example' => 0,
]) ])
->addRule('schedule', [ ->addRule('schedule', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task schedule in CRON syntax.', 'description' => 'Task schedule in CRON syntax.',
'example' => '* * * * *', 'example' => '* * * * *',
]) ])
->addRule('status', [ ->addRule('status', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Task status. Possible values: play, pause', // TODO - change to enabled disabled 'description' => 'Task status. Possible values: play, pause', // TODO - change to enabled disabled
'example' => 'enabled', 'example' => 'enabled',
]) ])
->addRule('updated', [ ->addRule('updated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Task last updated time in Unix timestamp.', 'description' => 'Task last updated time in Unix timestamp.',
'default' => 0, 'default' => 0,
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('previous', [ ->addRule('previous', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Task previous run time in Unix timestamp.', 'description' => 'Task previous run time in Unix timestamp.',
'default' => 0, 'default' => 0,
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('next', [ ->addRule('next', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Task next run time in Unix timestamp.', 'description' => 'Task next run time in Unix timestamp.',
'default' => 0, 'default' => 0,
'example' => 1592981650, 'example' => 1592981650,

View file

@ -11,23 +11,23 @@ class Team extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Team ID.', 'description' => 'Team ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Team name.', 'description' => 'Team name.',
'default' => '', 'default' => '',
'example' => 'VIP', 'example' => 'VIP',
]) ])
->addRule('dateCreated', [ ->addRule('dateCreated', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Team creation date in Unix timestamp.', 'description' => 'Team creation date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('sum', [ // TODO change key name? ->addRule('sum', [ // TODO change key name?
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'Total sum of team members.', 'description' => 'Total sum of team members.',
'example' => 7, 'example' => 7,
]) ])

View file

@ -9,6 +9,25 @@ class Token extends Model
{ {
public function __construct() public function __construct()
{ {
$this
->addRule('$id', [
'type' => self::TYPE_STRING,
'description' => 'Token ID.',
'example' => '5e5ea5c16897e',
])
// ->addRule('type', [ TODO: use this when token types will be strings
// 'type' => self::TYPE_STRING,
// 'description' => 'Token type. Possible values: play, pause',
// 'default' => '',
// 'example' => '127.0.0.1',
// ])
->addRule('expire', [
'type' => self::TYPE_INTEGER,
'description' => 'Token expiration date in Unix timestamp.',
'default' => 0,
'example' => 1592981250,
])
;
} }
/** /**
@ -18,7 +37,7 @@ class Token extends Model
*/ */
public function getName():string public function getName():string
{ {
return 'User'; return 'Token';
} }
/** /**
@ -28,6 +47,6 @@ class Token extends Model
*/ */
public function getType():string public function getType():string
{ {
return Response::MODEL_LOCALE; return Response::MODEL_TOKEN;
} }
} }

View file

@ -11,47 +11,47 @@ class User extends Model
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User ID.', 'description' => 'User ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User name.', 'description' => 'User name.',
'example' => 'John Doe', 'example' => 'John Doe',
]) ])
->addRule('registration', [ ->addRule('registration', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'User registration date in Unix timestamp.', 'description' => 'User registration date in Unix timestamp.',
'example' => 1592981250, 'example' => 1592981250,
]) ])
->addRule('status', [ ->addRule('status', [
'type' => 'integer', 'type' => self::TYPE_INTEGER,
'description' => 'User status. 0 for Unavtivated, 1 for active and 2 is blocked.', 'description' => 'User status. 0 for Unavtivated, 1 for active and 2 is blocked.',
'example' => 0, 'example' => 0,
]) ])
->addRule('email', [ ->addRule('email', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User email address.', 'description' => 'User email address.',
'example' => 'john@appwrite.io', 'example' => 'john@appwrite.io',
]) ])
->addRule('emailVerification', [ ->addRule('emailVerification', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Email verification status.', 'description' => 'Email verification status.',
'default' => false, 'default' => false,
'example' => true, 'example' => true,
]) ])
->addRule('prefs', [ ->addRule('prefs', [
'type' => 'json', 'type' => self::TYPE_JSON,
'description' => 'User preferences as a key-value object', 'description' => 'User preferences as a key-value object',
'default' => new \stdClass, 'default' => new \stdClass,
'example' => ['theme' => 'pink', 'timezone' => 'UTC'], 'example' => ['theme' => 'pink', 'timezone' => 'UTC'],
]) ])
->addRule('roles', [ ->addRule('roles', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'User list of roles', 'description' => 'User list of roles',
'default' => [], 'default' => [],
'example' => [], 'example' => '*',
'array' => true, 'array' => true,
]) ])
; ;

View file

@ -7,44 +7,49 @@ use Appwrite\Utopia\Response\Model;
class Webhook extends Model class Webhook extends Model
{ {
/**
* @var bool
*/
protected $public = false;
public function __construct() public function __construct()
{ {
$this $this
->addRule('$id', [ ->addRule('$id', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Webhook ID.', 'description' => 'Webhook ID.',
'example' => '5e5ea5c16897e', 'example' => '5e5ea5c16897e',
]) ])
->addRule('name', [ ->addRule('name', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Webhook name.', 'description' => 'Webhook name.',
'example' => 'My Webhook', 'example' => 'My Webhook',
]) ])
->addRule('url', [ ->addRule('url', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Webhook URL endpoint.', 'description' => 'Webhook URL endpoint.',
'example' => 'https://example.com/webhook', 'example' => 'https://example.com/webhook',
]) ])
->addRule('events', [ ->addRule('events', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'Webhook trigger events.', 'description' => 'Webhook trigger events.',
'default' => [], 'default' => [],
'example' => ['database.collections.update', 'database.collections.delete'], 'example' => ['database.collections.update', 'database.collections.delete'],
'array' => true, 'array' => true,
]) ])
->addRule('security', [ ->addRule('security', [
'type' => 'boolean', 'type' => self::TYPE_BOOLEAN,
'description' => 'Indicated if SSL / TLS Certificate verification is enabled.', 'description' => 'Indicated if SSL / TLS Certificate verification is enabled.',
'example' => true, 'example' => true,
]) ])
->addRule('httpUser', [ ->addRule('httpUser', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'HTTP basic authentication username.', 'description' => 'HTTP basic authentication username.',
'default' => '', 'default' => '',
'example' => 'username', 'example' => 'username',
]) ])
->addRule('httpPass', [ ->addRule('httpPass', [
'type' => 'string', 'type' => self::TYPE_STRING,
'description' => 'HTTP basic authentication password.', 'description' => 'HTTP basic authentication password.',
'default' => '', 'default' => '',
'example' => 'password', 'example' => 'password',

View file

@ -2,10 +2,13 @@
namespace Tests\E2E\Services\Account; namespace Tests\E2E\Services\Account;
use CURLFile;
use Exception;
use Tests\E2E\Client; use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectNone; use Tests\E2E\Scopes\ProjectNone;
use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideNone; use Tests\E2E\Scopes\SideNone;
use Utopia\CLI\Console;
class HTTPTest extends Scope class HTTPTest extends Scope
{ {
@ -92,4 +95,60 @@ class HTTPTest extends Scope
$this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(200, $response['headers']['status-code']);
$this->assertStringContainsString('# robotstxt.org/', $response['body']); $this->assertStringContainsString('# robotstxt.org/', $response['body']);
} }
public function testSpecSwagger2()
{
$response = $this->client->call(Client::METHOD_GET, '/specs/swagger2?platform=client', [
'content-type' => 'application/json',
], []);
if(!file_put_contents(__DIR__ . '/../../resources/swagger2.json', json_encode($response['body']))) {
throw new Exception('Failed to save spec file');
}
$client = new Client();
$client->setEndpoint('https://validator.swagger.io');
/**
* Test for SUCCESS
*/
$response = $client->call(Client::METHOD_POST, '/validator/debug', [
'content-type' => 'application/json',
], json_decode(file_get_contents(realpath(__DIR__ . '/../../resources/swagger2.json')), true));
$response['body'] = json_decode($response['body'], true);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertFalse(isset($response['body']['messages']));
unlink(realpath(__DIR__ . '/../../resources/swagger2.json'));
}
public function testSpecOpenAPI3()
{
$response = $this->client->call(Client::METHOD_GET, '/specs/open-api3?platform=client', [
'content-type' => 'application/json',
], []);
if(!file_put_contents(__DIR__ . '/../../resources/open-api3.json', json_encode($response['body']))) {
throw new Exception('Failed to save spec file');
}
$client = new Client();
$client->setEndpoint('https://validator.swagger.io');
/**
* Test for SUCCESS
*/
$response = $client->call(Client::METHOD_POST, '/validator/debug', [
'content-type' => 'application/json',
], json_decode(file_get_contents(realpath(__DIR__ . '/../../resources/open-api3.json')), true));
$response['body'] = json_decode($response['body'], true);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertFalse(isset($response['body']['messages']));
unlink(realpath(__DIR__ . '/../../resources/open-api3.json'));
}
} }

View file

@ -648,7 +648,6 @@ trait AccountBase
$this->assertEquals(201, $response['headers']['status-code']); $this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['$id']);
$this->assertEquals(2, $response['body']['type']);
$this->assertIsNumeric($response['body']['expire']); $this->assertIsNumeric($response['body']['expire']);
$lastEmail = $this->getLastEmail(); $lastEmail = $this->getLastEmail();
@ -940,7 +939,6 @@ trait AccountBase
$this->assertEquals(201, $response['headers']['status-code']); $this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['$id']);
$this->assertEquals(3, $response['body']['type']);
$this->assertIsNumeric($response['body']['expire']); $this->assertIsNumeric($response['body']['expire']);
$lastEmail = $this->getLastEmail(); $lastEmail = $this->getLastEmail();

View file

@ -221,10 +221,10 @@ class ProjectsConsoleClientTest extends Scope
$this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['$id']);
$this->assertEquals('Project Test 2', $response['body']['name']); $this->assertEquals('Project Test 2', $response['body']['name']);
// $this->assertArrayHasKey('platforms', $response['body']); // TODO enable when response model is enabled $this->assertArrayHasKey('platforms', $response['body']);
// $this->assertArrayHasKey('webhooks', $response['body']); // TODO enable when response model is enabled $this->assertArrayHasKey('webhooks', $response['body']);
// $this->assertArrayHasKey('keys', $response['body']); // TODO enable when response model is enabled $this->assertArrayHasKey('keys', $response['body']);
// $this->assertArrayHasKey('tasks', $response['body']); // TODO enable when response model is enabled $this->assertArrayHasKey('tasks', $response['body']);
$projectId = $response['body']['$id']; $projectId = $response['body']['$id'];
@ -443,7 +443,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertIsBool($response['body']['security']); $this->assertIsBool($response['body']['security']);
$this->assertEquals(false, $response['body']['security']); $this->assertEquals(false, $response['body']['security']);
$this->assertEquals('', $response['body']['httpUser']); $this->assertEquals('', $response['body']['httpUser']);
// $this->assertEquals('', $response['body']['httpPass']); // TODO add after encrypt refactor $this->assertEquals('', $response['body']['httpPass']);
$response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([ $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/webhooks/'.$webhookId, array_merge([
'content-type' => 'application/json', 'content-type' => 'application/json',
@ -462,7 +462,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertIsBool($response['body']['security']); $this->assertIsBool($response['body']['security']);
$this->assertEquals(false, $response['body']['security']); $this->assertEquals(false, $response['body']['security']);
$this->assertEquals('', $response['body']['httpUser']); $this->assertEquals('', $response['body']['httpUser']);
// $this->assertEquals('', $response['body']['httpPass']); // TODO add after encrypt refactor $this->assertEquals('', $response['body']['httpPass']);
/** /**
* Test for FAILURE * Test for FAILURE
@ -759,7 +759,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertContains('demo:value', $response['body']['httpHeaders']); $this->assertContains('demo:value', $response['body']['httpHeaders']);
$this->assertCount(1, $response['body']['httpHeaders']); $this->assertCount(1, $response['body']['httpHeaders']);
$this->assertEquals('username', $response['body']['httpUser']); $this->assertEquals('username', $response['body']['httpUser']);
// $this->assertEquals('password', $response['body']['httpPass']); // TODO add after encrypt refactor $this->assertEquals('password', $response['body']['httpPass']);
$data = array_merge($data, ['taskId' => $response['body']['$id']]); $data = array_merge($data, ['taskId' => $response['body']['$id']]);
@ -901,7 +901,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertContains('demo:value', $response['body']['httpHeaders']); $this->assertContains('demo:value', $response['body']['httpHeaders']);
$this->assertCount(1, $response['body']['httpHeaders']); $this->assertCount(1, $response['body']['httpHeaders']);
$this->assertEquals('username', $response['body']['httpUser']); $this->assertEquals('username', $response['body']['httpUser']);
// $this->assertEquals('password', $response['body']['httpPass']); // TODO add after encrypt refactor $this->assertEquals('password', $response['body']['httpPass']);
/** /**
* Test for FAILURE * Test for FAILURE
@ -952,7 +952,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertContains('demo2:value2', $response['body']['httpHeaders']); $this->assertContains('demo2:value2', $response['body']['httpHeaders']);
$this->assertCount(2, $response['body']['httpHeaders']); $this->assertCount(2, $response['body']['httpHeaders']);
$this->assertEquals('username1', $response['body']['httpUser']); $this->assertEquals('username1', $response['body']['httpUser']);
// $this->assertEquals('password1', $response['body']['httpPass']); // TODO add after encrypt refactor $this->assertEquals('password1', $response['body']['httpPass']);
$response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/tasks/'.$taskId, array_merge([ $response = $this->client->call(Client::METHOD_GET, '/projects/'.$id.'/tasks/'.$taskId, array_merge([
'content-type' => 'application/json', 'content-type' => 'application/json',
@ -972,7 +972,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertContains('demo2:value2', $response['body']['httpHeaders']); $this->assertContains('demo2:value2', $response['body']['httpHeaders']);
$this->assertCount(2, $response['body']['httpHeaders']); $this->assertCount(2, $response['body']['httpHeaders']);
$this->assertEquals('username1', $response['body']['httpUser']); $this->assertEquals('username1', $response['body']['httpUser']);
// $this->assertEquals('password1', $response['body']['httpPass']); // TODO add after encrypt refactor $this->assertEquals('password1', $response['body']['httpPass']);
/** /**
* Test for FAILURE * Test for FAILURE

View file

@ -118,4 +118,38 @@ class AuthTest extends TestCase
$this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_LOGIN, $secret), false); $this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_LOGIN, $secret), false);
$this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_LOGIN, 'false-secret'), false); $this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_LOGIN, 'false-secret'), false);
} }
public function testIsPreviliggedUser()
{
$this->assertEquals(false, Auth::isPreviliggedUser([]));
$this->assertEquals(false, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_GUEST => true]));
$this->assertEquals(false, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_MEMBER => true]));
$this->assertEquals(true, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_ADMIN => true]));
$this->assertEquals(true, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_DEVELOPER => true]));
$this->assertEquals(true, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_OWNER => true]));
$this->assertEquals(false, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_APP => true]));
$this->assertEquals(false, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_SYSTEM => true]));
$this->assertEquals(false, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_APP => true, 'role:'.Auth::USER_ROLE_APP => true]));
$this->assertEquals(false, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_APP => true, 'role:'.Auth::USER_ROLE_GUEST => true]));
$this->assertEquals(true, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_OWNER => true, 'role:'.Auth::USER_ROLE_GUEST => true]));
$this->assertEquals(true, Auth::isPreviliggedUser(['role:'.Auth::USER_ROLE_OWNER => true, 'role:'.Auth::USER_ROLE_ADMIN => true, 'role:'.Auth::USER_ROLE_DEVELOPER => true]));
}
public function testIsAppUser()
{
$this->assertEquals(false, Auth::isAppUser([]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_GUEST => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_MEMBER => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_ADMIN => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_DEVELOPER => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_OWNER => true]));
$this->assertEquals(true, Auth::isAppUser(['role:'.Auth::USER_ROLE_APP => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_SYSTEM => true]));
$this->assertEquals(true, Auth::isAppUser(['role:'.Auth::USER_ROLE_APP => true, 'role:'.Auth::USER_ROLE_APP => true]));
$this->assertEquals(true, Auth::isAppUser(['role:'.Auth::USER_ROLE_APP => true, 'role:'.Auth::USER_ROLE_GUEST => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_OWNER => true, 'role:'.Auth::USER_ROLE_GUEST => true]));
$this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_OWNER => true, 'role:'.Auth::USER_ROLE_ADMIN => true, 'role:'.Auth::USER_ROLE_DEVELOPER => true]));
}
} }

View file

@ -0,0 +1,83 @@
<?php
namespace Appwrite\Tests;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
use PHPUnit\Framework\TestCase;
class AuthorizationTest extends TestCase
{
/**
* @var Authorization
*/
protected $object = null;
/**
* @var Document
*/
protected $document = null;
public function setUp(): void
{
$this->document = new Document([
'$id' => uniqid(),
'$collection' => uniqid(),
'$permissions' => [
'read' => ['user:123', 'team:123'],
'write' => ['*'],
],
]);
$this->object = new Authorization($this->document, 'read');
}
public function tearDown(): void
{
}
public function testValues()
{
$this->assertEquals($this->object->isValid($this->document->getPermissions()), false);
Authorization::setRole('user:456');
Authorization::setRole('user:123');
$this->assertEquals(Authorization::isRole('user:456'), true);
$this->assertEquals(Authorization::isRole('user:457'), false);
$this->assertEquals(Authorization::isRole(''), false);
$this->assertEquals(Authorization::isRole('*'), true);
$this->assertEquals($this->object->isValid($this->document->getPermissions()), true);
Authorization::cleanRoles();
$this->assertEquals($this->object->isValid($this->document->getPermissions()), false);
Authorization::setRole('team:123');
$this->assertEquals($this->object->isValid($this->document->getPermissions()), true);
Authorization::cleanRoles();
Authorization::disable();
$this->assertEquals($this->object->isValid($this->document->getPermissions()), true);
Authorization::reset();
$this->assertEquals($this->object->isValid($this->document->getPermissions()), false);
Authorization::setDefaultStatus(false);
Authorization::disable();
$this->assertEquals($this->object->isValid($this->document->getPermissions()), true);
Authorization::reset();
$this->assertEquals($this->object->isValid($this->document->getPermissions()), true);
Authorization::enable();
$this->assertEquals($this->object->isValid($this->document->getPermissions()), false);
}
}