diff --git a/src/cloudron.js b/src/cloudron.js index 877390ca7..1ab7c20c2 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -8,12 +8,17 @@ exports = module.exports = { getConfig: getConfig, getDisks: getDisks, getLogs: getLogs, + getStatus: getStatus, reboot: reboot, onActivated: onActivated, - checkDiskSpace: checkDiskSpace + + checkDiskSpace: checkDiskSpace, + + configureWebadmin: configureWebadmin, + getWebadminStatus: getWebadminStatus }; var assert = require('assert'), @@ -21,6 +26,7 @@ var assert = require('assert'), config = require('./config.js'), cron = require('./cron.js'), debug = require('debug')('box:cloudron'), + domains = require('./domains.js'), df = require('@sindresorhus/df'), mailer = require('./mailer.js'), os = require('os'), @@ -35,6 +41,7 @@ var assert = require('assert'), shell = require('./shell.js'), spawn = require('child_process').spawn, split = require('split'), + sysinfo = require('./sysinfo.js'), users = require('./users.js'), util = require('util'); @@ -42,6 +49,16 @@ var REBOOT_CMD = path.join(__dirname, 'scripts/reboot.sh'); var NOOP_CALLBACK = function (error) { if (error) debug(error); }; +let gWebadminStatus = { + dns: false, + tls: false, + configuring: false, + restore: { + active: false, + error: null + } +}; + function CloudronError(reason, errorOrMessage) { assert.strictEqual(typeof reason, 'string'); assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined'); @@ -104,7 +121,7 @@ function runStartupTasks() { reverseProxy.configureDefaultServer(NOOP_CALLBACK); // always generate webadmin config since we have no versioning mechanism for the ejs - setup.configureWebadmin(NOOP_CALLBACK); + configureWebadmin(NOOP_CALLBACK); // check activation state and start the platform users.isActivated(function (error, activated) { @@ -278,3 +295,74 @@ function getLogs(unit, options, callback) { return callback(null, transformStream); } + +function configureWebadmin(callback) { + assert.strictEqual(typeof callback, 'function'); + + debug('configureWebadmin: adminDomain:%s status:%j', config.adminDomain(), gWebadminStatus); + + if (process.env.BOX_ENV === 'test' || !config.adminDomain() || gWebadminStatus.configuring) return callback(); + + gWebadminStatus.configuring = true; // re-entracy guard + + function configureReverseProxy(error) { + debug('configureReverseProxy: error %j', error || null); + + reverseProxy.configureAdmin({ userId: null, username: 'setup' }, function (error) { + debug('configureWebadmin: done error: %j', error || {}); + gWebadminStatus.configuring = false; + + if (error) return callback(error); + + gWebadminStatus.tls = true; + + callback(); + }); + } + + // update the DNS. configure nginx regardless of whether it succeeded so that + // box is accessible even if dns creds are invalid + sysinfo.getPublicIp(function (error, ip) { + if (error) return configureReverseProxy(error); + + domains.upsertDnsRecords(config.adminLocation(), config.adminDomain(), 'A', [ ip ], function (error) { + debug('addWebadminDnsRecord: updated records with error:', error); + if (error) return configureReverseProxy(error); + + domains.waitForDnsRecord(config.adminLocation(), config.adminDomain(), 'A', ip, { interval: 30000, times: 50000 }, function (error) { + if (error) return configureReverseProxy(error); + + gWebadminStatus.dns = true; + + configureReverseProxy(); + }); + }); + }); +} + +function getWebadminStatus() { + return gWebadminStatus; +} + +function getStatus(callback) { + assert.strictEqual(typeof callback, 'function'); + + users.isActivated(function (error, activated) { + if (error) return callback(new CloudronError(CloudronError.INTERNAL_ERROR, error)); + + settings.getCloudronName(function (error, cloudronName) { + if (error) return callback(new CloudronError(CloudronError.INTERNAL_ERROR, error)); + + callback(null, { + version: config.version(), + apiServerOrigin: config.apiServerOrigin(), // used by CaaS tool + provider: config.provider(), + cloudronName: cloudronName, + adminFqdn: config.adminDomain() ? config.adminFqdn() : null, + activated: activated, + edition: config.edition(), + webadminStatus: gWebadminStatus // only valid when !activated + }); + }); + }); +} diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 2049c1864..3af69ef43 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -10,7 +10,8 @@ exports = module.exports = { feedback: feedback, checkForUpdates: checkForUpdates, getLogs: getLogs, - getLogStream: getLogStream + getLogStream: getLogStream, + getStatus: getStatus, }; var appstore = require('../appstore.js'), @@ -166,3 +167,11 @@ function getLogStream(req, res, next) { logStream.on('error', res.end.bind(res, null)); }); } + +function getStatus(req, res, next) { + cloudron.getStatus(function (error, status) { + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(200, status)); + }); +} diff --git a/src/routes/setup.js b/src/routes/setup.js index 1f0e6f2f1..e4b4415ab 100644 --- a/src/routes/setup.js +++ b/src/routes/setup.js @@ -5,8 +5,7 @@ exports = module.exports = { setupTokenAuth: setupTokenAuth, provision: provision, activate: activate, - restore: restore, - getStatus: getStatus, + restore: restore }; var assert = require('assert'), @@ -94,14 +93,6 @@ function provision(req, res, next) { }); } -function getStatus(req, res, next) { - setup.getStatus(function (error, status) { - if (error) return next(new HttpError(500, error)); - - next(new HttpSuccess(200, status)); - }); -} - function activate(req, res, next) { assert.strictEqual(typeof req.body, 'object'); diff --git a/src/server.js b/src/server.js index 4969956b9..c5f760ee2 100644 --- a/src/server.js +++ b/src/server.js @@ -111,7 +111,7 @@ function initializeExpressSync() { router.post('/api/v1/cloudron/setup', routes.setup.providerTokenAuth, routes.setup.provision); // only available until no-domain router.post('/api/v1/cloudron/restore', routes.setup.restore); // only available until activated router.post('/api/v1/cloudron/activate', routes.setup.setupTokenAuth, routes.setup.activate); - router.get ('/api/v1/cloudron/status', routes.setup.getStatus); + router.get ('/api/v1/cloudron/status', routes.cloudron.getStatus); router.get ('/api/v1/cloudron/progress', routes.cloudron.getProgress); router.get ('/api/v1/cloudron/avatar', routes.settings.getCloudronAvatar); // this is a public alias for /api/v1/settings/cloudron_avatar diff --git a/src/setup.js b/src/setup.js index ba313e633..7937f83e3 100644 --- a/src/setup.js +++ b/src/setup.js @@ -3,11 +3,8 @@ exports = module.exports = { provision: provision, restore: restore, - getStatus: getStatus, activate: activate, - configureWebadmin: configureWebadmin, - SetupError: SetupError }; @@ -25,14 +22,12 @@ var assert = require('assert'), eventlog = require('./eventlog.js'), mail = require('./mail.js'), path = require('path'), - reverseProxy = require('./reverseproxy.js'), safe = require('safetydance'), semver = require('semver'), settingsdb = require('./settingsdb.js'), settings = require('./settings.js'), shell = require('./shell.js'), superagent = require('superagent'), - sysinfo = require('./sysinfo.js'), users = require('./users.js'), UsersError = users.UsersError, tld = require('tldjs'), @@ -42,16 +37,6 @@ var RESTART_CMD = path.join(__dirname, 'scripts/restart.sh'); var NOOP_CALLBACK = function (error) { if (error) debug(error); }; -var gWebadminStatus = { - dns: false, - tls: false, - configuring: false, - restore: { - active: false, - error: null - } -}; - function SetupError(reason, errorOrMessage) { assert.strictEqual(typeof reason, 'string'); assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined'); @@ -110,50 +95,6 @@ function autoprovision(autoconf, callback) { }); } -function configureWebadmin(callback) { - callback = callback || NOOP_CALLBACK; - - debug('configureWebadmin: adminDomain:%s status:%j', config.adminDomain(), gWebadminStatus); - - if (process.env.BOX_ENV === 'test' || !config.adminDomain() || gWebadminStatus.configuring) return callback(); - - gWebadminStatus.configuring = true; // re-entracy guard - - function configureReverseProxy(error) { - debug('configureReverseProxy: error %j', error || null); - - reverseProxy.configureAdmin({ userId: null, username: 'setup' }, function (error) { - debug('configureWebadmin: done error: %j', error || {}); - gWebadminStatus.configuring = false; - - if (error) return callback(error); - - gWebadminStatus.tls = true; - - callback(); - }); - } - - // update the DNS. configure nginx regardless of whether it succeeded so that - // box is accessible even if dns creds are invalid - sysinfo.getPublicIp(function (error, ip) { - if (error) return configureReverseProxy(error); - - domains.upsertDnsRecords(config.adminLocation(), config.adminDomain(), 'A', [ ip ], function (error) { - debug('addWebadminDnsRecord: updated records with error:', error); - if (error) return configureReverseProxy(error); - - domains.waitForDnsRecord(config.adminLocation(), config.adminDomain(), 'A', ip, { interval: 30000, times: 50000 }, function (error) { - if (error) return configureReverseProxy(error); - - gWebadminStatus.dns = true; - - configureReverseProxy(); - }); - }); - }); -} - function provision(dnsConfig, autoconf, auditSource, callback) { assert.strictEqual(typeof dnsConfig, 'object'); assert.strictEqual(typeof autoconf, 'object'); @@ -162,7 +103,9 @@ function provision(dnsConfig, autoconf, auditSource, callback) { if (config.adminDomain()) return callback(new SetupError(SetupError.ALREADY_SETUP)); - if (gWebadminStatus.configuring || gWebadminStatus.restore.active) return callback(new SetupError(SetupError.BAD_STATE, 'Already restoring or configuring')); + let webadminStatus = cloudron.getWebadminStatus(); + + if (webadminStatus.configuring || webadminStatus.restore.active) return callback(new SetupError(SetupError.BAD_STATE, 'Already restoring or configuring')); const domain = dnsConfig.domain.toLowerCase(); const zoneName = dnsConfig.zoneName ? dnsConfig.zoneName : (tld.getDomain(domain) || domain); @@ -202,7 +145,7 @@ function provision(dnsConfig, autoconf, auditSource, callback) { async.series([ autoprovision.bind(null, autoconf), - configureWebadmin + cloudron.configureWebadmin ], NOOP_CALLBACK); }); }); @@ -278,7 +221,9 @@ function restore(backupConfig, backupId, version, autoconf, auditSource, callbac if (!semver.valid(version)) return callback(new SetupError(SetupError.BAD_STATE, 'version is not a valid semver')); if (semver.major(config.version()) !== semver.major(version) || semver.minor(config.version()) !== semver.minor(version)) return callback(new SetupError(SetupError.BAD_STATE, `Run cloudron-setup with --version ${version} to restore from this backup`)); - if (gWebadminStatus.configuring || gWebadminStatus.restore.active) return callback(new SetupError(SetupError.BAD_STATE, 'Already restoring or configuring')); + let webadminStatus = cloudron.getWebadminStatus(); + + if (webadminStatus.configuring || webadminStatus.restore.active) return callback(new SetupError(SetupError.BAD_STATE, 'Already restoring or configuring')); users.isActivated(function (error, activated) { if (error) return callback(new SetupError(SetupError.INTERNAL_ERROR, error)); @@ -291,8 +236,8 @@ function restore(backupConfig, backupId, version, autoconf, auditSource, callbac debug(`restore: restoring from ${backupId} from provider ${backupConfig.provider} with format ${backupConfig.format}`); - gWebadminStatus.restore.active = true; - gWebadminStatus.restore.error = null; + webadminStatus.restore.active = true; + webadminStatus.restore.error = null; callback(null); // do no block @@ -307,31 +252,8 @@ function restore(backupConfig, backupId, version, autoconf, auditSource, callbac shell.sudo.bind(null, 'restart', [ RESTART_CMD ]) ], function (error) { debug('restore:', error); - if (error) gWebadminStatus.restore.error = error.message; - gWebadminStatus.restore.active = false; - }); - }); - }); -} - -function getStatus(callback) { - assert.strictEqual(typeof callback, 'function'); - - users.isActivated(function (error, activated) { - if (error) return callback(new SetupError(SetupError.INTERNAL_ERROR, error)); - - settings.getCloudronName(function (error, cloudronName) { - if (error) return callback(new SetupError(SetupError.INTERNAL_ERROR, error)); - - callback(null, { - version: config.version(), - apiServerOrigin: config.apiServerOrigin(), // used by CaaS tool - provider: config.provider(), - cloudronName: cloudronName, - adminFqdn: config.adminDomain() ? config.adminFqdn() : null, - activated: activated, - edition: config.edition(), - webadminStatus: gWebadminStatus // only valid when !activated + if (error) webadminStatus.restore.error = error.message; + webadminStatus.restore.active = false; }); }); });