diff --git a/src/plugins/api/index_pattern_endpoints.js b/src/plugins/api/index_pattern_endpoints.js index 861ffe5fa73b..7e7d83561a2b 100644 --- a/src/plugins/api/index_pattern_endpoints.js +++ b/src/plugins/api/index_pattern_endpoints.js @@ -1,11 +1,13 @@ const esErrors = require('elasticsearch').errors; const Boom = require('Boom'); +const Joi = require('Joi'); const _ = require('lodash'); const Promise = require('bluebird'); const getMappings = require('./lib/get_mappings'); const stitchPatternAndMappings = require('./lib/stitch_pattern_and_mappings'); const {templateToPattern, patternToTemplate} = require('./lib/convert_pattern_and_template_name'); const removeDeprecatedFieldProps = require('./lib/remove_deprecated_field_props'); +const indexPatternSchema = require('./lib/schemas/index_pattern_schema'); export default function (server) { @@ -97,6 +99,10 @@ export default function (server) { method: 'POST', handler: function (req, reply) { if (_.isEmpty(req.payload)) { return reply(Boom.badRequest('Payload required')); } + const validation = Joi.validate(req.payload, indexPatternSchema); + if (validation.error) { + return reply(Boom.badRequest(validation.error)); + } const client = server.plugins.elasticsearch.client; const indexPattern = _.cloneDeep(req.payload); diff --git a/src/plugins/api/lib/schemas/index_pattern_schema.js b/src/plugins/api/lib/schemas/index_pattern_schema.js new file mode 100644 index 000000000000..43a532bba66f --- /dev/null +++ b/src/plugins/api/lib/schemas/index_pattern_schema.js @@ -0,0 +1,14 @@ +var Joi = require('joi'); + +module.exports = Joi.object({ + title: Joi.string().required(), + timeFieldName: Joi.string(), + intervalName: Joi.string(), + fields: Joi.array().items(Joi.object({ + name: Joi.string().required(), + count: Joi.number().integer(), + scripted: Joi.boolean(), + mapping: Joi.object() + })), + fieldFormatMap: Joi.object() +}); diff --git a/test/unit/api/index_patterns/data.js b/test/unit/api/index_patterns/data.js new file mode 100644 index 000000000000..752e8da79a9d --- /dev/null +++ b/test/unit/api/index_patterns/data.js @@ -0,0 +1,34 @@ +module.exports = function createTestData() { + return { + indexPatternWithMappings: { + 'title': 'logstash-*', + 'timeFieldName': '@timestamp', + 'fields': [{ + 'name': 'geo.coordinates', + 'count': 0, + 'scripted': false, + 'mapping': {'type': 'geo_point', 'index': 'not_analyzed', 'doc_values': false} + }, { + 'name': 'ip', + 'count': 2, + 'scripted': false, + 'mapping': {'type': 'ip', 'index': 'not_analyzed', 'doc_values': true} + }, { + 'name': '@timestamp', + 'count': 0, + 'scripted': false, + 'mapping': {'type': 'date', 'index': 'not_analyzed', 'doc_values': true} + }, { + 'name': 'agent', + 'count': 0, + 'scripted': false, + 'mapping': {'type': 'string', 'index': 'analyzed', 'doc_values': false} + }, { + 'name': 'bytes', + 'count': 2, + 'scripted': false, + 'mapping': {'type': 'number', 'index': 'not_analyzed', 'doc_values': true} + }] + } + }; +}; diff --git a/test/unit/api/index_patterns/index.js b/test/unit/api/index_patterns/index.js index ed934995116c..38a44550fd31 100644 --- a/test/unit/api/index_patterns/index.js +++ b/test/unit/api/index_patterns/index.js @@ -4,6 +4,10 @@ define(function (require) { var ScenarioManager = require('intern/dojo/node!../../../fixtures/scenarioManager'); var request = require('intern/dojo/node!supertest-as-promised'); var url = require('intern/dojo/node!url'); + var Promise = require('bluebird'); + var createTestData = require('intern/dojo/node!../../../unit/api/index_patterns/data'); + var _ = require('intern/dojo/node!lodash'); + bdd.describe('index-patterns API', function () { var scenarioManager = new ScenarioManager(url.format(config.servers.elasticsearch)); @@ -27,10 +31,26 @@ define(function (require) { bdd.describe('POST index-patterns', function postIndexPatterns() { - bdd.it('should return 400 for a missing payload', function missingPayload() { - return request.post('/index-patterns') - .send({}) - .expect(400); + bdd.it('should return 400 for an invalid payload', function invalidPayload() { + return Promise.all([ + request.post('/index-patterns').expect(400), + + request.post('/index-patterns') + .send({}) + .expect(400), + + request.post('/index-patterns') + .send(_.assign(createTestData().indexPatternWithMappings, {title: false})) + .expect(400), + + request.post('/index-patterns') + .send(_.assign(createTestData().indexPatternWithMappings, {fields: {}})) + .expect(400), + + request.post('/index-patterns') + .send(_.assign(createTestData().indexPatternWithMappings, {fields: [{count: 0}]})) + .expect(400) + ]); }); });