mostly because code is being autogenerated by all the AI stuff using this prefix. it's also used in the stack trace.
154 lines
6.3 KiB
JavaScript
154 lines
6.3 KiB
JavaScript
'use strict';
|
|
|
|
exports = module.exports = {
|
|
getLocation,
|
|
clearLocation,
|
|
|
|
startPrepareLocation, // starts the task
|
|
prepareLocation, // the task to setup dns and cert
|
|
setupLocation, // initial setup from setup/restore
|
|
changeLocation, // only on dashboard change (post setup/restore)
|
|
|
|
getConfig,
|
|
|
|
_setLocation: setLocation,
|
|
};
|
|
|
|
const apps = require('./apps.js'),
|
|
appstore = require('./appstore.js'),
|
|
assert = require('node:assert'),
|
|
BoxError = require('./boxerror.js'),
|
|
branding = require('./branding.js'),
|
|
constants = require('./constants.js'),
|
|
debug = require('debug')('box:dashboard'),
|
|
dns = require('./dns.js'),
|
|
externalLdap = require('./externalldap.js'),
|
|
eventlog = require('./eventlog.js'),
|
|
Location = require('./location.js'),
|
|
mailServer = require('./mailserver.js'),
|
|
platform = require('./platform.js'),
|
|
reverseProxy = require('./reverseproxy.js'),
|
|
safe = require('safetydance'),
|
|
settings = require('./settings.js'),
|
|
system = require('./system.js'),
|
|
tasks = require('./tasks.js'),
|
|
userDirectory = require('./user-directory.js');
|
|
|
|
async function getLocation() {
|
|
const domain = await settings.get(settings.DASHBOARD_DOMAIN_KEY);
|
|
const subdomain = await settings.get(settings.DASHBOARD_SUBDOMAIN_KEY);
|
|
return new Location(subdomain, domain, Location.TYPE_DASHBOARD);
|
|
}
|
|
|
|
async function setLocation(subdomain, domain) {
|
|
assert.strictEqual(typeof subdomain, 'string');
|
|
assert.strictEqual(typeof domain, 'string');
|
|
|
|
await settings.set(settings.DASHBOARD_SUBDOMAIN_KEY, subdomain);
|
|
await settings.set(settings.DASHBOARD_DOMAIN_KEY, domain);
|
|
|
|
debug(`setLocation: ${domain || '<cleared>'}`);
|
|
}
|
|
|
|
async function clearLocation() {
|
|
await setLocation('', '');
|
|
}
|
|
|
|
async function getConfig() {
|
|
const ubuntuVersion = await system.getUbuntuVersion();
|
|
const kernelVersion = await system.getKernelVersion();
|
|
const profileConfig = await userDirectory.getProfileConfig();
|
|
const externalLdapConfig = await externalLdap.getConfig();
|
|
|
|
const { fqdn:adminFqdn, domain:adminDomain } = await getLocation();
|
|
|
|
// be picky about what we send out here since this is sent for 'normal' users as well
|
|
return {
|
|
apiServerOrigin: await appstore.getApiServerOrigin(),
|
|
webServerOrigin: await appstore.getWebServerOrigin(),
|
|
consoleServerOrigin: await appstore.getConsoleServerOrigin(),
|
|
adminDomain,
|
|
adminFqdn,
|
|
mailFqdn: (await mailServer.getLocation()).fqdn,
|
|
version: constants.VERSION,
|
|
ubuntuVersion,
|
|
kernelVersion,
|
|
isDemo: constants.DEMO,
|
|
cloudronName: await branding.getCloudronName(),
|
|
footer: await branding.renderFooter(),
|
|
features: appstore.getFeatures(),
|
|
profileLocked: profileConfig.lockUserProfiles,
|
|
mandatory2FA: profileConfig.mandatory2FA,
|
|
external2FA: externalLdap.supports2FA(externalLdapConfig),
|
|
ldapGroupsSynced: externalLdapConfig.syncGroups
|
|
};
|
|
}
|
|
|
|
async function startPrepareLocation(domain, auditSource) {
|
|
assert.strictEqual(typeof domain, 'string');
|
|
assert.strictEqual(typeof auditSource, 'object');
|
|
|
|
debug(`prepareLocation: ${domain}`);
|
|
|
|
if (constants.DEMO) throw new BoxError(BoxError.BAD_STATE, 'Not allowed in demo mode');
|
|
|
|
const fqdn = dns.fqdn(constants.DASHBOARD_SUBDOMAIN, domain);
|
|
for (const app of await apps.list()) {
|
|
const appName = `${app.label || app.fqdn} (${app.id})`;
|
|
if (app.fqdn === fqdn) throw new BoxError(BoxError.BAD_STATE, `Dashboard location conflicts with primary location of app '${appName}'`);
|
|
if (app.secondaryDomains.some(sd => sd.fqdn === fqdn)) throw new BoxError(BoxError.BAD_STATE, `Dashboard location conflicts with secondary location of app '${appName}'`);
|
|
if (app.redirectDomains.some(rd => rd.fqdn === fqdn)) throw new BoxError(BoxError.BAD_STATE, `Dashboard location conflicts with redirect location of app '${appName}'`);
|
|
if (app.aliasDomains.some(ad => ad.fqdn === fqdn)) throw new BoxError(BoxError.BAD_STATE, `Dashboard location conflicts with alias location of app '${appName}'`);
|
|
}
|
|
|
|
const taskId = await tasks.add(tasks.TASK_PREPARE_DASHBOARD_LOCATION, [ constants.DASHBOARD_SUBDOMAIN, domain, auditSource ]);
|
|
safe(tasks.startTask(taskId, {}), { debug }); // background
|
|
|
|
return taskId;
|
|
}
|
|
|
|
async function prepareLocation(subdomain, domain, auditSource, progressCallback) {
|
|
assert.strictEqual(typeof subdomain, 'string');
|
|
assert.strictEqual(typeof domain, 'string');
|
|
assert.strictEqual(typeof auditSource, 'object');
|
|
assert.strictEqual(typeof progressCallback, 'function');
|
|
|
|
const location = { subdomain, domain };
|
|
const fqdn = dns.fqdn(subdomain, domain);
|
|
progressCallback({ percent: 20, message: `Updating DNS of ${fqdn}` });
|
|
await dns.registerLocations([location], { overwriteDns: true }, progressCallback);
|
|
progressCallback({ percent: 40, message: `Waiting for DNS of ${fqdn}` });
|
|
await dns.waitForLocations([location], progressCallback);
|
|
progressCallback({ percent: 60, message: `Getting certificate of ${fqdn}` });
|
|
await reverseProxy.ensureCertificate(location, {}, auditSource);
|
|
}
|
|
|
|
async function setupLocation(subdomain, domain, auditSource) {
|
|
assert.strictEqual(typeof subdomain, 'string');
|
|
assert.strictEqual(typeof domain, 'string');
|
|
assert.strictEqual(typeof auditSource, 'object');
|
|
|
|
debug(`setupLocation: ${domain}`);
|
|
|
|
if (constants.DEMO) throw new BoxError(BoxError.BAD_STATE, 'Not allowed in demo mode');
|
|
|
|
await setLocation(subdomain, domain);
|
|
await platform.onDashboardLocationSet(subdomain, domain);
|
|
}
|
|
|
|
async function changeLocation(subdomain, domain, auditSource) {
|
|
assert.strictEqual(typeof subdomain, 'string');
|
|
assert.strictEqual(typeof domain, 'string');
|
|
assert.strictEqual(typeof auditSource, 'object');
|
|
|
|
const oldLocation = await getLocation();
|
|
await setupLocation(subdomain, domain, auditSource);
|
|
|
|
debug(`setupLocation: notifying appstore and platform of domain change to ${domain}`);
|
|
await eventlog.add(eventlog.ACTION_DASHBOARD_DOMAIN_UPDATE, auditSource, { subdomain, domain });
|
|
await safe(appstore.updateCloudron({ domain }), { debug });
|
|
await platform.onDashboardLocationChanged(auditSource);
|
|
|
|
await safe(reverseProxy.removeDashboardConfig(oldLocation.subdomain, oldLocation.domain), { debug });
|
|
}
|