diff --git a/src/apps.js b/src/apps.js index 62c978be6..f27c242e9 100644 --- a/src/apps.js +++ b/src/apps.js @@ -299,13 +299,11 @@ function validateLabel(label) { } function validateTags(tags) { - if (tags === null) return null; - + if (!Array.isArray(tags)) return new AppsError(AppsError.BAD_FIELD, 'tags must be an array of strings'); if (tags.length > 64) return new AppsError(AppsError.BAD_FIELD, 'Can only set up to 64 tags'); - for (const tag of tags) { - if (tag.length > 128) return new AppsError(AppsError.BAD_FIELD, 'tag must be less than 128'); - } + if (tags.some(tag => (!tag || typeof tag !== 'string'))) return new AppsError(AppsError.BAD_FIELD, 'tags must be an array of non-empty strings'); + if (tags.some(tag => tag.length > 128)) return new AppsError(AppsError.BAD_FIELD, 'tag must be less than 128'); return null; } diff --git a/src/routes/apps.js b/src/routes/apps.js index e9ab7e219..99f823053 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -119,10 +119,6 @@ function installApp(req, res, next) { if (data.backupFormat && typeof data.backupFormat !== 'string') return next(new HttpError(400, 'backupFormat must be string or null')); if ('label' in data && typeof data.label !== 'string') return next(new HttpError(400, 'label must be a string')); - if ('tags' in data) { - if (!Array.isArray(data.tags)) return next(new HttpError(400, 'tags must be a string array')); - if (data.tags.some(d => typeof d !== 'string')) return next(new HttpError(400, 'tags must be in array of strings')); - } // falsy values in cert and key unset the cert if (data.key && typeof data.cert !== 'string') return next(new HttpError(400, 'cert must be a string')); @@ -213,11 +209,6 @@ function configureApp(req, res, next) { } if ('label' in data && typeof data.label !== 'string') return next(new HttpError(400, 'label must be a string')); - if ('tags' in data) { - if (!Array.isArray(data.tags)) return next(new HttpError(400, 'tags must be an array of strings')); - if (data.tags.some(d => typeof d !== 'string')) return next(new HttpError(400, 'tags must be an array of strings')); - } - if ('dataDir' in data && typeof data.dataDir !== 'string') return next(new HttpError(400, 'dataDir must be a string')); debug('Configuring app id:%s data:%j', req.params.id, data); diff --git a/src/routes/test/apps-test.js b/src/routes/test/apps-test.js index f5d8d549c..e103d0382 100644 --- a/src/routes/test/apps-test.js +++ b/src/routes/test/apps-test.js @@ -1021,6 +1021,30 @@ describe('App installation', function () { }); }); + it('cannot reconfigure app with invalid tags', function (done) { + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') + .query({ access_token: token }) + .send({ location: APP_LOCATION_NEW, portBindings: { ECHO_SERVER_PORT: 7172 }, tags: 'foobar' }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') + .query({ access_token: token }) + .send({ location: APP_LOCATION_NEW, portBindings: { ECHO_SERVER_PORT: 7172 }, tags: ['hello', '', 'there' ] }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') + .query({ access_token: token }) + .send({ location: APP_LOCATION_NEW, portBindings: { ECHO_SERVER_PORT: 7172 }, tags: ['hello', 1234, 'there' ] }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + done(); + }); + }); + }); + }); + it('non admin cannot reconfigure app', function (done) { superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure') .query({ access_token: token_1 })