diff --git a/src/apps.js b/src/apps.js index b297ad7e2..1acb6bcf6 100644 --- a/src/apps.js +++ b/src/apps.js @@ -499,14 +499,14 @@ function removeInternalFields(app) { 'location', 'domain', 'fqdn', 'crontab', 'accessRestriction', 'manifest', 'portBindings', 'iconUrl', 'memoryLimit', 'cpuShares', 'operators', 'sso', 'debugMode', 'reverseProxyConfig', 'enableBackup', 'creationTime', 'updateTime', 'ts', 'tags', - 'label', 'alternateDomains', 'aliasDomains', 'env', 'enableAutomaticUpdate', 'dataDir', 'mounts', + 'label', 'redirectDomains', 'aliasDomains', 'env', 'enableAutomaticUpdate', 'dataDir', 'mounts', 'enableMailbox', 'mailboxName', 'mailboxDomain', 'enableInbox', 'inboxName', 'inboxDomain'); } // non-admins can only see these function removeRestrictedFields(app) { return _.pick(app, - 'id', 'appStoreId', 'installationState', 'error', 'runState', 'health', 'taskId', 'accessRestriction', 'alternateDomains', 'aliasDomains', 'sso', + 'id', 'appStoreId', 'installationState', 'error', 'runState', 'health', 'taskId', 'accessRestriction', 'redirectDomains', 'aliasDomains', 'sso', 'location', 'domain', 'fqdn', 'manifest', 'portBindings', 'iconUrl', 'creationTime', 'ts', 'tags', 'label', 'enableBackup'); } @@ -607,14 +607,14 @@ function postProcess(result) { delete result.domains; delete result.subdomainTypes; - result.alternateDomains = []; + result.redirectDomains = []; result.aliasDomains = []; for (let i = 0; i < subdomainTypes.length; i++) { if (subdomainTypes[i] === exports.SUBDOMAIN_TYPE_PRIMARY) { result.location = subdomains[i]; result.domain = domains[i]; } else if (subdomainTypes[i] === exports.SUBDOMAIN_TYPE_REDIRECT) { - result.alternateDomains.push({ domain: domains[i], subdomain: subdomains[i] }); + result.redirectDomains.push({ domain: domains[i], subdomain: subdomains[i] }); } else if (subdomainTypes[i] === exports.SUBDOMAIN_TYPE_ALIAS) { result.aliasDomains.push({ domain: domains[i], subdomain: subdomains[i] }); } @@ -652,7 +652,7 @@ function attachProperties(app, domainObjectMap) { app.portBindings = result; app.iconUrl = app.hasIcon || app.hasAppStoreIcon ? `/api/v1/apps/${app.id}/icon` : null; app.fqdn = dns.fqdn(app.location, domainObjectMap[app.domain]); - app.alternateDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); + app.redirectDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); app.aliasDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); } @@ -755,8 +755,8 @@ async function add(id, appStoreId, manifest, location, domain, portBindings, dat }); }); - if (data.alternateDomains) { - data.alternateDomains.forEach(function (d) { + if (data.redirectDomains) { + data.redirectDomains.forEach(function (d) { queries.push({ query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.SUBDOMAIN_TYPE_REDIRECT ] @@ -793,7 +793,7 @@ async function updateWithConstraints(id, app, constraints) { assert.strictEqual(typeof constraints, 'string'); assert(!('portBindings' in app) || typeof app.portBindings === 'object'); assert(!('accessRestriction' in app) || typeof app.accessRestriction === 'object' || app.accessRestriction === ''); - assert(!('alternateDomains' in app) || Array.isArray(app.alternateDomains)); + assert(!('redirectDomains' in app) || Array.isArray(app.redirectDomains)); assert(!('aliasDomains' in app) || Array.isArray(app.aliasDomains)); assert(!('tags' in app) || Array.isArray(app.tags)); assert(!('env' in app) || typeof app.env === 'object'); @@ -825,8 +825,8 @@ async function updateWithConstraints(id, app, constraints) { queries.push({ query: 'DELETE FROM subdomains WHERE appId = ?', args: [ id ]}); // all locations of an app must be updated together queries.push({ query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, app.domain, app.location, exports.SUBDOMAIN_TYPE_PRIMARY ]}); - if ('alternateDomains' in app) { - app.alternateDomains.forEach(function (d) { + if ('redirectDomains' in app) { + app.redirectDomains.forEach(function (d) { queries.push({ query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.SUBDOMAIN_TYPE_REDIRECT ]}); }); } @@ -850,7 +850,7 @@ async function updateWithConstraints(id, app, constraints) { if (p === 'manifest' || p === 'tags' || p === 'accessRestriction' || p === 'debugMode' || p === 'error' || p === 'reverseProxyConfig' || p === 'servicesConfig' || p === 'operators') { fields.push(`${p}Json = ?`); values.push(JSON.stringify(app[p])); - } else if (p !== 'portBindings' && p !== 'location' && p !== 'domain' && p !== 'alternateDomains' && p !== 'aliasDomains' && p !== 'env' && p !== 'mounts') { + } else if (p !== 'portBindings' && p !== 'location' && p !== 'domain' && p !== 'redirectDomains' && p !== 'aliasDomains' && p !== 'env' && p !== 'mounts') { fields.push(p + ' = ?'); values.push(app[p]); } @@ -1188,7 +1188,7 @@ async function install(data, auditSource) { debugMode = data.debugMode || null, enableBackup = 'enableBackup' in data ? data.enableBackup : true, enableAutomaticUpdate = 'enableAutomaticUpdate' in data ? data.enableAutomaticUpdate : true, - alternateDomains = data.alternateDomains || [], + redirectDomains = data.redirectDomains || [], aliasDomains = data.aliasDomains || [], env = data.env || {}, label = data.label || null, @@ -1244,7 +1244,7 @@ async function install(data, auditSource) { } const locations = [{ subdomain: location, domain, type: 'primary' }] - .concat(alternateDomains.map(ad => _.extend(ad, { type: 'redirect' }))) + .concat(redirectDomains.map(ad => _.extend(ad, { type: 'redirect' }))) .concat(aliasDomains.map(ad => _.extend(ad, { type: 'alias' }))); const domainObjectMap = await validateLocations(locations); @@ -1263,7 +1263,7 @@ async function install(data, auditSource) { mailboxDomain, enableBackup, enableAutomaticUpdate, - alternateDomains, + redirectDomains, aliasDomains, env, label, @@ -1290,7 +1290,7 @@ async function install(data, auditSource) { const newApp = _.extend({}, _.omit(app, 'icon'), { appStoreId, manifest, location, domain, portBindings }); newApp.fqdn = dns.fqdn(newApp.location, domainObjectMap[newApp.domain]); - newApp.alternateDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); + newApp.redirectDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); newApp.aliasDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); await eventlog.add(eventlog.ACTION_APP_INSTALL, auditSource, { appId, app: newApp, taskId }); @@ -1643,7 +1643,7 @@ async function setLocation(app, data, auditSource) { domain: data.domain.toLowerCase(), // these are intentionally reset, if not set portBindings: null, - alternateDomains: [], + redirectDomains: [], aliasDomains: [] }; @@ -1660,8 +1660,8 @@ async function setLocation(app, data, auditSource) { values.mailboxDomain = values.domain; } - if ('alternateDomains' in data) { - values.alternateDomains = data.alternateDomains; + if ('redirectDomains' in data) { + values.redirectDomains = data.redirectDomains; } if ('aliasDomains' in data) { @@ -1669,14 +1669,14 @@ async function setLocation(app, data, auditSource) { } const locations = [{ subdomain: values.location, domain: values.domain, type: 'primary' }] - .concat(values.alternateDomains.map(ad => _.extend(ad, { type: 'redirect' }))) + .concat(values.redirectDomains.map(ad => _.extend(ad, { type: 'redirect' }))) .concat(values.aliasDomains.map(ad => _.extend(ad, { type: 'alias' }))); const domainObjectMap = await validateLocations(locations); const task = { args: { - oldConfig: _.pick(app, 'location', 'domain', 'fqdn', 'alternateDomains', 'aliasDomains', 'portBindings'), + oldConfig: _.pick(app, 'location', 'domain', 'fqdn', 'redirectDomains', 'aliasDomains', 'portBindings'), skipDnsSetup: !!data.skipDnsSetup, overwriteDns: !!data.overwriteDns }, @@ -1687,7 +1687,7 @@ async function setLocation(app, data, auditSource) { if (taskError) throw taskError; values.fqdn = dns.fqdn(values.location, domainObjectMap[values.domain]); - values.alternateDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); + values.redirectDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); values.aliasDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); await eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, _.extend({ appId, app, taskId }, values)); @@ -2126,7 +2126,7 @@ async function clone(app, data, user, auditSource) { enableBackup: app.enableBackup, reverseProxyConfig: app.reverseProxyConfig, env: app.env, - alternateDomains: [], + redirectDomains: [], aliasDomains: [], servicesConfig: app.servicesConfig, label: app.label ? `${app.label}-clone` : '', @@ -2152,7 +2152,7 @@ async function clone(app, data, user, auditSource) { const newApp = _.extend({}, _.omit(obj, 'icon'), { appStoreId, manifest, location, domain, portBindings }); newApp.fqdn = dns.fqdn(newApp.location, domainObjectMap[newApp.domain]); - newApp.alternateDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); + newApp.redirectDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); newApp.aliasDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); await eventlog.add(eventlog.ACTION_APP_CLONE, auditSource, { appId: newAppId, oldAppId: appId, backupId, oldApp: app, newApp, taskId }); diff --git a/src/apptask.js b/src/apptask.js index 26d1a0045..ff4626564 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -254,8 +254,8 @@ async function waitForDnsPropagation(app) { if (error) throw new BoxError(BoxError.DNS_ERROR, `DNS AAAA Record is not synced yet: ${error.message}`, { ipv6, subdomain: app.location, domain: app.domain }); } - // now wait for alternateDomains and aliasDomains, if any - for (const domain of app.alternateDomains.concat(app.aliasDomains)) { + // now wait for redirectDomains and aliasDomains, if any + for (const domain of app.redirectDomains.concat(app.aliasDomains)) { [error] = await safe(dns.waitForDnsRecord(domain.subdomain, domain.domain, 'A', ipv4, { times: 240 })); if (error) throw new BoxError(BoxError.DNS_ERROR, `DNS A Record is not synced yet: ${error.message}`, { ipv4, subdomain: domain.subdomain, domain: domain.domain }); if (ipv6Enabled) { @@ -346,7 +346,7 @@ async function install(app, args, progressCallback) { if (!skipDnsSetup) { await progressCallback({ percent: 30, message: 'Registering subdomains' }); - await dns.registerLocations([ { subdomain: app.location, domain: app.domain }].concat(app.alternateDomains).concat(app.aliasDomains), { overwriteDns }, progressCallback); + await dns.registerLocations([ { subdomain: app.location, domain: app.domain }].concat(app.redirectDomains).concat(app.aliasDomains), { overwriteDns }, progressCallback); } await progressCallback({ percent: 40, message: 'Downloading image' }); @@ -462,8 +462,8 @@ async function changeLocation(app, args, progressCallback) { await deleteContainers(app, { managedOnly: true }); // unregister old domains - let obsoleteDomains = oldConfig.alternateDomains.filter(function (o) { - return !app.alternateDomains.some(function (n) { return n.subdomain === o.subdomain && n.domain === o.domain; }); + let obsoleteDomains = oldConfig.redirectDomains.filter(function (o) { + return !app.redirectDomains.some(function (n) { return n.subdomain === o.subdomain && n.domain === o.domain; }); }); if (oldConfig.aliasDomains) { @@ -479,7 +479,7 @@ async function changeLocation(app, args, progressCallback) { // setup dns if (!skipDnsSetup) { await progressCallback({ percent: 30, message: 'Registering subdomains' }); - await dns.registerLocations([ { subdomain: app.location, domain: app.domain }].concat(app.alternateDomains).concat(app.aliasDomains), { overwriteDns }, progressCallback); + await dns.registerLocations([ { subdomain: app.location, domain: app.domain }].concat(app.redirectDomains).concat(app.aliasDomains), { overwriteDns }, progressCallback); } // re-setup addons since they rely on the app's fqdn (e.g oauth) @@ -723,7 +723,7 @@ async function uninstall(app, args, progressCallback) { await docker.deleteImage(app.manifest); await progressCallback({ percent: 70, message: 'Unregistering domains' }); - await dns.unregisterLocations([ { subdomain: app.location, domain: app.domain } ].concat(app.alternateDomains).concat(app.aliasDomains), progressCallback); + await dns.unregisterLocations([ { subdomain: app.location, domain: app.domain } ].concat(app.redirectDomains).concat(app.aliasDomains), progressCallback); await progressCallback({ percent: 90, message: 'Cleanup logs' }); await cleanupLogs(app); diff --git a/src/dns.js b/src/dns.js index 35984d182..e7ce172e3 100644 --- a/src/dns.js +++ b/src/dns.js @@ -303,7 +303,7 @@ async function syncDnsRecords(options, progressCallback) { if (domain.domain === settings.mailDomain() && settings.mailFqdn() !== settings.dashboardFqdn()) locations.push({ subdomain: mailSubdomain, domain: settings.mailDomain() }); for (const app of allApps) { - const appLocations = [{ subdomain: app.location, domain: app.domain }].concat(app.alternateDomains).concat(app.aliasDomains); + const appLocations = [{ subdomain: app.location, domain: app.domain }].concat(app.redirectDomains).concat(app.aliasDomains); locations = locations.concat(appLocations.filter(al => al.domain === domain.domain)); } diff --git a/src/reverseproxy.js b/src/reverseproxy.js index 5e079b7b1..0ab403211 100644 --- a/src/reverseproxy.js +++ b/src/reverseproxy.js @@ -556,8 +556,8 @@ async function writeAppConfig(app) { let appDomains = []; appDomains.push({ domain: app.domain, fqdn: app.fqdn, type: 'primary' }); - app.alternateDomains.forEach(function (alternateDomain) { - appDomains.push({ domain: alternateDomain.domain, fqdn: alternateDomain.fqdn, type: 'alternate' }); + app.redirectDomains.forEach(function (redirectDomain) { + appDomains.push({ domain: redirectDomain.domain, fqdn: redirectDomain.fqdn, type: 'alternate' }); }); app.aliasDomains.forEach(function (aliasDomain) { @@ -584,8 +584,8 @@ async function configureApp(app, auditSource) { let appDomains = []; appDomains.push({ domain: app.domain, fqdn: app.fqdn, type: 'primary' }); - app.alternateDomains.forEach(function (alternateDomain) { - appDomains.push({ domain: alternateDomain.domain, fqdn: alternateDomain.fqdn, type: 'alternate' }); + app.redirectDomains.forEach(function (redirectDomain) { + appDomains.push({ domain: redirectDomain.domain, fqdn: redirectDomain.fqdn, type: 'alternate' }); }); app.aliasDomains.forEach(function (aliasDomain) { @@ -642,9 +642,9 @@ async function renewCerts(options, auditSource, progressCallback) { appDomains.push({ domain: app.domain, fqdn: app.fqdn, type: 'primary', app: app, nginxConfigFilename: path.join(paths.NGINX_APPCONFIG_DIR, app.id + '.conf') }); - app.alternateDomains.forEach(function (alternateDomain) { - const nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, `${app.id}-redirect-${alternateDomain.fqdn}.conf`); - appDomains.push({ domain: alternateDomain.domain, fqdn: alternateDomain.fqdn, type: 'alternate', app: app, nginxConfigFilename }); + app.redirectDomains.forEach(function (redirectDomain) { + const nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, `${app.id}-redirect-${redirectDomain.fqdn}.conf`); + appDomains.push({ domain: redirectDomain.domain, fqdn: redirectDomain.fqdn, type: 'alternate', app: app, nginxConfigFilename }); }); app.aliasDomains.forEach(function (aliasDomain) { diff --git a/src/routes/apps.js b/src/routes/apps.js index ffd82672b..25e523d5f 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -141,9 +141,9 @@ async function install(req, res, next) { if (('debugMode' in data) && typeof data.debugMode !== 'object') return next(new HttpError(400, 'debugMode must be an object')); - if ('alternateDomains' in data) { - if (!Array.isArray(data.alternateDomains)) return next(new HttpError(400, 'alternateDomains must be an array')); - if (data.alternateDomains.some(function (d) { return (typeof d.domain !== 'string' || typeof d.subdomain !== 'string'); })) return next(new HttpError(400, 'alternateDomains array must contain objects with domain and subdomain strings')); + if ('redirectDomains' in data) { + if (!Array.isArray(data.redirectDomains)) return next(new HttpError(400, 'redirectDomains must be an array')); + if (data.redirectDomains.some(function (d) { return (typeof d.domain !== 'string' || typeof d.subdomain !== 'string'); })) return next(new HttpError(400, 'redirectDomains array must contain objects with domain and subdomain strings')); } if ('aliasDomains' in data) { @@ -396,9 +396,9 @@ async function setLocation(req, res, next) { if ('portBindings' in req.body && typeof req.body.portBindings !== 'object') return next(new HttpError(400, 'portBindings must be an object')); - if ('alternateDomains' in req.body) { - if (!Array.isArray(req.body.alternateDomains)) return next(new HttpError(400, 'alternateDomains must be an array')); - if (req.body.alternateDomains.some(function (d) { return (typeof d.domain !== 'string' || typeof d.subdomain !== 'string'); })) return next(new HttpError(400, 'alternateDomains array must contain objects with domain and subdomain strings')); + if ('redirectDomains' in req.body) { + if (!Array.isArray(req.body.redirectDomains)) return next(new HttpError(400, 'redirectDomains must be an array')); + if (req.body.redirectDomains.some(function (d) { return (typeof d.domain !== 'string' || typeof d.subdomain !== 'string'); })) return next(new HttpError(400, 'redirectDomains array must contain objects with domain and subdomain strings')); } if ('aliasDomains' in req.body) { diff --git a/src/test/common.js b/src/test/common.js index 1c116ca4b..8e5a23a0e 100644 --- a/src/test/common.js +++ b/src/test/common.js @@ -105,7 +105,7 @@ const app = { accessRestriction: null, memoryLimit: 0, mailboxDomain: domain.domain, - alternateDomains: [], + redirectDomains: [], aliasDomains: [] }; Object.freeze(app);