Merge branch '0.7.x' of github.com:appwrite/appwrite into feat-upgrade-php-version
This commit is contained in:
commit
bc16ec93db
3
.env
3
.env
|
@ -34,4 +34,5 @@ _APP_FUNCTIONS_CPUS=1
|
|||
_APP_FUNCTIONS_MEMORY=128
|
||||
_APP_FUNCTIONS_MEMORY_SWAP=128
|
||||
_APP_MAINTENANCE_INTERVAL=86400
|
||||
_APP_SYSTEM_RESPONSE_FORMAT=
|
||||
_APP_SYSTEM_RESPONSE_FORMAT=
|
||||
_APP_USAGE_STATS=enabled
|
|
@ -18,6 +18,12 @@ before_install:
|
|||
- mkdir -p $HOME/.docker
|
||||
- echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json
|
||||
- sudo service docker start
|
||||
- >
|
||||
if [ ! -z "${DOCKERHUB_PULL_USERNAME:-}" ]; then
|
||||
set +x
|
||||
echo "${DOCKERHUB_PULL_PASSWORD}" | docker login --username "${DOCKERHUB_PULL_USERNAME}" --password-stdin
|
||||
set -x
|
||||
fi
|
||||
|
||||
install:
|
||||
- docker --version
|
||||
|
|
|
@ -37,8 +37,11 @@
|
|||
- Added new environment variables for ClamAV hostname and port ([#780](https://github.com/appwrite/appwrite/pull/780))
|
||||
- New OAuth adapter for Box.com (@armino-dev - [#420](https://github.com/appwrite/appwrite/issues/410))
|
||||
- New OAuth adapter for PayPal sandbox (@armino-dev - [#420](https://github.com/appwrite/appwrite/issues/410))
|
||||
- Introducing new permssion types: role:guest, role:member, role:app
|
||||
- Disabled rate-limits on server side integrations
|
||||
|
||||
### User Interface
|
||||
|
||||
- Updated grid for OAuth2 providers list in the console ([#413](https://github.com/appwrite/appwrite/issues/413))
|
||||
- Added Google Fonts to Appwrite for offline availability
|
||||
- Added option to delete user from the console (@PineappleIOnic - [#538](https://github.com/appwrite/appwrite/issues/538))
|
||||
|
@ -53,6 +56,7 @@
|
|||
- Added toggle to hide/show secret keys and passwords inside the dashboard (@kodumbeats, [#535](https://github.com/appwrite/appwrite/issues/535))
|
||||
|
||||
### Upgrades
|
||||
|
||||
- Upgraded QR codes generator library (@PedroCisnerosSantana - [#475](https://github.com/appwrite/appwrite/issues/475))
|
||||
- Upgraded Traefik image to version 2.3
|
||||
- Upgraded MariaDB to version 10.5.5
|
||||
|
@ -63,6 +67,7 @@
|
|||
- Upgraded device detctor to version 3.12.6
|
||||
|
||||
## Breaking Changes (Read before upgrading!)
|
||||
|
||||
- **Deprecated** `first` and `last` query params for documents list route in the database API
|
||||
- **Deprecated** Deprectaed Pubjabi Translations ('pn')
|
||||
- **Deprecated** `PATCH /account/prefs` is now updating the prefs payload and not just merging it
|
||||
|
@ -100,6 +105,7 @@
|
|||
- Fixed OAuth redirect when using the self-hosted instance default success URL ([#454](https://github.com/appwrite/appwrite/issues/454))
|
||||
- Fixed bug denying authentication with Github OAuth provider
|
||||
- Fixed a bug making read permission overwrite write permission in some cases
|
||||
|
||||
## Security
|
||||
|
||||
- Access to Health API now requires authentication with an API Key with access to `health.read` scope allowed
|
||||
|
|
|
@ -119,6 +119,7 @@ ENV _APP_SERVER=swoole \
|
|||
_APP_FUNCTIONS_MEMORY_SWAP=128 \
|
||||
_APP_SETUP=self-hosted \
|
||||
_APP_VERSION=$VERSION \
|
||||
_APP_USAGE_STATS=enabled \
|
||||
# 1 Day = 86400 s
|
||||
_APP_MAINTENANCE_INTERVAL=86400
|
||||
#ENV _APP_SMTP_SECURE ''
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
<?php
|
||||
|
||||
const ROLE_GUEST = 0;
|
||||
const ROLE_MEMBER = 1;
|
||||
const ROLE_ADMIN = 2;
|
||||
const ROLE_DEVELOPER = 3;
|
||||
const ROLE_OWNER = 4;
|
||||
const ROLE_APP = 5;
|
||||
const ROLE_SYSTEM = 6;
|
||||
const ROLE_ALL = '*';
|
||||
use Appwrite\Auth\Auth;
|
||||
|
||||
$logged = [
|
||||
'public',
|
||||
|
@ -57,7 +50,7 @@ $admins = [
|
|||
];
|
||||
|
||||
return [
|
||||
ROLE_GUEST => [
|
||||
Auth::USER_ROLE_GUEST => [
|
||||
'label' => 'Guest',
|
||||
'scopes' => [
|
||||
'public',
|
||||
|
@ -71,23 +64,23 @@ return [
|
|||
'execution.write',
|
||||
],
|
||||
],
|
||||
ROLE_MEMBER => [
|
||||
Auth::USER_ROLE_MEMBER => [
|
||||
'label' => 'Member',
|
||||
'scopes' => \array_merge($logged, []),
|
||||
],
|
||||
ROLE_ADMIN => [
|
||||
Auth::USER_ROLE_ADMIN => [
|
||||
'label' => 'Admin',
|
||||
'scopes' => \array_merge($admins, []),
|
||||
],
|
||||
ROLE_DEVELOPER => [
|
||||
Auth::USER_ROLE_DEVELOPER => [
|
||||
'label' => 'Developer',
|
||||
'scopes' => \array_merge($admins, []),
|
||||
],
|
||||
ROLE_OWNER => [
|
||||
Auth::USER_ROLE_OWNER => [
|
||||
'label' => 'Owner',
|
||||
'scopes' => \array_merge($logged, $admins, []),
|
||||
],
|
||||
ROLE_APP => [
|
||||
Auth::USER_ROLE_APP => [
|
||||
'label' => 'Application',
|
||||
'scopes' => ['health.read'],
|
||||
],
|
||||
|
|
|
@ -93,6 +93,14 @@ return [
|
|||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
[
|
||||
'name' => '_APP_USAGE_STATS',
|
||||
'description' => 'This variable allows you to disable the collection and displaying of usage stats. This value is set to \'enabled\' by default, to disable the usage stats set the value to \'disabled\'. When disabled, it\'s recommended to turn off the Worker Usage, Influxdb and Telegraf containers for better resource usage.',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => 'enabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
|
|
|
@ -156,96 +156,100 @@ App::get('/v1/functions/:functionId/usage')
|
|||
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||
throw new Exception('Function not found', 404);
|
||||
}
|
||||
|
||||
$period = [
|
||||
'24h' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||
'group' => '30m',
|
||||
],
|
||||
'7d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'30d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'90d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
];
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
$executions = [];
|
||||
$failures = [];
|
||||
$compute = [];
|
||||
|
||||
if ($client) {
|
||||
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||
$database = $client->selectDB('telegraf');
|
||||
|
||||
// Executions
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$executions[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Failures
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' AND "functionStatus"=\'failed\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$failures[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Compute
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_time" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$compute[] = [
|
||||
'value' => round((!empty($point['value'])) ? $point['value'] / 1000 : 0, 2), // minutes
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
|
||||
if($App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
|
||||
$period = [
|
||||
'24h' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||
'group' => '30m',
|
||||
],
|
||||
'7d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'30d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'90d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
];
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
$executions = [];
|
||||
$failures = [];
|
||||
$compute = [];
|
||||
|
||||
if ($client) {
|
||||
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||
$database = $client->selectDB('telegraf');
|
||||
|
||||
// Executions
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$executions[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Failures
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' AND "functionStatus"=\'failed\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$failures[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Compute
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_time" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$compute[] = [
|
||||
'value' => round((!empty($point['value'])) ? $point['value'] / 1000 : 0, 2), // minutes
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$response->json([
|
||||
'range' => $range,
|
||||
'executions' => [
|
||||
'data' => $executions,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $executions)),
|
||||
],
|
||||
'failures' => [
|
||||
'data' => $failures,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $failures)),
|
||||
],
|
||||
'compute' => [
|
||||
'data' => $compute,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $compute)),
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
$response->json([]);
|
||||
}
|
||||
|
||||
$response->json([
|
||||
'range' => $range,
|
||||
'executions' => [
|
||||
'data' => $executions,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $executions)),
|
||||
],
|
||||
'failures' => [
|
||||
'data' => $failures,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $failures)),
|
||||
],
|
||||
'compute' => [
|
||||
'data' => $compute,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $compute)),
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
App::put('/v1/functions/:functionId')
|
||||
|
@ -629,6 +633,8 @@ App::post('/v1/functions/:functionId/executions')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_EXECUTION)
|
||||
->label('abuse-limit', 60)
|
||||
->label('abuse-time', 60)
|
||||
->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)
|
||||
->inject('response')
|
||||
|
|
|
@ -176,74 +176,82 @@ App::get('/v1/projects/:projectId/usage')
|
|||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
$period = [
|
||||
'24h' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||
'group' => '30m',
|
||||
],
|
||||
'7d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'30d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'90d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
];
|
||||
if(App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
$requests = [];
|
||||
$network = [];
|
||||
$functions = [];
|
||||
|
||||
if ($client) {
|
||||
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||
$database = $client->selectDB('telegraf');
|
||||
|
||||
// Requests
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_requests_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$requests[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Network
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_network_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$network[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Functions
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$functions[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
$period = [
|
||||
'24h' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||
'group' => '30m',
|
||||
],
|
||||
'7d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'30d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'90d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
];
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
$requests = [];
|
||||
$network = [];
|
||||
$functions = [];
|
||||
|
||||
if ($client) {
|
||||
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||
$database = $client->selectDB('telegraf');
|
||||
|
||||
// Requests
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_requests_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$requests[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Network
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_network_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$network[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Functions
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$functions[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$requests = [];
|
||||
$network = [];
|
||||
$functions = [];
|
||||
}
|
||||
|
||||
|
||||
// Users
|
||||
|
||||
$projectDB->getCollection([
|
||||
|
|
|
@ -418,7 +418,6 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
|||
->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)
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->param('sessionId', null, new UID(), 'User unique session ID.')
|
||||
->inject('response')
|
||||
|
@ -465,7 +464,6 @@ App::delete('/v1/users/:userId/sessions')
|
|||
->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)
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
|
@ -509,7 +507,6 @@ App::delete('/v1/users/:userId')
|
|||
->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)
|
||||
->param('userId', '', function () {return new UID();}, 'User unique ID.')
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
|
|
|
@ -23,19 +23,13 @@ Config::setParam('domainVerification', false);
|
|||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $events, $audits, $usage, $deletes, $clients) {
|
||||
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $clients) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $console */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Utopia\Locale\Locale $locale */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $usage */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
/** @var Appwrite\Event\Event $functions */
|
||||
|
||||
/** @var bool $mode */
|
||||
/** @var array $clients */
|
||||
|
||||
|
@ -51,13 +45,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
throw new Exception('Missing or unknown project ID', 400);
|
||||
}
|
||||
|
||||
$console->setAttribute('platforms', [ // Allways allow current host
|
||||
'$collection' => Database::SYSTEM_COLLECTION_PLATFORMS,
|
||||
'name' => 'Current Host',
|
||||
'type' => 'web',
|
||||
'hostname' => $request->getHostname(),
|
||||
], Document::SET_TYPE_APPEND);
|
||||
|
||||
$referrer = $request->getReferer();
|
||||
$origin = \parse_url($request->getOrigin($referrer), PHP_URL_HOST);
|
||||
$protocol = \parse_url($request->getOrigin($referrer), PHP_URL_SCHEME);
|
||||
|
@ -127,8 +114,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
|
||||
$response
|
||||
->addHeader('Server', 'Appwrite')
|
||||
->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url='.\urlencode($request->getURI()))
|
||||
//->addHeader('X-Frame-Options', ($refDomain == 'http://localhost') ? 'SAMEORIGIN' : 'ALLOW-FROM ' . $refDomain)
|
||||
->addHeader('X-Content-Type-Options', 'nosniff')
|
||||
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
|
||||
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-SDK-Version, Cache-Control, Expires, Pragma')
|
||||
|
@ -140,7 +125,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
/*
|
||||
* Validate Client Domain - Check to avoid CSRF attack
|
||||
* Adding Appwrite API domains to allow XDOMAIN communication
|
||||
* Skip this check for non-web platforms which are not requiredto send an origin header
|
||||
* Skip this check for non-web platforms which are not required to send an origin header
|
||||
*/
|
||||
$origin = $request->getOrigin($request->getReferer(''));
|
||||
$originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', [])));
|
||||
|
@ -236,99 +221,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
throw new Exception('Password reset is required', 412);
|
||||
}
|
||||
|
||||
/*
|
||||
* Background Jobs
|
||||
*/
|
||||
|
||||
$events
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', $route->getLabel('event', ''))
|
||||
->setParam('payload', [])
|
||||
->setParam('functionId', null)
|
||||
->setParam('executionId', null)
|
||||
->setParam('trigger', 'event')
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', '')
|
||||
->setParam('resource', '')
|
||||
->setParam('userAgent', $request->getUserAgent(''))
|
||||
->setParam('ip', $request->getIP())
|
||||
->setParam('data', [])
|
||||
;
|
||||
|
||||
$usage
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('httpRequest', 1)
|
||||
->setParam('httpUrl', $request->getHostname().$request->getURI())
|
||||
->setParam('httpMethod', $request->getMethod())
|
||||
->setParam('networkRequestSize', 0)
|
||||
->setParam('networkResponseSize', 0)
|
||||
->setParam('storage', 0)
|
||||
;
|
||||
|
||||
$deletes
|
||||
->setParam('projectId', $project->getId())
|
||||
;
|
||||
|
||||
}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'events', 'audits', 'usage', 'deletes', 'clients']);
|
||||
|
||||
App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $mode) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $usage */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
/** @var Appwrite\Event\Event $functions */
|
||||
/** @var bool $mode */
|
||||
|
||||
if (!empty($events->getParam('event'))) {
|
||||
if(empty($events->getParam('payload'))) {
|
||||
$events->setParam('payload', $response->getPayload());
|
||||
}
|
||||
|
||||
$webhooks = clone $events;
|
||||
$functions = clone $events;
|
||||
|
||||
$webhooks
|
||||
->setQueue('v1-webhooks')
|
||||
->setClass('WebhooksV1')
|
||||
->trigger();
|
||||
|
||||
$functions
|
||||
->setQueue('v1-functions')
|
||||
->setClass('FunctionsV1')
|
||||
->trigger();
|
||||
}
|
||||
|
||||
if (!empty($audits->getParam('event'))) {
|
||||
$audits->trigger();
|
||||
}
|
||||
|
||||
if (!empty($deletes->getParam('type')) && !empty($deletes->getParam('document'))) {
|
||||
$deletes->trigger();
|
||||
}
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
if ($project->getId()
|
||||
&& $mode !== APP_MODE_ADMIN //TODO: add check to make sure user is admin
|
||||
&& !empty($route->getLabel('sdk.namespace', null))) { // Don't calculate console usage on admin mode
|
||||
|
||||
$usage
|
||||
->setParam('networkRequestSize', $request->getSize() + $usage->getParam('storage'))
|
||||
->setParam('networkResponseSize', $response->getSize())
|
||||
->trigger()
|
||||
;
|
||||
}
|
||||
|
||||
}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'mode']);
|
||||
}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'clients']);
|
||||
|
||||
App::options(function ($request, $response) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
|
|
|
@ -1,17 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Database\Validator\Authorization;
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Abuse\Abuse;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
use Appwrite\Storage\Device\Local;
|
||||
use Appwrite\Storage\Storage;
|
||||
|
||||
App::init(function ($utopia, $request, $response, $project, $user, $register) {
|
||||
App::init(function ($utopia, $request, $response, $project, $user, $register, $events, $audits, $usage, $deletes) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Utopia\Registry\Registry $register */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $usage */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
/** @var Appwrite\Event\Event $functions */
|
||||
|
||||
Storage::setDevice('files', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
|
||||
Storage::setDevice('functions', new Local(APP_STORAGE_FUNCTIONS.'/app-'.$project->getId()));
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
|
@ -49,7 +61,105 @@ App::init(function ($utopia, $request, $response, $project, $user, $register) {
|
|||
;
|
||||
}
|
||||
|
||||
if ($abuse->check() && App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') {
|
||||
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
if (($abuse->check() // Route is rate-limited
|
||||
&& App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') // Abuse is not diabled
|
||||
&& (!$isAppUser && !$isPreviliggedUser)) // User is not an admin or API key
|
||||
{
|
||||
throw new Exception('Too many requests', 429);
|
||||
}
|
||||
}, ['utopia', 'request', 'response', 'project', 'user', 'register'], 'api');
|
||||
|
||||
/*
|
||||
* Background Jobs
|
||||
*/
|
||||
$events
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', $route->getLabel('event', ''))
|
||||
->setParam('payload', [])
|
||||
->setParam('functionId', null)
|
||||
->setParam('executionId', null)
|
||||
->setParam('trigger', 'event')
|
||||
;
|
||||
|
||||
$audits
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', '')
|
||||
->setParam('resource', '')
|
||||
->setParam('userAgent', $request->getUserAgent(''))
|
||||
->setParam('ip', $request->getIP())
|
||||
->setParam('data', [])
|
||||
;
|
||||
|
||||
$usage
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('httpRequest', 1)
|
||||
->setParam('httpUrl', $request->getHostname().$request->getURI())
|
||||
->setParam('httpMethod', $request->getMethod())
|
||||
->setParam('networkRequestSize', 0)
|
||||
->setParam('networkResponseSize', 0)
|
||||
->setParam('storage', 0)
|
||||
;
|
||||
|
||||
$deletes
|
||||
->setParam('projectId', $project->getId())
|
||||
;
|
||||
|
||||
}, ['utopia', 'request', 'response', 'project', 'user', 'register', 'events', 'audits', 'usage', 'deletes'], 'api');
|
||||
|
||||
App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $mode) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $usage */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
/** @var Appwrite\Event\Event $functions */
|
||||
/** @var bool $mode */
|
||||
|
||||
if (!empty($events->getParam('event'))) {
|
||||
if(empty($events->getParam('payload'))) {
|
||||
$events->setParam('payload', $response->getPayload());
|
||||
}
|
||||
|
||||
$webhooks = clone $events;
|
||||
$functions = clone $events;
|
||||
|
||||
$webhooks
|
||||
->setQueue('v1-webhooks')
|
||||
->setClass('WebhooksV1')
|
||||
->trigger();
|
||||
|
||||
$functions
|
||||
->setQueue('v1-functions')
|
||||
->setClass('FunctionsV1')
|
||||
->trigger();
|
||||
}
|
||||
|
||||
if (!empty($audits->getParam('event'))) {
|
||||
$audits->trigger();
|
||||
}
|
||||
|
||||
if (!empty($deletes->getParam('type')) && !empty($deletes->getParam('document'))) {
|
||||
$deletes->trigger();
|
||||
}
|
||||
|
||||
$route = $utopia->match($request);
|
||||
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled'
|
||||
&& $project->getId()
|
||||
&& $mode !== APP_MODE_ADMIN //TODO: add check to make sure user is admin
|
||||
&& !empty($route->getLabel('sdk.namespace', null))) { // Don't calculate console usage on admin mode
|
||||
|
||||
$usage
|
||||
->setParam('networkRequestSize', $request->getSize() + $usage->getParam('storage'))
|
||||
->setParam('networkResponseSize', $response->getSize())
|
||||
->trigger()
|
||||
;
|
||||
}
|
||||
|
||||
}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'mode'], 'api');
|
||||
|
|
|
@ -37,6 +37,7 @@ App::init(function ($utopia, $request, $response, $layout) {
|
|||
->addHeader('Cache-Control', 'public, max-age='.$time)
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache
|
||||
->addHeader('X-Frame-Options', 'SAMEORIGIN') // Avoid console and homepage from showing in iframes
|
||||
->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url='.\urlencode($request->getURI()))
|
||||
->addHeader('X-UA-Compatible', 'IE=Edge') // Deny IE browsers from going into quirks mode
|
||||
;
|
||||
|
||||
|
|
|
@ -122,7 +122,8 @@ App::get('/console/home')
|
|||
/** @var Utopia\View $layout */
|
||||
|
||||
$page = new View(__DIR__.'/../../views/console/home/index.phtml');
|
||||
|
||||
$page
|
||||
->setParam('usageStatsEnabled',App::getEnv('_APP_USAGE_STATS','enabled') == 'enabled');
|
||||
$layout
|
||||
->setParam('title', APP_NAME.' - Console')
|
||||
->setParam('body', $page);
|
||||
|
@ -390,6 +391,7 @@ App::get('/console/functions/function')
|
|||
->setParam('fileLimit', App::getEnv('_APP_STORAGE_LIMIT', 0))
|
||||
->setParam('fileLimitHuman', Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0)))
|
||||
->setParam('timeout', (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900))
|
||||
->setParam('usageStatsEnabled',App::getEnv('_APP_USAGE_STATS','enabled') == 'enabled');
|
||||
;
|
||||
|
||||
$layout
|
||||
|
|
11
app/init.php
11
app/init.php
|
@ -319,7 +319,14 @@ App::setResource('deletes', function($register) {
|
|||
}, ['register']);
|
||||
|
||||
// Test Mock
|
||||
App::setResource('clients', function($console, $project) {
|
||||
App::setResource('clients', function($request, $console, $project) {
|
||||
$console->setAttribute('platforms', [ // Allways allow current host
|
||||
'$collection' => Database::SYSTEM_COLLECTION_PLATFORMS,
|
||||
'name' => 'Current Host',
|
||||
'type' => 'web',
|
||||
'hostname' => $request->getHostname(),
|
||||
], Document::SET_TYPE_APPEND);
|
||||
|
||||
/**
|
||||
* Get All verified client URLs for both console and current projects
|
||||
* + Filter for duplicated entries
|
||||
|
@ -345,7 +352,7 @@ App::setResource('clients', function($console, $project) {
|
|||
}))));
|
||||
|
||||
return $clients;
|
||||
}, ['console', 'project']);
|
||||
}, ['request', 'console', 'project']);
|
||||
|
||||
App::setResource('user', function($mode, $project, $console, $request, $response, $projectDB, $consoleDB) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
|
|
|
@ -3,6 +3,7 @@ $fileLimit = $this->getParam('fileLimit', 0);
|
|||
$fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
$events = array_keys($this->getParam('events', []));
|
||||
$timeout = $this->getParam('timeout', 900);
|
||||
$usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
?>
|
||||
<div
|
||||
data-service="functions.get"
|
||||
|
@ -240,6 +241,7 @@ $timeout = $this->getParam('timeout', 900);
|
|||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<?php if($usageStatsEnabled): ?>
|
||||
<li data-state="/console/functions/function/monitors?id={{router.params.id}}&project={{router.params.project}}">
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
|
||||
|
@ -318,6 +320,7 @@ $timeout = $this->getParam('timeout', 900);
|
|||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<li data-state="/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}">
|
||||
|
||||
<div class="text-fade text-size-small pull-end margin-top" data-ls-bind="{{project-function-executions.sum}} executions found"></div>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
$graph = $this->getParam('graph', false);
|
||||
$usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
?>
|
||||
|
||||
<div class="cover margin-bottom-small">
|
||||
|
@ -68,7 +69,7 @@ $graph = $this->getParam('graph', false);
|
|||
data-param-project-id="{{router.params.project}}"
|
||||
data-param-range="30d">
|
||||
|
||||
<?php if (!$graph) : ?>
|
||||
<?php if (!$graph && $usageStatsEnabled): ?>
|
||||
<div class="box dashboard">
|
||||
<div class="row responsive">
|
||||
<div class="col span-9">
|
||||
|
|
|
@ -57,7 +57,7 @@ $scopes = $this->getParam('scopes', []);
|
|||
<div class="row responsive thin">
|
||||
<?php foreach ($scopes as $i => $scope) : ?>
|
||||
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $scope; ?>">
|
||||
<input type="checkbox" name="scopes" data-ls-bind="{{key.scopes}}" value="<?php echo $scope; ?>" /> <?php echo $scope; ?>
|
||||
<input data-ls-attrs="id=scope-<?php echo $scope; ?>" type="checkbox" name="scopes" data-ls-bind="{{key.scopes}}" value="<?php echo $scope; ?>" /> <?php echo $scope; ?>
|
||||
</div>
|
||||
<?php if (($i + 1) % 2 === 0) : ?>
|
||||
</div>
|
||||
|
|
|
@ -76,6 +76,7 @@ services:
|
|||
- _APP_SMTP_SECURE
|
||||
- _APP_SMTP_USERNAME
|
||||
- _APP_SMTP_PASSWORD
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_INFLUXDB_HOST
|
||||
- _APP_INFLUXDB_PORT
|
||||
- _APP_STORAGE_LIMIT
|
||||
|
@ -239,6 +240,7 @@ services:
|
|||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_MEMORY_SWAP
|
||||
- _APP_USAGE_STATS
|
||||
|
||||
appwrite-worker-mails:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
|
@ -370,5 +372,4 @@ volumes:
|
|||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-influxdb:
|
||||
appwrite-chronograf:
|
||||
appwrite-config:
|
||||
|
|
|
@ -470,8 +470,10 @@ class FunctionsV1
|
|||
->setParam('networkRequestSize', 0)
|
||||
->setParam('networkResponseSize', 0)
|
||||
;
|
||||
|
||||
$usage->trigger();
|
||||
|
||||
if($App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
|
||||
$usage->trigger();
|
||||
}
|
||||
|
||||
$this->cleanup();
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ services:
|
|||
- _APP_SMTP_SECURE
|
||||
- _APP_SMTP_USERNAME
|
||||
- _APP_SMTP_PASSWORD
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_INFLUXDB_HOST
|
||||
- _APP_INFLUXDB_PORT
|
||||
- _APP_STORAGE_LIMIT
|
||||
|
@ -292,6 +293,7 @@ services:
|
|||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_MEMORY_SWAP
|
||||
- _APP_USAGE_STATS
|
||||
|
||||
appwrite-worker-mails:
|
||||
entrypoint: worker-mails
|
||||
|
|
4
public/dist/scripts/app-all.js
vendored
4
public/dist/scripts/app-all.js
vendored
|
@ -2330,8 +2330,8 @@ var variations={digits:/\d/.test(password),lower:/[a-z]/.test(password),upper:/[
|
|||
score+=(variationCount-1)*10;return parseInt(score);};var callback=function(){var score=calc(this.value);if(""===this.value)return(meter.className="password-meter");if(score>60)return(meter.className="password-meter strong");if(score>30)return(meter.className="password-meter medium");if(score>=0)return(meter.className="password-meter weak");};var meter=window.document.createElement("div");meter.className="password-meter";element.parentNode.insertBefore(meter,element.nextSibling);element.addEventListener("change",callback);element.addEventListener("keypress",callback);element.addEventListener("keyup",callback);element.addEventListener("keydown",callback);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-pell",controller:function(element,window,document,markdown,rtl){var div=document.createElement("div");element.className="pell hide";div.className="input pell";element.parentNode.insertBefore(div,element);element.tabIndex=-1;var turndownService=new TurndownService();turndownService.addRule("underline",{filter:["u"],replacement:function(content){return"__"+content+"__";}});var editor=window.pell.init({element:div,onChange:function onChange(html){alignText();element.value=turndownService.turndown(html);},defaultParagraphSeparator:"p",actions:[{name:"bold",icon:'<i class="icon-bold"></i>'},{name:"underline",icon:'<i class="icon-underline"></i>'},{name:"italic",icon:'<i class="icon-italic"></i>'},{name:"olist",icon:'<i class="icon-list-numbered"></i>'},{name:"ulist",icon:'<i class="icon-list-bullet"></i>'},{name:"link",icon:'<i class="icon-link"></i>'}]});var clean=function(e){e.stopPropagation();e.preventDefault();var clipboardData=e.clipboardData||window.clipboardData;console.log(clipboardData.getData("Text"));window.pell.exec("insertText",clipboardData.getData("Text"));return true;};var alignText=function(){let paragraphs=editor.content.querySelectorAll('p,li');let last='';for(let paragraph of paragraphs){var content=paragraph.textContent;if(content.trim()===''){content=last.textContent;}
|
||||
if(rtl.isRTL(content)){paragraph.style.direction='rtl';paragraph.style.textAlign='right';}
|
||||
else{paragraph.style.direction='ltr';paragraph.style.textAlign='left';}
|
||||
last=paragraph;}};var santize=function(e){clean(e);alignText(e);};element.addEventListener("change",function(){editor.content.innerHTML=markdown.render(element.value);alignText();});editor.content.setAttribute("placeholder",element.placeholder);editor.content.innerHTML=markdown.render(element.value);editor.content.tabIndex=0;alignText();editor.content.onkeydown=function preventTab(event){if(event.which===9){event.preventDefault();if(document.activeElement){var focussable=Array.prototype.filter.call(document.querySelectorAll('a:not([disabled]), button:not([disabled]), select:not([disabled]), input[type=text]:not([disabled]), input[type=checkbox]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'),function(element){return(element.offsetWidth>0||element.offsetHeight>0||element===document.activeElement);});var index=focussable.indexOf(document.activeElement);if(index>-1){if(event.shiftKey){var prevElement=focussable[index-1]||focussable[focussable.length-1];prevElement.focus();}else{var nextElement=focussable[index+1]||focussable[0];nextElement.focus();}}}}};div.addEventListener("paste",santize);div.addEventListener("drop",santize);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-remove",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){element.parentNode.removeChild(element);});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-run",repeat:false,controller:function(element,expression,container){let action=expression.parse(element.dataset["formsRun"]||'');element.addEventListener('click',function(){return container.path(action)();});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-select-all",controller:function(element){let select=document.createElement("button");let unselect=document.createElement("button");select.textContent='Select All';unselect.textContent='Unselect All';select.classList.add('link');select.classList.add('margin-top-tiny');select.classList.add('margin-start-small');select.classList.add('text-size-small');select.classList.add('pull-end');unselect.classList.add('link');unselect.classList.add('margin-top-tiny');unselect.classList.add('margin-start-small');unselect.classList.add('text-size-small');unselect.classList.add('pull-end');select.type='button';unselect.type='button';element.parentNode.insertBefore(select,element);element.parentNode.insertBefore(unselect,element);select.addEventListener('click',function(){let checkboxes=document.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=true;}})
|
||||
unselect.addEventListener('click',function(){let checkboxes=document.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=false;}})}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-show-secret",controller:function(element,document){let button=document.createElement("a");button.type="button";button.className="icon-eye";button.innerHTML="show/hide";button.style.cursor="pointer";button.style.fontSize="10px";if(element.attributes.getNamedItem("data-forms-show-secret-above")){element.insertAdjacentElement("beforebegin",button);}else{element.parentNode.insertBefore(button,element.nextSibling);}
|
||||
last=paragraph;}};var santize=function(e){clean(e);alignText(e);};element.addEventListener("change",function(){editor.content.innerHTML=markdown.render(element.value);alignText();});editor.content.setAttribute("placeholder",element.placeholder);editor.content.innerHTML=markdown.render(element.value);editor.content.tabIndex=0;alignText();editor.content.onkeydown=function preventTab(event){if(event.which===9){event.preventDefault();if(document.activeElement){var focussable=Array.prototype.filter.call(document.querySelectorAll('a:not([disabled]), button:not([disabled]), select:not([disabled]), input[type=text]:not([disabled]), input[type=checkbox]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'),function(element){return(element.offsetWidth>0||element.offsetHeight>0||element===document.activeElement);});var index=focussable.indexOf(document.activeElement);if(index>-1){if(event.shiftKey){var prevElement=focussable[index-1]||focussable[focussable.length-1];prevElement.focus();}else{var nextElement=focussable[index+1]||focussable[0];nextElement.focus();}}}}};div.addEventListener("paste",santize);div.addEventListener("drop",santize);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-remove",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){element.parentNode.removeChild(element);});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-run",repeat:false,controller:function(element,expression,container){let action=expression.parse(element.dataset["formsRun"]||'');element.addEventListener('click',function(){return container.path(action)();});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-select-all",controller:function(element){let select=document.createElement("button");let unselect=document.createElement("button");select.textContent='Select All';unselect.textContent='Unselect All';select.classList.add('link');select.classList.add('margin-top-tiny');select.classList.add('margin-start-small');select.classList.add('text-size-small');select.classList.add('pull-end');unselect.classList.add('link');unselect.classList.add('margin-top-tiny');unselect.classList.add('margin-start-small');unselect.classList.add('text-size-small');unselect.classList.add('pull-end');select.type='button';unselect.type='button';element.parentNode.insertBefore(select,element);element.parentNode.insertBefore(unselect,element);select.addEventListener('click',function(){let checkboxes=element.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=true;checkboxes[i].dispatchEvent(new Event('change'));}})
|
||||
unselect.addEventListener('click',function(){let checkboxes=element.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=false;checkboxes[i].dispatchEvent(new Event('change'));}})}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-show-secret",controller:function(element,document){let button=document.createElement("a");button.type="button";button.className="icon-eye";button.innerHTML="show/hide";button.style.cursor="pointer";button.style.fontSize="10px";if(element.attributes.getNamedItem("data-forms-show-secret-above")){element.insertAdjacentElement("beforebegin",button);}else{element.parentNode.insertBefore(button,element.nextSibling);}
|
||||
const toggle=function(event){switch(element.type){case"password":element.type="text";break;case"text":element.type="password";break;default:console.warn("data-forms-show-secret: element.type NOT text NOR password");}};button.addEventListener("click",toggle);},});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-switch",controller:function(element){let input=window.document.createElement("input");input.type="checkbox";input.className="button switch";let syncA=function(){let value=input.checked?"true":"false"
|
||||
let old=element.value;element.value=value;if(value!==old){element.dispatchEvent(new Event('change'));}};let syncB=function(){input.checked=(element.value==="true");};input.addEventListener("input",syncA);input.addEventListener("change",syncA);element.addEventListener("input",syncB);element.addEventListener("change",syncB);syncA();element.parentNode.insertBefore(input,element);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-tags",controller:function(element){let array=[];let tags=window.document.createElement("div");let preview=window.document.createElement("ul");let add=window.document.createElement("input");let listen=function(event){if((event.key==="Enter"||event.key===" "||event.key==="Tab")&&add.value.length>0){array.push(add.value);add.value="";element.value=JSON.stringify(array);check();if(event.key!=="Tab"){event.preventDefault();}}
|
||||
if((event.key==="Backspace"||event.key==="Delete")&&add.value===""){array.splice(-1,1);element.value=JSON.stringify(array);check();}
|
||||
|
|
4
public/dist/scripts/app.js
vendored
4
public/dist/scripts/app.js
vendored
|
@ -375,8 +375,8 @@ var variations={digits:/\d/.test(password),lower:/[a-z]/.test(password),upper:/[
|
|||
score+=(variationCount-1)*10;return parseInt(score);};var callback=function(){var score=calc(this.value);if(""===this.value)return(meter.className="password-meter");if(score>60)return(meter.className="password-meter strong");if(score>30)return(meter.className="password-meter medium");if(score>=0)return(meter.className="password-meter weak");};var meter=window.document.createElement("div");meter.className="password-meter";element.parentNode.insertBefore(meter,element.nextSibling);element.addEventListener("change",callback);element.addEventListener("keypress",callback);element.addEventListener("keyup",callback);element.addEventListener("keydown",callback);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-pell",controller:function(element,window,document,markdown,rtl){var div=document.createElement("div");element.className="pell hide";div.className="input pell";element.parentNode.insertBefore(div,element);element.tabIndex=-1;var turndownService=new TurndownService();turndownService.addRule("underline",{filter:["u"],replacement:function(content){return"__"+content+"__";}});var editor=window.pell.init({element:div,onChange:function onChange(html){alignText();element.value=turndownService.turndown(html);},defaultParagraphSeparator:"p",actions:[{name:"bold",icon:'<i class="icon-bold"></i>'},{name:"underline",icon:'<i class="icon-underline"></i>'},{name:"italic",icon:'<i class="icon-italic"></i>'},{name:"olist",icon:'<i class="icon-list-numbered"></i>'},{name:"ulist",icon:'<i class="icon-list-bullet"></i>'},{name:"link",icon:'<i class="icon-link"></i>'}]});var clean=function(e){e.stopPropagation();e.preventDefault();var clipboardData=e.clipboardData||window.clipboardData;console.log(clipboardData.getData("Text"));window.pell.exec("insertText",clipboardData.getData("Text"));return true;};var alignText=function(){let paragraphs=editor.content.querySelectorAll('p,li');let last='';for(let paragraph of paragraphs){var content=paragraph.textContent;if(content.trim()===''){content=last.textContent;}
|
||||
if(rtl.isRTL(content)){paragraph.style.direction='rtl';paragraph.style.textAlign='right';}
|
||||
else{paragraph.style.direction='ltr';paragraph.style.textAlign='left';}
|
||||
last=paragraph;}};var santize=function(e){clean(e);alignText(e);};element.addEventListener("change",function(){editor.content.innerHTML=markdown.render(element.value);alignText();});editor.content.setAttribute("placeholder",element.placeholder);editor.content.innerHTML=markdown.render(element.value);editor.content.tabIndex=0;alignText();editor.content.onkeydown=function preventTab(event){if(event.which===9){event.preventDefault();if(document.activeElement){var focussable=Array.prototype.filter.call(document.querySelectorAll('a:not([disabled]), button:not([disabled]), select:not([disabled]), input[type=text]:not([disabled]), input[type=checkbox]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'),function(element){return(element.offsetWidth>0||element.offsetHeight>0||element===document.activeElement);});var index=focussable.indexOf(document.activeElement);if(index>-1){if(event.shiftKey){var prevElement=focussable[index-1]||focussable[focussable.length-1];prevElement.focus();}else{var nextElement=focussable[index+1]||focussable[0];nextElement.focus();}}}}};div.addEventListener("paste",santize);div.addEventListener("drop",santize);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-remove",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){element.parentNode.removeChild(element);});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-run",repeat:false,controller:function(element,expression,container){let action=expression.parse(element.dataset["formsRun"]||'');element.addEventListener('click',function(){return container.path(action)();});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-select-all",controller:function(element){let select=document.createElement("button");let unselect=document.createElement("button");select.textContent='Select All';unselect.textContent='Unselect All';select.classList.add('link');select.classList.add('margin-top-tiny');select.classList.add('margin-start-small');select.classList.add('text-size-small');select.classList.add('pull-end');unselect.classList.add('link');unselect.classList.add('margin-top-tiny');unselect.classList.add('margin-start-small');unselect.classList.add('text-size-small');unselect.classList.add('pull-end');select.type='button';unselect.type='button';element.parentNode.insertBefore(select,element);element.parentNode.insertBefore(unselect,element);select.addEventListener('click',function(){let checkboxes=document.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=true;}})
|
||||
unselect.addEventListener('click',function(){let checkboxes=document.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=false;}})}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-show-secret",controller:function(element,document){let button=document.createElement("a");button.type="button";button.className="icon-eye";button.innerHTML="show/hide";button.style.cursor="pointer";button.style.fontSize="10px";if(element.attributes.getNamedItem("data-forms-show-secret-above")){element.insertAdjacentElement("beforebegin",button);}else{element.parentNode.insertBefore(button,element.nextSibling);}
|
||||
last=paragraph;}};var santize=function(e){clean(e);alignText(e);};element.addEventListener("change",function(){editor.content.innerHTML=markdown.render(element.value);alignText();});editor.content.setAttribute("placeholder",element.placeholder);editor.content.innerHTML=markdown.render(element.value);editor.content.tabIndex=0;alignText();editor.content.onkeydown=function preventTab(event){if(event.which===9){event.preventDefault();if(document.activeElement){var focussable=Array.prototype.filter.call(document.querySelectorAll('a:not([disabled]), button:not([disabled]), select:not([disabled]), input[type=text]:not([disabled]), input[type=checkbox]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'),function(element){return(element.offsetWidth>0||element.offsetHeight>0||element===document.activeElement);});var index=focussable.indexOf(document.activeElement);if(index>-1){if(event.shiftKey){var prevElement=focussable[index-1]||focussable[focussable.length-1];prevElement.focus();}else{var nextElement=focussable[index+1]||focussable[0];nextElement.focus();}}}}};div.addEventListener("paste",santize);div.addEventListener("drop",santize);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-remove",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){element.parentNode.removeChild(element);});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-run",repeat:false,controller:function(element,expression,container){let action=expression.parse(element.dataset["formsRun"]||'');element.addEventListener('click',function(){return container.path(action)();});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-select-all",controller:function(element){let select=document.createElement("button");let unselect=document.createElement("button");select.textContent='Select All';unselect.textContent='Unselect All';select.classList.add('link');select.classList.add('margin-top-tiny');select.classList.add('margin-start-small');select.classList.add('text-size-small');select.classList.add('pull-end');unselect.classList.add('link');unselect.classList.add('margin-top-tiny');unselect.classList.add('margin-start-small');unselect.classList.add('text-size-small');unselect.classList.add('pull-end');select.type='button';unselect.type='button';element.parentNode.insertBefore(select,element);element.parentNode.insertBefore(unselect,element);select.addEventListener('click',function(){let checkboxes=element.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=true;checkboxes[i].dispatchEvent(new Event('change'));}})
|
||||
unselect.addEventListener('click',function(){let checkboxes=element.querySelectorAll("input[type='checkbox']");for(var i=0;i<checkboxes.length;i++){checkboxes[i].checked=false;checkboxes[i].dispatchEvent(new Event('change'));}})}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-show-secret",controller:function(element,document){let button=document.createElement("a");button.type="button";button.className="icon-eye";button.innerHTML="show/hide";button.style.cursor="pointer";button.style.fontSize="10px";if(element.attributes.getNamedItem("data-forms-show-secret-above")){element.insertAdjacentElement("beforebegin",button);}else{element.parentNode.insertBefore(button,element.nextSibling);}
|
||||
const toggle=function(event){switch(element.type){case"password":element.type="text";break;case"text":element.type="password";break;default:console.warn("data-forms-show-secret: element.type NOT text NOR password");}};button.addEventListener("click",toggle);},});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-switch",controller:function(element){let input=window.document.createElement("input");input.type="checkbox";input.className="button switch";let syncA=function(){let value=input.checked?"true":"false"
|
||||
let old=element.value;element.value=value;if(value!==old){element.dispatchEvent(new Event('change'));}};let syncB=function(){input.checked=(element.value==="true");};input.addEventListener("input",syncA);input.addEventListener("change",syncA);element.addEventListener("input",syncB);element.addEventListener("change",syncB);syncA();element.parentNode.insertBefore(input,element);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-tags",controller:function(element){let array=[];let tags=window.document.createElement("div");let preview=window.document.createElement("ul");let add=window.document.createElement("input");let listen=function(event){if((event.key==="Enter"||event.key===" "||event.key==="Tab")&&add.value.length>0){array.push(add.value);add.value="";element.value=JSON.stringify(array);check();if(event.key!=="Tab"){event.preventDefault();}}
|
||||
if((event.key==="Backspace"||event.key==="Delete")&&add.value===""){array.splice(-1,1);element.value=JSON.stringify(array);check();}
|
||||
|
|
|
@ -31,18 +31,20 @@
|
|||
element.parentNode.insertBefore(unselect, element);
|
||||
|
||||
select.addEventListener('click', function () {
|
||||
let checkboxes = document.querySelectorAll("input[type='checkbox']");
|
||||
let checkboxes = element.querySelectorAll("input[type='checkbox']");
|
||||
|
||||
for(var i = 0; i < checkboxes.length; i++) {
|
||||
checkboxes[i].checked = true;
|
||||
checkboxes[i].dispatchEvent(new Event('change'));
|
||||
}
|
||||
})
|
||||
|
||||
unselect.addEventListener('click', function () {
|
||||
let checkboxes = document.querySelectorAll("input[type='checkbox']");
|
||||
let checkboxes = element.querySelectorAll("input[type='checkbox']");
|
||||
|
||||
for(var i = 0; i < checkboxes.length; i++) {
|
||||
checkboxes[i].checked = false;
|
||||
checkboxes[i].dispatchEvent(new Event('change'));
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -16,13 +16,14 @@ class Auth
|
|||
/**
|
||||
* User Roles.
|
||||
*/
|
||||
const USER_ROLE_GUEST = 0;
|
||||
const USER_ROLE_MEMBER = 1;
|
||||
const USER_ROLE_ADMIN = 2;
|
||||
const USER_ROLE_DEVELOPER = 3;
|
||||
const USER_ROLE_OWNER = 4;
|
||||
const USER_ROLE_APP = 5;
|
||||
const USER_ROLE_SYSTEM = 6;
|
||||
const USER_ROLE_GUEST = 'guest';
|
||||
const USER_ROLE_MEMBER = 'member';
|
||||
const USER_ROLE_ADMIN = 'admin';
|
||||
const USER_ROLE_DEVELOPER = 'developer';
|
||||
const USER_ROLE_OWNER = 'owner';
|
||||
const USER_ROLE_APP = 'app';
|
||||
const USER_ROLE_SYSTEM = 'system';
|
||||
const USER_ROLE_ALL = '*';
|
||||
|
||||
/**
|
||||
* Token Types.
|
||||
|
|
|
@ -252,9 +252,9 @@ class Response extends SwooleResponse
|
|||
{
|
||||
$output = $this->output($document, $model);
|
||||
|
||||
// If filter is set, parse the item
|
||||
// If filter is set, parse the output
|
||||
if(self::isFilter()){
|
||||
$item = self::getFilter()->parse($output, $model);
|
||||
$output = self::getFilter()->parse($output, $model);
|
||||
}
|
||||
|
||||
$this->json(!empty($output) ? $output : new stdClass());
|
||||
|
|
|
@ -13,27 +13,32 @@ class Collection extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Collection ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('$permissions', [
|
||||
'type' => Response::MODEL_PERMISSIONS,
|
||||
'description' => 'Collection permissions.',
|
||||
'default' => new \stdClass,
|
||||
'example' => new \stdClass,
|
||||
'array' => false,
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Collection name.',
|
||||
'default' => '',
|
||||
'example' => 'Movies',
|
||||
])
|
||||
->addRule('dateCreated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Collection creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('dateUpdated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Collection creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981550,
|
||||
])
|
||||
->addRule('rules', [
|
||||
|
|
|
@ -13,11 +13,13 @@ class Continent extends Model
|
|||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Continent name.',
|
||||
'default' => '',
|
||||
'example' => 'Europe',
|
||||
])
|
||||
->addRule('code', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Continent two letter code.',
|
||||
'default' => '',
|
||||
'example' => 'EU',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,11 +13,13 @@ class Country extends Model
|
|||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Country name.',
|
||||
'default' => '',
|
||||
'example' => 'United States',
|
||||
])
|
||||
->addRule('code', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Country two-character ISO 3166-1 alpha code.',
|
||||
'default' => '',
|
||||
'example' => 'US',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,36 +13,43 @@ class Currency extends Model
|
|||
->addRule('symbol', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Currency symbol.',
|
||||
'default' => '',
|
||||
'example' => '$',
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Currency name.',
|
||||
'default' => '',
|
||||
'example' => 'US dollar',
|
||||
])
|
||||
->addRule('symbolNative', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Currency native symbol.',
|
||||
'default' => '',
|
||||
'example' => '$',
|
||||
])
|
||||
->addRule('decimalDigits', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Number of decimal digits.',
|
||||
'default' => 0,
|
||||
'example' => 2,
|
||||
])
|
||||
->addRule('rounding', [
|
||||
'type' => self::TYPE_FLOAT,
|
||||
'description' => 'Currency digit rounding.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('code', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format.',
|
||||
'default' => '',
|
||||
'example' => 'USD',
|
||||
])
|
||||
->addRule('namePlural', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Currency plural name',
|
||||
'default' => '',
|
||||
'example' => 'US dollars',
|
||||
])
|
||||
// ->addRule('locations', [
|
||||
|
|
|
@ -18,26 +18,31 @@ class Domain extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Domain ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('domain', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Domain name.',
|
||||
'default' => '',
|
||||
'example' => 'appwrite.company.com',
|
||||
])
|
||||
->addRule('registerable', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Registerable domain name.',
|
||||
'default' => '',
|
||||
'example' => 'company.com',
|
||||
])
|
||||
->addRule('tld', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'TLD name.',
|
||||
'default' => '',
|
||||
'example' => 'com',
|
||||
])
|
||||
->addRule('verification', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'Verification process status.',
|
||||
'default' => false,
|
||||
'example' => true,
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,16 +13,19 @@ class Error extends Model
|
|||
->addRule('message', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Error message.',
|
||||
'default' => '',
|
||||
'example' => 'Not found',
|
||||
])
|
||||
->addRule('code', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Error code.',
|
||||
'default' => '',
|
||||
'example' => '404',
|
||||
])
|
||||
->addRule('version', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Server version number.',
|
||||
'default' => '',
|
||||
'example' => '1.0',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -19,16 +19,19 @@ class ErrorDev extends Error
|
|||
->addRule('file', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'File path.',
|
||||
'default' => '',
|
||||
'example' => '/usr/code/vendor/utopia-php/framework/src/App.php',
|
||||
])
|
||||
->addRule('line', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Line number.',
|
||||
'default' => 0,
|
||||
'example' => 209,
|
||||
])
|
||||
->addRule('trace', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Error trace.',
|
||||
'default' => [],
|
||||
'example' => [
|
||||
''
|
||||
],
|
||||
|
|
|
@ -13,46 +13,55 @@ class Execution extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Execution ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('functionId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea6g16897e',
|
||||
])
|
||||
->addRule('dateCreated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'The execution creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('trigger', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.',
|
||||
'default' => '',
|
||||
'example' => 'http',
|
||||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.',
|
||||
'default' => '',
|
||||
'example' => 'processing',
|
||||
])
|
||||
->addRule('exitCode', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'The script exit code.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('stdout', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The script stdout output string.',
|
||||
'default' => '',
|
||||
'example' => '',
|
||||
])
|
||||
->addRule('stderr', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The script stderr output string.',
|
||||
'default' => '',
|
||||
'example' => '',
|
||||
])
|
||||
->addRule('time', [
|
||||
'type' => self::TYPE_FLOAT,
|
||||
'description' => 'The script execution time in seconds.',
|
||||
'default' => 0,
|
||||
'example' => 0.400,
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,37 +13,44 @@ class File extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'File ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('$permissions', [
|
||||
'type' => Response::MODEL_PERMISSIONS,
|
||||
'description' => 'File permissions.',
|
||||
'default' => new \stdClass,
|
||||
'example' => new \stdClass,
|
||||
'array' => false,
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'File name.',
|
||||
'default' => '',
|
||||
'example' => 'Pink.png',
|
||||
])
|
||||
->addRule('dateCreated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'File creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('signature', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'File MD5 signature.',
|
||||
'default' => '',
|
||||
'example' => '5d529fd02b544198ae075bd57c1762bb',
|
||||
])
|
||||
->addRule('mimeType', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'File mime type.',
|
||||
'default' => '',
|
||||
'example' => 'image/png',
|
||||
])
|
||||
->addRule('sizeOriginal', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'File original size in bytes.',
|
||||
'default' => 0,
|
||||
'example' => 17890,
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,37 +13,44 @@ class Func extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('$permissions', [
|
||||
'type' => Response::MODEL_PERMISSIONS,
|
||||
'description' => 'Function permissions.',
|
||||
'default' => new \stdClass,
|
||||
'example' => new \stdClass,
|
||||
'array' => false,
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function name.',
|
||||
'default' => '',
|
||||
'example' => 'My Function',
|
||||
])
|
||||
->addRule('dateCreated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Function creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('dateUpdated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Function update date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981257,
|
||||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function status. Possible values: disabled, enabled',
|
||||
'default' => '',
|
||||
'example' => 'enabled',
|
||||
])
|
||||
->addRule('env', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function execution environment.',
|
||||
'default' => '',
|
||||
'example' => 'python-3.8',
|
||||
])
|
||||
->addRule('tag', [
|
||||
|
@ -74,14 +81,14 @@ class Func extends Model
|
|||
->addRule('scheduleNext', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Function next scheduled execution date in Unix timestamp.',
|
||||
'example' => 1592981292,
|
||||
'default' => 0,
|
||||
'example' => 1592981292,
|
||||
])
|
||||
->addRule('schedulePrevious', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Function next scheduled execution date in Unix timestamp.',
|
||||
'example' => 1592981237,
|
||||
'default' => 0,
|
||||
'example' => 1592981237,
|
||||
])
|
||||
->addRule('timeout', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
|
|
|
@ -18,11 +18,13 @@ class Key extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Key ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Key name.',
|
||||
'default' => '',
|
||||
'example' => 'My API Key',
|
||||
])
|
||||
->addRule('scopes', [
|
||||
|
@ -35,6 +37,7 @@ class Key extends Model
|
|||
->addRule('secret', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Secret key.',
|
||||
'default' => '',
|
||||
'example' => '919c2d18fb5d4...a2ae413da83346ad2',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,16 +13,19 @@ class Language extends Model
|
|||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Language name.',
|
||||
'default' => '',
|
||||
'example' => 'Italian',
|
||||
])
|
||||
->addRule('code', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Language two-character ISO 639-1 codes.',
|
||||
'default' => '',
|
||||
'example' => 'it',
|
||||
])
|
||||
->addRule('nativeName', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Language native name.',
|
||||
'default' => '',
|
||||
'example' => 'Italiano',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,26 +13,31 @@ class Locale extends Model
|
|||
->addRule('ip', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'User IP address.',
|
||||
'default' => '',
|
||||
'example' => '127.0.0.1',
|
||||
])
|
||||
->addRule('countryCode', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Country code in [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) two-character format',
|
||||
'default' => '',
|
||||
'example' => 'US',
|
||||
])
|
||||
->addRule('country', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Country name. This field support localization.',
|
||||
'default' => '',
|
||||
'example' => 'United States',
|
||||
])
|
||||
->addRule('continentCode', [
|
||||
'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.',
|
||||
'default' => '',
|
||||
'example' => 'NA',
|
||||
])
|
||||
->addRule('continent', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Continent name. This field support localization.',
|
||||
'default' => '',
|
||||
'example' => 'North America',
|
||||
])
|
||||
->addRule('eu', [
|
||||
|
@ -44,6 +49,7 @@ class Locale extends Model
|
|||
->addRule('currency', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Currency code in [ISO 4217-1](http://en.wikipedia.org/wiki/ISO_4217) three-character format',
|
||||
'default' => '',
|
||||
'example' => 'USD',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,16 +13,19 @@ class Log extends Model
|
|||
->addRule('event', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Event name.',
|
||||
'default' => '',
|
||||
'example' => 'account.sessions.create',
|
||||
])
|
||||
->addRule('ip', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'IP session in use when the session was created.',
|
||||
'default' => '',
|
||||
'example' => '127.0.0.1',
|
||||
])
|
||||
->addRule('time', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Log creation time in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('osCode', [
|
||||
|
|
|
@ -13,16 +13,19 @@ class Membership extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Membership ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('userId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'User ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('teamId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Team ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
|
@ -40,16 +43,19 @@ class Membership extends Model
|
|||
->addRule('invited', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Date, the user has been invited to join the team in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('joined', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Date, the user has accepted the invitation to join the team in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('confirm', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'User confirmation status, true if the user has joined the team or false otherwise.',
|
||||
'default' => false,
|
||||
'example' => false,
|
||||
])
|
||||
->addRule('roles', [
|
||||
|
|
|
@ -13,12 +13,14 @@ class Permissions extends Model
|
|||
->addRule('read', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Read permissions.',
|
||||
'default' => [],
|
||||
'example' => ['*', 'user:5e5ea5c16897e'],
|
||||
'array' => true,
|
||||
])
|
||||
->addRule('write', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Write permissions.',
|
||||
'default' => [],
|
||||
'example' => ['*', 'user:5e5ea5c16897e'],
|
||||
'array' => true,
|
||||
])
|
||||
|
|
|
@ -13,16 +13,19 @@ class Phone extends Model
|
|||
->addRule('code', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Phone code.',
|
||||
'default' => '',
|
||||
'example' => '+1',
|
||||
])
|
||||
->addRule('countryCode', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Country two-character ISO 3166-1 alpha code.',
|
||||
'default' => '',
|
||||
'example' => 'US',
|
||||
])
|
||||
->addRule('countryName', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Country name.',
|
||||
'default' => '',
|
||||
'example' => 'United States',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -18,21 +18,25 @@ class Platform extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Platform ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Platform name.',
|
||||
'default' => '',
|
||||
'example' => 'My Web App',
|
||||
])
|
||||
->addRule('type', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Platform type. Possible values are: web, flutter-ios, flutter-android, ios, android, and unity.',
|
||||
'default' => '',
|
||||
'example' => 'My Web App',
|
||||
])
|
||||
->addRule('key', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.',
|
||||
'default' => '',
|
||||
'example' => 'com.company.appname',
|
||||
])
|
||||
->addRule('store', [
|
||||
|
@ -43,6 +47,7 @@ class Platform extends Model
|
|||
->addRule('hostname', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Web app hostname. Empty string for other platforms.',
|
||||
'default' => '',
|
||||
'example' => true,
|
||||
])
|
||||
->addRule('httpUser', [
|
||||
|
|
|
@ -19,6 +19,7 @@ class Project extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Project ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
|
@ -36,6 +37,7 @@ class Project extends Model
|
|||
->addRule('teamId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Project team ID.',
|
||||
'default' => '',
|
||||
'example' => '1592981250',
|
||||
])
|
||||
->addRule('logo', [
|
||||
|
|
|
@ -13,6 +13,7 @@ class Rule extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Rule ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('$collection', [ // TODO remove this from public response
|
||||
|
@ -23,32 +24,37 @@ class Rule extends Model
|
|||
->addRule('type', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Rule type. Possible values: ',
|
||||
'default' => '',
|
||||
'example' => 'title',
|
||||
])
|
||||
->addRule('key', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Rule key.',
|
||||
'default' => '',
|
||||
'example' => 'title',
|
||||
])
|
||||
->addRule('label', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Rule label.',
|
||||
'default' => '',
|
||||
'example' => 'Title',
|
||||
])
|
||||
->addRule('default', [ // TODO should be of mixed types
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Rule default value.',
|
||||
'example' => 'Movie Name',
|
||||
'default' => '',
|
||||
'example' => 'Movie Name',
|
||||
])
|
||||
->addRule('array', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'Is array?',
|
||||
'default' => false,
|
||||
'example' => false,
|
||||
])
|
||||
->addRule('required', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'Is required?',
|
||||
'default' => false,
|
||||
'example' => true,
|
||||
])
|
||||
->addRule('list', [
|
||||
|
|
|
@ -13,6 +13,7 @@ class Session extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Session ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('userId', [
|
||||
|
|
|
@ -13,26 +13,31 @@ class Tag extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Tag ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('functionId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea6g16897e',
|
||||
])
|
||||
->addRule('dateCreated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'The tag creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('command', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The entrypoint command in use to execute the tag code.',
|
||||
'default' => '',
|
||||
'example' => 'enabled',
|
||||
])
|
||||
->addRule('size', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The code size in bytes.',
|
||||
'default' => '',
|
||||
'example' => 'python-3.8',
|
||||
])
|
||||
;
|
||||
|
|
|
@ -18,26 +18,31 @@ class Task extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Task ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Task name.',
|
||||
'default' => '',
|
||||
'example' => 'My Task',
|
||||
])
|
||||
->addRule('security', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'Indicated if SSL / TLS Certificate verification is enabled.',
|
||||
'default' => true,
|
||||
'example' => true,
|
||||
])
|
||||
->addRule('httpMethod', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Task HTTP Method.',
|
||||
'default' => '',
|
||||
'example' => 'POST',
|
||||
])
|
||||
->addRule('httpUrl', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Task HTTP URL.',
|
||||
'default' => '',
|
||||
'example' => 'https://example.com/task',
|
||||
])
|
||||
->addRule('httpHeaders', [
|
||||
|
@ -80,11 +85,13 @@ class Task extends Model
|
|||
->addRule('schedule', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Task schedule in CRON syntax.',
|
||||
'default' => '',
|
||||
'example' => '* * * * *',
|
||||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Task status. Possible values: play, pause', // TODO - change to enabled disabled
|
||||
'default' => '',
|
||||
'example' => 'enabled',
|
||||
])
|
||||
->addRule('updated', [
|
||||
|
|
|
@ -13,6 +13,7 @@ class Team extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Team ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
|
@ -24,11 +25,13 @@ class Team extends Model
|
|||
->addRule('dateCreated', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Team creation date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('sum', [ // TODO change key name?
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Total sum of team members.',
|
||||
'default' => 0,
|
||||
'example' => 7,
|
||||
])
|
||||
;
|
||||
|
|
|
@ -13,17 +13,19 @@ class Token extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Token ID.',
|
||||
'default' => '',
|
||||
'example' => 'bb8ea5c16897e',
|
||||
])
|
||||
->addRule('userId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'User ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c168bb8',
|
||||
])
|
||||
->addRule('secret', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.',
|
||||
'default' => 0,
|
||||
'default' => '',
|
||||
'example' => '',
|
||||
])
|
||||
->addRule('expire', [
|
||||
|
|
|
@ -13,26 +13,31 @@ class User extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'User ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'User name.',
|
||||
'default' => '',
|
||||
'example' => 'John Doe',
|
||||
])
|
||||
->addRule('registration', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'User registration date in Unix timestamp.',
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'User status. 0 for Unactivated, 1 for active and 2 is blocked.',
|
||||
'default' => 0,
|
||||
'example' => 0,
|
||||
])
|
||||
->addRule('email', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'User email address.',
|
||||
'default' => '',
|
||||
'example' => 'john@appwrite.io',
|
||||
])
|
||||
->addRule('emailVerification', [
|
||||
|
|
|
@ -18,16 +18,19 @@ class Webhook extends Model
|
|||
->addRule('$id', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Webhook ID.',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Webhook name.',
|
||||
'default' => '',
|
||||
'example' => 'My Webhook',
|
||||
])
|
||||
->addRule('url', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Webhook URL endpoint.',
|
||||
'default' => '',
|
||||
'example' => 'https://example.com/webhook',
|
||||
])
|
||||
->addRule('events', [
|
||||
|
@ -40,6 +43,7 @@ class Webhook extends Model
|
|||
->addRule('security', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'Indicated if SSL / TLS Certificate verification is enabled.',
|
||||
'default' => true,
|
||||
'example' => true,
|
||||
])
|
||||
->addRule('httpUser', [
|
||||
|
|
|
@ -149,4 +149,41 @@ class HTTPTest extends Scope
|
|||
|
||||
unlink(realpath(__DIR__ . '/../../resources/open-api3.json'));
|
||||
}
|
||||
|
||||
public function testResponseHeader() {
|
||||
|
||||
/**
|
||||
* Test without header
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/locale/continents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => 'console',
|
||||
], $this->getHeaders()));
|
||||
|
||||
$body = $response['body'];
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals($body['sum'], 7);
|
||||
$this->assertEquals($body['continents'][0]['name'], 'Africa');
|
||||
$this->assertEquals($body['continents'][0]['code'], 'AF');
|
||||
$this->assertEquals($body['continents'][1]['name'], 'Antarctica');
|
||||
$this->assertEquals($body['continents'][1]['code'], 'AN');
|
||||
$this->assertEquals($body['continents'][2]['name'], 'Asia');
|
||||
$this->assertEquals($body['continents'][2]['code'], 'AS');
|
||||
|
||||
/**
|
||||
* Test with header
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/locale/continents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => 'console',
|
||||
'x-appwrite-response-format' => '0.6.2'
|
||||
], $this->getHeaders()));
|
||||
|
||||
$body = $response['body'];
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals($body['sum'], 7);
|
||||
$this->assertEquals($body['continents']['AF'], 'Africa');
|
||||
$this->assertEquals($body['continents']['AN'], 'Antarctica');
|
||||
$this->assertEquals($body['continents']['AS'], 'Asia');
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ trait DatabaseBase
|
|||
]), [
|
||||
'name' => 'Actors',
|
||||
'read' => ['*'],
|
||||
'write' => ['role:1', 'role:2'],
|
||||
'write' => ['role:member', 'role:admin'],
|
||||
'rules' => [
|
||||
[
|
||||
'label' => 'First Name',
|
||||
|
@ -54,7 +54,7 @@ trait DatabaseBase
|
|||
]), [
|
||||
'name' => 'Movies',
|
||||
'read' => ['*'],
|
||||
'write' => ['role:1', 'role:2'],
|
||||
'write' => ['role:member', 'role:admin'],
|
||||
'rules' => [
|
||||
[
|
||||
'label' => 'Name',
|
||||
|
|
|
@ -27,7 +27,7 @@ class DatabaseCustomServerTest extends Scope
|
|||
]), [
|
||||
'name' => 'Actors',
|
||||
'read' => ['*'],
|
||||
'write' => ['role:1', 'role:2'],
|
||||
'write' => ['role:member', 'role:admin'],
|
||||
'rules' => [
|
||||
[
|
||||
'label' => 'First Name',
|
||||
|
|
|
@ -455,6 +455,7 @@ class FunctionsCustomServerTest extends Scope
|
|||
|
||||
public function testENVS():array
|
||||
{
|
||||
sleep(120);
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
|
@ -591,7 +592,7 @@ class FunctionsCustomServerTest extends Scope
|
|||
$executionId = $execution['body']['$id'] ?? '';
|
||||
$this->assertEquals(201, $execution['headers']['status-code']);
|
||||
|
||||
sleep(20);
|
||||
sleep(30);
|
||||
|
||||
$executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
@ -601,6 +602,11 @@ class FunctionsCustomServerTest extends Scope
|
|||
if($executions['body']['executions'][0]['status'] !== 'completed') {
|
||||
var_dump($env);
|
||||
var_dump($executions['body']['executions'][0]);
|
||||
$stdout = '';
|
||||
$stderr = '';
|
||||
Console::execute('docker logs appwrite-worker-functions', '', $stdout, $stderr);
|
||||
var_dump($stdout);
|
||||
var_dump($stderr);
|
||||
}
|
||||
|
||||
$this->assertEquals($executions['headers']['status-code'], 200);
|
||||
|
|
|
@ -78,6 +78,7 @@ services:
|
|||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_INFLUXDB_HOST
|
||||
- _APP_INFLUXDB_PORT
|
||||
- _APP_STORAGE_LIMIT
|
||||
|
|
Loading…
Reference in a new issue