diff --git a/src/apps.js b/src/apps.js index 3bb57bc32..854fed431 100644 --- a/src/apps.js +++ b/src/apps.js @@ -456,64 +456,70 @@ function configure(appId, data, auditSource, callback) { assert.strictEqual(typeof auditSource, 'object'); assert.strictEqual(typeof callback, 'function'); - var location = data.location.toLowerCase(), - portBindings = data.portBindings || null, - accessRestriction = data.accessRestriction || null, - cert = data.cert || null, - key = data.key || null, - memoryLimit = data.memoryLimit || 0, - altDomain = data.altDomain || null; - - var error = validateHostname(location, config.fqdn()); - if (error) return callback(error); - - error = validateAccessRestriction(accessRestriction); - if (error) return callback(error); - - error = certificates.validateCertificate(cert, key, config.appFqdn(location)); - if (error) return callback(new AppsError(AppsError.BAD_CERTIFICATE, error.message)); - - if (altDomain !== null && !validator.isFQDN(altDomain)) return callback(new AppsError(AppsError.BAD_FIELD, 'Invalid alt domain')); +console.dir(data); appdb.get(appId, function (error, app) { if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app')); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - error = validatePortBindings(portBindings, app.manifest.tcpPorts); - if (error) return callback(error); - - error = validateMemoryLimit(app.manifest, memoryLimit); - if (error) return callback(error); - - // memoryLimit might come in as 0 if not specified - memoryLimit = memoryLimit || app.memoryLimit || app.manifest.memoryLimit || constants.DEFAULT_MEMORY_LIMIT; - - // save cert to data/box/certs - if (cert && key) { - if (!safe.fs.writeFileSync(path.join(paths.APP_CERTS_DIR, config.appFqdn(location) + '.cert'), cert)) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving cert: ' + safe.error.message)); - if (!safe.fs.writeFileSync(path.join(paths.APP_CERTS_DIR, config.appFqdn(location) + '.key'), key)) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving key: ' + safe.error.message)); + var location, portBindings, values = { }; + if ('location' in data) { + location = values.location = data.location.toLowerCase(); + error = validateHostname(values.location, config.fqdn()); + if (error) return callback(error); + } else { + location = app.location; } - var values = { - location: location.toLowerCase(), - accessRestriction: accessRestriction, - portBindings: portBindings, - memoryLimit: memoryLimit, - altDomain: altDomain, + if ('accessRestriction' in data) { + values.accessRestriction = data.accessRestriction; + error = validateAccessRestriction(values.accessRestriction); + if (error) return callback(error); + } - oldConfig: { - location: app.location, - accessRestriction: app.accessRestriction, - portBindings: app.portBindings, - memoryLimit: app.memoryLimit, - altDomain: app.altDomain - } + if ('altDomain' in data) { + values.altDomain = data.altDomain; + if (values.altDomain !== null && !validator.isFQDN(values.altDomain)) return callback(new AppsError(AppsError.BAD_FIELD, 'Invalid alt domain')); + } + + if ('portBindings' in data) { + portBindings = values.portBindings = data.portBindings; + error = validatePortBindings(values.portBindings, app.manifest.tcpPorts); + if (error) return callback(error); + } else { + portBindings = app.portBindings; + } + + if ('memoryLimit' in data) { + values.memoryLimit = data.memoryLimit; + error = validateMemoryLimit(app.manifest, values.memoryLimit); + if (error) return callback(error); + + // memoryLimit might come in as 0 if not specified + values.memoryLimit = values.memoryLimit || app.memoryLimit || app.manifest.memoryLimit || constants.DEFAULT_MEMORY_LIMIT; + } + + // save cert to data/box/certs. TODO: move this to apptask when we have a real task queue + if ('cert' in data && 'key' in data) { + error = certificates.validateCertificate(data.cert, data.key, config.appFqdn(location)); + if (error) return callback(new AppsError(AppsError.BAD_CERTIFICATE, error.message)); + + if (!safe.fs.writeFileSync(path.join(paths.APP_CERTS_DIR, config.appFqdn(location) + '.cert'), data.cert)) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving cert: ' + safe.error.message)); + if (!safe.fs.writeFileSync(path.join(paths.APP_CERTS_DIR, config.appFqdn(location) + '.key'), data.key)) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving key: ' + safe.error.message)); + } + + values.oldConfig = { + location: app.location, + accessRestriction: app.accessRestriction, + portBindings: app.portBindings, + memoryLimit: app.memoryLimit, + altDomain: app.altDomain }; debug('Will configure app with id:%s values:%j', appId, values); appdb.setInstallationCommand(appId, appdb.ISTATE_PENDING_CONFIGURE, values, function (error) { - if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(location.toLowerCase(), portBindings, error)); + if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(location, portBindings, error)); if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.BAD_STATE)); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); diff --git a/src/routes/apps.js b/src/routes/apps.js index ad6e9eba6..c20a5c545 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -137,7 +137,7 @@ function configureApp(req, res, next) { var data = req.body; - if (typeof data.location !== 'string') return next(new HttpError(400, 'location is required')); + if ('location' in data && typeof data.location !== 'string') return next(new HttpError(400, 'location must be string')); if (('portBindings' in data) && typeof data.portBindings !== 'object') return next(new HttpError(400, 'portBindings must be an object')); if ('accessRestriction' in data && typeof data.accessRestriction !== 'object') return next(new HttpError(400, 'accessRestriction must be an object')); if ('cert' in data && typeof data.cert !== 'string') return next(new HttpError(400, 'cert must be a string')); @@ -147,7 +147,7 @@ function configureApp(req, res, next) { if ('memoryLimit' in data && typeof data.memoryLimit !== 'number') return next(new HttpError(400, 'memoryLimit is not a number')); if ('altDomain' in data && typeof data.altDomain !== 'string') return next(new HttpError(400, 'altDomain must be a string')); - debug('Configuring app id:%s location:%s bindings:%j accessRestriction:%j memoryLimit:%s', req.params.id, data.location, data.portBindings, data.accessRestriction, data.memoryLimit); + debug('Configuring app id:%s data:%j', req.params.id, data); apps.configure(req.params.id, data, auditSource(req), function (error) { if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); diff --git a/src/routes/test/apps-test.js b/src/routes/test/apps-test.js index 91c948b30..01f2cd0aa 100644 --- a/src/routes/test/apps-test.js +++ b/src/routes/test/apps-test.js @@ -1218,10 +1218,20 @@ describe('Apps', function () { }); } - it('cannot reconfigure app with missing location', function (done) { + it('cannot reconfigure app with bad location', function (done) { superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') .query({ access_token: token }) - .send({ password: PASSWORD, portBindings: { ECHO_SERVER_PORT: 7172 }, accessRestriction: null }) + .send({ password: PASSWORD, location: 1234, portBindings: { ECHO_SERVER_PORT: 7172 }, accessRestriction: null }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + done(); + }); + }); + + it('cannot reconfigure app with bad accessRestriction', function (done) { + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') + .query({ access_token: token }) + .send({ password: PASSWORD, portBindings: { ECHO_SERVER_PORT: 7172 }, accessRestriction: false }) .end(function (err, res) { expect(res.statusCode).to.equal(400); done(); @@ -1248,7 +1258,7 @@ describe('Apps', function () { }); }); - it('cannot reconfigure app with cert not bein a string', function (done) { + it('cannot reconfigure app with cert not being a string', function (done) { superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') .query({ access_token: token }) .send({ password: PASSWORD, location: APP_LOCATION_NEW, portBindings: { ECHO_SERVER_PORT: 7172 }, accessRestriction: null, cert: 1234, key: validKey1 })