diff --git a/migrations/20220207214956-rename-subdomains-to-locations.js b/migrations/20220207214956-rename-subdomains-to-locations.js new file mode 100644 index 000000000..5176cd188 --- /dev/null +++ b/migrations/20220207214956-rename-subdomains-to-locations.js @@ -0,0 +1,12 @@ +'use strict'; + +exports.up = function(db, callback) { + db.runSql('RENAME TABLE subdomains TO locations', function (error) { + if (error) console.error(error); + callback(error); + }); +}; + +exports.down = function(db, callback) { + callback(); +}; diff --git a/migrations/schema.sql b/migrations/schema.sql index de2bfe1dd..9de1c6bff 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -214,7 +214,7 @@ CREATE TABLE IF NOT EXISTS mailboxes( FOREIGN KEY(aliasDomain) REFERENCES mail(domain), UNIQUE (name, domain)); -CREATE TABLE IF NOT EXISTS subdomains( +CREATE TABLE IF NOT EXISTS locations( appId VARCHAR(128) NOT NULL, domain VARCHAR(128) NOT NULL, subdomain VARCHAR(128) NOT NULL, diff --git a/src/apps.js b/src/apps.js index f74a6d935..65e7653f8 100644 --- a/src/apps.js +++ b/src/apps.js @@ -773,7 +773,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da }); queries.push({ - query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', + query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, domain, subdomain, exports.LOCATION_TYPE_PRIMARY ] }); @@ -794,7 +794,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da if (data.secondaryDomains) { data.secondaryDomains.forEach(function (d) { queries.push({ - query: 'INSERT INTO subdomains (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)', + query: 'INSERT INTO locations (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_SECONDARY, d.environmentVariable ] }); }); @@ -803,7 +803,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da if (data.redirectDomains) { data.redirectDomains.forEach(function (d) { queries.push({ - query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', + query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_REDIRECT ] }); }); @@ -812,7 +812,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da if (data.aliasDomains) { data.aliasDomains.forEach(function (d) { queries.push({ - query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', + query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_ALIAS ] }); }); @@ -868,24 +868,24 @@ async function updateWithConstraints(id, app, constraints) { } if ('subdomain' in app && 'domain' in app) { // must be updated together as they are unique together - 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.subdomain, exports.LOCATION_TYPE_PRIMARY ]}); + queries.push({ query: 'DELETE FROM locations WHERE appId = ?', args: [ id ]}); // all locations of an app must be updated together + queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, app.domain, app.subdomain, exports.LOCATION_TYPE_PRIMARY ]}); if ('secondaryDomains' in app) { app.secondaryDomains.forEach(function (d) { - queries.push({ query: 'INSERT INTO subdomains (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_SECONDARY, d.environmentVariable ]}); + queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_SECONDARY, d.environmentVariable ]}); }); } 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.LOCATION_TYPE_REDIRECT ]}); + queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_REDIRECT ]}); }); } if ('aliasDomains' in app) { app.aliasDomains.forEach(function (d) { - queries.push({ query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_ALIAS ]}); + queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_ALIAS ]}); }); } } @@ -954,7 +954,7 @@ async function del(id) { assert.strictEqual(typeof id, 'string'); const queries = [ - { query: 'DELETE FROM subdomains WHERE appId = ?', args: [ id ] }, + { query: 'DELETE FROM locations WHERE appId = ?', args: [ id ] }, { query: 'DELETE FROM appPortBindings WHERE appId = ?', args: [ id ] }, { query: 'DELETE FROM appEnvVars WHERE appId = ?', args: [ id ] }, { query: 'DELETE FROM appPasswords WHERE identifier = ?', args: [ id ] }, @@ -975,7 +975,7 @@ async function delPortBinding(hostPort, type) { } async function clear() { - await database.query('DELETE FROM subdomains'); + await database.query('DELETE FROM locations'); await database.query('DELETE FROM appPortBindings'); await database.query('DELETE FROM appAddonConfigs'); await database.query('DELETE FROM appEnvVars'); @@ -992,7 +992,7 @@ async function getDomainObjectMap() { // each query simply join apps table with another table by id. we then join the full result together const PB_QUERY = 'SELECT id, GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables, GROUP_CONCAT(appPortBindings.type) AS portTypes FROM apps LEFT JOIN appPortBindings ON apps.id = appPortBindings.appId GROUP BY apps.id'; const ENV_QUERY = 'SELECT id, JSON_ARRAYAGG(appEnvVars.name) AS envNames, JSON_ARRAYAGG(appEnvVars.value) AS envValues FROM apps LEFT JOIN appEnvVars ON apps.id = appEnvVars.appId GROUP BY apps.id'; -const SUBDOMAIN_QUERY = 'SELECT id, JSON_ARRAYAGG(subdomains.subdomain) AS subdomains, JSON_ARRAYAGG(subdomains.domain) AS domains, JSON_ARRAYAGG(subdomains.type) AS subdomainTypes, JSON_ARRAYAGG(subdomains.environmentVariable) AS subdomainEnvironmentVariables FROM apps LEFT JOIN subdomains ON apps.id = subdomains.appId GROUP BY apps.id'; +const SUBDOMAIN_QUERY = 'SELECT id, JSON_ARRAYAGG(locations.subdomain) AS subdomains, JSON_ARRAYAGG(locations.domain) AS domains, JSON_ARRAYAGG(locations.type) AS subdomainTypes, JSON_ARRAYAGG(locations.environmentVariable) AS subdomainEnvironmentVariables FROM apps LEFT JOIN locations ON apps.id = locations.appId GROUP BY apps.id'; const MOUNTS_QUERY = 'SELECT id, JSON_ARRAYAGG(appMounts.volumeId) AS volumeIds, JSON_ARRAYAGG(appMounts.readOnly) AS volumeReadOnlys FROM apps LEFT JOIN appMounts ON apps.id = appMounts.appId GROUP BY apps.id'; const APPS_QUERY = `SELECT ${APPS_FIELDS_PREFIXED}, hostPorts, environmentVariables, portTypes, envNames, envValues, subdomains, domains, subdomainTypes, subdomainEnvironmentVariables, volumeIds, volumeReadOnlys FROM apps` + ` LEFT JOIN (${PB_QUERY}) AS q1 on q1.id = apps.id` @@ -1938,7 +1938,7 @@ async function getCertificate(subdomain, domain) { assert.strictEqual(typeof subdomain, 'string'); assert.strictEqual(typeof domain, 'string'); - const result = await database.query('SELECT certificateJson FROM subdomains WHERE subdomain=? AND domain=?', [ subdomain, domain ]); + const result = await database.query('SELECT certificateJson FROM locations WHERE subdomain=? AND domain=?', [ subdomain, domain ]); if (result.length === 0) return null; return JSON.parse(result[0].certificateJson); } diff --git a/src/domains.js b/src/domains.js index 91ce5439c..729ef05ae 100644 --- a/src/domains.js +++ b/src/domains.js @@ -280,7 +280,7 @@ async function del(domain, auditSource) { const [error, results] = await safe(database.transaction(queries)); if (error && error.code === 'ER_ROW_IS_REFERENCED_2') { if (error.message.indexOf('apps_mailDomain_constraint') !== -1) throw new BoxError(BoxError.CONFLICT, 'Domain is in use by an app or the mailbox of an app. Check the domains of apps and the Email section of each app.'); - if (error.message.indexOf('subdomains') !== -1) throw new BoxError(BoxError.CONFLICT, 'Domain is in use by one or more app(s).'); + if (error.message.indexOf('locations') !== -1) throw new BoxError(BoxError.CONFLICT, 'Domain is in use by one or more app(s).'); if (error.message.indexOf('mail') !== -1) throw new BoxError(BoxError.CONFLICT, 'Domain is in use by one or more mailboxes. Delete them first in the Email view.'); throw new BoxError(BoxError.CONFLICT, error.message); }