From c10500c882f6f666786fe39bda5915e87eceb919 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 23 Feb 2021 13:29:12 +0200 Subject: [PATCH 01/25] Added an option for a console god user --- .env | 3 +++ Dockerfile | 7 ++++++ app/config/collections.php | 1 + app/config/variables.php | 10 +++++++- app/controllers/api/account.php | 14 +++++++++++ app/controllers/web/home.php | 40 ++++++++++++++++++++++++++++++-- app/tasks/doctor.php | 4 +++- app/views/home/auth/signin.phtml | 5 +++- app/views/home/auth/signup.phtml | 7 +++++- 9 files changed, 85 insertions(+), 6 deletions(-) diff --git a/.env b/.env index 581af6d97..eb1c594ed 100644 --- a/.env +++ b/.env @@ -1,5 +1,8 @@ _APP_ENV=production _APP_ENV=development +_APP_CONSOLE_WHITELIST_GOD=enabled +_APP_CONSOLE_WHITELIST_EMAILS= +_APP_CONSOLE_WHITELIST_IPS= _APP_SYSTEM_EMAIL_NAME=Appwrite _APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io diff --git a/Dockerfile b/Dockerfile index c7316bd1d..52dbeaff7 100755 --- a/Dockerfile +++ b/Dockerfile @@ -72,6 +72,13 @@ ENV _APP_SERVER=swoole \ _APP_DOMAIN_TARGET=localhost \ _APP_HOME=https://appwrite.io \ _APP_EDITION=community \ + _APP_CONSOLE_WHITELIST_GOD=enabled \ + _APP_CONSOLE_WHITELIST_EMAILS= \ + _APP_CONSOLE_WHITELIST_IPS= \ + _APP_SYSTEM_EMAIL_NAME= \ + _APP_SYSTEM_EMAIL_ADDRESS= \ + _APP_SYSTEM_RESPONSE_FORMAT= \ + _APP_SYSTEM_SECURITY_EMAIL_ADDRESS= \ _APP_OPTIONS_ABUSE=enabled \ _APP_OPTIONS_FORCE_HTTPS=disabled \ _APP_OPENSSL_KEY_V1=your-secret-key \ diff --git a/app/config/collections.php b/app/config/collections.php index 9170b0757..ec735a278 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -43,6 +43,7 @@ $collections = [ 'legalCity' => '', 'legalAddress' => '', 'legalTaxId' => '', + 'authWhitelistGod' => App::getEnv('_APP_CONSOLE_WHITELIST_GOD', 'enabled'), 'authWhitelistEmails' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], 'authWhitelistIPs' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], 'authWhitelistDomains' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null)) : [], diff --git a/app/config/variables.php b/app/config/variables.php index 722796c6f..c8f571e1f 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -55,9 +55,17 @@ return [ 'required' => true, 'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.\nYou can use the same value as used for the Appwrite hostname.', ], + [ + 'name' => '_APP_CONSOLE_WHITELIST_GOD', + 'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registartion form. New users can be added by invting them to your project. By default this option is enabled.', + 'introduction' => '', + 'default' => 'enabled', + 'required' => false, + 'question' => '', + ], [ 'name' => '_APP_CONSOLE_WHITELIST_EMAILS', - 'description' => 'This option allows you to limit creation of users to Appwrite console. This option is very useful for small teams or sole developers. To enable it, pass a list of allowed email addresses separated by a comma.', + 'description' => 'This option allows you to limit creation of new users on the Appwrite console. This option is very useful for small teams or sole developers. To enable it, pass a list of allowed email addresses separated by a comma.', 'introduction' => '', 'default' => '', 'required' => false, diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index e8ae76312..9c6516f91 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -58,10 +58,24 @@ App::post('/v1/account') /** @var Appwrite\Event\Event $audits */ if ('console' === $project->getId()) { + $whitlistGod = $project->getAttribute('authWhitelistGod'); $whitlistEmails = $project->getAttribute('authWhitelistEmails'); $whitlistIPs = $project->getAttribute('authWhitelistIPs'); $whitlistDomains = $project->getAttribute('authWhitelistDomains'); + if($whitlistGod !== 'disabled') { + $sum = $projectDB->getCount([ // Count users + 'limit' => 1, + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_USERS, + ], + ]); + + if($sum !== 0) { + throw new Exception('Console registration is restricted. Contact your administrator for more information.', 401); + } + } + if (!empty($whitlistEmails) && !\in_array($email, $whitlistEmails)) { throw new Exception('Console registration is restricted to specific emails. Contact your administrator for more information.', 401); } diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index f302f0af3..18231e4a0 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -1,5 +1,6 @@ label('permission', 'public') ->label('scope', 'home') ->inject('response') - ->action(function ($response) { + ->inject('project') + ->inject('projectDB') + ->action(function ($response, $projectDB, $project) { /** @var Appwrite\Utopia\Response $response */ + /** @var Appwrite\Database\Database $projectDB */ + /** @var Appwrite\Database\Document $project */ - $response->redirect('/auth/signin'); + $response + ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') + ->addHeader('Expires', 0) + ->addHeader('Pragma', 'no-cache') + ; + + if ('console' === $project->getId()) { + $whitlistGod = $project->getAttribute('authWhitelistGod'); + + if($whitlistGod !== 'disabled') { + $sum = $projectDB->getCount([ // Count users + 'limit' => 1, + 'filters' => [ + '$collection='.Database::SYSTEM_COLLECTION_USERS, + ], + ]); + + if($sum !== 0) { + return $response->redirect('/auth/signin'); + } + } + } + + $response->redirect('/auth/signup'); }); App::get('/auth/signin') @@ -58,6 +86,10 @@ App::get('/auth/signin') $page = new View(__DIR__.'/../../views/home/auth/signin.phtml'); + $page + ->setParam('god', App::getEnv('_APP_CONSOLE_WHITELIST_GOD', 'enabled')) + ; + $layout ->setParam('title', 'Sign In - '.APP_NAME) ->setParam('body', $page); @@ -72,6 +104,10 @@ App::get('/auth/signup') /** @var Utopia\View $layout */ $page = new View(__DIR__.'/../../views/home/auth/signup.phtml'); + $page + ->setParam('god', App::getEnv('_APP_CONSOLE_WHITELIST_GOD', 'enabled')) + ; + $layout ->setParam('title', 'Sign Up - '.APP_NAME) ->setParam('body', $page); diff --git a/app/tasks/doctor.php b/app/tasks/doctor.php index 2918d4f1e..a6231daca 100644 --- a/app/tasks/doctor.php +++ b/app/tasks/doctor.php @@ -61,11 +61,13 @@ $cli Console::log('🟢 Abuse protection is enabled'); } + $authWhitelistGod = App::getEnv('_APP_CONSOLE_WHITELIST_GOD', null); $authWhitelistEmails = App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null); $authWhitelistIPs = App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null); $authWhitelistDomains = App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null); - if(empty($authWhitelistEmails) + if(empty($authWhitelistGod) + && empty($authWhitelistEmails) && empty($authWhitelistDomains) && empty($authWhitelistIPs) ) { diff --git a/app/views/home/auth/signin.phtml b/app/views/home/auth/signin.phtml index 405256a60..d89f7e41d 100644 --- a/app/views/home/auth/signin.phtml +++ b/app/views/home/auth/signin.phtml @@ -1,3 +1,6 @@ +getParam('god') !== 'disabled'); +?>
- Forgot password? or don't have an account? Sign up now + Forgot password? or don't have an account? Sign up now
diff --git a/app/views/home/auth/signup.phtml b/app/views/home/auth/signup.phtml index b5aac0143..03613746e 100644 --- a/app/views/home/auth/signup.phtml +++ b/app/views/home/auth/signup.phtml @@ -1,3 +1,6 @@ +getParam('god') !== 'disabled'); +?>

Sign Up @@ -44,6 +47,8 @@

+
Already have an account? -
\ No newline at end of file + + \ No newline at end of file From cdf54fd19c4c87425317447dafc4c03bc2c2e8d9 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 23 Feb 2021 14:00:31 +0200 Subject: [PATCH 02/25] Disable recovery when SMTP is off --- .env | 2 +- app/controllers/web/home.php | 4 ++++ app/views/home/auth/recovery.phtml | 11 ++++++++++- app/views/home/auth/signup.phtml | 4 ++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.env b/.env index eb1c594ed..927a863f2 100644 --- a/.env +++ b/.env @@ -26,7 +26,7 @@ _APP_INFLUXDB_HOST=influxdb _APP_INFLUXDB_PORT=8086 _APP_STATSD_HOST=telegraf _APP_STATSD_PORT=8125 -_APP_SMTP_HOST=maildev +_APP_SMTP_HOST= _APP_SMTP_PORT=25 _APP_SMTP_SECURE= _APP_SMTP_USERNAME= diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index 18231e4a0..0a26c67a8 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -123,6 +123,10 @@ App::get('/auth/recovery') $page = new View(__DIR__.'/../../views/home/auth/recovery.phtml'); + $page + ->setParam('smtpEnabled', (!empty(App::getEnv('_APP_SMTP_HOST')))) + ; + $layout ->setParam('title', 'Password Recovery - '.APP_NAME) ->setParam('body', $page); diff --git a/app/views/home/auth/recovery.phtml b/app/views/home/auth/recovery.phtml index 6f633b9a0..39ac4237f 100644 --- a/app/views/home/auth/recovery.phtml +++ b/app/views/home/auth/recovery.phtml @@ -1,3 +1,6 @@ +getParam('smtpEnabled', false); +?>

Password Recovery @@ -25,7 +28,13 @@ - + +
+ SMTP connection is disabled. Learn more +
+ + +

diff --git a/app/views/home/auth/signup.phtml b/app/views/home/auth/signup.phtml index 03613746e..6b5d01f7e 100644 --- a/app/views/home/auth/signup.phtml +++ b/app/views/home/auth/signup.phtml @@ -26,6 +26,10 @@ $god = ($this->getParam('god') !== 'disabled'); data-failure-param-alert-text="Registration Failed. Please try again later" data-failure-param-alert-classname="error"> + +

Please create your first god account

+ + From db898d9f9c2565bd6f5c33a9a45a1d956ed83134 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 23 Feb 2021 14:52:14 +0200 Subject: [PATCH 03/25] Fixed count method --- app/controllers/api/account.php | 5 +++-- app/views/install/compose.phtml | 1 + docker-compose.yml | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 9c6516f91..6674c30cd 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -64,12 +64,13 @@ App::post('/v1/account') $whitlistDomains = $project->getAttribute('authWhitelistDomains'); if($whitlistGod !== 'disabled') { - $sum = $projectDB->getCount([ // Count users - 'limit' => 1, + $projectDB->getCollection([ // Count users 'filters' => [ '$collection='.Database::SYSTEM_COLLECTION_USERS, ], ]); + + $sum = $projectDB->getSum(); if($sum !== 0) { throw new Exception('Console registration is restricted. Contact your administrator for more information.', 401); diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 1c0c98108..993944f26 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -56,6 +56,7 @@ services: - influxdb environment: - _APP_ENV + - _APP_CONSOLE_WHITELIST_GOD - _APP_CONSOLE_WHITELIST_EMAILS - _APP_CONSOLE_WHITELIST_IPS - _APP_SYSTEM_EMAIL_NAME diff --git a/docker-compose.yml b/docker-compose.yml index c4ad29c64..a9b9d0d87 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -75,6 +75,9 @@ services: - influxdb environment: - _APP_ENV + - _APP_CONSOLE_WHITELIST_GOD + - _APP_CONSOLE_WHITELIST_EMAILS + - _APP_CONSOLE_WHITELIST_IPS - _APP_SYSTEM_EMAIL_NAME - _APP_SYSTEM_EMAIL_ADDRESS - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS From 3b9b751d5a1f736f9b19367e41697f3e5961e04b Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 23 Feb 2021 15:03:43 +0200 Subject: [PATCH 04/25] Fixed count --- app/controllers/web/home.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index 0a26c67a8..1e4363440 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -60,13 +60,14 @@ App::get('/') $whitlistGod = $project->getAttribute('authWhitelistGod'); if($whitlistGod !== 'disabled') { - $sum = $projectDB->getCount([ // Count users - 'limit' => 1, + $projectDB->getCollection([ // Count users 'filters' => [ '$collection='.Database::SYSTEM_COLLECTION_USERS, ], ]); - + + $sum = $projectDB->getSum(); + if($sum !== 0) { return $response->redirect('/auth/signin'); } From 76cb9c14feb5a0c297d641fcac47b25b8e36519d Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 23 Feb 2021 15:19:19 +0200 Subject: [PATCH 05/25] Fix for tests --- .env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env b/.env index 927a863f2..1029b7b55 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ _APP_ENV=production _APP_ENV=development -_APP_CONSOLE_WHITELIST_GOD=enabled +_APP_CONSOLE_WHITELIST_GOD=disabled _APP_CONSOLE_WHITELIST_EMAILS= _APP_CONSOLE_WHITELIST_IPS= _APP_SYSTEM_EMAIL_NAME=Appwrite @@ -26,7 +26,7 @@ _APP_INFLUXDB_HOST=influxdb _APP_INFLUXDB_PORT=8086 _APP_STATSD_HOST=telegraf _APP_STATSD_PORT=8125 -_APP_SMTP_HOST= +_APP_SMTP_HOST=maildev _APP_SMTP_PORT=25 _APP_SMTP_SECURE= _APP_SMTP_USERNAME= From 61a73eec1f2e3bd83afb885549e71d354c9ff9a4 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 23 Apr 2021 23:33:19 +0300 Subject: [PATCH 06/25] Updated vars order --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 67aae2a26..4cc3d2ea9 100644 --- a/.env +++ b/.env @@ -1,9 +1,9 @@ _APP_ENV=production _APP_ENV=development +_APP_LOCALE=en _APP_CONSOLE_WHITELIST_GOD=disabled _APP_CONSOLE_WHITELIST_EMAILS= _APP_CONSOLE_WHITELIST_IPS= -_APP_LOCALE=en _APP_SYSTEM_EMAIL_NAME=Appwrite _APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io From a0d30aef8cf4f05163712eb50c0ca2b42689f5c0 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 7 May 2021 09:06:36 +0200 Subject: [PATCH 07/25] chore(vars): fix typo on god account description --- app/config/variables.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/variables.php b/app/config/variables.php index ee8818c6b..4b27e88aa 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -65,7 +65,7 @@ return [ ], [ 'name' => '_APP_CONSOLE_WHITELIST_GOD', - 'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registartion form. New users can be added by invting them to your project. By default this option is enabled.', + 'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by invting them to your project. By default this option is enabled.', 'introduction' => '', 'default' => 'enabled', 'required' => false, From 0c3bcb40a4061d99d5f6430e9a905bbdd02dacfc Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 10 May 2021 14:33:27 +0545 Subject: [PATCH 08/25] poc certificate auto generation --- app/http.php | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/app/http.php b/app/http.php index d144c2e54..0e88757ab 100644 --- a/app/http.php +++ b/app/http.php @@ -12,6 +12,7 @@ use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Utopia\App; use Utopia\CLI\Console; +use Utopia\Config\Config; // xdebug_start_trace('/tmp/trace'); @@ -65,22 +66,35 @@ Files::load(__DIR__ . '/../public'); include __DIR__ . '/controllers/general.php'; -$domain = App::getEnv('_APP_DOMAIN', ''); +function certificateSetup($domain) +{ + $domains = Config::getParam('domains', []); + if (!in_array($domain, $domains)) { + //schedule + Console::info('adding ' . $domain . ' to list of domains already checked'); + array_push($domains, $domain); + Config::setParam('domains', $domains); -Console::info('Issuing a TLS certificate for the master domain ('.$domain.') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. + Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script -ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], - 'domain' => $domain, - 'validateTarget' => false, - 'validateCNAME' => false, -]); + ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ + 'document' => [], + 'domain' => $domain, + 'validateTarget' => false, + 'validateCNAME' => false, + ]); + } + +} $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { $request = new Request($swooleRequest); $response = new Response($swooleResponse); + $domain = $request->getHostname(); + certificateSetup($domain); + if(Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From 75d8076ac95477208dd5ade1231f8bbdd4b9144d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 10 May 2021 16:23:05 +0545 Subject: [PATCH 09/25] skip certificate generation when localhost or hostname is IP --- app/http.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/http.php b/app/http.php index 0e88757ab..d71db4a6a 100644 --- a/app/http.php +++ b/app/http.php @@ -68,6 +68,7 @@ include __DIR__ . '/controllers/general.php'; function certificateSetup($domain) { + if($domain=='localhost' || (bool)ip2long($domain)) return; $domains = Config::getParam('domains', []); if (!in_array($domain, $domains)) { //schedule From c22dd1571f9b9d0f47b6cd83f9f26f686b6e210b Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 11:41:11 +0545 Subject: [PATCH 10/25] implementing review suggestions --- app/http.php | 54 +++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/app/http.php b/app/http.php index d71db4a6a..d38d33b7c 100644 --- a/app/http.php +++ b/app/http.php @@ -13,6 +13,7 @@ use Swoole\Http\Response as SwooleResponse; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Domains\Domain; // xdebug_start_trace('/tmp/trace'); @@ -66,35 +67,40 @@ Files::load(__DIR__ . '/../public'); include __DIR__ . '/controllers/general.php'; -function certificateSetup($domain) -{ - if($domain=='localhost' || (bool)ip2long($domain)) return; - $domains = Config::getParam('domains', []); - if (!in_array($domain, $domains)) { - //schedule - Console::info('adding ' . $domain . ' to list of domains already checked'); - array_push($domains, $domain); - Config::setParam('domains', $domains); - - Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script - - ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], - 'domain' => $domain, - 'validateTarget' => false, - 'validateCNAME' => false, - ]); - } - -} - $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { $request = new Request($swooleRequest); $response = new Response($swooleResponse); $domain = $request->getHostname(); - certificateSetup($domain); + $validDomains = Config::getParam('validDomains', []); + if (!array_key_exists($domain, $validDomains)) { + $domainCheck = new Domain(!empty($domain) ? $domain : ''); + if (empty($domainCheck->get()) || !$domainCheck->isKnown() || $domainCheck->isTest()()) { + $validDomains[$domain] = false; + } else { + $validDomains[$domain] = true; + } + Config::setParam('validDomains', $validDomains); + } + if ($validDomains[$domain]) { + $issuedDomains = Config::getParam('issuedDomains', []); + if (!array_key_exists($domain, $issuedDomains)) { + //schedule + Console::info('adding ' . $domain . ' to list of domains already checked'); + $issuedDomains[$domain] = true; + Config::setParam('issuedDomains', $issuedDomains); + + Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. + Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + + ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ + 'document' => [], + 'domain' => $domain, + 'validateTarget' => false, + 'validateCNAME' => false, + ]); + } + } if(Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From 35b76c1aee5f3fe3b87e9fa092e9e935bc3f14ae Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 16:32:02 +0545 Subject: [PATCH 11/25] refactoring moving ssl generation to init function --- app/controllers/general.php | 54 +++++++++++++++++++++++++++++++++++-- app/http.php | 31 --------------------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 1f7d4ebae..9b0a6e7fd 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -23,15 +23,65 @@ 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, $clients) { +App::init(function ($utopia, $request, $response, $console, $project, $consoleDB, $user, $locale, $clients) { /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ /** @var Appwrite\Database\Document $console */ /** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $user */ /** @var Utopia\Locale\Locale $locale */ /** @var bool $mode */ /** @var array $clients */ + + $domain = $request->getHostname(); + $checkedDomains = Config::getParam('checkedDomains', []); + if (!array_key_exists($domain, $checkedDomains)) { + $domain = new Domain(!empty($domain) ? $domain : ''); + + if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()()) { + $checkedDomains[$domain->get()] = false; + Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); + } else { + Console::info($domain->get() . ' is a valid domain.'); + + $dbDomain = $consoleDB->getCollectionFirst([ + 'limit' => 1, + 'offset' => 0, + 'filters' => [ + '$collection=' . Database::SYSTEM_COLLECTION_CERTIFICATES, + 'domain=' . $domain->get(), + ], + ]); + + if (empty($dbDomain)) { + $dbDomain = [ + '$collection' => Database::SYSTEM_COLLECTION_CERTIFICATES, + '$permissions' => [ + 'read' => [], + 'write' => [], + ], + 'domain' => $domain->get(), + ]; + $dbDomain = $consoleDB->createDocument($dbDomain); + + Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in 30 seconds. + Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + + ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ + 'document' => [], + 'domain' => $domain->get(), + 'validateTarget' => false, + 'validateCNAME' => false, + ]); + } + + $checkedDomains[$domain] = true; + + } + Console::info('adding ' . $domain->get() . ' to list of domains already checked'); + Config::setParam('checkedDomains', $checkedDomains); + } $localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); @@ -226,7 +276,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo throw new Exception('Password reset is required', 412); } -}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'clients']); +}, ['utopia', 'request', 'response', 'console', 'project', 'consoleDB', 'user', 'locale', 'clients']); App::options(function ($request, $response) { /** @var Utopia\Swoole\Request $request */ diff --git a/app/http.php b/app/http.php index d38d33b7c..efa47ffbd 100644 --- a/app/http.php +++ b/app/http.php @@ -71,37 +71,6 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $request = new Request($swooleRequest); $response = new Response($swooleResponse); - $domain = $request->getHostname(); - $validDomains = Config::getParam('validDomains', []); - if (!array_key_exists($domain, $validDomains)) { - $domainCheck = new Domain(!empty($domain) ? $domain : ''); - if (empty($domainCheck->get()) || !$domainCheck->isKnown() || $domainCheck->isTest()()) { - $validDomains[$domain] = false; - } else { - $validDomains[$domain] = true; - } - Config::setParam('validDomains', $validDomains); - } - if ($validDomains[$domain]) { - $issuedDomains = Config::getParam('issuedDomains', []); - if (!array_key_exists($domain, $issuedDomains)) { - //schedule - Console::info('adding ' . $domain . ' to list of domains already checked'); - $issuedDomains[$domain] = true; - Config::setParam('issuedDomains', $issuedDomains); - - Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script - - ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], - 'domain' => $domain, - 'validateTarget' => false, - 'validateCNAME' => false, - ]); - } - } - if(Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From 4170eaa45a729829d59f630a9cb2ce8d46ea8b83 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:00:26 +0545 Subject: [PATCH 12/25] fix error --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9b0a6e7fd..a7df8426f 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -39,7 +39,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB if (!array_key_exists($domain, $checkedDomains)) { $domain = new Domain(!empty($domain) ? $domain : ''); - if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()()) { + if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { $checkedDomains[$domain->get()] = false; Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); } else { From dc92498d93e77c1f236ff2b86944ceb94337e1e1 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:06:55 +0545 Subject: [PATCH 13/25] disable auth for writing --- app/controllers/general.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index a7df8426f..559e3baab 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -63,7 +63,9 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB ], 'domain' => $domain->get(), ]; + Authorization::disable(); $dbDomain = $consoleDB->createDocument($dbDomain); + Authorization::enable(); Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in 30 seconds. Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script From dc52c6975a8fbd4ce43a7eea2f56d651ca9eba6e Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:09:23 +0545 Subject: [PATCH 14/25] fix error --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 559e3baab..9323d0a21 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -78,7 +78,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB ]); } - $checkedDomains[$domain] = true; + $checkedDomains[$domain->get()] = true; } Console::info('adding ' . $domain->get() . ' to list of domains already checked'); From f83ad43187e4634e5d50c14110114122a78d1ca8 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:21:27 +0545 Subject: [PATCH 15/25] fix auth issue --- app/controllers/general.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9323d0a21..6ceca25e0 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -44,7 +44,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); } else { Console::info($domain->get() . ' is a valid domain.'); - + Authorization::disable(); $dbDomain = $consoleDB->getCollectionFirst([ 'limit' => 1, 'offset' => 0, @@ -63,7 +63,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB ], 'domain' => $domain->get(), ]; - Authorization::disable(); $dbDomain = $consoleDB->createDocument($dbDomain); Authorization::enable(); From be5b882fe74071b3759021a91da1b685c9f0af32 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 11:02:34 +0545 Subject: [PATCH 16/25] Apply suggestions from code review Co-authored-by: Eldad A. Fux --- app/controllers/general.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 6ceca25e0..695ac93d1 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -41,9 +41,8 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { $checkedDomains[$domain->get()] = false; - Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); + Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); } else { - Console::info($domain->get() . ' is a valid domain.'); Authorization::disable(); $dbDomain = $consoleDB->getCollectionFirst([ 'limit' => 1, @@ -66,8 +65,8 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB $dbDomain = $consoleDB->createDocument($dbDomain); Authorization::enable(); - Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in ~30 seconds. +.'); // TODO move this to installation script ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ 'document' => [], @@ -475,4 +474,4 @@ include_once __DIR__ . '/shared/web.php'; foreach (Config::getParam('services', []) as $service) { include_once $service['controller']; -} \ No newline at end of file +} From 0e90c75a1226ba3c554abf38f9100bab4ccc329c Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 11:04:48 +0545 Subject: [PATCH 17/25] refactor based on review --- app/controllers/general.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 695ac93d1..8f1f75be8 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -14,8 +14,6 @@ use Appwrite\Database\Database; use Appwrite\Database\Document; use Appwrite\Database\Validator\Authorization; use Appwrite\Network\Validator\Origin; -use Utopia\Storage\Device\Local; -use Utopia\Storage\Storage; use Appwrite\Utopia\Response\Filters\V06; use Utopia\CLI\Console; @@ -35,12 +33,12 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB /** @var array $clients */ $domain = $request->getHostname(); - $checkedDomains = Config::getParam('checkedDomains', []); - if (!array_key_exists($domain, $checkedDomains)) { + $domains = Config::getParam('domains', []); + if (!array_key_exists($domain, $domains)) { $domain = new Domain(!empty($domain) ? $domain : ''); if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { - $checkedDomains[$domain->get()] = false; + $domains[$domain->get()] = false; Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); } else { Authorization::disable(); @@ -65,22 +63,21 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB $dbDomain = $consoleDB->createDocument($dbDomain); Authorization::enable(); - Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in ~30 seconds. -.'); // TODO move this to installation script + Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in ~30 seconds..'); // TODO move this to installation script ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], + 'document' => $dbDomain, 'domain' => $domain->get(), 'validateTarget' => false, 'validateCNAME' => false, ]); } - $checkedDomains[$domain->get()] = true; + $domains[$domain->get()] = true; } Console::info('adding ' . $domain->get() . ' to list of domains already checked'); - Config::setParam('checkedDomains', $checkedDomains); + Config::setParam('domains', $domains); } $localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); From 3330841b9e0c95cf7d25e07cdaa2d6a4a20f8c0a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 12:57:08 +0545 Subject: [PATCH 18/25] changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index b8867b0e5..01e32bb79 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Version 0.8.0 (Not Released Yet) ## Features - +- Refactoring SSL generation to work on every request so no domain environment variable is required for SSL generation (#1133) - Added Anonymous Login ([RFC-010](https://github.com/appwrite/rfc/blob/main/010-anonymous-login.md), #914) - Added events for functions and executions (#971) - Added JWT support (#784) From 7a75c3558f7e67970d2c2e94e324671cff4c92e6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 16:10:57 +0545 Subject: [PATCH 19/25] remove log --- app/controllers/general.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 8f1f75be8..98db96a58 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -76,7 +76,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB $domains[$domain->get()] = true; } - Console::info('adding ' . $domain->get() . ' to list of domains already checked'); Config::setParam('domains', $domains); } From e2000dbdf81e1639ab1f4e7d0bd8a3f2d0f90b53 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 16:42:13 +0545 Subject: [PATCH 20/25] remove extra white space --- app/controllers/general.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 98db96a58..9d360f829 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -72,9 +72,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB 'validateCNAME' => false, ]); } - $domains[$domain->get()] = true; - } Config::setParam('domains', $domains); } From bd73b3aa580354f33cf2852684792d571016ffae Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 16:58:31 +0545 Subject: [PATCH 21/25] discord link in the footer --- app/views/console/comps/footer.phtml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/views/console/comps/footer.phtml b/app/views/console/comps/footer.phtml index be5696ce4..923304a9f 100644 --- a/app/views/console/comps/footer.phtml +++ b/app/views/console/comps/footer.phtml @@ -12,6 +12,14 @@ $version = $this->getParam('version', '').'.'.APP_CACHE_BUSTER; data-analytics-label="GitHub Link" href="https://github.com/appwrite/appwrite" target="_blank" rel="noopener"> GitHub +
  • + Discord +
  • Date: Wed, 12 May 2021 14:35:46 +0300 Subject: [PATCH 22/25] Leverage auth limit for god feature --- app/config/collections.php | 3 +-- app/config/variables.php | 2 +- app/controllers/api/account.php | 20 -------------------- app/tasks/doctor.php | 2 -- 4 files changed, 2 insertions(+), 25 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index f61698538..15a6e0abe 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -44,10 +44,9 @@ $collections = [ 'legalCity' => '', 'legalAddress' => '', 'legalTaxId' => '', - 'authWhitelistGod' => App::getEnv('_APP_CONSOLE_WHITELIST_GOD', 'enabled'), 'authWhitelistEmails' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], 'authWhitelistIPs' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], - 'authWhitelistDomains' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null)) : [], + 'usersAuthLimit' => (App::getEnv('_APP_CONSOLE_WHITELIST_GOD', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user ], Database::SYSTEM_COLLECTION_COLLECTIONS => [ '$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS, diff --git a/app/config/variables.php b/app/config/variables.php index becafcd1e..11bf59af2 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -66,7 +66,7 @@ return [ [ 'name' => '_APP_CONSOLE_WHITELIST_GOD', 'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by invting them to your project. By default this option is enabled.', - 'introduction' => '', + 'introduction' => '0.8.0', 'default' => 'enabled', 'required' => false, 'question' => '', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 177384876..294ae817b 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -59,24 +59,8 @@ App::post('/v1/account') /** @var Appwrite\Event\Event $audits */ if ('console' === $project->getId()) { - $whitlistGod = $project->getAttribute('authWhitelistGod'); $whitlistEmails = $project->getAttribute('authWhitelistEmails'); $whitlistIPs = $project->getAttribute('authWhitelistIPs'); - $whitlistDomains = $project->getAttribute('authWhitelistDomains'); - - if($whitlistGod !== 'disabled') { - $projectDB->getCollection([ // Count users - 'filters' => [ - '$collection='.Database::SYSTEM_COLLECTION_USERS, - ], - ]); - - $sum = $projectDB->getSum(); - - if($sum !== 0) { - throw new Exception('Console registration is restricted. Contact your administrator for more information.', 401); - } - } if (!empty($whitlistEmails) && !\in_array($email, $whitlistEmails)) { throw new Exception('Console registration is restricted to specific emails. Contact your administrator for more information.', 401); @@ -85,10 +69,6 @@ App::post('/v1/account') if (!empty($whitlistIPs) && !\in_array($request->getIP(), $whitlistIPs)) { throw new Exception('Console registration is restricted to specific IPs. Contact your administrator for more information.', 401); } - - if (!empty($whitlistDomains) && !\in_array(\substr(\strrchr($email, '@'), 1), $whitlistDomains)) { - throw new Exception('Console registration is restricted to specific domains. Contact your administrator for more information.', 401); - } } $limit = $project->getAttribute('usersAuthLimit', 0); diff --git a/app/tasks/doctor.php b/app/tasks/doctor.php index 20f4e01bc..5feb96047 100644 --- a/app/tasks/doctor.php +++ b/app/tasks/doctor.php @@ -64,11 +64,9 @@ $cli $authWhitelistGod = App::getEnv('_APP_CONSOLE_WHITELIST_GOD', null); $authWhitelistEmails = App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null); $authWhitelistIPs = App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null); - $authWhitelistDomains = App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null); if(empty($authWhitelistGod) && empty($authWhitelistEmails) - && empty($authWhitelistDomains) && empty($authWhitelistIPs) ) { Console::log('🔴 Console access limits are disabled'); From d94771471c0a47df3853620306e55ec80e4f9795 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 17:40:16 +0545 Subject: [PATCH 23/25] format update for travis reboot --- app/views/console/comps/footer.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/console/comps/footer.phtml b/app/views/console/comps/footer.phtml index 923304a9f..065dabb14 100644 --- a/app/views/console/comps/footer.phtml +++ b/app/views/console/comps/footer.phtml @@ -1,6 +1,6 @@ getParam('home', ''); -$version = $this->getParam('version', '').'.'.APP_CACHE_BUSTER; +$version = $this->getParam('version', '') . '.' . APP_CACHE_BUSTER; ?>