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); ?>