diff --git a/.env b/.env index ce43bfd853..1cc5b84a31 100644 --- a/.env +++ b/.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= \ No newline at end of file +_APP_SYSTEM_RESPONSE_FORMAT= +_APP_USAGE_STATS=enabled \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index d9ec45dd6c..ee147b9cbf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,7 @@ - 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. ### User Interface - Updated grid for OAuth2 providers list in the console ([#413](https://github.com/appwrite/appwrite/issues/413)) diff --git a/Dockerfile b/Dockerfile index 37ad125ee1..0017d68dcb 100755 --- a/Dockerfile +++ b/Dockerfile @@ -99,6 +99,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 '' diff --git a/app/config/roles.php b/app/config/roles.php index 8dfaf78eb4..506b2403c6 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -1,13 +1,6 @@ [ + 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'], ], diff --git a/app/config/variables.php b/app/config/variables.php index 80dd6fdb82..d713acd5bf 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -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' => '', + ], ], ], [ diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 35a807f949..54df37ab21 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -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') diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 74a26dd48a..0b22e40614 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -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([ diff --git a/app/controllers/general.php b/app/controllers/general.php index 81b90ba29a..47873edac3 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -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 */ @@ -120,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') @@ -133,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', []))); @@ -229,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 */ diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 4dc69b7850..bc2707f249 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -6,14 +6,24 @@ 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); @@ -60,4 +70,96 @@ App::init(function ($utopia, $request, $response, $project, $user, $register) { { throw new Exception('Too many requests', 429); } -}, ['utopia', 'request', 'response', 'project', 'user', 'register'], 'api'); \ No newline at end of file + + /* + * 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'); diff --git a/app/controllers/shared/web.php b/app/controllers/shared/web.php index 42d2a18c55..43eaf74d09 100644 --- a/app/controllers/shared/web.php +++ b/app/controllers/shared/web.php @@ -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 ; diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index bddc8ea8bb..b8fc5a621e 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -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 diff --git a/app/views/console/functions/function.phtml b/app/views/console/functions/function.phtml index 2c262c5bed..e1203dd027 100644 --- a/app/views/console/functions/function.phtml +++ b/app/views/console/functions/function.phtml @@ -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); ?>
getParam('timeout', 900);
+
  • getParam('timeout', 900);
  • +
  • diff --git a/app/views/console/home/index.phtml b/app/views/console/home/index.phtml index 173336728e..0fc6838eb6 100644 --- a/app/views/console/home/index.phtml +++ b/app/views/console/home/index.phtml @@ -1,5 +1,6 @@ getParam('graph', false); +$usageStatsEnabled = $this->getParam('usageStatsEnabled',true); ?>
    @@ -68,7 +69,7 @@ $graph = $this->getParam('graph', false); data-param-project-id="{{router.params.project}}" data-param-range="30d"> - +
    diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 5d74fd8ef9..098d4d4070 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -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: @@ -370,5 +372,4 @@ volumes: appwrite-certificates: appwrite-functions: appwrite-influxdb: - appwrite-chronograf: appwrite-config: diff --git a/app/workers/functions.php b/app/workers/functions.php index ab43914078..bb74bb0e60 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -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(); } diff --git a/docker-compose.yml b/docker-compose.yml index 2acd6d3ed2..83024b8296 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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 diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 88eb11299d..f2d786c937 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -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. diff --git a/src/Appwrite/Utopia/Response/Model/Collection.php b/src/Appwrite/Utopia/Response/Model/Collection.php index 1fce01bbbe..9b1f184b97 100644 --- a/src/Appwrite/Utopia/Response/Model/Collection.php +++ b/src/Appwrite/Utopia/Response/Model/Collection.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Continent.php b/src/Appwrite/Utopia/Response/Model/Continent.php index faae10c141..82948b646a 100644 --- a/src/Appwrite/Utopia/Response/Model/Continent.php +++ b/src/Appwrite/Utopia/Response/Model/Continent.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Country.php b/src/Appwrite/Utopia/Response/Model/Country.php index f9b5ae8784..85ed0a2d5d 100644 --- a/src/Appwrite/Utopia/Response/Model/Country.php +++ b/src/Appwrite/Utopia/Response/Model/Country.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Currency.php b/src/Appwrite/Utopia/Response/Model/Currency.php index e912f2ab4d..ac5cb9d060 100644 --- a/src/Appwrite/Utopia/Response/Model/Currency.php +++ b/src/Appwrite/Utopia/Response/Model/Currency.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Domain.php b/src/Appwrite/Utopia/Response/Model/Domain.php index 2e58a3053f..46aff1a567 100644 --- a/src/Appwrite/Utopia/Response/Model/Domain.php +++ b/src/Appwrite/Utopia/Response/Model/Domain.php @@ -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, ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Error.php b/src/Appwrite/Utopia/Response/Model/Error.php index 3ce03bc671..48e30cd817 100644 --- a/src/Appwrite/Utopia/Response/Model/Error.php +++ b/src/Appwrite/Utopia/Response/Model/Error.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/ErrorDev.php b/src/Appwrite/Utopia/Response/Model/ErrorDev.php index d4a667529d..9fa0c4095a 100644 --- a/src/Appwrite/Utopia/Response/Model/ErrorDev.php +++ b/src/Appwrite/Utopia/Response/Model/ErrorDev.php @@ -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' => [ '' ], diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index c1183d6b24..22c7710ec6 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -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, ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/File.php b/src/Appwrite/Utopia/Response/Model/File.php index a7ad05e1e4..5d0d511539 100644 --- a/src/Appwrite/Utopia/Response/Model/File.php +++ b/src/Appwrite/Utopia/Response/Model/File.php @@ -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, ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index 8802c56dec..067a4741d7 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -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, diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 28be3adbf5..c939382cc2 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Language.php b/src/Appwrite/Utopia/Response/Model/Language.php index e2dd8d638f..8819b520bb 100644 --- a/src/Appwrite/Utopia/Response/Model/Language.php +++ b/src/Appwrite/Utopia/Response/Model/Language.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Locale.php b/src/Appwrite/Utopia/Response/Model/Locale.php index d67470a39e..7f430d8072 100644 --- a/src/Appwrite/Utopia/Response/Model/Locale.php +++ b/src/Appwrite/Utopia/Response/Model/Locale.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Log.php b/src/Appwrite/Utopia/Response/Model/Log.php index dc3bb6955e..baf2f83347 100644 --- a/src/Appwrite/Utopia/Response/Model/Log.php +++ b/src/Appwrite/Utopia/Response/Model/Log.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Membership.php b/src/Appwrite/Utopia/Response/Model/Membership.php index 34f60a72b8..e5be5d3d1d 100644 --- a/src/Appwrite/Utopia/Response/Model/Membership.php +++ b/src/Appwrite/Utopia/Response/Model/Membership.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Permissions.php b/src/Appwrite/Utopia/Response/Model/Permissions.php index 3847bd9387..0377d2e1f8 100644 --- a/src/Appwrite/Utopia/Response/Model/Permissions.php +++ b/src/Appwrite/Utopia/Response/Model/Permissions.php @@ -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, ]) diff --git a/src/Appwrite/Utopia/Response/Model/Phone.php b/src/Appwrite/Utopia/Response/Model/Phone.php index 0d47ebb867..e077193e8d 100644 --- a/src/Appwrite/Utopia/Response/Model/Phone.php +++ b/src/Appwrite/Utopia/Response/Model/Phone.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Platform.php b/src/Appwrite/Utopia/Response/Model/Platform.php index 06c61d3e1b..207b4fe81f 100644 --- a/src/Appwrite/Utopia/Response/Model/Platform.php +++ b/src/Appwrite/Utopia/Response/Model/Platform.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Project.php b/src/Appwrite/Utopia/Response/Model/Project.php index e481631898..9ff5817583 100644 --- a/src/Appwrite/Utopia/Response/Model/Project.php +++ b/src/Appwrite/Utopia/Response/Model/Project.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Rule.php b/src/Appwrite/Utopia/Response/Model/Rule.php index cb075c8a7f..178dd90d7c 100644 --- a/src/Appwrite/Utopia/Response/Model/Rule.php +++ b/src/Appwrite/Utopia/Response/Model/Rule.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Session.php b/src/Appwrite/Utopia/Response/Model/Session.php index a0edfbb4b6..4bc23ab79a 100644 --- a/src/Appwrite/Utopia/Response/Model/Session.php +++ b/src/Appwrite/Utopia/Response/Model/Session.php @@ -13,6 +13,7 @@ class Session extends Model ->addRule('$id', [ 'type' => self::TYPE_STRING, 'description' => 'Session ID.', + 'default' => '', 'example' => '5e5ea5c16897e', ]) ->addRule('userId', [ diff --git a/src/Appwrite/Utopia/Response/Model/Tag.php b/src/Appwrite/Utopia/Response/Model/Tag.php index a3a403187f..b48e157291 100644 --- a/src/Appwrite/Utopia/Response/Model/Tag.php +++ b/src/Appwrite/Utopia/Response/Model/Tag.php @@ -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', ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Task.php b/src/Appwrite/Utopia/Response/Model/Task.php index 53ec1474e6..6843eba9a0 100644 --- a/src/Appwrite/Utopia/Response/Model/Task.php +++ b/src/Appwrite/Utopia/Response/Model/Task.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Team.php b/src/Appwrite/Utopia/Response/Model/Team.php index 67442dade5..b5f7482a19 100644 --- a/src/Appwrite/Utopia/Response/Model/Team.php +++ b/src/Appwrite/Utopia/Response/Model/Team.php @@ -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, ]) ; diff --git a/src/Appwrite/Utopia/Response/Model/Token.php b/src/Appwrite/Utopia/Response/Model/Token.php index 9d00fe6f91..fb34f01fd7 100644 --- a/src/Appwrite/Utopia/Response/Model/Token.php +++ b/src/Appwrite/Utopia/Response/Model/Token.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/User.php b/src/Appwrite/Utopia/Response/Model/User.php index e11d49ed8f..b917a14a0d 100644 --- a/src/Appwrite/Utopia/Response/Model/User.php +++ b/src/Appwrite/Utopia/Response/Model/User.php @@ -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', [ diff --git a/src/Appwrite/Utopia/Response/Model/Webhook.php b/src/Appwrite/Utopia/Response/Model/Webhook.php index f8b8ac7432..0ad9ce6ab8 100644 --- a/src/Appwrite/Utopia/Response/Model/Webhook.php +++ b/src/Appwrite/Utopia/Response/Model/Webhook.php @@ -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', [ diff --git a/tests/e2e/Services/Database/DatabaseBase.php b/tests/e2e/Services/Database/DatabaseBase.php index f769184827..8285cb2076 100644 --- a/tests/e2e/Services/Database/DatabaseBase.php +++ b/tests/e2e/Services/Database/DatabaseBase.php @@ -18,7 +18,7 @@ trait DatabaseBase ]), [ 'name' => 'Actors', 'read' => ['*'], - 'write' => ['role:1', 'role:2'], + 'write' => ['role:member', 'role:admin'], 'rules' => [ [ 'label' => 'First Name', @@ -55,7 +55,7 @@ trait DatabaseBase ]), [ 'name' => 'Movies', 'read' => ['*'], - 'write' => ['role:1', 'role:2'], + 'write' => ['role:member', 'role:admin'], 'rules' => [ [ 'label' => 'Name', diff --git a/tests/e2e/Services/Database/DatabaseCustomServerTest.php b/tests/e2e/Services/Database/DatabaseCustomServerTest.php index 2f0bdfc766..3bb9c3e82d 100644 --- a/tests/e2e/Services/Database/DatabaseCustomServerTest.php +++ b/tests/e2e/Services/Database/DatabaseCustomServerTest.php @@ -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', diff --git a/tests/resources/docker/docker-compose.yml b/tests/resources/docker/docker-compose.yml index c300ece0a6..9f4074c540 100644 --- a/tests/resources/docker/docker-compose.yml +++ b/tests/resources/docker/docker-compose.yml @@ -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