From 32275aca5675a9c729605af63fbf22c4fc0f0aa5 Mon Sep 17 00:00:00 2001 From: Harish Krishna Date: Fri, 19 Sep 2014 00:48:05 -0400 Subject: [PATCH] split sanitizers into reusable pieces. renaming sanitise to suggest. using suggest sanitizer for search. adding reverse sanitizer. updating tests.. --- app.js | 10 ++-- sanitiser/_input.js | 26 ++++++++++ sanitiser/_latlonzoom.js | 47 ++++++++++++++++++ sanitiser/_layers.js | 40 ++++++++++++++++ sanitiser/_sanitize.js | 17 +++++++ sanitiser/_size.js | 27 +++++++++++ sanitiser/reverse.js | 23 +++++++++ sanitiser/sanitise.js | 84 --------------------------------- sanitiser/suggest.js | 26 ++++++++++ test/unit/sanitiser/sanitise.js | 15 +++--- 10 files changed, 221 insertions(+), 94 deletions(-) create mode 100644 sanitiser/_input.js create mode 100644 sanitiser/_latlonzoom.js create mode 100644 sanitiser/_layers.js create mode 100644 sanitiser/_sanitize.js create mode 100644 sanitiser/_size.js create mode 100644 sanitiser/reverse.js delete mode 100644 sanitiser/sanitise.js create mode 100644 sanitiser/suggest.js diff --git a/app.js b/app.js index c9694900..a355ccfe 100644 --- a/app.js +++ b/app.js @@ -14,7 +14,9 @@ middlewares.search = require('./middleware/search'); /** ----------------------- sanitisers ----------------------- **/ var sanitisers = {}; -sanitisers.sanitiser= require('./sanitiser/sanitise'); +sanitisers.suggest = require('./sanitiser/suggest'); +sanitisers.search = sanitisers.suggest; +sanitisers.reverse = require('./sanitiser/reverse'); /** ----------------------- controllers ----------------------- **/ @@ -29,13 +31,13 @@ controllers.search = require('./controller/search'); app.get( '/', controllers.index() ); // suggest API -app.get( '/suggest', sanitisers.sanitiser.middleware, controllers.suggest() ); +app.get( '/suggest', sanitisers.suggest.middleware, controllers.suggest() ); // search API -app.get( '/search', sanitisers.sanitiser.middleware, middlewares.search.middleware, controllers.search() ); +app.get( '/search', sanitisers.search.middleware, middlewares.search.middleware, controllers.search() ); // reverse API -app.get( '/reverse', sanitisers.sanitiser.middleware, controllers.search(undefined, require('query/reverse')) ); +app.get( '/reverse', sanitisers.reverse.middleware, controllers.search(undefined, require('query/reverse')) ); /** ----------------------- error middleware ----------------------- **/ diff --git a/sanitiser/_input.js b/sanitiser/_input.js new file mode 100644 index 00000000..436c0c73 --- /dev/null +++ b/sanitiser/_input.js @@ -0,0 +1,26 @@ +// validate inputs, convert types and apply defaults +function sanitize( req ){ + + req.clean = req.clean || {}; + var params= req.query; + + // ensure the input params are a valid object + if( Object.prototype.toString.call( params ) !== '[object Object]' ){ + params = {}; + } + + // input text + if('string' !== typeof params.input || !params.input.length){ + return { + 'error': true, + 'message': 'invalid param \'input\': text length, must be >0' + }; + } + req.clean.input = params.input; + + return { 'error': false }; + +} + +// export function +module.exports = sanitize; \ No newline at end of file diff --git a/sanitiser/_latlonzoom.js b/sanitiser/_latlonzoom.js new file mode 100644 index 00000000..5120074d --- /dev/null +++ b/sanitiser/_latlonzoom.js @@ -0,0 +1,47 @@ +// validate inputs, convert types and apply defaults +function sanitize( req ){ + + var clean = req.clean || {}; + var params= req.query; + + // ensure the input params are a valid object + if( Object.prototype.toString.call( params ) !== '[object Object]' ){ + params = {}; + } + + // lat + var lat = parseFloat( params.lat, 10 ); + if( isNaN( lat ) || lat < 0 || lat > 90 ){ + return { + 'error': true, + 'message': 'invalid param \'lat\': must be >0 and <90' + } + } + clean.lat = lat; + + // lon + var lon = parseFloat( params.lon, 10 ); + if( isNaN( lon ) || lon < -180 || lon > 180 ){ + return { + 'error': true, + 'message': 'invalid param \'lon\': must be >-180 and <180' + } + } + clean.lon = lon; + + // zoom level + var zoom = parseInt( params.zoom, 10 ); + if( !isNaN( zoom ) ){ + clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max + } else { + clean.zoom = 10; // default + } + + req.clean = clean; + + return { 'error': false }; + +} + +// export function +module.exports = sanitize; diff --git a/sanitiser/_layers.js b/sanitiser/_layers.js new file mode 100644 index 00000000..c4f5d6eb --- /dev/null +++ b/sanitiser/_layers.js @@ -0,0 +1,40 @@ +var indeces = require('../query/indeces'); + +// validate inputs, convert types and apply defaults +function sanitize( req ){ + + var clean = req.clean || {}; + var params= req.query; + + // ensure the input params are a valid object + if( Object.prototype.toString.call( params ) !== '[object Object]' ){ + params = {}; + } + + // which layers to query + if('string' === typeof params.layers && params.layers.length){ + var layers = params.layers.split(',').map( function( layer ){ + return layer.toLowerCase(); // lowercase inputs + }); + for( var x=0; x0' ); - } - clean.input = params.input; - - // total results - var size = parseInt( params.size, 10 ); - if( !isNaN( size ) ){ - clean.size = Math.min( Math.max( size, 1 ), 40 ); // max - } else { - clean.size = 10; // default - } - - // which layers to query - if('string' === typeof params.layers && params.layers.length){ - var layers = params.layers.split(',').map( function( layer ){ - return layer.toLowerCase(); // lowercase inputs - }); - for( var x=0; x 90 ){ - return cb( 'invalid param \'lat\': must be >0 and <90' ); - } - clean.lat = lat; - - // lon - var lon = parseFloat( params.lon, 10 ); - if( isNaN( lon ) || lon < -180 || lon > 180 ){ - return cb( 'invalid param \'lon\': must be >-180 and <180' ); - } - clean.lon = lon; - - // zoom level - var zoom = parseInt( params.zoom, 10 ); - if( !isNaN( zoom ) ){ - clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max - } else { - clean.zoom = 10; // default - } - - return cb( undefined, clean ); - -} - -// export function -module.exports = sanitize; - -// middleware -module.exports.middleware = function( req, res, next ){ - sanitize( req.query, function( err, clean ){ - if( err ){ - res.status(400); // 400 Bad Request - return next(err); - } - req.clean = clean; - next(); - }); -}; \ No newline at end of file diff --git a/sanitiser/suggest.js b/sanitiser/suggest.js new file mode 100644 index 00000000..91fd6267 --- /dev/null +++ b/sanitiser/suggest.js @@ -0,0 +1,26 @@ + +var logger = require('../src/logger'), + _sanitize = require('../sanitiser/_sanitize'), + sanitizers = { + input: require('../sanitiser/_input'), + size: require('../sanitiser/_size'), + layers: require('../sanitiser/_layers'), + latlonzoom: require('../sanitiser/_latlonzoom') + }; + +var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); } + +// export sanitize for testing +module.exports.sanitize = sanitize; + +// middleware +module.exports.middleware = function( req, res, next ){ + sanitize( req, function( err, clean ){ + if( err ){ + res.status(400); // 400 Bad Request + return next(err); + } + req.clean = clean; + next(); + }); +}; \ No newline at end of file diff --git a/test/unit/sanitiser/sanitise.js b/test/unit/sanitiser/sanitise.js index 79ca4a06..bb1402ec 100644 --- a/test/unit/sanitiser/sanitise.js +++ b/test/unit/sanitiser/sanitise.js @@ -1,7 +1,10 @@ -var sanitize = require('../../../sanitiser/sanitise'), +var suggest = require('../../../sanitiser/suggest'), + _sanitize = suggest.sanitize, + middleware = suggest.middleware, defaultError = 'invalid param \'input\': text length, must be >0', - defaultClean = { input: 'test', lat: 0, layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood' ], lon: 0, size: 10, zoom: 10 }; + defaultClean = { input: 'test', lat: 0, layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood' ], lon: 0, size: 10, zoom: 10 }, + sanitize = function(query, cb) { _sanitize({'query':query}, cb); } module.exports.tests = {}; @@ -12,8 +15,8 @@ module.exports.tests.interface = function(test, common) { t.end(); }); test('middleware interface', function(t) { - t.equal(typeof sanitize.middleware, 'function', 'middleware is a function'); - t.equal(sanitize.middleware.length, 3, 'sanitize is valid middleware'); + t.equal(typeof middleware, 'function', 'middleware is a function'); + t.equal(middleware.length, 3, 'sanitizee has a valid middleware'); t.end(); }); }; @@ -175,7 +178,7 @@ module.exports.tests.middleware_failure = function(test, common) { t.equal(message, defaultError); t.end(); }; - sanitize.middleware( {}, res, next ); + middleware( {}, res, next ); }); }; @@ -187,7 +190,7 @@ module.exports.tests.middleware_success = function(test, common) { t.deepEqual(req.clean, defaultClean); t.end(); }; - sanitize.middleware( req, undefined, next ); + middleware( req, undefined, next ); }); };