diff --git a/dashboard/src/js/client.js b/dashboard/src/js/client.js index 11fae1d49..c4b1f7cb7 100644 --- a/dashboard/src/js/client.js +++ b/dashboard/src/js/client.js @@ -2790,7 +2790,7 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout domain: domain }; - post('/api/v1/dashboard/prepare_domain', data, null, function (error, data, status) { + post('/api/v1/dashboard/prepare_location', data, null, function (error, data, status) { if (error) return callback(error); if (status !== 202) return callback(new ClientError(status, data)); @@ -2803,7 +2803,7 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout domain: domain }; - post('/api/v1/dashboard/switch_domain', data, null, function (error, data, status) { + post('/api/v1/dashboard/location', data, null, function (error, data, status) { if (error) return callback(error); if (status !== 204) return callback(new ClientError(status, data)); diff --git a/src/dashboard.js b/src/dashboard.js index 4b5541448..cc8cf400a 100644 --- a/src/dashboard.js +++ b/src/dashboard.js @@ -3,12 +3,12 @@ exports = module.exports = { getLocation, setLocation, + clearLocation, setupDnsAndCert, - prepareDomain, - setDashboardDomain, - switchDomain, + prepareLocation, + changeLocation, getConfig, }; @@ -24,24 +24,14 @@ const apps = require('./apps.js'), dns = require('./dns.js'), mailServer = require('./mailserver.js'), network = require('./network.js'), - oidc = require('./oidc.js'), + platform = require('./platform.js'), reverseProxy = require('./reverseproxy.js'), safe = require('safetydance'), - services = require('./services.js'), settings = require('./settings.js'), system = require('./system.js'), tasks = require('./tasks.js'), users = require('./users.js'); -async function setLocation(domain, fqdn) { - assert.strictEqual(typeof domain, 'string'); - assert.strictEqual(typeof fqdn, 'string'); - - // should probably be just one key. or make this a transaction - await settings.set(settings.DASHBOARD_DOMAIN_KEY, domain); - await settings.set(settings.DASHBOARD_FQDN_KEY, fqdn); -} - async function getLocation() { const domain = await settings.get(settings.DASHBOARD_DOMAIN_KEY) || ''; const fqdn = await settings.get(settings.DASHBOARD_FQDN_KEY) || ''; @@ -49,6 +39,20 @@ async function getLocation() { return { domain, fqdn, subdomain: constants.DASHBOARD_SUBDOMAIN }; } +async function setLocation(domain) { + assert.strictEqual(typeof domain, 'string'); + + const fqdn = dns.fqdn(constants.DASHBOARD_SUBDOMAIN, domain); + await settings.set(settings.DASHBOARD_DOMAIN_KEY, domain); + await settings.set(settings.DASHBOARD_FQDN_KEY, fqdn); + + debug(`setLocation: ${domain}`); +} + +async function clearLocation() { + await setLocation(''); +} + async function getConfig() { const ubuntuVersion = await system.getUbuntuVersion(); const profileConfig = await users.getProfileConfig(); @@ -73,62 +77,39 @@ async function getConfig() { }; } -async function prepareDomain(domain, auditSource) { +async function prepareLocation(domain, auditSource) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof auditSource, 'object'); - debug(`prepareDomain: ${domain}`); + debug(`prepareLocation: ${domain}`); if (constants.DEMO) throw new BoxError(BoxError.CONFLICT, 'Not allowed in demo mode'); const fqdn = dns.fqdn(constants.DASHBOARD_SUBDOMAIN, domain); - const result = await apps.list(); if (result.some(app => app.fqdn === fqdn)) throw new BoxError(BoxError.BAD_STATE, 'Dashboard location conflicts with an existing app'); const taskId = await tasks.add(tasks.TASK_SETUP_DNS_AND_CERT, [ constants.DASHBOARD_SUBDOMAIN, domain, auditSource ]); - tasks.startTask(taskId, {}); return taskId; } -// call this only pre activation since it won't start mail server -async function setDashboardDomain(domain, auditSource) { +async function changeLocation(domain, auditSource) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof auditSource, 'object'); - debug(`setDashboardDomain: ${domain}`); + debug(`changeLocation: ${domain}`); + + if (constants.DEMO) throw new BoxError(BoxError.CONFLICT, 'Not allowed in demo mode'); await reverseProxy.writeDashboardConfig(domain); const fqdn = dns.fqdn(constants.DASHBOARD_SUBDOMAIN, domain); - await setLocation(domain, fqdn); - + await setLocation(domain); await safe(appstore.updateCloudron({ domain }), { debug }); - await eventlog.add(eventlog.ACTION_DASHBOARD_DOMAIN_UPDATE, auditSource, { domain, fqdn }); -} - -// call this only post activation because it will restart mail server -async function switchDomain(domain, auditSource) { - assert.strictEqual(typeof domain, 'string'); - assert.strictEqual(typeof auditSource, 'object'); - - debug(`switchDomain: ${domain}`); - - if (constants.DEMO) throw new BoxError(BoxError.CONFLICT, 'Not allowed in demo mode'); - - await setDashboardDomain(domain, auditSource); - - // mark apps using oidc addon to be reconfigured - const [, installedApps] = await safe(apps.list()); - await safe(apps.configureInstalledApps(installedApps.filter((a) => !!a.manifest.addons.oidc), auditSource)); - - await safe(services.rebuildService('turn', auditSource), { debug }); // to update the realm variable - - await oidc.stop(); - await oidc.start(); + await platform.onDashboardLocationChanged(auditSource); } async function setupDnsAndCert(subdomain, domain, auditSource, progressCallback) { diff --git a/src/platform.js b/src/platform.js index e50f3aed6..e9436a538 100644 --- a/src/platform.js +++ b/src/platform.js @@ -5,6 +5,7 @@ exports = module.exports = { uninitialize, onActivated, + onDashboardLocationChanged, getStatus }; @@ -228,3 +229,16 @@ async function onActivated(restoreOptions) { await timers.setTimeout(30000); await reverseProxy.writeDefaultConfig({ activated :true }); } + +async function onDashboardLocationChanged(auditSource) { + assert.strictEqual(typeof auditSource, 'object'); + + // mark apps using oidc addon to be reconfigured + const [, installedApps] = await safe(apps.list()); + await safe(apps.configureInstalledApps(installedApps.filter((a) => !!a.manifest.addons.oidc), auditSource)); + + await safe(services.rebuildService('turn', auditSource), { debug }); // to update the realm variable + + await oidc.stop(); + await oidc.start(); +} diff --git a/src/provision.js b/src/provision.js index e69f908e1..a81dd1994 100644 --- a/src/provision.js +++ b/src/provision.js @@ -65,7 +65,7 @@ async function ensureDhparams() { async function unprovision() { // TODO: also cancel any existing configureWebadmin task - await dashboard.setLocation('', ''); + await dashboard.clearLocation(); await mail.clearDomains(); await domains.clear(); } @@ -77,7 +77,7 @@ async function setupTask(domain, auditSource) { try { await dashboard.setupDnsAndCert(constants.DASHBOARD_SUBDOMAIN, domain, auditSource, (progress) => setProgress('setup', progress.message)); await ensureDhparams(); - await cloudron.setDashboardDomain(domain, auditSource); + await cloudron.setLocation(domain); setProgress('setup', 'Done'), await eventlog.add(eventlog.ACTION_PROVISION, auditSource, {}); } catch (error) { @@ -180,7 +180,7 @@ async function restoreTask(backupConfig, remotePath, ipv4Config, options, auditS const { subdomain:dashboardSubdomain, domain:dashboardDomain } = await dashboard.getLocation(); // load this fresh from after the backup.restore if (!options.skipDnsSetup) await dashboard.setupDnsAndCert(dashboardSubdomain, dashboardDomain, auditSource, (progress) => setProgress('restore', progress.message)); - await cloudron.setDashboardDomain(dashboardDomain, auditSource); + await dashboard.setLocation(dashboardDomain, auditSource); await backups.setConfig(backupConfig); await eventlog.add(eventlog.ACTION_RESTORE, auditSource, { remotePath }); diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js index 409d5ef01..ba7a5b697 100644 --- a/src/routes/dashboard.js +++ b/src/routes/dashboard.js @@ -3,8 +3,8 @@ exports = module.exports = { getConfig, - prepareDomain, - switchDomain + prepareLocation, + changeLocation }; const AuditSource = require('../auditsource.js'), @@ -21,19 +21,19 @@ async function getConfig(req, res, next) { next(new HttpSuccess(200, cloudronConfig)); } -async function prepareDomain(req, res, next) { +async function prepareLocation(req, res, next) { if (!req.body.domain || typeof req.body.domain !== 'string') return next(new HttpError(400, 'domain must be a string')); - const [error, taskId] = await safe(dashboard.prepareDomain(req.body.domain, AuditSource.fromRequest(req))); + const [error, taskId] = await safe(dashboard.prepareLocation(req.body.domain, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(202, { taskId })); } -async function switchDomain(req, res, next) { +async function changeLocation(req, res, next) { if (!req.body.domain || typeof req.body.domain !== 'string') return next(new HttpError(400, 'domain must be a string')); - const [error] = await safe(dashboard.switchDomain(req.body.domain, AuditSource.fromRequest(req))); + const [error] = await safe(dashboard.changeLocation(req.body.domain, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(204, {})); diff --git a/src/server.js b/src/server.js index 474a72b3e..d0f87a9e6 100644 --- a/src/server.js +++ b/src/server.js @@ -115,9 +115,9 @@ async function initializeExpressSync() { router.post('/api/v1/cloudron/time_zone', json, token, authorizeAdmin, routes.cloudron.setTimeZone); // config route for dashboard that any auth user (not just admin) can access - router.get ('/api/v1/dashboard/config', token, authorizeUser, routes.dashboard.getConfig); - router.post('/api/v1/dashboard/prepare_domain', json, token, authorizeAdmin, routes.dashboard.prepareDomain); - router.post('/api/v1/dashboard/switch_domain', json, token, authorizeAdmin, routes.dashboard.switchDomain); + router.get ('/api/v1/dashboard/config', token, authorizeUser, routes.dashboard.getConfig); + router.post('/api/v1/dashboard/prepare_location', json, token, authorizeAdmin, routes.dashboard.prepareLocation); + router.post('/api/v1/dashboard/location', json, token, authorizeAdmin, routes.dashboard.changeLocation); // system (vm/server) router.get ('/api/v1/system/reboot', token, authorizeAdmin, routes.system.isRebootRequired); diff --git a/src/test/common.js b/src/test/common.js index 016f57c86..634494e3e 100644 --- a/src/test/common.js +++ b/src/test/common.js @@ -215,7 +215,7 @@ async function databaseSetup() { await database.initialize(); await database._clear(); await appstore._setApiServerOrigin(exports.mockApiServerOrigin); - await dashboard.setLocation(exports.dashboardDomain, exports.dashboardFqdn); + await dashboard.setLocation(exports.dashboardDomain); } async function domainSetup() {