diff --git a/src/appdb.js b/src/appdb.js index 4829c5087..048335dc4 100644 --- a/src/appdb.js +++ b/src/appdb.js @@ -177,7 +177,7 @@ function getAll(callback) { }); } -function add(id, appStoreId, manifest, location, portBindings, accessRestriction, memoryLimit, callback) { +function add(id, appStoreId, manifest, location, portBindings, accessRestriction, memoryLimit, altDomain, callback) { assert.strictEqual(typeof id, 'string'); assert.strictEqual(typeof appStoreId, 'string'); assert(manifest && typeof manifest === 'object'); @@ -186,6 +186,7 @@ function add(id, appStoreId, manifest, location, portBindings, accessRestriction assert.strictEqual(typeof portBindings, 'object'); assert.strictEqual(typeof accessRestriction, 'object'); assert.strictEqual(typeof memoryLimit, 'number'); + assert(altDomain === null || typeof altDomain === 'string'); assert.strictEqual(typeof callback, 'function'); portBindings = portBindings || { }; @@ -195,8 +196,8 @@ function add(id, appStoreId, manifest, location, portBindings, accessRestriction var queries = [ ]; queries.push({ - query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, location, accessRestrictionJson, memoryLimit) VALUES (?, ?, ?, ?, ?, ?, ?)', - args: [ id, appStoreId, manifestJson, exports.ISTATE_PENDING_INSTALL, location, accessRestrictionJson, memoryLimit ] + query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, location, accessRestrictionJson, memoryLimit, altDomain) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', + args: [ id, appStoreId, manifestJson, exports.ISTATE_PENDING_INSTALL, location, accessRestrictionJson, memoryLimit, altDomain ] }); Object.keys(portBindings).forEach(function (env) { diff --git a/src/apps.js b/src/apps.js index 0f40063b2..32835d2bb 100644 --- a/src/apps.js +++ b/src/apps.js @@ -353,7 +353,7 @@ function purchase(appStoreId, callback) { }); } -function install(appId, appStoreId, manifest, location, portBindings, accessRestriction, icon, cert, key, memoryLimit, callback) { +function install(appId, appStoreId, manifest, location, portBindings, accessRestriction, icon, cert, key, memoryLimit, altDomain, callback) { assert.strictEqual(typeof appId, 'string'); assert.strictEqual(typeof appStoreId, 'string'); assert(manifest && typeof manifest === 'object'); @@ -364,6 +364,7 @@ function install(appId, appStoreId, manifest, location, portBindings, accessRest assert(cert === null || typeof cert === 'string'); assert(key === null || typeof key === 'string'); assert.strictEqual(typeof memoryLimit, 'number'); + assert(altDomain === null || typeof altDomain === 'string'); assert.strictEqual(typeof callback, 'function'); var error = manifestFormat.parse(manifest); @@ -387,6 +388,8 @@ function install(appId, appStoreId, manifest, location, portBindings, accessRest // memoryLimit might come in as 0 if not specified memoryLimit = memoryLimit || manifest.memoryLimit || constants.DEFAULT_MEMORY_LIMIT; + if (altDomain !== null && !validator.isFQDN(altDomain)) return callback(new AppsError(AppsError.BAD_FIELD, 'Invalid alt domain')); + // singleUser mode requires accessRestriction to contain exactly one user if (manifest.singleUser && accessRestriction === null) return callback(new AppsError(AppsError.USER_REQUIRED)); if (manifest.singleUser && accessRestriction.users.length !== 1) return callback(new AppsError(AppsError.USER_REQUIRED)); @@ -407,7 +410,7 @@ function install(appId, appStoreId, manifest, location, portBindings, accessRest purchase(appStoreId, function (error) { if (error) return callback(error); - appdb.add(appId, appStoreId, manifest, location.toLowerCase(), portBindings, accessRestriction, memoryLimit, function (error) { + appdb.add(appId, appStoreId, manifest, location.toLowerCase(), portBindings, accessRestriction, memoryLimit, altDomain, function (error) { if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(location.toLowerCase(), portBindings, error)); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); diff --git a/src/routes/apps.js b/src/routes/apps.js index ac0a178f2..bf110dee5 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -126,13 +126,14 @@ function installApp(req, res, next) { if (data.cert && !data.key) return next(new HttpError(400, 'key must be provided')); if (!data.cert && data.key) return next(new HttpError(400, 'cert must be provided')); if ('memoryLimit' in data && typeof data.memoryLimit !== 'number') return next(new HttpError(400, 'memoryLimit is not a number')); + if (data.altDomain && typeof data.altDomain !== 'string') return next(new HttpError(400, 'altDomain must be a string')); // allow tests to provide an appId for testing var appId = (process.env.BOX_ENV === 'test' && typeof data.appId === 'string') ? data.appId : uuid.v4(); debug('Installing app id:%s storeid:%s loc:%s port:%j accessRestriction:%j memoryLimit:%s manifest:%j', appId, data.appStoreId, data.location, data.portBindings, data.accessRestriction, data.memoryLimit, data.manifest); - apps.install(appId, data.appStoreId, data.manifest, data.location, data.portBindings || null, data.accessRestriction, data.icon || null, data.cert || null, data.key || null, data.memoryLimit || 0, function (error) { + apps.install(appId, data.appStoreId, data.manifest, data.location, data.portBindings || null, data.accessRestriction, data.icon || null, data.cert || null, data.key || null, data.memoryLimit || 0, data.altDomain || null, function (error) { if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.')); if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.')); diff --git a/src/routes/test/backups-test.js b/src/routes/test/backups-test.js index a2739a812..8ed6d27e0 100644 --- a/src/routes/test/backups-test.js +++ b/src/routes/test/backups-test.js @@ -53,7 +53,7 @@ function setup(done) { function addApp(callback) { var manifest = { version: '0.0.1', manifestVersion: 1, dockerImage: 'foo', healthCheckPath: '/', httpPort: 3, title: 'ok', addons: { } }; - appdb.add('appid', 'appStoreId', manifest, 'location', [ ] /* portBindings */, null /* accessRestriction */, 0 /* memoryLimit */, callback); + appdb.add('appid', 'appStoreId', manifest, 'location', [ ] /* portBindings */, null /* accessRestriction */, 0 /* memoryLimit */, null /* altDomain */, callback); }, function createSettings(callback) { diff --git a/src/routes/test/oauth2-test.js b/src/routes/test/oauth2-test.js index 0d7954efd..f4bdc3fd8 100644 --- a/src/routes/test/oauth2-test.js +++ b/src/routes/test/oauth2-test.js @@ -155,7 +155,8 @@ describe('OAuth2', function () { location: 'test', portBindings: {}, accessRestriction: null, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var APP_1 = { @@ -165,7 +166,8 @@ describe('OAuth2', function () { location: 'test1', portBindings: {}, accessRestriction: { users: [ 'foobar' ] }, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var APP_2 = { @@ -175,7 +177,8 @@ describe('OAuth2', function () { location: 'test2', portBindings: {}, accessRestriction: { users: [ USER_0.id ] }, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var APP_3 = { @@ -185,7 +188,8 @@ describe('OAuth2', function () { location: 'test3', portBindings: {}, accessRestriction: { groups: [ 'someothergroup', 'admin', 'anothergroup' ] }, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; // unknown app @@ -308,10 +312,10 @@ describe('OAuth2', function () { clientdb.add.bind(null, CLIENT_7.id, CLIENT_7.appId, CLIENT_7.type, CLIENT_7.clientSecret, CLIENT_7.redirectURI, CLIENT_7.scope), clientdb.add.bind(null, CLIENT_8.id, CLIENT_8.appId, CLIENT_8.type, CLIENT_8.clientSecret, CLIENT_8.redirectURI, CLIENT_8.scope), clientdb.add.bind(null, CLIENT_9.id, CLIENT_9.appId, CLIENT_9.type, CLIENT_9.clientSecret, CLIENT_9.redirectURI, CLIENT_9.scope), - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit), - appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.memoryLimit), - appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.memoryLimit), - appdb.add.bind(null, APP_3.id, APP_3.appStoreId, APP_3.manifest, APP_3.location, APP_3.portBindings, APP_3.accessRestriction, APP_3.memoryLimit), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, APP_0.altDomain), + appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.memoryLimit, APP_1.altDomain), + appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.memoryLimit, APP_2.altDomain), + appdb.add.bind(null, APP_3.id, APP_3.appStoreId, APP_3.manifest, APP_3.location, APP_3.portBindings, APP_3.accessRestriction, APP_3.memoryLimit, APP_3.altDomain), function (callback) { user.create(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, function (error, userObject) { expect(error).to.not.be.ok(); diff --git a/src/routes/test/settings-test.js b/src/routes/test/settings-test.js index a855d9202..88ef5a6c8 100644 --- a/src/routes/test/settings-test.js +++ b/src/routes/test/settings-test.js @@ -56,7 +56,7 @@ function setup(done) { function addApp(callback) { var manifest = { version: '0.0.1', manifestVersion: 1, dockerImage: 'foo', healthCheckPath: '/', httpPort: 3, title: 'ok' }; - appdb.add('appid', 'appStoreId', manifest, 'location', [ ] /* portBindings */, null /* accessRestriction */, 0 /* memoryLimit */, callback); + appdb.add('appid', 'appStoreId', manifest, 'location', [ ] /* portBindings */, null /* accessRestriction */, 0 /* memoryLimit */, null /* altDomain */, callback); } ], done); } diff --git a/src/routes/test/simpleauth-test.js b/src/routes/test/simpleauth-test.js index 14533b290..5f73cc0a1 100644 --- a/src/routes/test/simpleauth-test.js +++ b/src/routes/test/simpleauth-test.js @@ -30,7 +30,8 @@ describe('SimpleAuth API', function () { location: 'test0', portBindings: {}, accessRestriction: { users: [ 'foobar', 'someone'] }, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var APP_1 = { @@ -40,7 +41,8 @@ describe('SimpleAuth API', function () { location: 'test1', portBindings: {}, accessRestriction: { users: [ 'foobar', 'someone' ] }, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var APP_2 = { @@ -50,7 +52,8 @@ describe('SimpleAuth API', function () { location: 'test2', portBindings: {}, accessRestriction: null, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var APP_3 = { @@ -60,7 +63,8 @@ describe('SimpleAuth API', function () { location: 'test3', portBindings: {}, accessRestriction: { groups: [ 'someothergroup', 'admin', 'anothergroup' ] }, - memoryLimit: 0 + memoryLimit: 0, + altDomain: null }; var CLIENT_0 = { @@ -155,10 +159,10 @@ describe('SimpleAuth API', function () { clientdb.add.bind(null, CLIENT_3.id, CLIENT_3.appId, CLIENT_3.type, CLIENT_3.clientSecret, CLIENT_3.redirectURI, CLIENT_3.scope), clientdb.add.bind(null, CLIENT_4.id, CLIENT_4.appId, CLIENT_4.type, CLIENT_4.clientSecret, CLIENT_4.redirectURI, CLIENT_4.scope), clientdb.add.bind(null, CLIENT_5.id, CLIENT_5.appId, CLIENT_5.type, CLIENT_5.clientSecret, CLIENT_5.redirectURI, CLIENT_5.scope), - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit), - appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.memoryLimit), - appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.memoryLimit), - appdb.add.bind(null, APP_3.id, APP_3.appStoreId, APP_3.manifest, APP_3.location, APP_3.portBindings, APP_3.accessRestriction, APP_3.memoryLimit) + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, APP_0.altDomain), + appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.memoryLimit, APP_1.altDomain), + appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.memoryLimit, APP_2.altDomain), + appdb.add.bind(null, APP_3.id, APP_3.appStoreId, APP_3.manifest, APP_3.location, APP_3.portBindings, APP_3.accessRestriction, APP_3.memoryLimit, APP_3.altDomain) ], done); }); diff --git a/src/routes/test/sysadmin-test.js b/src/routes/test/sysadmin-test.js index c76df3875..8e2ecee32 100644 --- a/src/routes/test/sysadmin-test.js +++ b/src/routes/test/sysadmin-test.js @@ -51,7 +51,7 @@ function setup(done) { function addApp(callback) { var manifest = { version: '0.0.1', manifestVersion: 1, dockerImage: 'foo', healthCheckPath: '/', httpPort: 3, title: 'ok', addons: { } }; - appdb.add('appid', 'appStoreId', manifest, 'location', [ ] /* portBindings */, null /* accessRestriction */, 0 /* memoryLimit */, callback); + appdb.add('appid', 'appStoreId', manifest, 'location', [ ] /* portBindings */, null /* accessRestriction */, 0 /* memoryLimit */, null /* altDomain */, callback); }, function createSettings(callback) { diff --git a/src/test/apps-test.js b/src/test/apps-test.js index eddd32ce0..3cae564d0 100644 --- a/src/test/apps-test.js +++ b/src/test/apps-test.js @@ -113,9 +113,9 @@ describe('Apps', function () { groups.create.bind(null, GROUP_1), groups.addMember.bind(null, groups.ADMIN_GROUP_ID, ADMIN_0.id), groups.addMember.bind(null, GROUP_0, USER_1.id), - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit), - appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.memoryLimit), - appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.memoryLimit) + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, null), + appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.memoryLimit, null), + appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.memoryLimit, null) ], done); }); diff --git a/src/test/apptask-test.js b/src/test/apptask-test.js index 6fcb6ef02..8e3d2e3e3 100644 --- a/src/test/apptask-test.js +++ b/src/test/apptask-test.js @@ -84,7 +84,7 @@ describe('apptask', function () { config.set('version', '0.5.0'); async.series([ database.initialize, - appdb.add.bind(null, APP.id, APP.appStoreId, APP.manifest, APP.location, APP.portBindings, APP.accessRestriction, APP.memoryLimit), + appdb.add.bind(null, APP.id, APP.appStoreId, APP.manifest, APP.location, APP.portBindings, APP.accessRestriction, APP.memoryLimit, null), settings.setDnsConfig.bind(null, { provider: 'route53', accessKeyId: 'accessKeyId', secretAccessKey: 'secretAccessKey', endpoint: 'http://localhost:5353' }), settings.setTlsConfig.bind(null, { provider: 'caas' }) ], done); diff --git a/src/test/database-test.js b/src/test/database-test.js index ab9568acf..851267153 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -536,7 +536,7 @@ describe('database', function () { }); it('add succeeds', function (done) { - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, function (error) { + appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, null, function (error) { expect(error).to.be(null); done(); }); @@ -560,7 +560,7 @@ describe('database', function () { }); it('add of same app fails', function (done) { - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, [ ], APP_0.accessRestriction, APP_0.memoryLimit, function (error) { + appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, [ ], APP_0.accessRestriction, APP_0.memoryLimit, null, function (error) { expect(error).to.be.a(DatabaseError); expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS); done(); @@ -632,7 +632,7 @@ describe('database', function () { }); it('add second app succeeds', function (done) { - appdb.add(APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, [ ], APP_1.accessRestriction, APP_1.memoryLimit, function (error) { + appdb.add(APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, [ ], APP_1.accessRestriction, APP_1.memoryLimit, null, function (error) { expect(error).to.be(null); done(); }); diff --git a/src/test/ldap-test.js b/src/test/ldap-test.js index a9a86923f..c2bb1b2c6 100644 --- a/src/test/ldap-test.js +++ b/src/test/ldap-test.js @@ -68,7 +68,7 @@ function setup(done) { database.initialize.bind(null), database._clear.bind(null), ldapServer.start.bind(null), - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, null), appdb.update.bind(null, APP_0.id, { containerId: APP_0.containerId }), function (callback) { user.createOwner(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, function (error, result) { diff --git a/src/test/updatechecker-test.js b/src/test/updatechecker-test.js index 462ad2dd9..3d3bdb648 100644 --- a/src/test/updatechecker-test.js +++ b/src/test/updatechecker-test.js @@ -248,7 +248,7 @@ describe('updatechecker - checkAppUpdates', function () { database.initialize, database._clear, mailer._clearMailQueue, - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.memoryLimit, null), user.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName) ], done); });