diff --git a/lib/models/filter/circle.js b/lib/models/filter/circle.js index 45b1b8a5..b09b6446 100644 --- a/lib/models/filter/circle.js +++ b/lib/models/filter/circle.js @@ -18,15 +18,28 @@ function filterQueryTpl ({ sql, column, srid, lng, lat, radiusInMeters } = {}) { module.exports = class CircleFilter { constructor (filterDefinition, filterParams) { const { circle } = filterParams; + let _circle; if (!circle) { - throw new Error('Circle filter expects to have a "circle" param'); + const error = new Error('Circle filter expects to have a "circle" param'); + error.type = 'filter'; + throw error; } - const { lng, lat, radius } = JSON.parse(circle); + try { + _circle = JSON.parse(circle); + } catch (err) { + const error = new Error('Invalid circle parameter. Expected a valid JSON'); + error.type = 'filter'; + throw error; + } + + const { lng, lat, radius } = _circle; if (!Number.isFinite(lng) || !Number.isFinite(lat) || !Number.isFinite(radius)) { - throw new Error('Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"'); + const error = new Error('Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"'); + error.type = 'filter'; + throw error; } this.column = filterDefinition.column || 'the_geom_webmercator'; diff --git a/lib/models/filter/polygon.js b/lib/models/filter/polygon.js index 1dbdcc83..357f00bf 100644 --- a/lib/models/filter/polygon.js +++ b/lib/models/filter/polygon.js @@ -23,17 +23,25 @@ module.exports = class PolygonFilter { const { polygon } = filterParams; if (!polygon) { - throw new Error('Polygon filter expects to have a "polygon" param'); + const error = new Error('Polygon filter expects to have a "polygon" param'); + error.type = 'filter'; + throw error; } - const geojson = JSON.parse(polygon); + let geojson; - if (geojson.type !== 'Polygon') { - throw new Error('Invalid type of geometry. Valid ones: "Polygon"'); + try { + geojson = JSON.parse(polygon); + } catch (err) { + const error = new Error('Invalid polygon parameter. Expected a valid GeoJSON'); + error.type = 'filter'; + throw error; } - if (!Array.isArray(geojson.coordinates)) { - throw new Error('Invalid geometry, it must be an array of coordinates (long/lat)'); + if (geojson.type !== 'Polygon') { + const error = new Error('Invalid type of geometry. Valid ones: "Polygon"'); + error.type = 'filter'; + throw error; } try { diff --git a/test/acceptance/dataviews/spatial-filters-test.js b/test/acceptance/dataviews/spatial-filters-test.js index 6ef98ed2..829829da 100644 --- a/test/acceptance/dataviews/spatial-filters-test.js +++ b/test/acceptance/dataviews/spatial-filters-test.js @@ -130,6 +130,91 @@ describe('spatial filters', function () { { category: 'category_1', value: 1, agg: false } ] } + }, { + dataview: 'categories', + params: { + circle: JSON.stringify({ + lng: 0, + radius: 5000 + }), + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"' + ], + errors_with_context: [ + { + type: 'filter', + message: 'Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"' + } + ] + } + }, { + dataview: 'categories', + params: { + circle: JSON.stringify({ + lat: 0, + radius: 5000 + }), + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"' + ], + errors_with_context: [ + { + type: 'filter', + message: 'Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"' + } + ] + } + }, { + dataview: 'categories', + params: { + circle: JSON.stringify({ + lng: 0, + lat: 0 + }), + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"' + ], + errors_with_context: [ + { + type: 'filter', + message: 'Missing parameter for Circle Filter, expected: "lng", "lat", and "radius"' + } + ] + } + }, { + dataview: 'categories', + params: { + circle: 'wadus', + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Invalid circle parameter. Expected a valid JSON' + ], + errors_with_context: [ + { + type: 'filter', + message: 'Invalid circle parameter. Expected a valid JSON' + } + ] + } }, { dataview: 'categories', @@ -174,6 +259,69 @@ describe('spatial filters', function () { { category: 'category_1', value: 1, agg: false } ] } + }, { + dataview: 'categories', + params: { + polygon: 'wadus', + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Invalid polygon parameter. Expected a valid GeoJSON' + ], + errors_with_context: [ + { + type: 'filter', + message: 'Invalid polygon parameter. Expected a valid GeoJSON' + } + ] + } + }, { + dataview: 'categories', + params: { + polygon: JSON.stringify({ + type: 'Point', + coordinates: [30, 10] + }), + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Invalid type of geometry. Valid ones: "Polygon"' + ], + errors_with_context: [ + { + type: 'filter', + message: 'Invalid type of geometry. Valid ones: "Polygon"' + } + ] + } + }, { + dataview: 'categories', + params: { + polygon: JSON.stringify({ + type: 'Polygon', + coordinates: [[[]]] + }), + response: { + status: 400 + } + }, + expected: { + errors: [ + 'Too few ordinates in GeoJSON' + ], + errors_with_context: [ + { + type: 'unknown', + message: 'Too few ordinates in GeoJSON' + } + ] + } }, { dataview: 'counter',