diff --git a/migrations/schema.sql b/migrations/schema.sql index 6ea7dfbdc..6ddcbbbf5 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -193,5 +193,5 @@ CREATE TABLE IF NOT EXISTS subdomains( FOREIGN KEY(domain) REFERENCES domains(domain), FOREIGN KEY(appId) REFERENCES apps(id), UNIQUE (subdomain, domain)) - + CHARACTER SET utf8 COLLATE utf8_bin; \ No newline at end of file diff --git a/src/appdb.js b/src/appdb.js index 5e74f2e1b..0418bd05c 100644 --- a/src/appdb.js +++ b/src/appdb.js @@ -50,6 +50,10 @@ exports = module.exports = { HEALTH_ERROR: 'error', HEALTH_DEAD: 'dead', + // subdomain table types + SUBDOMAIN_TYPE_PRIMARY: 'primary', + SUBDOMAIN_TYPE_REDIRECT: 'redirect', + _clear: clear }; @@ -62,7 +66,7 @@ var assert = require('assert'), util = require('util'); var APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationState', 'apps.installationProgress', 'apps.runState', - 'apps.health', 'apps.containerId', 'apps.manifestJson', 'apps.httpPort', 'apps.location', 'apps.domain', 'apps.dnsRecordId', + 'apps.health', 'apps.containerId', 'apps.manifestJson', 'apps.httpPort', 'subdomains.subdomain AS location', 'subdomains.domain', 'apps.dnsRecordId', 'apps.accessRestrictionJson', 'apps.restoreConfigJson', 'apps.oldConfigJson', 'apps.updateConfigJson', 'apps.memoryLimit', 'apps.xFrameOptions', 'apps.sso', 'apps.debugModeJson', 'apps.robotsTxt', 'apps.enableBackup', 'apps.creationTime', 'apps.updateTime', 'apps.ownerId', 'apps.ts' ].join(','); @@ -124,7 +128,10 @@ function get(id, callback) { database.query('SELECT ' + APPS_FIELDS_PREFIXED + ',' + 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables' - + ' FROM apps LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId WHERE apps.id = ? GROUP BY apps.id', [ id ], function (error, result) { + + ' FROM apps' + + ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId' + + ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND type = ?' + + ' WHERE apps.id = ? GROUP BY apps.id', [ exports.SUBDOMAIN_TYPE_PRIMARY, id ], function (error, result) { if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); @@ -140,7 +147,10 @@ function getByHttpPort(httpPort, callback) { database.query('SELECT ' + APPS_FIELDS_PREFIXED + ',' + 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables' - + ' FROM apps LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId WHERE httpPort = ? GROUP BY apps.id', [ httpPort ], function (error, result) { + + ' FROM apps' + + ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId' + + ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND type = ?' + + ' WHERE httpPort = ? GROUP BY apps.id', [ exports.SUBDOMAIN_TYPE_PRIMARY, httpPort ], function (error, result) { if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); @@ -156,7 +166,10 @@ function getByContainerId(containerId, callback) { database.query('SELECT ' + APPS_FIELDS_PREFIXED + ',' + 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables' - + ' FROM apps LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId WHERE containerId = ? GROUP BY apps.id', [ containerId ], function (error, result) { + + ' FROM apps' + + ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId' + + ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND type = ?' + + ' WHERE containerId = ? GROUP BY apps.id', [ exports.SUBDOMAIN_TYPE_PRIMARY, containerId ], function (error, result) { if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); @@ -171,8 +184,10 @@ function getAll(callback) { database.query('SELECT ' + APPS_FIELDS_PREFIXED + ',' + 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables' - + ' FROM apps LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId' - + ' GROUP BY apps.id ORDER BY apps.id', function (error, results) { + + ' FROM apps' + + ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId' + + ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND type = ?' + + ' GROUP BY apps.id ORDER BY apps.id', [ exports.SUBDOMAIN_TYPE_PRIMARY ], function (error, results) { if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); results.forEach(postProcess); @@ -208,12 +223,18 @@ function add(id, appStoreId, manifest, location, domain, ownerId, portBindings, var debugModeJson = data.debugMode ? JSON.stringify(data.debugMode) : null; var queries = []; + queries.push({ query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, location, domain, accessRestrictionJson, memoryLimit, xFrameOptions, restoreConfigJson, sso, debugModeJson, robotsTxt, ownerId) ' + ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', args: [ id, appStoreId, manifestJson, installationState, location, domain, accessRestrictionJson, memoryLimit, xFrameOptions, restoreConfigJson, sso, debugModeJson, robotsTxt, ownerId ] }); + queries.push({ + query: 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', + args: [ id, domain, location, exports.SUBDOMAIN_TYPE_PRIMARY ] + }); + Object.keys(portBindings).forEach(function (env) { queries.push({ query: 'INSERT INTO appPortBindings (environmentVariable, hostPort, appId) VALUES (?, ?, ?)', @@ -282,6 +303,7 @@ function del(id, callback) { assert.strictEqual(typeof callback, 'function'); var queries = [ + { query: 'DELETE FROM subdomains WHERE appId = ?', args: [ id ] }, { query: 'DELETE FROM mailboxes WHERE ownerId=?', args: [ id ] }, { query: 'DELETE FROM appPortBindings WHERE appId = ?', args: [ id ] }, { query: 'DELETE FROM apps WHERE id = ?', args: [ id ] } @@ -299,6 +321,7 @@ function clear(callback) { assert.strictEqual(typeof callback, 'function'); async.series([ + database.query.bind(null, 'DELETE FROM subdomains'), database.query.bind(null, 'DELETE FROM appPortBindings'), database.query.bind(null, 'DELETE FROM appAddonConfigs'), database.query.bind(null, 'DELETE FROM apps') @@ -332,6 +355,14 @@ function updateWithConstraints(id, app, constraints, callback) { }); } + if ('location' in app) { + queries.push({ query: 'UPDATE subdomains SET subdomain = ? WHERE appId = ? AND type = ?', args: [ app.location, id, exports.SUBDOMAIN_TYPE_PRIMARY ]}); + } + + if ('domain' in app) { + queries.push({ query: 'UPDATE subdomains SET domain = ? WHERE appId = ? AND type = ?', args: [ app.domain, id, exports.SUBDOMAIN_TYPE_PRIMARY ]}); + } + var fields = [ ], values = [ ]; for (var p in app) { if (p === 'manifest' || p === 'oldConfig' || p === 'updateConfig' || p === 'restoreConfig' || p === 'accessRestriction' || p === 'debugMode') {