diff --git a/Makefile b/Makefile index 5ca7973a..98454b25 100644 --- a/Makefile +++ b/Makefile @@ -18,35 +18,26 @@ config.status--test: config/environments/test.js: config.status--test ./config.status--test +TEST_SUITE := $(shell find test/{acceptance,integration,unit} -name "*.js") +TEST_SUITE_UNIT := $(shell find test/unit -name "*.js") +TEST_SUITE_INTEGRATION := $(shell find test/integration -name "*.js") +TEST_SUITE_ACCEPTANCE := $(shell find test/acceptance -name "*.js") + test: config/environments/test.js @echo "***tests***" - @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} \ - test/unit/cartodb/*.js \ - test/unit/cartodb/ported/*.js \ - test/unit/cartodb/cache/model/*.js \ - test/integration/*.js \ - test/acceptance/*.js \ - test/acceptance/cache/*.js \ - test/acceptance/ported/*.js \ - test/unit/cartodb/ported/*.js + @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} $(TEST_SUITE) test-unit: config/environments/test.js @echo "***tests***" - @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} \ - test/unit/cartodb/*.js \ - test/unit/cartodb/ported/*.js \ - test/unit/cartodb/cache/model/*.js + @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} $(TEST_SUITE_UNIT) test-integration: config/environments/test.js @echo "***tests***" - @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} \ - test/integration/*.js + @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} $(TEST_SUITE_INTEGRATION) test-acceptance: config/environments/test.js @echo "***tests***" - @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} \ - test/acceptance/*.js \ - test/acceptance/cache/*.js + @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} $(TEST_SUITE_ACCEPTANCE) jshint: @echo "***jshint***" diff --git a/lib/cartodb/controllers/base.js b/lib/cartodb/controllers/base.js new file mode 100644 index 00000000..ac7a2e6a --- /dev/null +++ b/lib/cartodb/controllers/base.js @@ -0,0 +1,241 @@ +var assert = require('assert'); + +var _ = require('underscore'); +var step = require('step'); +var debug = require('debug')('windshaft:cartodb'); + +var LZMA = require('lzma').LZMA; +var lzmaWorker = new LZMA(); + +// Whitelist query parameters and attach format +var REQUEST_QUERY_PARAMS_WHITELIST = [ + 'config', + 'map_key', + 'api_key', + 'auth_token', + 'callback' +]; + +function BaseController(authApi, pgConnection) { + this.authApi = authApi; + this.pgConnection = pgConnection; +} + +module.exports = BaseController; + +// jshint maxcomplexity:9 +/** + * Whitelist input and get database name & default geometry type from + * subdomain/user metadata held in CartoDB Redis + * @param req - standard express request obj. Should have host & table + * @param callback + */ +BaseController.prototype.req2params = function(req, callback){ + var self = this; + + if ( req.query.lzma ) { + + // Decode (from base64) + var lzma = new Buffer(req.query.lzma, 'base64') + .toString('binary') + .split('') + .map(function(c) { + return c.charCodeAt(0) - 128; + }); + + + // Decompress + lzmaWorker.decompress( + lzma, + function(result) { + if (req.profiler) { + req.profiler.done('lzma'); + } + try { + delete req.query.lzma; + _.extend(req.query, JSON.parse(result)); + self.req2params(req, callback); + } catch (err) { + req.profiler.done('req2params'); + callback(new Error('Error parsing lzma as JSON: ' + err)); + } + } + ); + return; + } + + req.query = _.pick(req.query, REQUEST_QUERY_PARAMS_WHITELIST); + req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object + + var user = req.context.user; + + if ( req.params.token ) { + // Token might match the following patterns: + // - {user}@{tpl_id}@{token}:{cache_buster} + //console.log("Request parameters include token " + req.params.token); + var tksplit = req.params.token.split(':'); + req.params.token = tksplit[0]; + if ( tksplit.length > 1 ) { + req.params.cache_buster= tksplit[1]; + } + tksplit = req.params.token.split('@'); + if ( tksplit.length > 1 ) { + req.params.signer = tksplit.shift(); + if ( ! req.params.signer ) { + req.params.signer = user; + } + else if ( req.params.signer !== user ) { + var err = new Error( + 'Cannot use map signature of user "' + req.params.signer + '" on db of user "' + user + '"' + ); + err.http_status = 403; + req.profiler.done('req2params'); + callback(err); + return; + } + if ( tksplit.length > 1 ) { + /*var template_hash = */tksplit.shift(); // unused + } + req.params.token = tksplit.shift(); + //console.log("Request for token " + req.params.token + " with signature from " + req.params.signer); + } + } + + // bring all query values onto req.params object + _.extend(req.params, req.query); + + if (req.profiler) { + req.profiler.done('req2params.setup'); + } + + step( + function getPrivacy(){ + self.authApi.authorize(req, this); + }, + function validateAuthorization(err, authorized) { + if (req.profiler) { + req.profiler.done('authorize'); + } + assert.ifError(err); + if(!authorized) { + err = new Error("Sorry, you are unauthorized (permission denied)"); + err.http_status = 403; + throw err; + } + return null; + }, + function getDatabase(err){ + assert.ifError(err); + self.pgConnection.setDBConn(user, req.params, this); + }, + function finishSetup(err) { + if ( err ) { + req.profiler.done('req2params'); + return callback(err, req); + } + + // Add default database connection parameters + // if none given + _.defaults(req.params, { + dbuser: global.environment.postgres.user, + dbpassword: global.environment.postgres.password, + dbhost: global.environment.postgres.host, + dbport: global.environment.postgres.port + }); + + req.profiler.done('req2params'); + callback(null, req); + } + ); +}; +// jshint maxcomplexity:6 + + +BaseController.prototype.send = function(req, res, args) { + if (global.environment && global.environment.api_hostname) { + res.header('X-Served-By-Host', global.environment.api_hostname); + } + + if (req.params && req.params.dbhost) { + res.header('X-Served-By-DB-Host', req.params.dbhost); + } + + if (req.profiler) { + res.header('X-Tiler-Profiler', req.profiler.toJSONString()); + } + + res.send.apply(res, args); + + if (req.profiler ) { + try { + // May throw due to dns, see + // See http://github.com/CartoDB/Windshaft/issues/166 + req.profiler.sendStats(); + } catch (err) { + debug("error sending profiling stats: " + err); + } + } +}; + +BaseController.prototype.sendError = function(req, res, err, label) { + label = label || 'UNKNOWN'; + + var statusCode = findStatusCode(err); + + debug('[%s ERROR] -- %d: %s', label, statusCode, err); + + // If a callback was requested, force status to 200 + if (req.query && req.query.callback) { + statusCode = 200; + } + + var errorResponseBody = { errors: [errorMessage(err)] }; + + this.send(req, res, [errorResponseBody, statusCode]); +}; + +function errorMessage(err) { + // See https://github.com/Vizzuality/Windshaft-cartodb/issues/68 + var message = (_.isString(err) ? err : err.message) || 'Unknown error'; + + // Strip connection info, if any + return message + // See https://github.com/CartoDB/Windshaft/issues/173 + .replace(/Connection string: '[^']*'\n\s/im, '') + // See https://travis-ci.org/CartoDB/Windshaft/jobs/20703062#L1644 + .replace(/is the server.*encountered/im, 'encountered'); +} +module.exports.errorMessage = errorMessage; + +function findStatusCode(err) { + var statusCode; + if ( err.http_status ) { + statusCode = err.http_status; + } else { + statusCode = statusFromErrorMessage('' + err); + } + return statusCode; +} +module.exports.findStatusCode = findStatusCode; + +function statusFromErrorMessage(errMsg) { + // Find an appropriate statusCode based on message + var statusCode = 400; + if ( -1 !== errMsg.indexOf('permission denied') ) { + statusCode = 403; + } + else if ( -1 !== errMsg.indexOf('authentication failed') ) { + statusCode = 403; + } + else if (errMsg.match(/Postgis Plugin.*[\s|\n].*column.*does not exist/)) { + statusCode = 400; + } + else if ( -1 !== errMsg.indexOf('does not exist') ) { + if ( -1 !== errMsg.indexOf(' role ') ) { + statusCode = 403; // role 'xxx' does not exist + } else { + statusCode = 404; + } + } + return statusCode; +} diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 57a7628f..59e7a98b 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -1,6 +1,9 @@ var assert = require('assert'); var step = require('step'); +var util = require('util'); +var BaseController = require('./base'); + var cors = require('../middleware/cors'); var MapStoreMapConfigProvider = require('../models/mapconfig/map_store_provider'); @@ -8,6 +11,8 @@ var TablesCacheEntry = require('../cache/model/database_tables_entry'); /** * @param app + * @param {AuthApi} authApi + * @param {PgConnection} pgConnection * @param {MapStore} mapStore * @param {TileBackend} tileBackend * @param {PreviewBackend} previewBackend @@ -18,8 +23,10 @@ var TablesCacheEntry = require('../cache/model/database_tables_entry'); * @param {LayergroupAffectedTables} layergroupAffectedTables * @constructor */ -function LayergroupController(app, mapStore, tileBackend, previewBackend, attributesBackend, surrogateKeysCache, - userLimitsApi, queryTablesApi, layergroupAffectedTables) { +function LayergroupController(app, authApi, pgConnection, mapStore, tileBackend, previewBackend, attributesBackend, + surrogateKeysCache, userLimitsApi, queryTablesApi, layergroupAffectedTables) { + BaseController.call(this, authApi, pgConnection); + this.app = app; this.mapStore = mapStore; this.tileBackend = tileBackend; @@ -31,6 +38,8 @@ function LayergroupController(app, mapStore, tileBackend, previewBackend, attrib this.layergroupAffectedTables = layergroupAffectedTables; } +util.inherits(LayergroupController, BaseController); + module.exports = LayergroupController; @@ -52,7 +61,7 @@ LayergroupController.prototype.attributes = function(req, res) { step( function setupParams() { - self.app.req2params(req, this); + self.req2params(req, this); }, function retrieveFeatureAttributes(err) { assert.ifError(err); @@ -66,7 +75,7 @@ LayergroupController.prototype.attributes = function(req, res) { req.profiler.add(stats || {}); if (err) { - res.sendError(err, 'GET ATTRIBUTES'); + self.sendError(req, res, err, 'GET ATTRIBUTES'); } else { self.sendResponse(req, res, [tile, 200]); } @@ -95,7 +104,7 @@ LayergroupController.prototype.tileOrLayer = function (req, res) { step( function mapController$prepareParams() { - self.app.req2params(req, this); + self.req2params(req, this); }, function mapController$getTileOrGrid(err) { assert.ifError(err); @@ -146,7 +155,7 @@ LayergroupController.prototype.finalizeGetTileOrGrid = function(err, req, res, t } err.message = errMsg; - res.sendError(err, 'TILE RENDER'); + this.sendError(req, res, err, 'TILE RENDER'); global.statsClient.increment('windshaft.tiles.error'); global.statsClient.increment('windshaft.tiles.' + formatStat + '.error'); } else { @@ -181,7 +190,7 @@ LayergroupController.prototype.staticMap = function(req, res, width, height, zoo step( function() { - self.app.req2params(req, this); + self.req2params(req, this); }, function(err) { assert.ifError(err); @@ -200,7 +209,7 @@ LayergroupController.prototype.staticMap = function(req, res, width, height, zoo req.profiler.add(stats || {}); if (err) { - res.sendError(err, 'STATIC_MAP'); + self.sendError(req, res, err, 'STATIC_MAP'); } else { res.setHeader('Content-Type', headers['Content-Type'] || 'image/' + format); self.sendResponse(req, res, [image, 200]); @@ -239,7 +248,7 @@ LayergroupController.prototype.sendResponse = function(req, res, args) { res.header('X-Cache-Channel', tablesCacheEntry.getCacheChannel()); self.surrogateKeysCache.tag(res, tablesCacheEntry); } - res.sendResponse(args); + self.send(req, res, args); } ); diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 73182387..ffa776a7 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -3,6 +3,9 @@ var assert = require('assert'); var step = require('step'); var windshaft = require('windshaft'); +var util = require('util'); +var BaseController = require('./base'); + var cors = require('../middleware/cors'); var MapConfig = windshaft.model.MapConfig; @@ -17,6 +20,7 @@ var CreateLayergroupMapConfigProvider = require('../models/mapconfig/create_laye /** * @param app + * @param {AuthApi} authApi * @param {PgConnection} pgConnection * @param {TemplateMaps} templateMaps * @param {MapBackend} mapBackend @@ -27,8 +31,11 @@ var CreateLayergroupMapConfigProvider = require('../models/mapconfig/create_laye * @param {LayergroupAffectedTables} layergroupAffectedTables * @constructor */ -function MapController(app, pgConnection, templateMaps, mapBackend, metadataBackend, queryTablesApi, +function MapController(app, authApi, pgConnection, templateMaps, mapBackend, metadataBackend, queryTablesApi, surrogateKeysCache, userLimitsApi, layergroupAffectedTables) { + + BaseController.call(this, authApi, pgConnection); + this.app = app; this.pgConnection = pgConnection; this.templateMaps = templateMaps; @@ -42,6 +49,8 @@ function MapController(app, pgConnection, templateMaps, mapBackend, metadataBack this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps); } +util.inherits(MapController, BaseController); + module.exports = MapController; @@ -121,7 +130,7 @@ MapController.prototype.create = function(req, res, prepareConfigFn) { step( function setupParams(){ - self.app.req2params(req, this); + self.req2params(req, this); }, prepareConfigFn, function beforeLayergroupCreate(err, requestMapConfig) { @@ -155,10 +164,10 @@ MapController.prototype.create = function(req, res, prepareConfigFn) { }, function finish(err, layergroup) { if (err) { - res.sendError(err, 'ANONYMOUS LAYERGROUP'); + self.sendError(req, res, err, 'ANONYMOUS LAYERGROUP'); } else { res.header('X-Layergroup-Id', layergroup.layergroupid); - res.sendResponse([layergroup, 200]); + self.send(req, res, [layergroup, 200]); } } ); @@ -174,7 +183,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn step( function setupParams(){ - self.app.req2params(req, this); + self.req2params(req, this); }, function getTemplateParams() { prepareParamsFn(this); @@ -209,7 +218,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn }, function finishTemplateInstantiation(err, layergroup) { if (err) { - res.sendError(err, 'NAMED MAP LAYERGROUP'); + self.sendError(req, res, err, 'NAMED MAP LAYERGROUP'); } else { var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8); layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid; @@ -217,7 +226,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn res.header('X-Layergroup-Id', layergroup.layergroupid); self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName())); - res.sendResponse([layergroup, 200]); + self.send(req, res, [layergroup, 200]); } } ); diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index c123c461..d921b956 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -2,12 +2,18 @@ var step = require('step'); var assert = require('assert'); var _ = require('underscore'); var NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); + +var util = require('util'); +var BaseController = require('./base'); + var cors = require('../middleware/cors'); var TablesCacheEntry = require('../cache/model/database_tables_entry'); -function NamedMapsController(app, namedMapProviderCache, tileBackend, previewBackend, surrogateKeysCache, - tablesExtentApi) { +function NamedMapsController(app, authApi, pgConnection, namedMapProviderCache, tileBackend, previewBackend, + surrogateKeysCache, tablesExtentApi) { + BaseController.call(this, authApi, pgConnection); + this.app = app; this.namedMapProviderCache = namedMapProviderCache; this.tileBackend = tileBackend; @@ -16,6 +22,8 @@ function NamedMapsController(app, namedMapProviderCache, tileBackend, previewBac this.tablesExtentApi = tablesExtentApi; } +util.inherits(NamedMapsController, BaseController); + module.exports = NamedMapsController; NamedMapsController.prototype.register = function(app) { @@ -60,7 +68,7 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header self.surrogateKeysCache.tag(res, tablesCacheEntry); } } - res.sendResponse([resource, 200]); + self.send(req, res, [resource, 200]); } ); }; @@ -73,7 +81,7 @@ NamedMapsController.prototype.tile = function(req, res) { var namedMapProvider; step( function reqParams() { - self.app.req2params(req, this); + self.req2params(req, this); }, function getTile() { namedMapProvider = self.namedMapProviderCache.get( @@ -90,7 +98,7 @@ NamedMapsController.prototype.tile = function(req, res) { req.profiler.add(stats); } if (err) { - res.sendError(err, 'NAMED_MAP_TILE'); + self.sendError(req, res, err, 'NAMED_MAP_TILE'); } else { self.sendResponse(req, res, tile, headers, namedMapProvider); } @@ -110,7 +118,7 @@ NamedMapsController.prototype.staticMap = function(req, res) { var namedMapProvider; step( function reqParams() { - self.app.req2params(req, this); + self.req2params(req, this); }, function getTemplate(err) { assert.ifError(err); @@ -179,7 +187,7 @@ NamedMapsController.prototype.staticMap = function(req, res) { } if (err) { - res.sendError(err, 'STATIC_VIZ_MAP'); + self.sendError(req, res, err, 'STATIC_VIZ_MAP'); } else { self.sendResponse(req, res, image, headers, namedMapProvider); } diff --git a/lib/cartodb/controllers/named_maps_admin.js b/lib/cartodb/controllers/named_maps_admin.js index 53265cd5..c393b1c3 100644 --- a/lib/cartodb/controllers/named_maps_admin.js +++ b/lib/cartodb/controllers/named_maps_admin.js @@ -1,19 +1,28 @@ var step = require('step'); var assert = require('assert'); var templateName = require('../backends/template_maps').templateName; + +var util = require('util'); +var BaseController = require('./base'); + var cors = require('../middleware/cors'); /** * @param {TemplateMaps} templateMaps * @param {AuthApi} authApi + * @param {PgConnection} pgConnection * @constructor */ -function NamedMapsAdminController(templateMaps, authApi) { +function NamedMapsAdminController(templateMaps, authApi, pgConnection) { + BaseController.call(this, authApi, pgConnection); + this.templateMaps = templateMaps; this.authApi = authApi; } +util.inherits(NamedMapsAdminController, BaseController); + module.exports = NamedMapsAdminController; NamedMapsAdminController.prototype.register = function(app) { @@ -45,7 +54,7 @@ NamedMapsAdminController.prototype.create = function(req, res) { assert.ifError(err); return { template_id: tpl_id }; }, - finishFn(res, 'POST TEMPLATE') + finishFn(self, req, res, 'POST TEMPLATE') ); }; @@ -73,7 +82,7 @@ NamedMapsAdminController.prototype.update = function(req, res) { return { template_id: tpl_id }; }, - finishFn(res, 'PUT TEMPLATE') + finishFn(self, req, res, 'PUT TEMPLATE') ); }; @@ -109,7 +118,7 @@ NamedMapsAdminController.prototype.retrieve = function(req, res) { delete tpl_val.auth_id; return { template: tpl_val }; }, - finishFn(res, 'GET TEMPLATE') + finishFn(self, req, res, 'GET TEMPLATE') ); }; @@ -137,7 +146,7 @@ NamedMapsAdminController.prototype.destroy = function(req, res) { assert.ifError(err); return { status: 'ok' }; }, - finishFn(res, 'DELETE TEMPLATE', ['', 204]) + finishFn(self, req, res, 'DELETE TEMPLATE', ['', 204]) ); }; @@ -163,16 +172,16 @@ NamedMapsAdminController.prototype.list = function(req, res) { assert.ifError(err); return { template_ids: tpl_ids }; }, - finishFn(res, 'GET TEMPLATE LIST') + finishFn(self, req, res, 'GET TEMPLATE LIST') ); }; -function finishFn(res, description, okResponse) { +function finishFn(controller, req, res, description, okResponse) { return function finish(err, response){ if (err) { - res.sendError(err, description); + controller.sendError(req, res, err, description); } else { - res.sendResponse(okResponse || [response, 200]); + controller.send(req, res, okResponse || [response, 200]); } }; } diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index d2006ead..8f1e3de8 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -1,10 +1,7 @@ -var assert = require('assert'); - var express = require('express'); var RedisPool = require('redis-mpool'); var cartodbRedis = require('cartodb-redis'); var _ = require('underscore'); -var step = require('step'); var controller = require('./controllers'); @@ -32,18 +29,6 @@ var PgConnection = require('./backends/pg_connection'); var CdbRequest = require('./models/cdb_request'); var cdbRequest = new CdbRequest(); -var LZMA = require('lzma').LZMA; -// Whitelist query parameters and attach format -var REQUEST_QUERY_PARAMS_WHITELIST = [ - 'config', - 'map_key', - 'api_key', - 'auth_token', - 'callback' -]; - -var lzmaWorker = new LZMA(); - var timeoutErrorTilePath = __dirname + '/../../assets/render-timeout-fallback.png'; var timeoutErrorTile = require('fs').readFileSync(timeoutErrorTilePath, {encoding: null}); @@ -178,6 +163,8 @@ module.exports = function(serverOptions) { new controller.Layergroup( app, + authApi, + pgConnection, mapStore, tileBackend, previewBackend, @@ -190,6 +177,7 @@ module.exports = function(serverOptions) { new controller.Map( app, + authApi, pgConnection, templateMaps, mapBackend, @@ -202,6 +190,8 @@ module.exports = function(serverOptions) { new controller.NamedMaps( app, + authApi, + pgConnection, namedMapProviderCache, tileBackend, previewBackend, @@ -209,7 +199,7 @@ module.exports = function(serverOptions) { tablesExtentApi ).register(app); - new controller.NamedMapsAdmin(templateMaps, authApi).register(app); + new controller.NamedMapsAdmin(templateMaps, authApi, pgConnection).register(app); new controller.ServerInfo().register(app); @@ -217,131 +207,6 @@ module.exports = function(serverOptions) { * END Routing ******************************************************************************************************************/ - // jshint maxcomplexity:10 - /** - * Whitelist input and get database name & default geometry type from - * subdomain/user metadata held in CartoDB Redis - * @param req - standard express request obj. Should have host & table - * @param callback - */ - app.req2params = function(req, callback){ - - if ( req.query.lzma ) { - - // Decode (from base64) - var lzma = new Buffer(req.query.lzma, 'base64') - .toString('binary') - .split('') - .map(function(c) { - return c.charCodeAt(0) - 128; - }); - - // Decompress - lzmaWorker.decompress( - lzma, - function(result) { - if (req.profiler) { - req.profiler.done('lzma'); - } - try { - delete req.query.lzma; - _.extend(req.query, JSON.parse(result)); - app.req2params(req, callback); - } catch (err) { - req.profiler.done('req2params'); - callback(new Error('Error parsing lzma as JSON: ' + err)); - } - } - ); - return; - } - - req.query = _.pick(req.query, REQUEST_QUERY_PARAMS_WHITELIST); - req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object - - var user = req.context.user; - - if ( req.params.token ) { - // Token might match the following patterns: - // - {user}@{tpl_id}@{token}:{cache_buster} - //console.log("Request parameters include token " + req.params.token); - var tksplit = req.params.token.split(':'); - req.params.token = tksplit[0]; - if ( tksplit.length > 1 ) { - req.params.cache_buster= tksplit[1]; - } - tksplit = req.params.token.split('@'); - if ( tksplit.length > 1 ) { - req.params.signer = tksplit.shift(); - if ( ! req.params.signer ) { - req.params.signer = user; - } - else if ( req.params.signer !== user ) { - var err = new Error( - 'Cannot use map signature of user "' + req.params.signer + '" on db of user "' + user + '"' - ); - err.http_status = 403; - req.profiler.done('req2params'); - callback(err); - return; - } - if ( tksplit.length > 1 ) { - /*var template_hash = */tksplit.shift(); // unused - } - req.params.token = tksplit.shift(); - //console.log("Request for token " + req.params.token + " with signature from " + req.params.signer); - } - } - - // bring all query values onto req.params object - _.extend(req.params, req.query); - - if (req.profiler) { - req.profiler.done('req2params.setup'); - } - - step( - function getPrivacy(){ - authApi.authorize(req, this); - }, - function validateAuthorization(err, authorized) { - if (req.profiler) { - req.profiler.done('authorize'); - } - assert.ifError(err); - if(!authorized) { - err = new Error("Sorry, you are unauthorized (permission denied)"); - err.http_status = 403; - throw err; - } - return null; - }, - function getDatabase(err){ - assert.ifError(err); - pgConnection.setDBConn(user, req.params, this); - }, - function finishSetup(err) { - if ( err ) { - req.profiler.done('req2params'); - return callback(err, req); - } - - // Add default database connection parameters - // if none given - _.defaults(req.params, { - dbuser: global.environment.postgres.user, - dbpassword: global.environment.postgres.password, - dbhost: global.environment.postgres.host, - dbport: global.environment.postgres.port - }); - - req.profiler.done('req2params'); - callback(null, req); - } - ); - }; - // jshint maxcomplexity:6 - return app; }; @@ -390,62 +255,6 @@ function bootstrap(opts) { res.removeHeader('x-powered-by'); - res.sendResponse = function(args) { - if (global.environment && global.environment.api_hostname) { - res.header('X-Served-By-Host', global.environment.api_hostname); - } - - if (req.params && req.params.dbhost) { - res.header('X-Served-By-DB-Host', req.params.dbhost); - } - - if (req.profiler) { - res.header('X-Tiler-Profiler', req.profiler.toJSONString()); - } - - res.send.apply(res, args); - - if (req.profiler ) { - try { - // May throw due to dns, see - // See http://github.com/CartoDB/Windshaft/issues/166 - req.profiler.sendStats(); - } catch (err) { - console.error("error sending profiling stats: " + err); - } - } - }; - res.sendError = function(err, label) { - - label = label || 'UNKNOWN'; - - var statusCode = findStatusCode(err); - - // use console.log for statusCode != 500 ? - if (statusCode >= 500) { - console.error('[%s ERROR] -- %d: %s', label, statusCode, err); - } else { - console.warn('[%s WARN] -- %d: %s', label, statusCode, err); - } - - // If a callback was requested, force status to 200 - if (req.query.callback) { - statusCode = 200; - } - - // See https://github.com/Vizzuality/Windshaft-cartodb/issues/68 - var message = (_.isString(err) ? err : err.message) || 'Unknown error'; - // Strip connection info, if any - message = message - // See https://github.com/CartoDB/Windshaft/issues/173 - .replace(/Connection string: '[^']*'\\n/, '') - // See https://travis-ci.org/CartoDB/Windshaft/jobs/20703062#L1644 - .replace(/is the server.*encountered/im, 'encountered'); - - var errorResponseBody = { errors: [message] }; - - res.sendResponse([errorResponseBody, statusCode]); - }; next(); }); @@ -506,39 +315,6 @@ function surrogateKeysCacheBackends(serverOptions) { return cacheBackends; } -function findStatusCode(err) { - var statusCode; - if ( err.http_status ) { - statusCode = err.http_status; - } else { - statusCode = statusFromErrorMessage('' + err); - } - return statusCode; -} -module.exports.findStatusCode = findStatusCode; - -function statusFromErrorMessage(errMsg) { - // Find an appropriate statusCode based on message - var statusCode = 400; - if ( -1 !== errMsg.indexOf('permission denied') ) { - statusCode = 403; - } - else if ( -1 !== errMsg.indexOf('authentication failed') ) { - statusCode = 403; - } - else if (errMsg.match(/Postgis Plugin.*[\s|\n].*column.*does not exist/)) { - statusCode = 400; - } - else if ( -1 !== errMsg.indexOf('does not exist') ) { - if ( -1 !== errMsg.indexOf(' role ') ) { - statusCode = 403; // role 'xxx' does not exist - } else { - statusCode = 404; - } - } - return statusCode; -} - function mapnikVersion(opts) { return opts.grainstore.mapnik_version || mapnik.versions.mapnik; } diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4ed16d49..5c9696ef 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -119,309 +119,7 @@ }, "fastly-purge": { "version": "1.0.0", - "from": "fastly-purge@~1.0.0", - "dependencies": { - "request": { - "version": "2.62.0", - "from": "request@^2.55.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.62.0.tgz", - "dependencies": { - "bl": { - "version": "1.0.0", - "from": "bl@~1.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.0.tgz", - "dependencies": { - "readable-stream": { - "version": "2.0.2", - "from": "readable-stream@~2.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.2.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.1", - "from": "core-util-is@~1.0.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@~2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "process-nextick-args": { - "version": "1.0.3", - "from": "process-nextick-args@~1.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.3.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@~0.10.x", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "util-deprecate": { - "version": "1.0.1", - "from": "util-deprecate@~1.0.1", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.1.tgz" - } - } - } - } - }, - "caseless": { - "version": "0.11.0", - "from": "caseless@~0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" - }, - "extend": { - "version": "3.0.0", - "from": "extend@~3.0.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" - }, - "forever-agent": { - "version": "0.6.1", - "from": "forever-agent@~0.6.0", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" - }, - "form-data": { - "version": "1.0.0-rc3", - "from": "form-data@~1.0.0-rc1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", - "dependencies": { - "async": { - "version": "1.4.2", - "from": "async@^1.4.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.4.2.tgz" - } - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "from": "json-stringify-safe@~5.0.0", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" - }, - "mime-types": { - "version": "2.1.6", - "from": "mime-types@~2.1.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz", - "dependencies": { - "mime-db": { - "version": "1.18.0", - "from": "mime-db@~1.18.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.18.0.tgz" - } - } - }, - "node-uuid": { - "version": "1.4.3", - "from": "node-uuid@~1.4.0", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" - }, - "qs": { - "version": "5.1.0", - "from": "qs@~5.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" - }, - "tunnel-agent": { - "version": "0.4.1", - "from": "tunnel-agent@~0.4.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.1.tgz" - }, - "tough-cookie": { - "version": "2.0.0", - "from": "tough-cookie@>=0.12.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.0.0.tgz" - }, - "http-signature": { - "version": "0.11.0", - "from": "http-signature@~0.11.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", - "dependencies": { - "assert-plus": { - "version": "0.1.5", - "from": "assert-plus@^0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" - }, - "asn1": { - "version": "0.1.11", - "from": "asn1@0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" - }, - "ctype": { - "version": "0.5.3", - "from": "ctype@0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" - } - } - }, - "oauth-sign": { - "version": "0.8.0", - "from": "oauth-sign@~0.8.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.0.tgz" - }, - "hawk": { - "version": "3.1.0", - "from": "hawk@~3.1.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.0.tgz", - "dependencies": { - "hoek": { - "version": "2.16.0", - "from": "hoek@2.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.0.tgz" - }, - "boom": { - "version": "2.8.0", - "from": "boom@^2.8.x", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.8.0.tgz" - }, - "cryptiles": { - "version": "2.0.5", - "from": "cryptiles@2.x.x", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" - }, - "sntp": { - "version": "1.0.9", - "from": "sntp@1.x.x", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" - } - } - }, - "aws-sign2": { - "version": "0.5.0", - "from": "aws-sign2@~0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" - }, - "stringstream": { - "version": "0.0.4", - "from": "stringstream@~0.0.4", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" - }, - "combined-stream": { - "version": "1.0.5", - "from": "combined-stream@~1.0.1", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "from": "delayed-stream@~1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - } - } - }, - "isstream": { - "version": "0.1.2", - "from": "isstream@~0.1.1", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - }, - "har-validator": { - "version": "1.8.0", - "from": "har-validator@^1.6.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", - "dependencies": { - "bluebird": { - "version": "2.10.0", - "from": "bluebird@^2.9.30", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.0.tgz" - }, - "chalk": { - "version": "1.1.1", - "from": "chalk@^1.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", - "dependencies": { - "ansi-styles": { - "version": "2.1.0", - "from": "ansi-styles@^2.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz" - }, - "escape-string-regexp": { - "version": "1.0.3", - "from": "escape-string-regexp@^1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" - }, - "has-ansi": { - "version": "2.0.0", - "from": "has-ansi@^2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "from": "ansi-regex@^2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" - } - } - }, - "strip-ansi": { - "version": "3.0.0", - "from": "strip-ansi@^3.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz", - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "from": "ansi-regex@^2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" - } - } - }, - "supports-color": { - "version": "2.0.0", - "from": "supports-color@^2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - } - } - }, - "commander": { - "version": "2.8.1", - "from": "commander@^2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "dependencies": { - "graceful-readlink": { - "version": "1.0.1", - "from": "graceful-readlink@>= 1.0.0", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" - } - } - }, - "is-my-json-valid": { - "version": "2.12.2", - "from": "is-my-json-valid@^2.12.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.2.tgz", - "dependencies": { - "generate-function": { - "version": "2.0.0", - "from": "generate-function@^2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" - }, - "generate-object-property": { - "version": "1.2.0", - "from": "generate-object-property@^1.1.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "dependencies": { - "is-property": { - "version": "1.0.2", - "from": "is-property@^1.0.0", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" - } - } - }, - "jsonpointer": { - "version": "2.0.0", - "from": "jsonpointer@2.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" - }, - "xtend": { - "version": "4.0.0", - "from": "xtend@^4.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" - } - } - } - } - } - } - } - } + "from": "fastly-purge@~1.0.0" }, "log4js": { "version": "0.6.25", @@ -526,13 +224,308 @@ } }, "request": { - "version": "2.9.203", - "from": "request@~2.9.203", - "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz" + "version": "2.62.0", + "from": "request@~2.62.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.62.0.tgz", + "dependencies": { + "bl": { + "version": "1.0.0", + "from": "bl@~1.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.0.tgz", + "dependencies": { + "readable-stream": { + "version": "2.0.2", + "from": "readable-stream@~2.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.2.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "process-nextick-args": { + "version": "1.0.3", + "from": "process-nextick-args@~1.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.3.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.1", + "from": "util-deprecate@~1.0.1", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.1.tgz" + } + } + } + } + }, + "caseless": { + "version": "0.11.0", + "from": "caseless@~0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" + }, + "extend": { + "version": "3.0.0", + "from": "extend@~3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "forever-agent": { + "version": "0.6.1", + "from": "forever-agent@~0.6.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + }, + "form-data": { + "version": "1.0.0-rc3", + "from": "form-data@~1.0.0-rc1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", + "dependencies": { + "async": { + "version": "1.4.2", + "from": "async@^1.4.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.4.2.tgz" + } + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + }, + "mime-types": { + "version": "2.1.6", + "from": "mime-types@~2.1.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz", + "dependencies": { + "mime-db": { + "version": "1.18.0", + "from": "mime-db@~1.18.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.18.0.tgz" + } + } + }, + "node-uuid": { + "version": "1.4.3", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" + }, + "qs": { + "version": "5.1.0", + "from": "qs@~5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" + }, + "tunnel-agent": { + "version": "0.4.1", + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.1.tgz" + }, + "tough-cookie": { + "version": "2.0.0", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.0.0.tgz" + }, + "http-signature": { + "version": "0.11.0", + "from": "http-signature@~0.11.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@^0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" + } + } + }, + "oauth-sign": { + "version": "0.8.0", + "from": "oauth-sign@~0.8.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.0.tgz" + }, + "hawk": { + "version": "3.1.0", + "from": "hawk@~3.1.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.0.tgz", + "dependencies": { + "hoek": { + "version": "2.16.2", + "from": "hoek@2.x.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.2.tgz" + }, + "boom": { + "version": "2.8.0", + "from": "boom@^2.8.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.8.0.tgz" + }, + "cryptiles": { + "version": "2.0.5", + "from": "cryptiles@2.x.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + }, + "sntp": { + "version": "1.0.9", + "from": "sntp@1.x.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "stringstream": { + "version": "0.0.4", + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" + }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@~1.0.1", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "dependencies": { + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@~1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + } + } + }, + "isstream": { + "version": "0.1.2", + "from": "isstream@~0.1.1", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + }, + "har-validator": { + "version": "1.8.0", + "from": "har-validator@^1.6.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", + "dependencies": { + "bluebird": { + "version": "2.10.0", + "from": "bluebird@^2.9.30", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.0.tgz" + }, + "chalk": { + "version": "1.1.1", + "from": "chalk@^1.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", + "dependencies": { + "ansi-styles": { + "version": "2.1.0", + "from": "ansi-styles@^2.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz" + }, + "escape-string-regexp": { + "version": "1.0.3", + "from": "escape-string-regexp@^1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" + }, + "has-ansi": { + "version": "2.0.0", + "from": "has-ansi@^2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@^2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "strip-ansi": { + "version": "3.0.0", + "from": "strip-ansi@^3.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@^2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@^2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + } + } + }, + "commander": { + "version": "2.8.1", + "from": "commander@^2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "dependencies": { + "graceful-readlink": { + "version": "1.0.1", + "from": "graceful-readlink@>= 1.0.0", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + } + } + }, + "is-my-json-valid": { + "version": "2.12.2", + "from": "is-my-json-valid@^2.12.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.2.tgz", + "dependencies": { + "generate-function": { + "version": "2.0.0", + "from": "generate-function@^2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + }, + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@^1.1.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "dependencies": { + "is-property": { + "version": "1.0.2", + "from": "is-property@^1.0.0", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + } + } + }, + "jsonpointer": { + "version": "2.0.0", + "from": "jsonpointer@2.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" + }, + "xtend": { + "version": "4.0.0", + "from": "xtend@^4.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" + } + } + } + } + } + } }, "step": { "version": "0.0.6", - "from": "step@~0.0.5", + "from": "step@~0.0.6", "resolved": "https://registry.npmjs.org/step/-/step-0.0.6.tgz" }, "step-profiler": { @@ -2340,7 +2333,7 @@ }, "mime": { "version": "1.2.11", - "from": "mime@~1.2.11", + "from": "mime@~1.2.9", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } @@ -2823,306 +2816,6 @@ "from": "torque.js@~2.11.0", "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-2.11.0.tgz" }, - "request": { - "version": "2.62.0", - "from": "request@2.62.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.62.0.tgz", - "dependencies": { - "bl": { - "version": "1.0.0", - "from": "bl@~1.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.0.tgz", - "dependencies": { - "readable-stream": { - "version": "2.0.2", - "from": "readable-stream@~2.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.2.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.1", - "from": "core-util-is@~1.0.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@~2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "process-nextick-args": { - "version": "1.0.3", - "from": "process-nextick-args@~1.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.3.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@~0.10.x", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "util-deprecate": { - "version": "1.0.1", - "from": "util-deprecate@~1.0.1", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.1.tgz" - } - } - } - } - }, - "caseless": { - "version": "0.11.0", - "from": "caseless@~0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" - }, - "extend": { - "version": "3.0.0", - "from": "extend@~3.0.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" - }, - "forever-agent": { - "version": "0.6.1", - "from": "forever-agent@~0.6.0", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" - }, - "form-data": { - "version": "1.0.0-rc3", - "from": "form-data@~1.0.0-rc1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", - "dependencies": { - "async": { - "version": "1.4.2", - "from": "async@^1.4.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.4.2.tgz" - } - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "from": "json-stringify-safe@~5.0.0", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" - }, - "mime-types": { - "version": "2.1.6", - "from": "mime-types@~2.1.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz", - "dependencies": { - "mime-db": { - "version": "1.18.0", - "from": "mime-db@~1.18.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.18.0.tgz" - } - } - }, - "node-uuid": { - "version": "1.4.3", - "from": "node-uuid@~1.4.0", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" - }, - "qs": { - "version": "5.1.0", - "from": "qs@~5.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" - }, - "tunnel-agent": { - "version": "0.4.1", - "from": "tunnel-agent@~0.4.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.1.tgz" - }, - "tough-cookie": { - "version": "2.0.0", - "from": "tough-cookie@>=0.12.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.0.0.tgz" - }, - "http-signature": { - "version": "0.11.0", - "from": "http-signature@~0.11.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", - "dependencies": { - "assert-plus": { - "version": "0.1.5", - "from": "assert-plus@^0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" - }, - "asn1": { - "version": "0.1.11", - "from": "asn1@0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" - }, - "ctype": { - "version": "0.5.3", - "from": "ctype@0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" - } - } - }, - "oauth-sign": { - "version": "0.8.0", - "from": "oauth-sign@~0.8.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.0.tgz" - }, - "hawk": { - "version": "3.1.0", - "from": "hawk@~3.1.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.0.tgz", - "dependencies": { - "hoek": { - "version": "2.16.0", - "from": "hoek@2.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.0.tgz" - }, - "boom": { - "version": "2.8.0", - "from": "boom@^2.8.x", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.8.0.tgz" - }, - "cryptiles": { - "version": "2.0.5", - "from": "cryptiles@2.x.x", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" - }, - "sntp": { - "version": "1.0.9", - "from": "sntp@1.x.x", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" - } - } - }, - "aws-sign2": { - "version": "0.5.0", - "from": "aws-sign2@~0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" - }, - "stringstream": { - "version": "0.0.4", - "from": "stringstream@~0.0.4", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" - }, - "combined-stream": { - "version": "1.0.5", - "from": "combined-stream@~1.0.1", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "from": "delayed-stream@~1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - } - } - }, - "isstream": { - "version": "0.1.2", - "from": "isstream@~0.1.1", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - }, - "har-validator": { - "version": "1.8.0", - "from": "har-validator@^1.6.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", - "dependencies": { - "bluebird": { - "version": "2.10.0", - "from": "bluebird@^2.9.30", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.0.tgz" - }, - "chalk": { - "version": "1.1.1", - "from": "chalk@^1.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", - "dependencies": { - "ansi-styles": { - "version": "2.1.0", - "from": "ansi-styles@^2.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz" - }, - "escape-string-regexp": { - "version": "1.0.3", - "from": "escape-string-regexp@^1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" - }, - "has-ansi": { - "version": "2.0.0", - "from": "has-ansi@^2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "from": "ansi-regex@^2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" - } - } - }, - "strip-ansi": { - "version": "3.0.0", - "from": "strip-ansi@^3.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz", - "dependencies": { - "ansi-regex": { - "version": "2.0.0", - "from": "ansi-regex@^2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" - } - } - }, - "supports-color": { - "version": "2.0.0", - "from": "supports-color@^2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - } - } - }, - "commander": { - "version": "2.8.1", - "from": "commander@^2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "dependencies": { - "graceful-readlink": { - "version": "1.0.1", - "from": "graceful-readlink@>= 1.0.0", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" - } - } - }, - "is-my-json-valid": { - "version": "2.12.2", - "from": "is-my-json-valid@^2.12.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.2.tgz", - "dependencies": { - "generate-function": { - "version": "2.0.0", - "from": "generate-function@^2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" - }, - "generate-object-property": { - "version": "1.2.0", - "from": "generate-object-property@^1.1.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "dependencies": { - "is-property": { - "version": "1.0.2", - "from": "is-property@^1.0.0", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" - } - } - }, - "jsonpointer": { - "version": "2.0.0", - "from": "jsonpointer@2.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" - }, - "xtend": { - "version": "4.0.0", - "from": "xtend@^4.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" - } - } - } - } - } - } - }, "abaculus": { "version": "1.1.0", "from": "https://github.com/CartoDB/abaculus/tarball/cdb", diff --git a/package.json b/package.json index 5d36f972..6302368e 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,9 @@ "underscore" : "~1.6.0", "dot": "~1.0.2", "windshaft": "https://github.com/CartoDB/Windshaft/tarball/backend-foundations-mvt", - "step": "~0.0.5", + "step": "~0.0.6", "queue-async": "~1.0.7", - "request": "~2.9.203", + "request": "~2.62.0", "cartodb-redis": "~0.13.0", "cartodb-psql": "~0.4.0", "fastly-purge": "~1.0.0", @@ -43,7 +43,7 @@ "devDependencies": { "istanbul": "~0.3.6", "mocha": "~1.21.4", - "nock": "~1.3.0", + "nock": "~2.11.0", "jshint": "~2.6.0", "redis": "~0.8.6", "strftime": "~0.8.2", diff --git a/test/acceptance/cache/surrogate_keys_invalidation.js b/test/acceptance/cache/surrogate_keys_invalidation.js index d222a0ad..57412633 100644 --- a/test/acceptance/cache/surrogate_keys_invalidation.js +++ b/test/acceptance/cache/surrogate_keys_invalidation.js @@ -158,7 +158,9 @@ describe('templates surrogate keys', function() { status: 200 }, function(res) { - next(null, res); + setTimeout(function() { + next(null, res); + }, 50); } ); }, @@ -229,7 +231,9 @@ describe('templates surrogate keys', function() { status: 204 }, function(res) { - next(null, res); + setTimeout(function() { + next(null, res); + }, 50); } ); }, @@ -256,6 +260,15 @@ describe('templates surrogate keys', function() { .matchHeader('Invalidation-Match', invalidationMatchHeader) .reply(503, ''); + var fastlyScope = nock(FastlyPurge.FASTLY_API_ENDPOINT) + .post(fastlyPurgePath) + .matchHeader('Fastly-Key', FAKE_FASTLY_API_KEY) + .matchHeader('Fastly-Soft-Purge', 1) + .matchHeader('Accept', 'application/json') + .reply(200, { + status:'ok' + }); + step( function createTemplateToUpdate() { createTemplate(this); @@ -280,7 +293,9 @@ describe('templates surrogate keys', function() { status: 200 }, function(res) { - next(null, res); + setTimeout(function() { + next(null, res); + }, 50); } ); }, @@ -292,6 +307,7 @@ describe('templates surrogate keys', function() { assert.deepEqual(parsedBody, expectedBody); assert.equal(scope.pendingMocks().length, 0); + assert.equal(fastlyScope.pendingMocks().length, 0); return null; }, diff --git a/test/acceptance/ported/attributes.js b/test/acceptance/ported/attributes.js index 6c9f9c1c..da6bfcba 100644 --- a/test/acceptance/ported/attributes.js +++ b/test/acceptance/ported/attributes.js @@ -5,11 +5,12 @@ var redis = require('redis'); var step = require('step'); var cartodbServer = require('../../../lib/cartodb/server'); var PortedServerOptions = require('./support/ported_server_options'); +var BaseController = require('../../../lib/cartodb/controllers/base'); + describe('attributes', function() { var server = cartodbServer(PortedServerOptions); - server.req2params = PortedServerOptions.req2params; server.setMaxListeners(0); var redis_client = redis.createClient(PortedServerOptions.redis.port); @@ -38,6 +39,16 @@ describe('attributes', function() { assert.equal(res.headers['access-control-allow-origin'], '*'); } + var req2paramsFn; + before(function() { + req2paramsFn = BaseController.prototype.req2params; + BaseController.prototype.req2params = PortedServerOptions.req2params; + }); + + after(function() { + BaseController.prototype.req2params = req2paramsFn; + }); + it("can only be fetched from layer having an attributes spec", function(done) { var expected_token; diff --git a/test/acceptance/ported/blend.js b/test/acceptance/ported/blend.js index 11f971bb..eca436ae 100644 --- a/test/acceptance/ported/blend.js +++ b/test/acceptance/ported/blend.js @@ -3,8 +3,21 @@ require('../../support/test_helper'); var assert = require('../../support/assert'); var testClient = require('./support/test_client'); +var PortedServerOptions = require('./support/ported_server_options'); +var BaseController = require('../../../lib/cartodb/controllers/base'); + describe('blend png renderer', function() { + var req2paramsFn; + before(function() { + req2paramsFn = BaseController.prototype.req2params; + BaseController.prototype.req2params = PortedServerOptions.req2params; + }); + + after(function() { + BaseController.prototype.req2params = req2paramsFn; + }); + var IMAGE_TOLERANCE_PER_MIL = 20; function plainTorqueMapConfig(plainColor) { diff --git a/test/acceptance/ported/blend_filtering.js b/test/acceptance/ported/blend_filtering.js index 46e35699..c1b11933 100644 --- a/test/acceptance/ported/blend_filtering.js +++ b/test/acceptance/ported/blend_filtering.js @@ -5,13 +5,20 @@ var testClient = require('./support/test_client'); var fs = require('fs'); var http = require('http'); +var PortedServerOptions = require('./support/ported_server_options'); +var BaseController = require('../../../lib/cartodb/controllers/base'); + describe('blend layer filtering', function() { var IMG_TOLERANCE_PER_MIL = 20; var httpRendererResourcesServer; + var req2paramsFn; before(function(done) { + req2paramsFn = BaseController.prototype.req2params; + BaseController.prototype.req2params = PortedServerOptions.req2params; + // Start a server to test external resources httpRendererResourcesServer = http.createServer( function(request, response) { var filename = __dirname + '/../../fixtures/http/light_nolabels-1-0-0.png'; @@ -25,6 +32,7 @@ describe('blend layer filtering', function() { }); after(function(done) { + BaseController.prototype.req2params = req2paramsFn; httpRendererResourcesServer.close(done); }); diff --git a/test/acceptance/ported/blend_http_fallback.js b/test/acceptance/ported/blend_http_fallback.js index 60fd5555..7d0d89c2 100644 --- a/test/acceptance/ported/blend_http_fallback.js +++ b/test/acceptance/ported/blend_http_fallback.js @@ -5,13 +5,19 @@ var testClient = require('./support/test_client'); var fs = require('fs'); var http = require('http'); +var PortedServerOptions = require('./support/ported_server_options'); +var BaseController = require('../../../lib/cartodb/controllers/base'); + describe('blend http fallback', function() { var IMG_TOLERANCE_PER_MIL = 20; var httpRendererResourcesServer; + var req2paramsFn; before(function(done) { + req2paramsFn = BaseController.prototype.req2params; + BaseController.prototype.req2params = PortedServerOptions.req2params; // Start a server to test external resources httpRendererResourcesServer = http.createServer( function(request, response) { if (request.url.match(/^\/error404\//)) { @@ -33,6 +39,7 @@ describe('blend http fallback', function() { }); after(function(done) { + BaseController.prototype.req2params = req2paramsFn; httpRendererResourcesServer.close(done); }); diff --git a/test/acceptance/ported/blend_http_timeout.js b/test/acceptance/ported/blend_http_timeout.js index 53c917e3..341f72b3 100644 --- a/test/acceptance/ported/blend_http_timeout.js +++ b/test/acceptance/ported/blend_http_timeout.js @@ -6,8 +6,21 @@ var serverOptions = require('./support/ported_server_options'); var fs = require('fs'); var http = require('http'); +var PortedServerOptions = require('./support/ported_server_options'); +var BaseController = require('../../../lib/cartodb/controllers/base'); + describe.skip('blend http client timeout', function() { + var req2paramsFn; + before(function() { + req2paramsFn = BaseController.prototype.req2params; + BaseController.prototype.req2params = PortedServerOptions.req2params; + }); + + after(function() { + BaseController.prototype.req2params = req2paramsFn; + }); + var mapConfig = { version: '1.3.0', layers: [ diff --git a/test/acceptance/ported/external_resources.js b/test/acceptance/ported/external_resources.js index 378d7f2d..0b365ef8 100644 --- a/test/acceptance/ported/external_resources.js +++ b/test/acceptance/ported/external_resources.js @@ -7,6 +7,8 @@ var PortedServerOptions = require('./support/ported_server_options'); var http = require('http'); var testClient = require('./support/test_client'); +var BaseController = require('../../../lib/cartodb/controllers/base'); + function rmdir_recursive_sync(dirname) { var files = fs.readdirSync(dirname); for (var i=0; i