diff --git a/src/backuptask.js b/src/backuptask.js index 97932a920..16e5eeaa8 100644 --- a/src/backuptask.js +++ b/src/backuptask.js @@ -659,12 +659,13 @@ function restore(backupConfig, backupId, progressCallback, callback) { debug('restore: download completed, importing database'); - database.importFromFile(`${dataLayout.localRoot()}/box.mysqldump`, function (error) { + database.importFromFile(`${dataLayout.localRoot()}/box.mysqldump`, async function (error) { if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); debug('restore: database imported'); - settings.initCache(callback); + [error] = await safe(settings.initCache()); + callback(error); }); }); } diff --git a/src/cloudron.js b/src/cloudron.js index 6122420d3..3e602ace4 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -155,33 +155,29 @@ function runStartupTasks() { }); } -function getConfig(callback) { - assert.strictEqual(typeof callback, 'function'); - +async function getConfig() { const release = safe.fs.readFileSync('/etc/lsb-release', 'utf-8'); - if (release === null) return callback(new BoxError(BoxError.FS_ERROR, safe.error.message)); + if (release === null) throw new BoxError(BoxError.FS_ERROR, safe.error.message); const ubuntuVersion = release.match(/DISTRIB_DESCRIPTION="(.*)"/)[1]; - settings.getAll(function (error, allSettings) { - if (error) return callback(error); + const allSettings = await settings.list(); - // be picky about what we send out here since this is sent for 'normal' users as well - callback(null, { - apiServerOrigin: settings.apiServerOrigin(), - webServerOrigin: settings.webServerOrigin(), - adminDomain: settings.dashboardDomain(), - adminFqdn: settings.dashboardFqdn(), - mailFqdn: settings.mailFqdn(), - version: constants.VERSION, - ubuntuVersion, - isDemo: settings.isDemo(), - cloudronName: allSettings[settings.CLOUDRON_NAME_KEY], - footer: branding.renderFooter(allSettings[settings.FOOTER_KEY] || constants.FOOTER), - features: appstore.getFeatures(), - profileLocked: allSettings[settings.DIRECTORY_CONFIG_KEY].lockUserProfiles, - mandatory2FA: allSettings[settings.DIRECTORY_CONFIG_KEY].mandatory2FA - }); - }); + // be picky about what we send out here since this is sent for 'normal' users as well + return { + apiServerOrigin: settings.apiServerOrigin(), + webServerOrigin: settings.webServerOrigin(), + adminDomain: settings.dashboardDomain(), + adminFqdn: settings.dashboardFqdn(), + mailFqdn: settings.mailFqdn(), + version: constants.VERSION, + ubuntuVersion, + isDemo: settings.isDemo(), + cloudronName: allSettings[settings.CLOUDRON_NAME_KEY], + footer: branding.renderFooter(allSettings[settings.FOOTER_KEY] || constants.FOOTER), + features: appstore.getFeatures(), + profileLocked: allSettings[settings.DIRECTORY_CONFIG_KEY].lockUserProfiles, + mandatory2FA: allSettings[settings.DIRECTORY_CONFIG_KEY].mandatory2FA + }; } async function reboot() { diff --git a/src/cron.js b/src/cron.js index 5f72b4e3b..11454003e 100644 --- a/src/cron.js +++ b/src/cron.js @@ -62,9 +62,7 @@ const NOOP_CALLBACK = function (error) { if (error) debug(error); }; // Months: 0-11 // Day of Week: 0-6 -function startJobs(callback) { - assert.strictEqual(typeof callback, 'function'); - +async function startJobs() { debug('startJobs: starting cron jobs'); const randomTick = Math.floor(60*Math.random()); @@ -129,16 +127,12 @@ function startJobs(callback) { start: true }); - settings.getAll(function (error, allSettings) { - if (error) return callback(error); + const allSettings = await settings.list(); - const tz = allSettings[settings.TIME_ZONE_KEY]; - backupConfigChanged(allSettings[settings.BACKUP_CONFIG_KEY], tz); - autoupdatePatternChanged(allSettings[settings.AUTOUPDATE_PATTERN_KEY], tz); - dynamicDnsChanged(allSettings[settings.DYNAMIC_DNS_KEY]); - - callback(); - }); + const tz = allSettings[settings.TIME_ZONE_KEY]; + backupConfigChanged(allSettings[settings.BACKUP_CONFIG_KEY], tz); + autoupdatePatternChanged(allSettings[settings.AUTOUPDATE_PATTERN_KEY], tz); + dynamicDnsChanged(allSettings[settings.DYNAMIC_DNS_KEY]); } // eslint-disable-next-line no-unused-vars diff --git a/src/provision.js b/src/provision.js index 9ba32c5e3..7445ab04c 100644 --- a/src/provision.js +++ b/src/provision.js @@ -242,26 +242,20 @@ function restore(backupConfig, backupId, version, sysinfoConfig, options, auditS }); } -function getStatus(callback) { - assert.strictEqual(typeof callback, 'function'); +async function getStatus() { + const activated = await users.isActivated(); - util.callbackify(users.isActivated)(function (error, activated) { - if (error) return callback(error); + const allSettings = await settings.list(); - settings.getAll(function (error, allSettings) { - if (error) return callback(error); - - callback(null, _.extend({ - version: constants.VERSION, - apiServerOrigin: settings.apiServerOrigin(), // used by CaaS tool - webServerOrigin: settings.webServerOrigin(), // used by CaaS tool - cloudronName: allSettings[settings.CLOUDRON_NAME_KEY], - footer: branding.renderFooter(allSettings[settings.FOOTER_KEY] || constants.FOOTER), - adminFqdn: settings.dashboardDomain() ? settings.dashboardFqdn() : null, - language: allSettings[settings.LANGUAGE_KEY], - activated: activated, - provider: settings.provider() // used by setup wizard of marketplace images - }, gProvisionStatus)); - }); - }); + return _.extend({ + version: constants.VERSION, + apiServerOrigin: settings.apiServerOrigin(), // used by CaaS tool + webServerOrigin: settings.webServerOrigin(), // used by CaaS tool + cloudronName: allSettings[settings.CLOUDRON_NAME_KEY], + footer: branding.renderFooter(allSettings[settings.FOOTER_KEY] || constants.FOOTER), + adminFqdn: settings.dashboardDomain() ? settings.dashboardFqdn() : null, + language: allSettings[settings.LANGUAGE_KEY], + activated: activated, + provider: settings.provider() // used by setup wizard of marketplace images + }, gProvisionStatus); } diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 6ce7c4309..e0c89b167 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -156,12 +156,11 @@ async function isRebootRequired(req, res, next) { next(new HttpSuccess(200, { rebootRequired })); } -function getConfig(req, res, next) { - cloudron.getConfig(function (error, cloudronConfig) { - if (error) return next(BoxError.toHttpError(error)); +async function getConfig(req, res, next) { + const [error, cloudronConfig] = await safe(cloudron.getConfig()); + if (error) return next(BoxError.toHttpError(error)); - next(new HttpSuccess(200, cloudronConfig)); - }); + next(new HttpSuccess(200, cloudronConfig)); } function getDisks(req, res, next) { diff --git a/src/routes/provision.js b/src/routes/provision.js index 2c2de5d98..98d9fa669 100644 --- a/src/routes/provision.js +++ b/src/routes/provision.js @@ -126,10 +126,9 @@ function restore(req, res, next) { }); } -function getStatus(req, res, next) { - provision.getStatus(function (error, status) { - if (error) return next(BoxError.toHttpError(error)); +async function getStatus(req, res, next) { + const [error, status] = await safe(provision.getStatus()); + if (error) return next(BoxError.toHttpError(error)); - next(new HttpSuccess(200, status)); - }); + next(new HttpSuccess(200, status)); } diff --git a/src/settings.js b/src/settings.js index 33967cf0f..b241cd01d 100644 --- a/src/settings.js +++ b/src/settings.js @@ -61,7 +61,7 @@ exports = module.exports = { getSupportConfig, provider, - getAll, + list, initCache, // these values come from the cache @@ -127,6 +127,7 @@ const assert = require('assert'), constants = require('./constants.js'), cron = require('./cron.js'), CronJob = require('cron').CronJob, + database = require('./database.js'), debug = require('debug')('box:settings'), docker = require('./docker.js'), externalLdap = require('./externalldap.js'), @@ -139,6 +140,8 @@ const assert = require('assert'), translation = require('./translation.js'), _ = require('underscore'); +const SETTINGS_FIELDS = [ 'name', 'value' ].join(','); + let gDefaults = (function () { var result = { }; result[exports.AUTOUPDATE_PATTERN_KEY] = cron.DEFAULT_AUTOUPDATE_PATTERN; @@ -802,50 +805,41 @@ function setCloudronToken(token, callback) { }); } -function getAll(callback) { - assert.strictEqual(typeof callback, 'function'); +async function list() { + const settings = await database.query(`SELECT ${SETTINGS_FIELDS} FROM settings WHERE value IS NOT NULL ORDER BY name`); - settingsdb.getAll(function (error, settings) { - if (error) return callback(error); + const result = _.extend({ }, gDefaults); + settings.forEach(function (setting) { result[setting.name] = setting.value; }); - var result = _.extend({ }, gDefaults); - settings.forEach(function (setting) { result[setting.name] = setting.value; }); + // convert booleans + result[exports.DYNAMIC_DNS_KEY] = !!result[exports.DYNAMIC_DNS_KEY]; + result[exports.UNSTABLE_APPS_KEY] = !!result[exports.UNSTABLE_APPS_KEY]; + result[exports.DEMO_KEY] = !!result[exports.DEMO_KEY]; - // convert booleans - result[exports.DYNAMIC_DNS_KEY] = !!result[exports.DYNAMIC_DNS_KEY]; - result[exports.UNSTABLE_APPS_KEY] = !!result[exports.UNSTABLE_APPS_KEY]; - result[exports.DEMO_KEY] = !!result[exports.DEMO_KEY]; - - // convert JSON objects - [exports.BACKUP_CONFIG_KEY, exports.DIRECTORY_CONFIG_KEY, exports.SERVICES_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY ].forEach(function (key) { - result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]); - }); - - callback(null, result); + // convert JSON objects + [exports.BACKUP_CONFIG_KEY, exports.DIRECTORY_CONFIG_KEY, exports.SERVICES_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY ].forEach(function (key) { + result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]); }); + + return result; } -function initCache(callback) { +async function initCache() { debug('initCache: pre-load settings'); - getAll(function (error, allSettings) { - if (error) return callback(error); + const allSettings = await list(); + const provider = safe.fs.readFileSync(paths.PROVIDER_FILE, 'utf8'); - const provider = safe.fs.readFileSync(paths.PROVIDER_FILE, 'utf8'); - - gCache = { - apiServerOrigin: allSettings[exports.API_SERVER_ORIGIN_KEY], - webServerOrigin: allSettings[exports.WEB_SERVER_ORIGIN_KEY], - dashboardDomain: allSettings[exports.DASHBOARD_DOMAIN_KEY], - dashboardFqdn: allSettings[exports.DASHBOARD_FQDN_KEY], - mailDomain: allSettings[exports.MAIL_DOMAIN_KEY], - mailFqdn: allSettings[exports.MAIL_FQDN_KEY], - isDemo: allSettings[exports.DEMO_KEY], - provider: provider ? provider.trim() : 'generic' - }; - - callback(); - }); + gCache = { + apiServerOrigin: allSettings[exports.API_SERVER_ORIGIN_KEY], + webServerOrigin: allSettings[exports.WEB_SERVER_ORIGIN_KEY], + dashboardDomain: allSettings[exports.DASHBOARD_DOMAIN_KEY], + dashboardFqdn: allSettings[exports.DASHBOARD_FQDN_KEY], + mailDomain: allSettings[exports.MAIL_DOMAIN_KEY], + mailFqdn: allSettings[exports.MAIL_FQDN_KEY], + isDemo: allSettings[exports.DEMO_KEY], + provider: provider ? provider.trim() : 'generic' + }; } // this is together so we can do this in a transaction later diff --git a/src/test/settings-test.js b/src/test/settings-test.js index b56d620e7..a08e53976 100644 --- a/src/test/settings-test.js +++ b/src/test/settings-test.js @@ -107,15 +107,12 @@ describe('Settings', function () { }); }); - it('can get all values', function (done) { - settings.getAll(function (error, allSettings) { - expect(error).to.be(null); - expect(allSettings[settings.TIME_ZONE_KEY]).to.be.a('string'); - expect(allSettings[settings.AUTOUPDATE_PATTERN_KEY]).to.be.a('string'); - expect(allSettings[settings.CLOUDRON_NAME_KEY]).to.be.a('string'); - expect(allSettings[settings.UNSTABLE_APPS_KEY]).to.be.a('boolean'); - done(); - }); + it('can get all values', async function () { + const allSettings = await settings.list(); + expect(allSettings[settings.TIME_ZONE_KEY]).to.be.a('string'); + expect(allSettings[settings.AUTOUPDATE_PATTERN_KEY]).to.be.a('string'); + expect(allSettings[settings.CLOUDRON_NAME_KEY]).to.be.a('string'); + expect(allSettings[settings.UNSTABLE_APPS_KEY]).to.be.a('boolean'); }); }); });