diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index b3fcfc3c7..235bb18cc 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -229,7 +229,7 @@ App::put('/v1/database/collections/:collectionId') ->param('name', null, function () { return new Text(256); }, 'Collection name.') ->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions(/docs/permissions) and get a full list of available permissions.') ->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.') - ->param('rules', [], function () use ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true) + ->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true, ['projectDB']) ->action(function ($collectionId, $name, $read, $write, $rules, $response, $projectDB, $webhook, $audit) { /** @var Utopia\Response $response */ /** @var Appwrite\Database\Database $projectDB */ diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 6068984ea..fce99548b 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -37,51 +37,53 @@ App::post('/v1/projects') ->param('legalCity', '', function () { return new Text(256); }, 'Project legal City.', true) ->param('legalAddress', '', function () { return new Text(256); }, 'Project legal Address.', true) ->param('legalTaxId', '', function () { return new Text(256); }, 'Project legal Tax ID.', true) - ->action( - function ($name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId) use ($response, $consoleDB, $projectDB) { - $team = $projectDB->getDocument($teamId); + ->action(function ($name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId, $response, $consoleDB, $projectDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ + /** @var Appwrite\Database\Database $projectDB */ - if (empty($team->getId()) || Database::SYSTEM_COLLECTION_TEAMS != $team->getCollection()) { - throw new Exception('Team not found', 404); - } + $team = $projectDB->getDocument($teamId); - $project = $consoleDB->createDocument( - [ - '$collection' => Database::SYSTEM_COLLECTION_PROJECTS, - '$permissions' => [ - 'read' => ['team:'.$teamId], - 'write' => ['team:'.$teamId.'/owner', 'team:'.$teamId.'/developer'], - ], - 'name' => $name, - 'description' => $description, - 'logo' => $logo, - 'url' => $url, - 'legalName' => $legalName, - 'legalCountry' => $legalCountry, - 'legalState' => $legalState, - 'legalCity' => $legalCity, - 'legalAddress' => $legalAddress, - 'legalTaxId' => $legalTaxId, - 'teamId' => $team->getId(), - 'platforms' => [], - 'webhooks' => [], - 'keys' => [], - 'tasks' => [], - ] - ); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $consoleDB->createNamespace($project->getId()); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($project->getArrayCopy()) - ; + if (empty($team->getId()) || Database::SYSTEM_COLLECTION_TEAMS != $team->getCollection()) { + throw new Exception('Team not found', 404); } - ); + + $project = $consoleDB->createDocument( + [ + '$collection' => Database::SYSTEM_COLLECTION_PROJECTS, + '$permissions' => [ + 'read' => ['team:'.$teamId], + 'write' => ['team:'.$teamId.'/owner', 'team:'.$teamId.'/developer'], + ], + 'name' => $name, + 'description' => $description, + 'logo' => $logo, + 'url' => $url, + 'legalName' => $legalName, + 'legalCountry' => $legalCountry, + 'legalState' => $legalState, + 'legalCity' => $legalCity, + 'legalAddress' => $legalAddress, + 'legalTaxId' => $legalTaxId, + 'teamId' => $team->getId(), + 'platforms' => [], + 'webhooks' => [], + 'keys' => [], + 'tasks' => [], + ] + ); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $consoleDB->createNamespace($project->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->json($project->getArrayCopy()) + ; + }, ['response', 'consoleDB', 'projectDB']); App::get('/v1/projects') ->desc('List Projects') @@ -89,49 +91,22 @@ App::get('/v1/projects') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'list') - ->action( - function () use ($response, $consoleDB) { - $results = $consoleDB->getCollection([ - 'limit' => 20, - 'offset' => 0, - 'orderField' => 'name', - 'orderType' => 'ASC', - 'orderCast' => 'string', - 'filters' => [ - '$collection='.Database::SYSTEM_COLLECTION_PROJECTS, - ], - ]); - - foreach ($results as $project) { - foreach (Config::getParam('providers') as $provider => $node) { - $secret = \json_decode($project->getAttribute('usersOauth2'.\ucfirst($provider).'Secret', '{}'), true); - - if (!empty($secret) && isset($secret['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$secret['version']); - $project->setAttribute('usersOauth2'.\ucfirst($provider).'Secret', OpenSSL::decrypt($secret['data'], $secret['method'], $key, 0, \hex2bin($secret['iv']), \hex2bin($secret['tag']))); - } - } - } - - $response->json($results); - } - ); - -App::get('/v1/projects/:projectId') - ->desc('Get Project') - ->groups(['api', 'projects']) - ->label('scope', 'projects.read') - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'get') - ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') - ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + ->action(function ($response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ + + $results = $consoleDB->getCollection([ + 'limit' => 20, + 'offset' => 0, + 'orderField' => 'name', + 'orderType' => 'ASC', + 'orderCast' => 'string', + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_PROJECTS, + ], + ]); + foreach ($results as $project) { foreach (Config::getParam('providers') as $provider => $node) { $secret = \json_decode($project->getAttribute('usersOauth2'.\ucfirst($provider).'Secret', '{}'), true); @@ -140,10 +115,39 @@ App::get('/v1/projects/:projectId') $project->setAttribute('usersOauth2'.\ucfirst($provider).'Secret', OpenSSL::decrypt($secret['data'], $secret['method'], $key, 0, \hex2bin($secret['iv']), \hex2bin($secret['tag']))); } } - - $response->json($project->getArrayCopy()); } - ); + + $response->json($results); + }, ['response', 'consoleDB']); + +App::get('/v1/projects/:projectId') + ->desc('Get Project') + ->groups(['api', 'projects']) + ->label('scope', 'projects.read') + ->label('sdk.namespace', 'projects') + ->label('sdk.method', 'get') + ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') + ->action(function ($projectId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ + + $project = $consoleDB->getDocument($projectId); + + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); + } + + foreach (Config::getParam('providers') as $provider => $node) { + $secret = \json_decode($project->getAttribute('usersOauth2'.\ucfirst($provider).'Secret', '{}'), true); + + if (!empty($secret) && isset($secret['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$secret['version']); + $project->setAttribute('usersOauth2'.\ucfirst($provider).'Secret', OpenSSL::decrypt($secret['data'], $secret['method'], $key, 0, \hex2bin($secret['iv']), \hex2bin($secret['tag']))); + } + } + + $response->json($project->getArrayCopy()); + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/usage') ->desc('Get Project') @@ -153,159 +157,162 @@ App::get('/v1/projects/:projectId/usage') ->label('sdk.method', 'getUsage') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') ->param('range', 'last30', function () { return new WhiteList(['daily', 'monthly', 'last30', 'last90']); }, 'Date range.', true) - ->action( - function ($projectId, $range) use ($response, $consoleDB, $projectDB, $register) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $range, $response, $consoleDB, $projectDB, $register) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ + /** @var Appwrite\Database\Database $projectDB */ + /** @var Utopia\Registry\Registry $register */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); + $project = $consoleDB->getDocument($projectId); + + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); + } + + $period = [ + 'daily' => [ + 'start' => DateTime::createFromFormat('U', \strtotime('today')), + 'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')), + 'group' => '1m', + ], + 'monthly' => [ + 'start' => DateTime::createFromFormat('U', \strtotime('midnight first day of this month')), + 'end' => DateTime::createFromFormat('U', \strtotime('midnight last day of this month')), + 'group' => '1d', + ], + 'last30' => [ + 'start' => DateTime::createFromFormat('U', \strtotime('-30 days')), + 'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')), + 'group' => '1d', + ], + 'last90' => [ + 'start' => DateTime::createFromFormat('U', \strtotime('-90 days')), + 'end' => DateTime::createFromFormat('U', \strtotime('today')), + 'group' => '1d', + ], + // 'yearly' => [ + // 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')), + // 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')), + // 'group' => '4w', + // ], + ]; + + $client = $register->get('influxdb'); + + $requests = []; + $network = []; + + 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']), + ]; } - $period = [ - 'daily' => [ - 'start' => DateTime::createFromFormat('U', \strtotime('today')), - 'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')), - 'group' => '1m', - ], - 'monthly' => [ - 'start' => DateTime::createFromFormat('U', \strtotime('midnight first day of this month')), - 'end' => DateTime::createFromFormat('U', \strtotime('midnight last day of this month')), - 'group' => '1d', - ], - 'last30' => [ - 'start' => DateTime::createFromFormat('U', \strtotime('-30 days')), - 'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')), - 'group' => '1d', - ], - 'last90' => [ - 'start' => DateTime::createFromFormat('U', \strtotime('-90 days')), - 'end' => DateTime::createFromFormat('U', \strtotime('today')), - 'group' => '1d', - ], - // 'yearly' => [ - // 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')), - // 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')), - // 'group' => '4w', - // ], - ]; + // 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(); - $client = $register->get('influxdb'); - - $requests = []; - $network = []; - - 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']), - ]; - } + foreach ($points as $point) { + $network[] = [ + 'value' => (!empty($point['value'])) ? $point['value'] : 0, + 'date' => \strtotime($point['time']), + ]; } + } - // Users + // Users - $projectDB->getCollection([ + $projectDB->getCollection([ + 'limit' => 0, + 'offset' => 0, + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_USERS, + ], + ]); + + $usersTotal = $projectDB->getSum(); + + // Documents + + $collections = $projectDB->getCollection([ + 'limit' => 100, + 'offset' => 0, + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_COLLECTIONS, + ], + ]); + + $collectionsTotal = $projectDB->getSum(); + + $documents = []; + + foreach ($collections as $collection) { + $result = $projectDB->getCollection([ 'limit' => 0, 'offset' => 0, 'filters' => [ - '$collection='.Database::SYSTEM_COLLECTION_USERS, + '$collection='.$collection['$id'], ], ]); - $usersTotal = $projectDB->getSum(); - - // Documents - - $collections = $projectDB->getCollection([ - 'limit' => 100, - 'offset' => 0, - 'filters' => [ - '$collection='.Database::SYSTEM_COLLECTION_COLLECTIONS, - ], - ]); - - $collectionsTotal = $projectDB->getSum(); - - $documents = []; - - foreach ($collections as $collection) { - $result = $projectDB->getCollection([ - 'limit' => 0, - 'offset' => 0, - 'filters' => [ - '$collection='.$collection['$id'], - ], - ]); - - $documents[] = ['name' => $collection['name'], 'total' => $projectDB->getSum()]; - } - - // Tasks - $tasksTotal = \count($project->getAttribute('tasks', [])); - - $response->json([ - 'requests' => [ - 'data' => $requests, - 'total' => \array_sum(\array_map(function ($item) { - return $item['value']; - }, $requests)), - ], - 'network' => [ - 'data' => $network, - 'total' => \array_sum(\array_map(function ($item) { - return $item['value']; - }, $network)), - ], - 'collections' => [ - 'data' => $collections, - 'total' => $collectionsTotal, - ], - 'documents' => [ - 'data' => $documents, - 'total' => \array_sum(\array_map(function ($item) { - return $item['total']; - }, $documents)), - ], - 'users' => [ - 'data' => [], - 'total' => $usersTotal, - ], - 'tasks' => [ - 'data' => [], - 'total' => $tasksTotal, - ], - 'storage' => [ - 'total' => $projectDB->getCount( - [ - 'filters' => [ - '$collection='.Database::SYSTEM_COLLECTION_FILES, - ], - ] - ), - ], - ]); + $documents[] = ['name' => $collection['name'], 'total' => $projectDB->getSum()]; } - ); + + // Tasks + $tasksTotal = \count($project->getAttribute('tasks', [])); + + $response->json([ + 'requests' => [ + 'data' => $requests, + 'total' => \array_sum(\array_map(function ($item) { + return $item['value']; + }, $requests)), + ], + 'network' => [ + 'data' => $network, + 'total' => \array_sum(\array_map(function ($item) { + return $item['value']; + }, $network)), + ], + 'collections' => [ + 'data' => $collections, + 'total' => $collectionsTotal, + ], + 'documents' => [ + 'data' => $documents, + 'total' => \array_sum(\array_map(function ($item) { + return $item['total']; + }, $documents)), + ], + 'users' => [ + 'data' => [], + 'total' => $usersTotal, + ], + 'tasks' => [ + 'data' => [], + 'total' => $tasksTotal, + ], + 'storage' => [ + 'total' => $projectDB->getCount( + [ + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_FILES, + ], + ] + ), + ], + ]); + }, ['response', 'consoleDB', 'projectDB', 'register']); App::patch('/v1/projects/:projectId') ->desc('Update Project') @@ -324,34 +331,35 @@ App::patch('/v1/projects/:projectId') ->param('legalCity', '', function () { return new Text(256); }, 'Project legal city.', true) ->param('legalAddress', '', function () { return new Text(256); }, 'Project legal address.', true) ->param('legalTaxId', '', function () { return new Text(256); }, 'Project legal tax ID.', true) - ->action( - function ($projectId, $name, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $name, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $project = $consoleDB->updateDocument(\array_merge($project->getArrayCopy(), [ - 'name' => $name, - 'description' => $description, - 'logo' => $logo, - 'url' => $url, - 'legalName' => $legalName, - 'legalCountry' => $legalCountry, - 'legalState' => $legalState, - 'legalCity' => $legalCity, - 'legalAddress' => $legalAddress, - 'legalTaxId' => $legalTaxId, - ])); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $response->json($project->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $project = $consoleDB->updateDocument(\array_merge($project->getArrayCopy(), [ + 'name' => $name, + 'description' => $description, + 'logo' => $logo, + 'url' => $url, + 'legalName' => $legalName, + 'legalCountry' => $legalCountry, + 'legalState' => $legalState, + 'legalCity' => $legalCity, + 'legalAddress' => $legalAddress, + 'legalTaxId' => $legalTaxId, + ])); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $response->json($project->getArrayCopy()); + }, ['response', 'consoleDB']); App::patch('/v1/projects/:projectId/oauth2') ->desc('Update Project OAuth2') @@ -363,37 +371,38 @@ App::patch('/v1/projects/:projectId/oauth2') ->param('provider', '', function () { return new WhiteList(\array_keys(Config::getParam('providers'))); }, 'Provider Name', false) ->param('appId', '', function () { return new Text(256); }, 'Provider app ID.', true) ->param('secret', '', function () { return new text(512); }, 'Provider secret key.', true) - ->action( - function ($projectId, $provider, $appId, $secret) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $provider, $appId, $secret, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $key = App::getEnv('_APP_OPENSSL_KEY_V1'); - $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); - $tag = null; - $secret = \json_encode([ - 'data' => OpenSSL::encrypt($secret, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), - 'method' => OpenSSL::CIPHER_AES_128_GCM, - 'iv' => \bin2hex($iv), - 'tag' => \bin2hex($tag), - 'version' => '1', - ]); - - $project = $consoleDB->updateDocument(\array_merge($project->getArrayCopy(), [ - 'usersOauth2'.\ucfirst($provider).'Appid' => $appId, - 'usersOauth2'.\ucfirst($provider).'Secret' => $secret, - ])); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $response->json($project->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $key = App::getEnv('_APP_OPENSSL_KEY_V1'); + $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); + $tag = null; + $secret = \json_encode([ + 'data' => OpenSSL::encrypt($secret, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), + 'method' => OpenSSL::CIPHER_AES_128_GCM, + 'iv' => \bin2hex($iv), + 'tag' => \bin2hex($tag), + 'version' => '1', + ]); + + $project = $consoleDB->updateDocument(\array_merge($project->getArrayCopy(), [ + 'usersOauth2'.\ucfirst($provider).'Appid' => $appId, + 'usersOauth2'.\ucfirst($provider).'Secret' => $secret, + ])); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $response->json($project->getArrayCopy()); + }, ['response', 'consoleDB']); App::delete('/v1/projects/:projectId') ->desc('Delete Project') @@ -403,41 +412,44 @@ App::delete('/v1/projects/:projectId') ->label('sdk.method', 'delete') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') ->param('password', '', function () { return new UID(); }, 'Your user password for confirmation. Must be between 6 to 32 chars.') - ->action( - function ($projectId, $password) use ($response, $consoleDB, $user, $deletes) { - if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password - throw new Exception('Invalid credentials', 401); - } + ->action(function ($projectId, $password, $response, $user, $consoleDB, $deletes) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Document $user */ + /** @var Appwrite\Database\Database $consoleDB */ + /** @var Appwrite\Event\Event $deletes */ - $project = $consoleDB->getDocument($projectId); + if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password + throw new Exception('Invalid credentials', 401); + } - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $deletes->setParam('document', $project->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); + } - foreach (['keys', 'webhooks', 'tasks', 'platforms', 'domains'] as $key) { // Delete all children (keys, webhooks, tasks [stop tasks?], platforms) - $list = $project->getAttribute('webhooks', []); + $deletes->setParam('document', $project->getArrayCopy()); - foreach ($list as $document) { /* @var $document Document */ - if (!$consoleDB->deleteDocument($projectId)) { - throw new Exception('Failed to remove project document ('.$key.')] from DB', 500); - } + foreach (['keys', 'webhooks', 'tasks', 'platforms', 'domains'] as $key) { // Delete all children (keys, webhooks, tasks [stop tasks?], platforms) + $list = $project->getAttribute('webhooks', []); + + foreach ($list as $document) { /* @var $document Document */ + if (!$consoleDB->deleteDocument($projectId)) { + throw new Exception('Failed to remove project document ('.$key.')] from DB', 500); } } - - if (!$consoleDB->deleteDocument($project->getAttribute('teamId', null))) { - throw new Exception('Failed to remove project team from DB', 500); - } - - if (!$consoleDB->deleteDocument($projectId)) { - throw new Exception('Failed to remove project from DB', 500); - } - - $response->noContent(); } - ); + + if (!$consoleDB->deleteDocument($project->getAttribute('teamId', null))) { + throw new Exception('Failed to remove project team from DB', 500); + } + + if (!$consoleDB->deleteDocument($projectId)) { + throw new Exception('Failed to remove project from DB', 500); + } + + $response->noContent(); + }, ['response', 'user', 'consoleDB', 'deletes']); // Webhooks @@ -454,58 +466,59 @@ App::post('/v1/projects/:projectId/webhooks') ->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true) ->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password.', true) - ->action( - function ($projectId, $name, $events, $url, $security, $httpUser, $httpPass) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $name, $events, $url, $security, $httpUser, $httpPass, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $key = App::getEnv('_APP_OPENSSL_KEY_V1'); - $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); - $tag = null; - $httpPass = \json_encode([ - 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), - 'method' => OpenSSL::CIPHER_AES_128_GCM, - 'iv' => \bin2hex($iv), - 'tag' => \bin2hex($tag), - 'version' => '1', - ]); - - $webhook = $consoleDB->createDocument([ - '$collection' => Database::SYSTEM_COLLECTION_WEBHOOKS, - '$permissions' => [ - 'read' => ['team:'.$project->getAttribute('teamId', null)], - 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], - ], - 'name' => $name, - 'events' => $events, - 'url' => $url, - 'security' => (int) $security, - 'httpUser' => $httpUser, - 'httpPass' => $httpPass, - ]); - - if (false === $webhook) { - throw new Exception('Failed saving webhook to DB', 500); - } - - $project->setAttribute('webhooks', $webhook, Document::SET_TYPE_APPEND); - - $project = $consoleDB->updateDocument($project->getArrayCopy()); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($webhook->getArrayCopy()) - ; + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); + $key = App::getEnv('_APP_OPENSSL_KEY_V1'); + $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); + $tag = null; + $httpPass = \json_encode([ + 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), + 'method' => OpenSSL::CIPHER_AES_128_GCM, + 'iv' => \bin2hex($iv), + 'tag' => \bin2hex($tag), + 'version' => '1', + ]); + + $webhook = $consoleDB->createDocument([ + '$collection' => Database::SYSTEM_COLLECTION_WEBHOOKS, + '$permissions' => [ + 'read' => ['team:'.$project->getAttribute('teamId', null)], + 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], + ], + 'name' => $name, + 'events' => $events, + 'url' => $url, + 'security' => (int) $security, + 'httpUser' => $httpUser, + 'httpPass' => $httpPass, + ]); + + if (false === $webhook) { + throw new Exception('Failed saving webhook to DB', 500); + } + + $project->setAttribute('webhooks', $webhook, Document::SET_TYPE_APPEND); + + $project = $consoleDB->updateDocument($project->getArrayCopy()); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->json($webhook->getArrayCopy()) + ; + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/webhooks') ->desc('List Webhooks') @@ -514,31 +527,32 @@ App::get('/v1/projects/:projectId/webhooks') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listWebhooks') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') - ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $webhooks = $project->getAttribute('webhooks', []); - - foreach ($webhooks as $webhook) { /* @var $webhook Document */ - $httpPass = \json_decode($webhook->getAttribute('httpPass', '{}'), true); - - if (empty($httpPass) || !isset($httpPass['version'])) { - continue; - } - - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); - - $webhook->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); - } - - $response->json($webhooks); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $webhooks = $project->getAttribute('webhooks', []); + + foreach ($webhooks as $webhook) { /* @var $webhook Document */ + $httpPass = \json_decode($webhook->getAttribute('httpPass', '{}'), true); + + if (empty($httpPass) || !isset($httpPass['version'])) { + continue; + } + + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); + + $webhook->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); + } + + $response->json($webhooks); + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Get Webhook') @@ -548,31 +562,31 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->label('sdk.method', 'getWebhook') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('webhookId', null, function () { return new UID(); }, 'Webhook unique ID.') - ->action( - function ($projectId, $webhookId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $webhookId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $webhook = $project->search('$id', $webhookId, $project->getAttribute('webhooks', [])); - - if (empty($webhook) || !$webhook instanceof Document) { - throw new Exception('Webhook not found', 404); - } - - $httpPass = \json_decode($webhook->getAttribute('httpPass', '{}'), true); - - if (!empty($httpPass) && isset($httpPass['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); - $webhook->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); - } - - $response->json($webhook->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + $webhook = $project->search('$id', $webhookId, $project->getAttribute('webhooks', [])); + + if (empty($webhook) || !$webhook instanceof Document) { + throw new Exception('Webhook not found', 404); + } + + $httpPass = \json_decode($webhook->getAttribute('httpPass', '{}'), true); + + if (!empty($httpPass) && isset($httpPass['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); + $webhook->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); + } + + $response->json($webhook->getArrayCopy()); + }, ['response', 'consoleDB']); App::put('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Update Webhook') @@ -587,48 +601,49 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('url', null, function () { return new Text(2000); }, 'Webhook URL.') ->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true) ->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password.', true) - ->action( - function ($projectId, $webhookId, $name, $events, $url, $security, $httpUser, $httpPass) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $webhookId, $name, $events, $url, $security, $httpUser, $httpPass, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $key = App::getEnv('_APP_OPENSSL_KEY_V1'); - $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); - $tag = null; - $httpPass = \json_encode([ - 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), - 'method' => OpenSSL::CIPHER_AES_128_GCM, - 'iv' => \bin2hex($iv), - 'tag' => \bin2hex($tag), - 'version' => '1', - ]); - - $webhook = $project->search('$id', $webhookId, $project->getAttribute('webhooks', [])); - - if (empty($webhook) || !$webhook instanceof Document) { - throw new Exception('Webhook not found', 404); - } - - $webhook - ->setAttribute('name', $name) - ->setAttribute('events', $events) - ->setAttribute('url', $url) - ->setAttribute('security', (int) $security) - ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass) - ; - - if (false === $consoleDB->updateDocument($webhook->getArrayCopy())) { - throw new Exception('Failed saving webhook to DB', 500); - } - - $response->json($webhook->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); + $key = App::getEnv('_APP_OPENSSL_KEY_V1'); + $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); + $tag = null; + $httpPass = \json_encode([ + 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), + 'method' => OpenSSL::CIPHER_AES_128_GCM, + 'iv' => \bin2hex($iv), + 'tag' => \bin2hex($tag), + 'version' => '1', + ]); + + $webhook = $project->search('$id', $webhookId, $project->getAttribute('webhooks', [])); + + if (empty($webhook) || !$webhook instanceof Document) { + throw new Exception('Webhook not found', 404); + } + + $webhook + ->setAttribute('name', $name) + ->setAttribute('events', $events) + ->setAttribute('url', $url) + ->setAttribute('security', (int) $security) + ->setAttribute('httpUser', $httpUser) + ->setAttribute('httpPass', $httpPass) + ; + + if (false === $consoleDB->updateDocument($webhook->getArrayCopy())) { + throw new Exception('Failed saving webhook to DB', 500); + } + + $response->json($webhook->getArrayCopy()); + }, ['response', 'consoleDB']); App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Delete Webhook') @@ -638,27 +653,28 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->label('sdk.method', 'deleteWebhook') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('webhookId', null, function () { return new UID(); }, 'Webhook unique ID.') - ->action( - function ($projectId, $webhookId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $webhookId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $webhook = $project->search('$id', $webhookId, $project->getAttribute('webhooks', [])); - - if (empty($webhook) || !$webhook instanceof Document) { - throw new Exception('Webhook not found', 404); - } - - if (!$consoleDB->deleteDocument($webhook->getId())) { - throw new Exception('Failed to remove webhook from DB', 500); - } - - $response->noContent(); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $webhook = $project->search('$id', $webhookId, $project->getAttribute('webhooks', [])); + + if (empty($webhook) || !$webhook instanceof Document) { + throw new Exception('Webhook not found', 404); + } + + if (!$consoleDB->deleteDocument($webhook->getId())) { + throw new Exception('Failed to remove webhook from DB', 500); + } + + $response->noContent(); + }, ['response', 'consoleDB']); // Keys @@ -671,43 +687,44 @@ App::post('/v1/projects/:projectId/keys') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('name', null, function () { return new Text(256); }, 'Key name.') ->param('scopes', null, function () { return new ArrayList(new WhiteList(Config::getParam('scopes'))); }, 'Key scopes list.') - ->action( - function ($projectId, $name, $scopes) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $name, $scopes, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $key = $consoleDB->createDocument([ - '$collection' => Database::SYSTEM_COLLECTION_KEYS, - '$permissions' => [ - 'read' => ['team:'.$project->getAttribute('teamId', null)], - 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], - ], - 'name' => $name, - 'scopes' => $scopes, - 'secret' => \bin2hex(\random_bytes(128)), - ]); - - if (false === $key) { - throw new Exception('Failed saving key to DB', 500); - } - - $project->setAttribute('keys', $key, Document::SET_TYPE_APPEND); - - $project = $consoleDB->updateDocument($project->getArrayCopy()); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($key->getArrayCopy()) - ; + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $key = $consoleDB->createDocument([ + '$collection' => Database::SYSTEM_COLLECTION_KEYS, + '$permissions' => [ + 'read' => ['team:'.$project->getAttribute('teamId', null)], + 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], + ], + 'name' => $name, + 'scopes' => $scopes, + 'secret' => \bin2hex(\random_bytes(128)), + ]); + + if (false === $key) { + throw new Exception('Failed saving key to DB', 500); + } + + $project->setAttribute('keys', $key, Document::SET_TYPE_APPEND); + + $project = $consoleDB->updateDocument($project->getArrayCopy()); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->json($key->getArrayCopy()) + ; + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/keys') ->desc('List Keys') @@ -716,17 +733,18 @@ App::get('/v1/projects/:projectId/keys') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listKeys') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') - ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ + + $project = $consoleDB->getDocument($projectId); - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - - $response->json($project->getAttribute('keys', [])); //FIXME make sure array objects return correctly + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $response->json($project->getAttribute('keys', [])); //FIXME make sure array objects return correctly + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/keys/:keyId') ->desc('Get Key') @@ -736,23 +754,21 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->label('sdk.method', 'getKey') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('keyId', null, function () { return new UID(); }, 'Key unique ID.') - ->action( - function ($projectId, $keyId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $keyId, $response, $consoleDB) { + $project = $consoleDB->getDocument($projectId); - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - - $key = $project->search('$id', $keyId, $project->getAttribute('keys', [])); - - if (empty($key) || !$key instanceof Document) { - throw new Exception('Key not found', 404); - } - - $response->json($key->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $key = $project->search('$id', $keyId, $project->getAttribute('keys', [])); + + if (empty($key) || !$key instanceof Document) { + throw new Exception('Key not found', 404); + } + + $response->json($key->getArrayCopy()); + }, ['response', 'consoleDB']); App::put('/v1/projects/:projectId/keys/:keyId') ->desc('Update Key') @@ -764,32 +780,33 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->param('keyId', null, function () { return new UID(); }, 'Key unique ID.') ->param('name', null, function () { return new Text(256); }, 'Key name.') ->param('scopes', null, function () { return new ArrayList(new WhiteList(Config::getParam('scopes'))); }, 'Key scopes list') - ->action( - function ($projectId, $keyId, $name, $scopes) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $keyId, $name, $scopes, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $key = $project->search('$id', $keyId, $project->getAttribute('keys', [])); - - if (empty($key) || !$key instanceof Document) { - throw new Exception('Key not found', 404); - } - - $key - ->setAttribute('name', $name) - ->setAttribute('scopes', $scopes) - ; - - if (false === $consoleDB->updateDocument($key->getArrayCopy())) { - throw new Exception('Failed saving key to DB', 500); - } - - $response->json($key->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $key = $project->search('$id', $keyId, $project->getAttribute('keys', [])); + + if (empty($key) || !$key instanceof Document) { + throw new Exception('Key not found', 404); + } + + $key + ->setAttribute('name', $name) + ->setAttribute('scopes', $scopes) + ; + + if (false === $consoleDB->updateDocument($key->getArrayCopy())) { + throw new Exception('Failed saving key to DB', 500); + } + + $response->json($key->getArrayCopy()); + }, ['response', 'consoleDB']); App::delete('/v1/projects/:projectId/keys/:keyId') ->desc('Delete Key') @@ -799,27 +816,28 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->label('sdk.method', 'deleteKey') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('keyId', null, function () { return new UID(); }, 'Key unique ID.') - ->action( - function ($projectId, $keyId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $keyId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $key = $project->search('$id', $keyId, $project->getAttribute('keys', [])); - - if (empty($key) || !$key instanceof Document) { - throw new Exception('Key not found', 404); - } - - if (!$consoleDB->deleteDocument($key->getId())) { - throw new Exception('Failed to remove key from DB', 500); - } - - $response->noContent(); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $key = $project->search('$id', $keyId, $project->getAttribute('keys', [])); + + if (empty($key) || !$key instanceof Document) { + throw new Exception('Key not found', 404); + } + + if (!$consoleDB->deleteDocument($key->getId())) { + throw new Exception('Failed to remove key from DB', 500); + } + + $response->noContent(); + }, ['response', 'consoleDB']); // Tasks @@ -838,73 +856,74 @@ App::post('/v1/projects/:projectId/tasks') ->param('httpHeaders', null, function () { return new ArrayList(new Text(256)); }, 'Task HTTP headers list.', true) ->param('httpUser', '', function () { return new Text(256); }, 'Task HTTP user.', true) ->param('httpPass', '', function () { return new Text(256); }, 'Task HTTP password.', true) - ->action( - function ($projectId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $cron = CronExpression::factory($schedule); - $next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null; - - $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $key = App::getEnv('_APP_OPENSSL_KEY_V1'); - $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); - $tag = null; - $httpPass = \json_encode([ - 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), - 'method' => OpenSSL::CIPHER_AES_128_GCM, - 'iv' => \bin2hex($iv), - 'tag' => \bin2hex($tag), - 'version' => '1', - ]); - - $task = $consoleDB->createDocument([ - '$collection' => Database::SYSTEM_COLLECTION_TASKS, - '$permissions' => [ - 'read' => ['team:'.$project->getAttribute('teamId', null)], - 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], - ], - 'name' => $name, - 'status' => $status, - 'schedule' => $schedule, - 'updated' => \time(), - 'previous' => null, - 'next' => $next, - 'security' => (int) $security, - 'httpMethod' => $httpMethod, - 'httpUrl' => $httpUrl, - 'httpHeaders' => $httpHeaders, - 'httpUser' => $httpUser, - 'httpPass' => $httpPass, - 'log' => '{}', - 'failures' => 0, - ]); - - if (false === $task) { - throw new Exception('Failed saving tasks to DB', 500); - } - - $project->setAttribute('tasks', $task, Document::SET_TYPE_APPEND); - - $project = $consoleDB->updateDocument($project->getArrayCopy()); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - if ($next) { - ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy()); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($task->getArrayCopy()) - ; + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $cron = CronExpression::factory($schedule); + $next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null; + + $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); + $key = App::getEnv('_APP_OPENSSL_KEY_V1'); + $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); + $tag = null; + $httpPass = \json_encode([ + 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), + 'method' => OpenSSL::CIPHER_AES_128_GCM, + 'iv' => \bin2hex($iv), + 'tag' => \bin2hex($tag), + 'version' => '1', + ]); + + $task = $consoleDB->createDocument([ + '$collection' => Database::SYSTEM_COLLECTION_TASKS, + '$permissions' => [ + 'read' => ['team:'.$project->getAttribute('teamId', null)], + 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], + ], + 'name' => $name, + 'status' => $status, + 'schedule' => $schedule, + 'updated' => \time(), + 'previous' => null, + 'next' => $next, + 'security' => (int) $security, + 'httpMethod' => $httpMethod, + 'httpUrl' => $httpUrl, + 'httpHeaders' => $httpHeaders, + 'httpUser' => $httpUser, + 'httpPass' => $httpPass, + 'log' => '{}', + 'failures' => 0, + ]); + + if (false === $task) { + throw new Exception('Failed saving tasks to DB', 500); + } + + $project->setAttribute('tasks', $task, Document::SET_TYPE_APPEND); + + $project = $consoleDB->updateDocument($project->getArrayCopy()); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + if ($next) { + ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy()); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->json($task->getArrayCopy()) + ; + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/tasks') ->desc('List Tasks') @@ -913,31 +932,32 @@ App::get('/v1/projects/:projectId/tasks') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listTasks') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') - ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $tasks = $project->getAttribute('tasks', []); - - foreach ($tasks as $task) { /* @var $task Document */ - $httpPass = \json_decode($task->getAttribute('httpPass', '{}'), true); - - if (empty($httpPass) || !isset($httpPass['version'])) { - continue; - } - - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); - - $task->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); - } - - $response->json($tasks); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $tasks = $project->getAttribute('tasks', []); + + foreach ($tasks as $task) { /* @var $task Document */ + $httpPass = \json_decode($task->getAttribute('httpPass', '{}'), true); + + if (empty($httpPass) || !isset($httpPass['version'])) { + continue; + } + + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); + + $task->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); + } + + $response->json($tasks); + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/tasks/:taskId') ->desc('Get Task') @@ -947,30 +967,31 @@ App::get('/v1/projects/:projectId/tasks/:taskId') ->label('sdk.method', 'getTask') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('taskId', null, function () { return new UID(); }, 'Task unique ID.') - ->action( - function ($projectId, $taskId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $taskId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $task = $project->search('$id', $taskId, $project->getAttribute('tasks', [])); - - if (empty($task) || !$task instanceof Document) { - throw new Exception('Task not found', 404); - } - - $httpPass = \json_decode($task->getAttribute('httpPass', '{}'), true); - - if (!empty($httpPass) && isset($httpPass['version'])) { - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); - $task->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); - } - - $response->json($task->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $task = $project->search('$id', $taskId, $project->getAttribute('tasks', [])); + + if (empty($task) || !$task instanceof Document) { + throw new Exception('Task not found', 404); + } + + $httpPass = \json_decode($task->getAttribute('httpPass', '{}'), true); + + if (!empty($httpPass) && isset($httpPass['version'])) { + $key = App::getEnv('_APP_OPENSSL_KEY_V'.$httpPass['version']); + $task->setAttribute('httpPass', OpenSSL::decrypt($httpPass['data'], $httpPass['method'], $key, 0, \hex2bin($httpPass['iv']), \hex2bin($httpPass['tag']))); + } + + $response->json($task->getArrayCopy()); + }, ['response', 'consoleDB']); App::put('/v1/projects/:projectId/tasks/:taskId') ->desc('Update Task') @@ -989,60 +1010,61 @@ App::put('/v1/projects/:projectId/tasks/:taskId') ->param('httpHeaders', null, function () { return new ArrayList(new Text(256)); }, 'Task HTTP headers list.', true) ->param('httpUser', '', function () { return new Text(256); }, 'Task HTTP user.', true) ->param('httpPass', '', function () { return new Text(256); }, 'Task HTTP password.', true) - ->action( - function ($projectId, $taskId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $taskId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $task = $project->search('$id', $taskId, $project->getAttribute('tasks', [])); - - if (empty($task) || !$task instanceof Document) { - throw new Exception('Task not found', 404); - } - - $cron = CronExpression::factory($schedule); - $next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null; - - $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $key = App::getEnv('_APP_OPENSSL_KEY_V1'); - $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); - $tag = null; - $httpPass = \json_encode([ - 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), - 'method' => OpenSSL::CIPHER_AES_128_GCM, - 'iv' => \bin2hex($iv), - 'tag' => \bin2hex($tag), - 'version' => '1', - ]); - - $task - ->setAttribute('name', $name) - ->setAttribute('status', $status) - ->setAttribute('schedule', $schedule) - ->setAttribute('updated', \time()) - ->setAttribute('next', $next) - ->setAttribute('security', (int) $security) - ->setAttribute('httpMethod', $httpMethod) - ->setAttribute('httpUrl', $httpUrl) - ->setAttribute('httpHeaders', $httpHeaders) - ->setAttribute('httpUser', $httpUser) - ->setAttribute('httpPass', $httpPass) - ; - - if (false === $consoleDB->updateDocument($task->getArrayCopy())) { - throw new Exception('Failed saving tasks to DB', 500); - } - - if ($next) { - ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy()); - } - - $response->json($task->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $task = $project->search('$id', $taskId, $project->getAttribute('tasks', [])); + + if (empty($task) || !$task instanceof Document) { + throw new Exception('Task not found', 404); + } + + $cron = CronExpression::factory($schedule); + $next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null; + + $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); + $key = App::getEnv('_APP_OPENSSL_KEY_V1'); + $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); + $tag = null; + $httpPass = \json_encode([ + 'data' => OpenSSL::encrypt($httpPass, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), + 'method' => OpenSSL::CIPHER_AES_128_GCM, + 'iv' => \bin2hex($iv), + 'tag' => \bin2hex($tag), + 'version' => '1', + ]); + + $task + ->setAttribute('name', $name) + ->setAttribute('status', $status) + ->setAttribute('schedule', $schedule) + ->setAttribute('updated', \time()) + ->setAttribute('next', $next) + ->setAttribute('security', (int) $security) + ->setAttribute('httpMethod', $httpMethod) + ->setAttribute('httpUrl', $httpUrl) + ->setAttribute('httpHeaders', $httpHeaders) + ->setAttribute('httpUser', $httpUser) + ->setAttribute('httpPass', $httpPass) + ; + + if (false === $consoleDB->updateDocument($task->getArrayCopy())) { + throw new Exception('Failed saving tasks to DB', 500); + } + + if ($next) { + ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy()); + } + + $response->json($task->getArrayCopy()); + }, ['response', 'consoleDB']); App::delete('/v1/projects/:projectId/tasks/:taskId') ->desc('Delete Task') @@ -1052,27 +1074,28 @@ App::delete('/v1/projects/:projectId/tasks/:taskId') ->label('sdk.method', 'deleteTask') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('taskId', null, function () { return new UID(); }, 'Task unique ID.') - ->action( - function ($projectId, $taskId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $taskId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $task = $project->search('$id', $taskId, $project->getAttribute('tasks', [])); - - if (empty($task) || !$task instanceof Document) { - throw new Exception('Task not found', 404); - } - - if (!$consoleDB->deleteDocument($task->getId())) { - throw new Exception('Failed to remove tasks from DB', 500); - } - - $response->noContent(); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $task = $project->search('$id', $taskId, $project->getAttribute('tasks', [])); + + if (empty($task) || !$task instanceof Document) { + throw new Exception('Task not found', 404); + } + + if (!$consoleDB->deleteDocument($task->getId())) { + throw new Exception('Failed to remove tasks from DB', 500); + } + + $response->noContent(); + }, ['response', 'consoleDB']); // Platforms @@ -1088,47 +1111,48 @@ App::post('/v1/projects/:projectId/platforms') ->param('key', '', function () { return new Text(256); }, 'Package name for android or bundle ID for iOS.', true) ->param('store', '', function () { return new Text(256); }, 'App store or Google Play store ID.', true) ->param('hostname', '', function () { return new Text(256); }, 'Platform client hostname.', true) - ->action( - function ($projectId, $type, $name, $key, $store, $hostname) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $type, $name, $key, $store, $hostname, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $platform = $consoleDB->createDocument([ - '$collection' => Database::SYSTEM_COLLECTION_PLATFORMS, - '$permissions' => [ - 'read' => ['team:'.$project->getAttribute('teamId', null)], - 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], - ], - 'type' => $type, - 'name' => $name, - 'key' => $key, - 'store' => $store, - 'hostname' => $hostname, - 'dateCreated' => \time(), - 'dateUpdated' => \time(), - ]); - - if (false === $platform) { - throw new Exception('Failed saving platform to DB', 500); - } - - $project->setAttribute('platforms', $platform, Document::SET_TYPE_APPEND); - - $project = $consoleDB->updateDocument($project->getArrayCopy()); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($platform->getArrayCopy()) - ; + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $platform = $consoleDB->createDocument([ + '$collection' => Database::SYSTEM_COLLECTION_PLATFORMS, + '$permissions' => [ + 'read' => ['team:'.$project->getAttribute('teamId', null)], + 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], + ], + 'type' => $type, + 'name' => $name, + 'key' => $key, + 'store' => $store, + 'hostname' => $hostname, + 'dateCreated' => \time(), + 'dateUpdated' => \time(), + ]); + + if (false === $platform) { + throw new Exception('Failed saving platform to DB', 500); + } + + $project->setAttribute('platforms', $platform, Document::SET_TYPE_APPEND); + + $project = $consoleDB->updateDocument($project->getArrayCopy()); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->json($platform->getArrayCopy()) + ; + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/platforms') ->desc('List Platforms') @@ -1137,19 +1161,20 @@ App::get('/v1/projects/:projectId/platforms') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listPlatforms') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') - ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $platforms = $project->getAttribute('platforms', []); - - $response->json($platforms); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $platforms = $project->getAttribute('platforms', []); + + $response->json($platforms); + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/platforms/:platformId') ->desc('Get Platform') @@ -1159,23 +1184,24 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->label('sdk.method', 'getPlatform') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('platformId', null, function () { return new UID(); }, 'Platform unique ID.') - ->action( - function ($projectId, $platformId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $platformId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $platform = $project->search('$id', $platformId, $project->getAttribute('platforms', [])); - - if (empty($platform) || !$platform instanceof Document) { - throw new Exception('Platform not found', 404); - } - - $response->json($platform->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $platform = $project->search('$id', $platformId, $project->getAttribute('platforms', [])); + + if (empty($platform) || !$platform instanceof Document) { + throw new Exception('Platform not found', 404); + } + + $response->json($platform->getArrayCopy()); + }, ['response', 'consoleDB']); App::put('/v1/projects/:projectId/platforms/:platformId') ->desc('Update Platform') @@ -1189,35 +1215,36 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->param('key', '', function () { return new Text(256); }, 'Package name for android or bundle ID for iOS.', true) ->param('store', '', function () { return new Text(256); }, 'App store or Google Play store ID.', true) ->param('hostname', '', function () { return new Text(256); }, 'Platform client URL.', true) - ->action( - function ($projectId, $platformId, $name, $key, $store, $hostname) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $platformId, $name, $key, $store, $hostname, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $platform = $project->search('$id', $platformId, $project->getAttribute('platforms', [])); - - if (empty($platform) || !$platform instanceof Document) { - throw new Exception('Platform not found', 404); - } - - $platform - ->setAttribute('name', $name) - ->setAttribute('dateUpdated', \time()) - ->setAttribute('key', $key) - ->setAttribute('store', $store) - ->setAttribute('hostname', $hostname) - ; - - if (false === $consoleDB->updateDocument($platform->getArrayCopy())) { - throw new Exception('Failed saving platform to DB', 500); - } - - $response->json($platform->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $platform = $project->search('$id', $platformId, $project->getAttribute('platforms', [])); + + if (empty($platform) || !$platform instanceof Document) { + throw new Exception('Platform not found', 404); + } + + $platform + ->setAttribute('name', $name) + ->setAttribute('dateUpdated', \time()) + ->setAttribute('key', $key) + ->setAttribute('store', $store) + ->setAttribute('hostname', $hostname) + ; + + if (false === $consoleDB->updateDocument($platform->getArrayCopy())) { + throw new Exception('Failed saving platform to DB', 500); + } + + $response->json($platform->getArrayCopy()); + }, ['response', 'consoleDB']); App::delete('/v1/projects/:projectId/platforms/:platformId') ->desc('Delete Platform') @@ -1227,27 +1254,28 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->label('sdk.method', 'deletePlatform') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('platformId', null, function () { return new UID(); }, 'Platform unique ID.') - ->action( - function ($projectId, $platformId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $platformId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $platform = $project->search('$id', $platformId, $project->getAttribute('platforms', [])); - - if (empty($platform) || !$platform instanceof Document) { - throw new Exception('Platform not found', 404); - } - - if (!$consoleDB->deleteDocument($platform->getId())) { - throw new Exception('Failed to remove platform from DB', 500); - } - - $response->noContent(); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $platform = $project->search('$id', $platformId, $project->getAttribute('platforms', [])); + + if (empty($platform) || !$platform instanceof Document) { + throw new Exception('Platform not found', 404); + } + + if (!$consoleDB->deleteDocument($platform->getId())) { + throw new Exception('Failed to remove platform from DB', 500); + } + + $response->noContent(); + }, ['response', 'consoleDB']); // Domains @@ -1259,60 +1287,61 @@ App::post('/v1/projects/:projectId/domains') ->label('sdk.method', 'createDomain') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('domain', null, function () { return new DomainValidator(); }, 'Domain name.') - ->action( - function ($projectId, $domain) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $domain, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $document = $project->search('domain', $domain, $project->getAttribute('domains', [])); - - if (!empty($document)) { - throw new Exception('Domain already exists', 409); - } - - $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - - if (!$target->isKnown() || $target->isTest()) { - throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500); - } - - $domain = new Domain($domain); - - $domain = $consoleDB->createDocument([ - '$collection' => Database::SYSTEM_COLLECTION_DOMAINS, - '$permissions' => [ - 'read' => ['team:'.$project->getAttribute('teamId', null)], - 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], - ], - 'updated' => \time(), - 'domain' => $domain->get(), - 'tld' => $domain->getSuffix(), - 'registerable' => $domain->getRegisterable(), - 'verification' => false, - 'certificateId' => null, - ]); - - if (false === $domain) { - throw new Exception('Failed saving domain to DB', 500); - } - - $project->setAttribute('domains', $domain, Document::SET_TYPE_APPEND); - - $project = $consoleDB->updateDocument($project->getArrayCopy()); - - if (false === $project) { - throw new Exception('Failed saving project to DB', 500); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($domain->getArrayCopy()) - ; + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $document = $project->search('domain', $domain, $project->getAttribute('domains', [])); + + if (!empty($document)) { + throw new Exception('Domain already exists', 409); + } + + $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); + + if (!$target->isKnown() || $target->isTest()) { + throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500); + } + + $domain = new Domain($domain); + + $domain = $consoleDB->createDocument([ + '$collection' => Database::SYSTEM_COLLECTION_DOMAINS, + '$permissions' => [ + 'read' => ['team:'.$project->getAttribute('teamId', null)], + 'write' => ['team:'.$project->getAttribute('teamId', null).'/owner', 'team:'.$project->getAttribute('teamId', null).'/developer'], + ], + 'updated' => \time(), + 'domain' => $domain->get(), + 'tld' => $domain->getSuffix(), + 'registerable' => $domain->getRegisterable(), + 'verification' => false, + 'certificateId' => null, + ]); + + if (false === $domain) { + throw new Exception('Failed saving domain to DB', 500); + } + + $project->setAttribute('domains', $domain, Document::SET_TYPE_APPEND); + + $project = $consoleDB->updateDocument($project->getArrayCopy()); + + if (false === $project) { + throw new Exception('Failed saving project to DB', 500); + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->json($domain->getArrayCopy()) + ; + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/domains') ->desc('List Domains') @@ -1321,19 +1350,20 @@ App::get('/v1/projects/:projectId/domains') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listDomains') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') - ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $domains = $project->getAttribute('domains', []); - - $response->json($domains); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $domains = $project->getAttribute('domains', []); + + $response->json($domains); + }, ['response', 'consoleDB']); App::get('/v1/projects/:projectId/domains/:domainId') ->desc('Get Domain') @@ -1343,23 +1373,24 @@ App::get('/v1/projects/:projectId/domains/:domainId') ->label('sdk.method', 'getDomain') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('domainId', null, function () { return new UID(); }, 'Domain unique ID.') - ->action( - function ($projectId, $domainId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $domainId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $domain = $project->search('$id', $domainId, $project->getAttribute('domains', [])); - - if (empty($domain) || !$domain instanceof Document) { - throw new Exception('Domain not found', 404); - } - - $response->json($domain->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $domain = $project->search('$id', $domainId, $project->getAttribute('domains', [])); + + if (empty($domain) || !$domain instanceof Document) { + throw new Exception('Domain not found', 404); + } + + $response->json($domain->getArrayCopy()); + }, ['response', 'consoleDB']); App::patch('/v1/projects/:projectId/domains/:domainId/verification') ->desc('Update Domain Verification Status') @@ -1369,54 +1400,55 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification') ->label('sdk.method', 'updateDomainVerification') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('domainId', null, function () { return new UID(); }, 'Domain unique ID.') - ->action( - function ($projectId, $domainId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $domainId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $domain = $project->search('$id', $domainId, $project->getAttribute('domains', [])); - - if (empty($domain) || !$domain instanceof Document) { - throw new Exception('Domain not found', 404); - } - - $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - - if (!$target->isKnown() || $target->isTest()) { - throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500); - } - - if ($domain->getAttribute('verification') === true) { - return $response->json($domain->getArrayCopy()); - } - - // Verify Domain with DNS records - $validator = new CNAME($target->get()); - - if (!$validator->isValid($domain->getAttribute('domain', ''))) { - throw new Exception('Failed to verify domain', 401); - } - - $domain - ->setAttribute('verification', true) - ; - - if (false === $consoleDB->updateDocument($domain->getArrayCopy())) { - throw new Exception('Failed saving domains to DB', 500); - } - - // Issue a TLS certificate when domain is verified - Resque::enqueue('v1-certificates', 'CertificatesV1', [ - 'document' => $domain->getArrayCopy(), - 'domain' => $domain->getAttribute('domain'), - ]); - - $response->json($domain->getArrayCopy()); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); + + $domain = $project->search('$id', $domainId, $project->getAttribute('domains', [])); + + if (empty($domain) || !$domain instanceof Document) { + throw new Exception('Domain not found', 404); + } + + $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); + + if (!$target->isKnown() || $target->isTest()) { + throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500); + } + + if ($domain->getAttribute('verification') === true) { + return $response->json($domain->getArrayCopy()); + } + + // Verify Domain with DNS records + $validator = new CNAME($target->get()); + + if (!$validator->isValid($domain->getAttribute('domain', ''))) { + throw new Exception('Failed to verify domain', 401); + } + + $domain + ->setAttribute('verification', true) + ; + + if (false === $consoleDB->updateDocument($domain->getArrayCopy())) { + throw new Exception('Failed saving domains to DB', 500); + } + + // Issue a TLS certificate when domain is verified + Resque::enqueue('v1-certificates', 'CertificatesV1', [ + 'document' => $domain->getArrayCopy(), + 'domain' => $domain->getAttribute('domain'), + ]); + + $response->json($domain->getArrayCopy()); + }, ['response', 'consoleDB']); App::delete('/v1/projects/:projectId/domains/:domainId') ->desc('Delete Domain') @@ -1426,24 +1458,25 @@ App::delete('/v1/projects/:projectId/domains/:domainId') ->label('sdk.method', 'deleteDomain') ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('domainId', null, function () { return new UID(); }, 'Domain unique ID.') - ->action( - function ($projectId, $domainId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); + ->action(function ($projectId, $domainId, $response, $consoleDB) { + /** @var Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ - if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } + $project = $consoleDB->getDocument($projectId); - $domain = $project->search('$id', $domainId, $project->getAttribute('domains', [])); - - if (empty($domain) || !$domain instanceof Document) { - throw new Exception('Domain not found', 404); - } - - if (!$consoleDB->deleteDocument($domain->getId())) { - throw new Exception('Failed to remove domains from DB', 500); - } - - $response->noContent(); + if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { + throw new Exception('Project not found', 404); } - ); \ No newline at end of file + + $domain = $project->search('$id', $domainId, $project->getAttribute('domains', [])); + + if (empty($domain) || !$domain instanceof Document) { + throw new Exception('Domain not found', 404); + } + + if (!$consoleDB->deleteDocument($domain->getId())) { + throw new Exception('Failed to remove domains from DB', 500); + } + + $response->noContent(); + }, ['response', 'consoleDB']); \ No newline at end of file diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index 962373bd5..fb64331c3 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -331,7 +331,7 @@ App::get('/console/users/teams/team') ->groups(['web', 'console']) ->label('permission', 'public') ->label('scope', 'console') - ->action(function () use ($layout) { + ->action(function ($layout) { /** @var Utopia\View $layout */ $page = new View(__DIR__.'/../../views/console/users/team.phtml'); diff --git a/public/index.php b/public/index.php index ef4d11d2a..794382ff5 100644 --- a/public/index.php +++ b/public/index.php @@ -14,6 +14,6 @@ ini_set('display_errors', 0); ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); -trigger_error('hide errors in prod', E_USER_NOTICE); +//trigger_error('hide errors in prod', E_USER_NOTICE); include __DIR__ . '/../app/app.php';