From ba0f394a488e6d0f2fea795fe827cb1270db2bd4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 10 Feb 2015 00:03:44 +0100 Subject: [PATCH 01/59] Remove infowindow endpoint --- lib/cartodb/cartodb_windshaft.js | 21 -------- lib/cartodb/server_options.js | 27 ----------- test/acceptance/server.js | 83 -------------------------------- 3 files changed, 131 deletions(-) diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js index a5a01620..be05d495 100644 --- a/lib/cartodb/cartodb_windshaft.js +++ b/lib/cartodb/cartodb_windshaft.js @@ -166,27 +166,6 @@ var CartodbWindshaft = function(serverOptions) { * END Routing ******************************************************************************************************************/ - /** - * Helper to allow access to the layer to be used in the maps infowindow popup. - */ - ws.get(serverOptions.base_url + '/infowindow', function(req, res){ - ws.doCORS(res); - Step( - function(){ - serverOptions.getInfowindow(req, this); - }, - function(err, data){ - if (err){ - ws.sendError(res, {error: err.message}, 500, 'GET INFOWINDOW', err); - //ws.sendResponse(res, [{error: err.message}, 500]); - } else { - ws.sendResponse(res, [{infowindow: data}, 200]); - } - } - ); - }); - - /** * Helper to allow access to metadata to be used in embedded maps. */ diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 59e9fc3f..8b051fc0 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -766,33 +766,6 @@ module.exports = function(redisPool) { ); }; - /** - * Little helper method to get the current list of infowindow variables and return to client - * @param req - * @param callback - */ - me.getInfowindow = function(req, callback){ - var that = this; - var user = me.userByReq(req); - - Step( - function(){ - // TODO: if this step really needed ? - that.req2params(req, this); - }, - function getDatabase(err){ - if (err) throw err; - cartoData.getUserDBName(user, this); - }, - function getInfowindow(err, dbname){ - if (err) throw err; - cartoData.getTableInfowindow(dbname, req.params.table, this); - }, - function(err, data){ - callback(err, data); - } - ); - }; /** * Little helper method to get map metadata and return to client diff --git a/test/acceptance/server.js b/test/acceptance/server.js index a2e2324e..bf3514bb 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -490,89 +490,6 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( }); }); - ///////////////////////////////////////////////////////////////////////////////// - // - // GET INFOWINDOW - // - ///////////////////////////////////////////////////////////////////////////////// - - test("get'ing blank infowindow returns blank", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_tablez/infowindow', - method: 'GET' - },{ - status: 200, - headers: { 'X-Cache-Channel': test_database+':my_tablez' }, - body: '{"infowindow":null}' - }, function() { done(); }); - }); - - test("get'ing blank infowindow with callback returns blank with callback", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_tablez/infowindow?callback=simon', - method: 'GET' - },{ - status: 200, - body: 'simon({"infowindow":null});' - }, function() { done(); }); - }); - - - test("get'ing completed infowindow with callback returns information with callback", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table/infowindow?callback=simon', - method: 'GET' - },{ - status: 200, - body: 'simon({"infowindow":"this, that, the other"});' - }, function() { done(); }); - }); - - test("get'ing infowindow of private table should fail when unauthenticated", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/infowindow', - method: 'GET' - },{}, function(res) { - // FIXME: should be 403 Forbidden - assert.equal(res.statusCode, 500, res.statusCode + ': ' + res.body); - done(); - }); - }); - - // See http://github.com/Vizzuality/Windshaft-cartodb/issues/55 - test("get'ing infowindow of private table should fail on unknown username", - function(done) { - assert.response(server, { - headers: {host: 'unknown_user'}, - url: '/tiles/test_table_private_1/infowindow', - method: 'GET' - },{ - }, function(res) { - // FIXME: should be 403 Forbidden - assert.equal(res.statusCode, 500, res.statusCode + ': ' + res.body); - assert.deepEqual(JSON.parse(res.body), - {error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"}); - done(); - }); - }); - - test("get'ing infowindow of private table should succeed when authenticated", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/infowindow?map_key=1234', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - done(); - }); - }); - ///////////////////////////////////////////////////////////////////////////////// // // GET GRID From a4eade31a2e7d5607384791b373e1ed59395a49e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 10 Feb 2015 00:08:08 +0100 Subject: [PATCH 02/59] Removes map_metadata endpoint --- lib/cartodb/cartodb_windshaft.js | 20 ------------ lib/cartodb/server_options.js | 29 ----------------- test/acceptance/server.js | 54 -------------------------------- 3 files changed, 103 deletions(-) diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js index be05d495..f57248fa 100644 --- a/lib/cartodb/cartodb_windshaft.js +++ b/lib/cartodb/cartodb_windshaft.js @@ -166,26 +166,6 @@ var CartodbWindshaft = function(serverOptions) { * END Routing ******************************************************************************************************************/ - /** - * Helper to allow access to metadata to be used in embedded maps. - */ - ws.get(serverOptions.base_url + '/map_metadata', function(req, res){ - ws.doCORS(res); - Step( - function(){ - serverOptions.getMapMetadata(req, this); - }, - function(err, data){ - if (err){ - ws.sendError(res, {error: err.message}, 500, 'GET MAP_METADATA', err); - //ws.sendResponse(res, [err.message, 500]); - } else { - ws.sendResponse(res, [{map_metadata: data}, 200]); - } - } - ); - }); - /** * Helper API to allow per table tile cache (and sql cache) to be invalidated remotely. * Keep endpoint for backwards compatibility diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 8b051fc0..e6ef0330 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -766,34 +766,5 @@ module.exports = function(redisPool) { ); }; - - /** - * Little helper method to get map metadata and return to client - * @param req - * @param callback - */ - me.getMapMetadata = function(req, callback){ - var that = this; - var user = me.userByReq(req); - - Step( - function(){ - // TODO: if this step really needed ? - that.req2params(req, this); - }, - function getDatabase(err){ - if (err) throw err; - cartoData.getUserDBName(user, this); - }, - function getMapMetadata(err, dbname){ - if (err) throw err; - cartoData.getTableMapMetadata(dbname, req.params.table, this); - }, - function(err, data){ - callback(err, data); - } - ); - }; - return me; }; diff --git a/test/acceptance/server.js b/test/acceptance/server.js index bf3514bb..8378c642 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -1208,60 +1208,6 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( }); }); - ///////////////////////////////////////////////////////////////////////////////// - // - // GET METADATA - // - ///////////////////////////////////////////////////////////////////////////////// - - test("does not provide metadata of private table to unauthenticated requests", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/map_metadata', - method: 'GET' - },{}, function(res) { - // FIXME: should be 403 instead - assert.equal(res.statusCode, 500, res.statusCode + ': ' + res.body); - assert.ok(!res.headers.hasOwnProperty('cache-control')); - done(); - }); - }); - - test("does provide metadata of private table to authenticated requests", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/map_metadata?map_key=1234', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - done(); - }); - }); - - test("does provide metadata of public table to unauthenticated requests", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/map_metadata', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - // TODO: show metadata ? - done(); - }); - }); - - test("does provide metadata of public table to authenticated requests", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/map_metadata?map_key=1234', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - // TODO: show metadata ? - done(); - }); - }); - ///////////////////////////////////////////////////////////////////////////////// // // DELETE CACHE From 636591ecbb7533db9261310840fc26339f233b10 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 10 Feb 2015 00:13:50 +0100 Subject: [PATCH 03/59] Removes flush_cache endpoint --- lib/cartodb/cartodb_windshaft.js | 9 ----- test/acceptance/server.js | 62 -------------------------------- 2 files changed, 71 deletions(-) diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js index f57248fa..063e0572 100644 --- a/lib/cartodb/cartodb_windshaft.js +++ b/lib/cartodb/cartodb_windshaft.js @@ -166,15 +166,6 @@ var CartodbWindshaft = function(serverOptions) { * END Routing ******************************************************************************************************************/ - /** - * Helper API to allow per table tile cache (and sql cache) to be invalidated remotely. - * Keep endpoint for backwards compatibility - */ - ws.del(serverOptions.base_url + '/flush_cache', function(req, res){ - ws.doCORS(res); - ws.sendResponse(res, [{status: 'ok'}, 200]); - }); - var healthCheck = new HealthCheck(cartoData, Windshaft.tilelive); ws.get('/health', function(req, res) { var healthConfig = global.environment.health || {}; diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 8378c642..e02991a2 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -1177,68 +1177,6 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( }); }); - ///////////////////////////////////////////////////////////////////////////////// - // - // DELETE CACHE - // - ///////////////////////////////////////////////////////////////////////////////// - - test("forbids flushing cache without specifying table name", function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/flush_cache', - method: 'DELETE' - },{}, function(res) { - assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body); - assert.ok(!res.headers.hasOwnProperty('cache-control')); - done(); - }); - }); - - test("allows flushing table cache by unauthenticated user", function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/flush_cache', - method: 'DELETE' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - // TODO: also check that varnish is signalled (using VarnishEmu) - // NOTE: requires enable_cache=1 in test.js - done(); - }); - }); - - ///////////////////////////////////////////////////////////////////////////////// - // - // DELETE CACHE - // - ///////////////////////////////////////////////////////////////////////////////// - - test("forbids flushing cache without specifying table name", function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/flush_cache', - method: 'DELETE' - },{}, function(res) { - assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body); - assert.ok(!res.headers.hasOwnProperty('cache-control')); - done(); - }); - }); - - test("allows flushing table cache by unauthenticated user", function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/flush_cache', - method: 'DELETE' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - // TODO: also check that varnish is signalled (using VarnishEmu) - // NOTE: requires enable_cache=1 in test.js - done(); - }); - }); - ///////////////////////////////////////////////////////////////////////////////// // // Tear down From 59dfd11e5b01edfed528a43034e9ef72a7c4951f Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 10 Feb 2015 16:57:43 +0100 Subject: [PATCH 04/59] Remove geom_type retrieval --- lib/cartodb/server_options.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index e6ef0330..5620a9ae 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -740,18 +740,9 @@ module.exports = function(redisPool) { if(err) throw err; that.setDBConn(user, req.params, this); }, - function getGeometryType(err){ - if (req.profiler) req.profiler.done('setDBConn'); - if (err) throw err; - if ( ! req.params.table ) return null; - cartoData.getTableGeometryType(req.params.dbname, req.params.table, this); - }, - function finishSetup(err, data){ + function finishSetup(err) { if ( err ) { callback(err, req); return; } - if (!_.isNull(data)) - _.extend(req.params, {geom_type: data}); - // Add default database connection parameters // if none given _.defaults(req.params, { From a0243e0bf75df681c2166f51569afdf729148015 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 11 Feb 2015 18:43:47 +0100 Subject: [PATCH 05/59] Rely on windshaft's remove old api branch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b9d0efda..660646b4 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "node-varnish": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0", "underscore" : "~1.6.0", "dot": "~1.0.2", - "windshaft": "https://github.com/CartoDB/Windshaft/tarball/0.35.1", + "windshaft": "https://github.com/CartoDB/Windshaft/tarball/259-remove-old-api", "step": "~0.0.5", "request": "~2.9.203", "cartodb-redis": "https://github.com/CartoDB/node-cartodb-redis/tarball/0.11.0", From 597cb5286dfb183ade6c61d997962dec83e9ea0a Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 11 Feb 2015 18:44:09 +0100 Subject: [PATCH 06/59] No more before/after state change actions as there is no longer a style change --- lib/cartodb/cartodb_windshaft.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js index 063e0572..b0040668 100644 --- a/lib/cartodb/cartodb_windshaft.js +++ b/lib/cartodb/cartodb_windshaft.js @@ -25,23 +25,6 @@ var CartodbWindshaft = function(serverOptions) { var cartoData = require('cartodb-redis')({pool: redisPool}); - if(serverOptions.cache_enabled) { - console.log("cache invalidation enabled, varnish on ", serverOptions.varnish_host, ' ', serverOptions.varnish_port); - Cache.init(serverOptions.varnish_host, serverOptions.varnish_port, serverOptions.varnish_secret); - serverOptions.afterStateChange = function(req, data, callback) { - Cache.invalidate_db(req.params.dbname, req.params.table); - callback(null, data); - } - } - - serverOptions.beforeStateChange = function(req, callback) { - var err = null; - if ( ! req.params.hasOwnProperty('_authorizedByApiKey') ) { - err = new Error("map state cannot be changed by unauthenticated request!"); - } - callback(err, req); - }; - // This is for Templated maps // // "named" is the official, "template" is for backward compatibility up to 1.6.x From a2a09979e4f1f68eb89e3f4b553f80b2502949f7 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 11 Feb 2015 18:47:11 +0100 Subject: [PATCH 07/59] Remove dump render cache stats --- app.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app.js b/app.js index 61d3dfad..740d91c4 100755 --- a/app.js +++ b/app.js @@ -105,16 +105,6 @@ ws.on('listening', function() { + " (" + ENV + ")"); }); -// DEPRECATED, use SIGUSR2 -process.on('SIGUSR1', function() { - console.log('WARNING: handling of SIGUSR1 by Windshaft-CartoDB is deprecated, please send SIGUSR2 instead'); - ws.dumpCacheStats(); -}); - -process.on('SIGUSR2', function() { - ws.dumpCacheStats(); -}); - process.on('SIGHUP', function() { global.log4js.clearAndShutdownAppenders(function() { global.log4js.configure(log4js_config); From 032188479526530685e8fc18b31b5ddc786c579c Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 12:29:20 +0100 Subject: [PATCH 08/59] Re-generate npm-shrinkwrap.json to use windshaft/master. A lot of tests from acceptance/server.js will fail --- npm-shrinkwrap.json | 151 ++++++++++++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 48 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4f437dd6..a96a981c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -14,11 +14,13 @@ "dependencies": { "generic-pool": { "version": "2.0.3", - "from": "generic-pool@2.0.3" + "from": "generic-pool@2.0.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz" }, "buffer-writer": { "version": "1.0.0", - "from": "buffer-writer@1.0.0" + "from": "buffer-writer@1.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz" } } } @@ -36,19 +38,23 @@ "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@~2.1.1" + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "redis": { "version": "0.12.1", - "from": "redis@~0.12.1" + "from": "redis@~0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" }, "hiredis": { "version": "0.1.17", "from": "hiredis@~0.1.17", + "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@*" + "from": "bindings@*", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.1.2", @@ -83,7 +89,8 @@ "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", @@ -92,11 +99,13 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2" + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -124,19 +133,23 @@ "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@~2.1.1" + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "redis": { "version": "0.12.1", - "from": "redis@~0.12.1" + "from": "redis@~0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" }, "hiredis": { "version": "0.1.17", "from": "hiredis@~0.1.17", + "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@*" + "from": "bindings@*", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.1.2", @@ -164,17 +177,20 @@ }, "lru-cache": { "version": "2.2.4", - "from": "lru-cache@~2.2.1" + "from": "lru-cache@~2.2.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@~5.0.0" + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" } } }, "step": { "version": "0.0.5", - "from": "step@~0.0.5" + "from": "step@~0.0.5", + "resolved": "https://registry.npmjs.org/step/-/step-0.0.5.tgz" }, "underscore": { "version": "1.6.0", @@ -182,8 +198,9 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" }, "windshaft": { - "version": "0.40.0", - "from": "windshaft@~0.40.0", + "version": "0.41.0", + "from": "https://github.com/CartoDB/Windshaft/tarball/master", + "resolved": "https://github.com/CartoDB/Windshaft/tarball/master", "dependencies": { "chronograph": { "version": "0.1.0", @@ -193,6 +210,7 @@ "grainstore": { "version": "0.23.0", "from": "grainstore@~0.23.0", + "resolved": "https://registry.npmjs.org/grainstore/-/grainstore-0.23.0.tgz", "dependencies": { "redis-mpool": { "version": "0.1.0", @@ -201,19 +219,23 @@ "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@~2.1.1" + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "redis": { "version": "0.12.1", - "from": "redis@~0.12.1" + "from": "redis@~0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" }, "hiredis": { "version": "0.1.17", "from": "hiredis@~0.1.17", + "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@*" + "from": "bindings@*", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.1.2", @@ -246,7 +268,8 @@ "dependencies": { "sax": { "version": "0.5.8", - "from": "sax@0.5.x" + "from": "sax@0.5.x", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz" } } }, @@ -262,7 +285,8 @@ }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1" + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } } @@ -275,7 +299,8 @@ "dependencies": { "generic-pool": { "version": "2.0.4", - "from": "generic-pool@~2.0.3" + "from": "generic-pool@~2.0.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.4.tgz" }, "request": { "version": "2.34.0", @@ -284,15 +309,18 @@ "dependencies": { "qs": { "version": "0.6.6", - "from": "qs@~0.6.0" + "from": "qs@~0.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@~5.0.0" + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@~0.5.0" + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "node-uuid": { "version": "1.4.3", @@ -302,6 +330,7 @@ "tough-cookie": { "version": "0.12.1", "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", @@ -313,6 +342,7 @@ "form-data": { "version": "0.1.4", "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", @@ -335,7 +365,8 @@ }, "tunnel-agent": { "version": "0.3.0", - "from": "tunnel-agent@~0.3.0" + "from": "tunnel-agent@~0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" }, "http-signature": { "version": "0.10.1", @@ -361,7 +392,8 @@ }, "oauth-sign": { "version": "0.3.0", - "from": "oauth-sign@~0.3.0" + "from": "oauth-sign@~0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" }, "hawk": { "version": "1.0.0", @@ -380,17 +412,20 @@ }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@0.2.x" + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "sntp@0.2.x" + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "aws-sign2@~0.5.0" + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" } } }, @@ -1631,7 +1666,8 @@ }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@~0.3.3" + "from": "mkdirp@~0.3.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" }, "optimist": { "version": "0.6.1", @@ -1645,7 +1681,8 @@ }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1" + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } } @@ -1704,7 +1741,8 @@ }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1" + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } } @@ -1717,7 +1755,8 @@ "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@~2.1.1" + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "mime": { "version": "1.2.11", @@ -1733,7 +1772,8 @@ "dependencies": { "nan": { "version": "1.2.0", - "from": "nan@~1.2.0" + "from": "nan@~1.2.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.2.0.tgz" }, "mapnik-vector-tile": { "version": "0.5.5", @@ -2144,7 +2184,8 @@ }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1" + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } } @@ -2152,11 +2193,13 @@ }, "step-profiler": { "version": "0.2.1", - "from": "step-profiler@~0.2.1" + "from": "step-profiler@~0.2.1", + "resolved": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.2.1.tgz" }, "torque.js": { "version": "2.11.0", - "from": "torque.js@~2.11.0" + "from": "torque.js@~2.11.0", + "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-2.11.0.tgz" }, "request": { "version": "2.48.0", @@ -2175,7 +2218,8 @@ "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", @@ -2184,11 +2228,13 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -2201,11 +2247,13 @@ }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@~0.5.0" + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "form-data": { "version": "0.1.4", "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "mime": { "version": "1.2.11", @@ -2221,7 +2269,8 @@ }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@~5.0.0" + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "mime-types": { "version": "1.0.2", @@ -2240,11 +2289,13 @@ }, "tunnel-agent": { "version": "0.4.0", - "from": "tunnel-agent@~0.4.0" + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" }, "tough-cookie": { "version": "0.12.1", "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", @@ -2297,21 +2348,25 @@ }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@0.2.x" + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "sntp@0.2.x" + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "aws-sign2@~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" + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" }, "combined-stream": { "version": "0.0.7", From 25e4e3bd337cc6027f798a109e91abb47ff7db22 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 12:40:24 +0100 Subject: [PATCH 09/59] jshint --- test/acceptance/server.js | 171 ++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 83 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index e31333c9..075684e8 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -1,11 +1,9 @@ var assert = require('../support/assert'); -var tests = module.exports = {}; var _ = require('underscore'); var redis = require('redis'); var querystring = require('querystring'); var semver = require('semver'); -var Step = require('step'); -var http = require('http'); +var step = require('step'); var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js'); var helper = require(__dirname + '/../support/test_helper'); @@ -30,15 +28,27 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { var default_style; if ( semver.satisfies(mapnik_version, '<2.1.0') ) { // 2.0.0 default - default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}'; + default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;marker-line-color: white;' + + 'marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ' + + 'ellipse;marker-allow-overlap: true;}'; } else if ( semver.satisfies(mapnik_version, '<2.2.0') ) { // 2.1.0 default - default_style = '#<%= table %>[mapnik-geometry-type=1] {marker-fill: #FF6600;marker-opacity: 1;marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}#<%= table %>[mapnik-geometry-type=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}#<%= table %>[mapnik-geometry-type=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1; line-color: #FFFFFF;}'; + default_style = '#<%= table %>[mapnik-geometry-type=1] {marker-fill: #FF6600;marker-opacity: 1;' + + 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + + 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + + '#<%= table %>[mapnik-geometry-type=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + + '#<%= table %>[mapnik-geometry-type=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + + ' line-color: #FFFFFF;}'; } else { // 2.2.0+ default - default_style = '#<%= table %>["mapnik::geometry_type"=1] {marker-fill: #FF6600;marker-opacity: 1;marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}#<%= table %>["mapnik::geometry_type"=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}#<%= table %>["mapnik::geometry_type"=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1; line-color: #FFFFFF;}'; + default_style = '#<%= table %>["mapnik::geometry_type"=1] {marker-fill: #FF6600;marker-opacity: 1;' + + 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + + 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + + '#<%= table %>["mapnik::geometry_type"=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + + '#<%= table %>["mapnik::geometry_type"=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + + ' line-color: #FFFFFF;}'; } // A couple of styles to use during testing @@ -58,7 +68,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { // TODO: I guess this should be a 404 instead... test("get call to server returns 200", function(done){ - Step( + step( function doGet() { var next = this; assert.response(server, { @@ -121,7 +131,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { method: 'GET' },{ status: 200, - headers: { 'X-Cache-Channel': test_database+':my_table' }, + headers: { 'X-Cache-Channel': test_database+':my_table' } }, function(res) { var parsed = JSON.parse(res.body); assert.equal(parsed.style, _.template(default_style, {table: 'my_table'})); @@ -186,7 +196,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { test("get'ing unrenderable style", function(done) { var base_key = 'map_style|'+test_database+'|issue94'; var style = '#s{bogus}'; - Step( + step( function checkRedis() { redis_client.keys(base_key+'*', this); }, @@ -212,7 +222,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var parsed = JSON.parse(res.body); assert.equal(parsed.style, style); - return null + return null; }, function finish(err) { done(err); @@ -260,7 +270,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { data: querystring.stringify({style: '#my_table3{'}) },{}, function(res) { assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); - assert.ok( RegExp(/missing closing/i).test(res.body) ); + assert.ok( new RegExp(/missing closing/i).test(res.body) ); done(); }); }); @@ -272,12 +282,12 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, data: querystring.stringify({style: '#my_table4{backgxxxxxround-color:#fff;foo:bar}'}) },{ - status: 400, + status: 400 }, function(res) { var parsed = JSON.parse(res.body); assert.equal(parsed.length, 2); - assert.ok( RegExp(/Unrecognized rule: backgxxxxxround-color/).test(parsed[0]) ); - assert.ok( RegExp(/Unrecognized rule: foo/).test(parsed[1]) ); + assert.ok( new RegExp(/Unrecognized rule: backgxxxxxround-color/).test(parsed[0]) ); + assert.ok( new RegExp(/Unrecognized rule: foo/).test(parsed[1]) ); done(); }); }); @@ -333,7 +343,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { url: '/tiles/my_table5/style', method: 'GET' },{ - status: 200, + status: 200 }, function(res) { var parsed = JSON.parse(res.body); assert.equal(parsed.style, 'Map { background-color:#fff; }'); @@ -420,7 +430,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.response(server, { url: '/tiles/my_table5/style', method: 'DELETE', - headers: {host: 'localhost'}, + headers: {host: 'localhost'} },{}, function(res) { // FIXME: should be 403 Forbidden assert.equal(res.statusCode, 400, res.body); @@ -431,7 +441,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { url: '/tiles/my_table5/style?map_key=1234', method: 'GET' },{ - status: 200, + status: 200 }, function(res) { var parsed = JSON.parse(res.body); assert.equal(parsed.style, 'Map { background-color:#fff; }'); @@ -447,7 +457,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.response(server, { url: '/tiles/my_table5/style?map_key=1234', method: 'DELETE', - headers: {host: 'localhost'}, + headers: {host: 'localhost'} },{}, function(res) { assert.equal(res.statusCode, 200, res.body); @@ -481,7 +491,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.response(server, { url: '/tiles/my_table5/style?api_key=1234', method: 'DELETE', - headers: {host: 'localhost'}, + headers: {host: 'localhost'} },{}, function(res) { assert.equal(res.statusCode, 200, res.body); done(); @@ -518,7 +528,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { }); test("get'ing a json with default style and sql should return a constrained grid", function(done){ - var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08'"}) + var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08'"}); assert.response(server, { headers: {host: 'localhost'}, url: '/tiles/gadm4/6/31/24.grid.json?' + sql, @@ -601,7 +611,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { url: '/tiles/gadm4/6/31/24.png', method: 'GET' },{ - status: 200, + status: 200 }, function(res) { var cc = res.headers['cache-control']; assert.ok(cc); @@ -619,7 +629,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { url: '/tiles/gadm4/6/31/24.png?cache_policy=persist', method: 'GET' },{ - status: 200, + status: 200 }, function(res) { var cc = res.headers['cache-control']; assert.ok(cc); @@ -653,7 +663,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { test("get'ing a tile with default style and complex sql should return a constrained image", function(done){ - var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08' AND codccaa > 60"}) + var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08' AND codccaa > 60"}); assert.response(server, { headers: {host: 'localhost'}, url: '/tiles/gadm4/6/31/24.png?' + sql, @@ -666,7 +676,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { test("get'ing a tile with data from private table should succeed when authenticated", function(done){ // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft - var sql = querystring.stringify({sql: "SELECT * FROM test_table_private_1", map_key: 1234}) + var sql = querystring.stringify({sql: "SELECT * FROM test_table_private_1", map_key: 1234}); assert.response(server, { headers: {host: 'localhost'}, // NOTE: we encode a public table in the URL ! @@ -681,7 +691,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { // See https://github.com/Vizzuality/Windshaft-cartodb/issues/38 test("get'ing a tile with data from private table should succeed when authenticated with api_key", function(done){ // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft - var sql = querystring.stringify({sql: "SELECT * FROM test_table_private_1", api_key: 1234}) + var sql = querystring.stringify({sql: "SELECT * FROM test_table_private_1", api_key: 1234}); assert.response(server, { headers: {host: 'localhost'}, url: '/tiles/gadm4/6/31/24.png?' + sql, @@ -730,7 +740,8 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { }); }); - test("get'ing a tile with data from private table should fail when unauthenticated (uses old redis key)", function(done){ + test("get'ing a tile with data from private table should fail when unauthenticated (uses old redis key)", + function(done) { var sql = querystring.stringify({ sql: "SELECT * FROM test_table_private_1", cache_buster:3, @@ -764,11 +775,11 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { - if (err) throw err; - done(); - }); + assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', + IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + if (err) throw err; + done(); + }); }); }); @@ -777,7 +788,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { var style = querystring.stringify({style: test_style_black_200, style_version: '2.0.0'}); var backupDBHost = global.environment.postgres.host; global.environment.postgres.host = '6.6.6.6'; - Step ( + step ( function() { var next = this; assert.response(server, { @@ -797,9 +808,9 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, this); }, - function checkImage(err, similarity) { + function checkImage(err/*, similarity*/) { if (err) throw err; - return null + return null; }, function finish(err) { global.environment.postgres.host = backupDBHost; @@ -813,13 +824,12 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { var style = querystring.stringify({style: test_style_black_200, style_version: '2.0.0'}); var backupDBPass = global.environment.postgres_auth_pass; global.environment.postgres_auth_pass = '<%= user_password %>'; - Step ( + step ( function() { var next = this; assert.response(server, { headers: {host: 'cartodb250user'}, - url: '/tiles/test_table/15/16046/12354.png?' - + 'cache_buster=4.20&api_key=4321&' + style, + url: '/tiles/test_table/15/16046/12354.png?' + 'cache_buster=4.20&api_key=4321&' + style, method: 'GET', encoding: 'binary' },{}, function(res){ @@ -834,9 +844,9 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, this); }, - function checkImage(err, similarity) { + function checkImage(err/*, similarity*/) { if (err) throw err; - return null + return null; }, function finish(err) { global.environment.postgres_auth_pass = backupDBPass; @@ -856,11 +866,11 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { - if (err) throw err; - done(); - }); + assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', + IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + if (err) throw err; + done(); + }); }); }); @@ -870,10 +880,9 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { style_version: '2.1.0', cache_buster: 5 }; - Step ( + step ( function compressQuery () { //console.log("Compressing starts"); - var next = this; helper.lzma_compress_to_base64(JSON.stringify(qo), 1, this); }, function sendRequest(err, lzma) { @@ -893,10 +902,10 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { - next(err); - }); + assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', + IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + next(err); + }); }, function finish(err) { done(err); @@ -906,8 +915,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { // See http://github.com/Vizzuality/Windshaft-cartodb/issues/57 test("GET'ing a tile as anonymous with style set by POST", function(done){ - var style = querystring.stringify({style: test_style_black_210, style_version: '2.1.0'}); - Step ( + step ( function postStyle1() { var next = this; assert.response(server, { @@ -934,7 +942,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); assert.imageEqualsFile(res.body, './test/fixtures/blank.png', IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL, - function(err, similarity) { + function(err/*, similarity*/) { if (err) next(err); else next(); }); @@ -954,7 +962,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); assert.imageEqualsFile(res.body, './test/fixtures/blank.png', IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL, - function(err, similarity) { + function(err/*, similarity*/) { if (err) next(err); else next(); }); @@ -990,12 +998,12 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { - // NOTE: we expect them to be EQUAL here - if (err) { next(err); return; } - next(); - }); + assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', + IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + // NOTE: we expect them to be EQUAL here + if (err) { next(err); return; } + next(); + }); }); }, // Delete the style @@ -1027,12 +1035,13 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var ct = res.headers['content-type']; assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { - // NOTE: we expect them to be different here - if (err) next(); - else next(new Error('Last posted style still in effect after delete')); - }); + assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', + IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + // NOTE: we expect them to be different here + if (err) next(); + else next(new Error('Last posted style still in effect after delete')); + } + ); }); }, function finish(err) { @@ -1043,14 +1052,13 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { test("uses sqlapi to figure source data of query", function(done){ var qo = { - sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator " - + "FROM gadm4 g, test_table t " - + "WHERE g.cartodb_id = t.cartodb_id", + sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator" + + " FROM gadm4 g, test_table t" + + " WHERE g.cartodb_id = t.cartodb_id", map_key: 1234 }; - var sqlapi; - Step( - function sendRequest(err) { + step( + function sendRequest() { var next = this; assert.response(server, { headers: {host: 'localhost'}, @@ -1087,9 +1095,8 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { sql: "SELECT * from gadm4", map_key: 1234 }; - var sqlapi; - Step( - function sendRequest(err) { + step( + function sendRequest() { var next = this; assert.response(server, { headers: {host: 'localhost'}, @@ -1102,7 +1109,7 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var last_request = sqlapi_server.getLastRequest(); assert.ok(last_request); - var host = last_request.headers['host']; + var host = last_request.headers.host; assert.ok(host); assert.equal(last_request.method, 'GET'); assert.equal(host, 'localhost.donot_look_this_up'); @@ -1118,15 +1125,13 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API test("requests to skip cache on sqlapi error", function(done){ var qo = { - sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator " - + ", 'SQLAPIERROR' is not null " - + "FROM gadm4 g, test_table t " - + "WHERE g.cartodb_id = t.cartodb_id", + sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator, 'SQLAPIERROR' is not null" + + " FROM gadm4 g, test_table t" + + " WHERE g.cartodb_id = t.cartodb_id", map_key: 1234 }; - var sqlapi; - Step( - function sendRequest(err) { + step( + function sendRequest() { var next = this; assert.response(server, { headers: {host: 'localhost'}, From 6d32199c53652c6855aa67e44024b7fba75e7625 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 12:42:39 +0100 Subject: [PATCH 10/59] Remove get style tests --- test/acceptance/server.js | 114 +------------------------------------- 1 file changed, 1 insertion(+), 113 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 075684e8..114d8509 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -16,7 +16,7 @@ var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) { +[true].forEach(function(cdbQueryTablesFromPostgresEnabledValue) { suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { @@ -118,118 +118,6 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { }); }); - ///////////////////////////////////////////////////////////////////////////////// - // - // GET STYLE - // - ///////////////////////////////////////////////////////////////////////////////// - - test("get'ing blank style returns default style", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table/style', - method: 'GET' - },{ - status: 200, - headers: { 'X-Cache-Channel': test_database+':my_table' } - }, function(res) { - var parsed = JSON.parse(res.body); - assert.equal(parsed.style, _.template(default_style, {table: 'my_table'})); - assert.equal(parsed.style_version, mapnik_version); - done(); - }); - }); - - // See https://github.com/Vizzuality/Windshaft-cartodb/issues/43 - test("get'ing style of private table should fail when unauthenticated", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/style', - method: 'GET' - },{ - }, function(res) { - assert.equal(res.statusCode, 403, res.statusCode + ':' + res.body); - assert.deepEqual(JSON.parse(res.body), - {error: 'Sorry, you are unauthorized (permission denied)'}); - assert.ok(!res.headers.hasOwnProperty('cache-control')); - done(); - }); - }); - - // See http://github.com/Vizzuality/Windshaft-cartodb/issues/55 - test("get'ing style of private table should fail on unknown username", - function(done) { - assert.response(server, { - headers: {host: 'unknown_user'}, - url: '/tiles/test_table_private_1/style', - method: 'GET' - },{ - }, function(res) { - // FIXME: should be 403 Forbidden or 404 User Not Found - assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); - assert.deepEqual(JSON.parse(res.body), - {error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"}); - assert.ok(!res.headers.hasOwnProperty('cache-control')); - done(); - }); - }); - - test("get'ing style of private table should succeed when authenticated", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/style?map_key=1234', - method: 'GET' - },{ - }, function(res) { - assert.equal(res.statusCode, 200, res.body); - var parsed = JSON.parse(res.body); - var style = _.template(default_style, {table: 'test_table_private_1'}); - assert.equal(parsed.style, style); - assert.equal(parsed.style_version, mapnik_version); - done(); - }); - }); - - // See https://github.com/CartoDB/Windshaft-cartodb/issues/94 - test("get'ing unrenderable style", function(done) { - var base_key = 'map_style|'+test_database+'|issue94'; - var style = '#s{bogus}'; - step( - function checkRedis() { - redis_client.keys(base_key+'*', this); - }, - function setupRedisBase(err, matches) { - if ( err ) throw err; - assert.equal(matches.length, 0, - 'Unexpected redis keys at test start: ' + matches.join("\n")); - redis_client.set(base_key, - JSON.stringify({ style: style }), - this); - }, - function getStyle(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/issue94/style', - method: 'GET' - }, {}, function(res) { next(null, res); }); - }, - function checkStyle(err, res) { - if ( err ) throw err; - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var parsed = JSON.parse(res.body); - assert.equal(parsed.style, style); - return null; - }, - function finish(err) { - done(err); - } - ); - }); - ///////////////////////////////////////////////////////////////////////////////// // // POST STYLE From 0e3f72ce0bb9ee92c178483d50a19426b42ca66d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 14:21:08 +0100 Subject: [PATCH 11/59] PHONY coverage --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e8177443..11899d75 100644 --- a/Makefile +++ b/Makefile @@ -38,4 +38,4 @@ coverage: check: test -.PHONY: pre-install test +.PHONY: pre-install test jshint coverage From 02bc7b9fbf34b93e0ed27aac0edf762938fe3fd1 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 14:27:41 +0100 Subject: [PATCH 12/59] Remove per-table varnish invalidation --- lib/cartodb/cache_validator.js | 25 ------------------------- package.json | 1 - test/acceptance/cache_validator.js | 21 --------------------- 3 files changed, 47 deletions(-) delete mode 100644 lib/cartodb/cache_validator.js delete mode 100644 test/acceptance/cache_validator.js diff --git a/lib/cartodb/cache_validator.js b/lib/cartodb/cache_validator.js deleted file mode 100644 index 4b3f2181..00000000 --- a/lib/cartodb/cache_validator.js +++ /dev/null @@ -1,25 +0,0 @@ -var Varnish = require('node-varnish'); -var varnish_queue = null; - -function init(host, port, secret) { - varnish_queue = new Varnish.VarnishQueue(host, port, secret); - varnish_queue.on('error', function(e) { - console.log("[CACHE VALIDATOR ERROR] " + e); - }); -} - -function invalidate_db(dbname, table) { - var cmd = 'purge obj.http.X-Cache-Channel ~ "^' + dbname + - ':(.*'+ table +'.*)|(table)$"'; - try{ - varnish_queue.run_cmd(cmd, false); - } catch (e) { - console.log("[CACHE VALIDATOR ERROR] could not queue command " + - cmd + " -- " + e); - } -} - -module.exports = { - init: init, - invalidate_db: invalidate_db -}; diff --git a/package.json b/package.json index 64618960..23cf68e2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "Sandro Santilli " ], "dependencies": { - "node-varnish": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0", "underscore" : "~1.6.0", "dot": "~1.0.2", "windshaft": "https://github.com/CartoDB/Windshaft/tarball/master", diff --git a/test/acceptance/cache_validator.js b/test/acceptance/cache_validator.js deleted file mode 100644 index 79939740..00000000 --- a/test/acceptance/cache_validator.js +++ /dev/null @@ -1,21 +0,0 @@ -var assert = require('../support/assert'); -require(__dirname + '/../support/test_helper'); -var CacheValidator = require(__dirname + '/../../lib/cartodb/cache_validator'); - -var VarnishEmu = require('../support/VarnishEmu'); - -suite('cache_validator', function() { - - test('should call purge on varnish when invalidate database', function(done) { - var varnish = new VarnishEmu(function(cmds) { - assert.ok(cmds.length == 1); - assert.equal('purge obj.http.X-Cache-Channel ~ \"^test_db:(.*test_cache.*)|(table)$\"\n', cmds[0].toString('utf8')); - done(); - }, - function() { - CacheValidator.init('localhost', 1337); - CacheValidator.invalidate_db('test_db', 'test_cache'); - }); - }); - -}); From 07297f6bda1e0443910b0b599bd5e0574661002a Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 14:44:42 +0100 Subject: [PATCH 13/59] Remove cdbQueryTablesFromPostgres option, now uses it by default --- lib/cartodb/api/query_tables_api.js | 82 ++++++++++------------------- test/acceptance/multilayer.js | 7 ++- test/acceptance/named_layers.js | 2 - test/acceptance/server.js | 7 +-- test/acceptance/templates.js | 7 +-- 5 files changed, 33 insertions(+), 72 deletions(-) diff --git a/lib/cartodb/api/query_tables_api.js b/lib/cartodb/api/query_tables_api.js index 1db18489..63b87158 100644 --- a/lib/cartodb/api/query_tables_api.js +++ b/lib/cartodb/api/query_tables_api.js @@ -1,4 +1,3 @@ -var sqlApi = require('../sql/sql_api'); var PSQL = require('cartodb-psql'); var step = require('step'); @@ -74,56 +73,36 @@ function handleAffectedTablesAndLastUpdatedTimeRows(err, rows, callback) { QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) { var self = this; - if (shouldQueryPostgresDirectly()) { + var params = {}; - var params = {}; - - step( - function setAuth() { - self.pgConnection.setDBAuth(username, params, this); - }, - function setConn(err) { - if (err) { - throw err; - } - self.pgConnection.setDBConn(username, params, this); - }, - function executeQuery(err) { - if (err) { - throw err; - } - var psql = new PSQL({ - user: params.dbuser, - pass: params.dbpass, - host: params.dbhost, - port: params.dbport, - dbname: params.dbname - }); - psql.query(query, function(err, resultSet) { - resultSet = resultSet || {}; - var rows = resultSet.rows || []; - queryHandler(err, rows, callback); - }); + step( + function setAuth() { + self.pgConnection.setDBAuth(username, params, this); + }, + function setConn(err) { + if (err) { + throw err; } - ); - - } else { - - step( - function getApiKey() { - self.metadataBackend.getUserMapKey(username, this); - }, - function executeQuery(err, apiKey) { - if (err) { - throw err; - } - sqlApi.query(username, apiKey, query, function(err, rows) { - queryHandler(err, rows, callback); - }); + self.pgConnection.setDBConn(username, params, this); + }, + function executeQuery(err) { + if (err) { + throw err; } - ); - - } + var psql = new PSQL({ + user: params.dbuser, + pass: params.dbpass, + host: params.dbhost, + port: params.dbport, + dbname: params.dbname + }); + psql.query(query, function(err, resultSet) { + resultSet = resultSet || {}; + var rows = resultSet.rows || []; + queryHandler(err, rows, callback); + }); + } + ); }; @@ -135,10 +114,3 @@ function prepareSql(sql) { .replace(affectedTableRegexCache.pixel_height, '1') ; } - - -function shouldQueryPostgresDirectly() { - return global.environment && - global.environment.enabledFeatures && - global.environment.enabledFeatures.cdbQueryTablesFromPostgres; -} diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index 3af4d95a..d9382d9c 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -23,11 +23,12 @@ var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); ['/tiles/layergroup', '/u/localhost/tiles/layergroup'].forEach(function(layergroup_url) { -[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) { -var suiteName = 'multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue + ";layergroup_url=" + layergroup_url; +var suiteName = 'multilayer:postgres=layergroup_url=' + layergroup_url; suite(suiteName, function() { + var cdbQueryTablesFromPostgresEnabledValue = true + var redis_client = redis.createClient(global.environment.redis.port); var sqlapi_server; var expected_last_updated_epoch = 1234567890123; // this is hard-coded into SQLAPIEmu @@ -38,7 +39,6 @@ suite(suiteName, function() { var test_database = test_user + '_db'; suiteSetup(function(done){ - global.environment.enabledFeatures = { cdbQueryTablesFromPostgres: cdbQueryTablesFromPostgresEnabledValue }; sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); }); @@ -1444,4 +1444,3 @@ suite(suiteName, function() { }); }); -}); diff --git a/test/acceptance/named_layers.js b/test/acceptance/named_layers.js index 3b52f982..992d1981 100644 --- a/test/acceptance/named_layers.js +++ b/test/acceptance/named_layers.js @@ -96,7 +96,6 @@ suite('named_layers', function() { }; suiteSetup(function(done) { - global.environment.enabledFeatures = {cdbQueryTablesFromPostgres: true}; templateMaps.addTemplate(username, nestedNamedMapTemplate, function(err) { if (err) { return done(err); @@ -637,7 +636,6 @@ suite('named_layers', function() { suiteTeardown(function(done) { - global.environment.enabledFeatures = {cdbQueryTablesFromPostgres: false}; templateMaps.delTemplate(username, nestedNamedMapTemplateName, function(err) { if (err) { return done(err); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 114d8509..6702a603 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -16,9 +16,9 @@ var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -[true].forEach(function(cdbQueryTablesFromPostgresEnabledValue) { +var cdbQueryTablesFromPostgresEnabledValue = true; -suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { +suite('server', function() { var redis_client = redis.createClient(global.environment.redis.port); var sqlapi_server; @@ -56,7 +56,6 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; suiteSetup(function(done){ - global.environment.enabledFeatures = { cdbQueryTablesFromPostgres: cdbQueryTablesFromPostgresEnabledValue }; sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); }); @@ -1090,5 +1089,3 @@ suite('server:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { }); }); - -}); diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index f0df7414..7d6b301a 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -25,9 +25,7 @@ var serverOptions = ServerOptions(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) { - -suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { +suite('template_api', function() { serverOptions.channelCache = {}; var redis_client = redis.createClient(global.environment.redis.port); @@ -36,7 +34,6 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio var expected_last_updated = new Date(expected_last_updated_epoch).toISOString(); suiteSetup(function(done){ - global.environment.enabledFeatures = { cdbQueryTablesFromPostgres: cdbQueryTablesFromPostgresEnabledValue }; sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); // TODO: check redis is clean ? }); @@ -2121,5 +2118,3 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio }); }); - -}); From 23f5be6c338510a4fc18744abfeb53b369a2360e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 15:00:33 +0100 Subject: [PATCH 14/59] Remove config and sql api backend --- config/environments/development.js.example | 20 ------- config/environments/production.js.example | 20 ------- config/environments/staging.js.example | 20 ------- config/environments/test.js.example | 22 -------- lib/cartodb/server_options.js | 9 --- lib/cartodb/sql/sql_api.js | 66 ---------------------- 6 files changed, 157 deletions(-) delete mode 100644 lib/cartodb/sql/sql_api.js diff --git a/config/environments/development.js.example b/config/environments/development.js.example index d6bfba7f..edc45308 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -133,26 +133,6 @@ var config = { statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd } } - ,sqlapi: { - protocol: 'http', - // If "host" is given, it will be used - // to connect to the SQL-API without a - // DNS lookup - host: '127.0.0.1', - port: 8080, - // The "domain" part will be appended to - // the cartodb username and passed to - // SQL-API requests in the Host HTTP header - domain: 'localhost.lan', - version: 'v1', - // Maximum lenght of SQL query for GET - // requests. Longer queries will be sent - // using POST. Defaults to 2048 - max_get_sql_length: 2048, - // Maximum time to wait for a response, - // in milliseconds. Defaults to 100. - timeout: 100 - } ,varnish: { host: 'localhost', port: 6082, // the por for the telnet interface where varnish is listening to diff --git a/config/environments/production.js.example b/config/environments/production.js.example index e58aea66..fecc6e9a 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -127,26 +127,6 @@ var config = { statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd } } - ,sqlapi: { - protocol: 'https', - // If "host" is given, it will be used - // to connect to the SQL-API without a - // DNS lookup - //host: '127.0.0.1', - port: 8080, - // The "domain" part will be appended to - // the cartodb username and passed to - // SQL-API requests in the Host HTTP header - domain: 'cartodb.com', - version: 'v2', - // Maximum lenght of SQL query for GET - // requests. Longer queries will be sent - // using POST. Defaults to 2048 - max_get_sql_length: 2048, - // Maximum time to wait for a response, - // in milliseconds. Defaults to 100. - timeout: 100 - } ,varnish: { host: 'localhost', port: 6082, // the por for the telnet interface where varnish is listening to diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 8f4b0941..3f125e55 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -127,26 +127,6 @@ var config = { statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd } } - ,sqlapi: { - protocol: 'https', - // If "host" is given, it will be used - // to connect to the SQL-API without a - // DNS lookup - //host: '127.0.0.1', - port: 8080, - // The "domain" part will be appended to - // the cartodb username and passed to - // SQL-API requests in the Host HTTP header - domain: 'cartodb.com', - version: 'v2', - // Maximum lenght of SQL query for GET - // requests. Longer queries will be sent - // using POST. Defaults to 2048 - max_get_sql_length: 2048, - // Maximum time to wait for a response, - // in milliseconds. Defaults to 100. - timeout: 100 - } ,varnish: { host: 'localhost', port: 6082, // the por for the telnet interface where varnish is listening to diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 64c40ffd..ca209751 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -129,28 +129,6 @@ var config = { statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd } } - ,sqlapi: { - protocol: 'http', - // If "host" is given, it will be used - // to connect to the SQL-API without a - // DNS lookup - host: '127.0.0.1', - port: 1080, - // The "domain" part will be appended to - // the cartodb username and passed to - // SQL-API requests in the Host HTTP header - domain: 'donot_look_this_up', - // This port will be used by "make check" for testing purposes - // It must be available - version: 'v1', - // Maximum lenght of SQL query for GET - // requests. Longer queries will be sent - // using POST. Defaults to 2048 - max_get_sql_length: 2048, - // Maximum time to wait for a response, - // in milliseconds. Defaults to 100. - timeout: 100 - } ,varnish: { host: '', port: null, // the por for the telnet interface where varnish is listening to diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 6bf0c32b..da3e6156 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -7,15 +7,6 @@ var LZMA = require('lzma').LZMA; var TemplateMaps = require('./template_maps.js'); var MapConfigNamedLayersAdapter = require('./models/mapconfig_named_layers_adapter'); -// This is for backward compatibility with 1.3.3 -if ( _.isUndefined(global.environment.sqlapi.domain) ) { - // Only use "host" as "domain" if it contains alphanumeric characters - var host = global.environment.sqlapi.host; - if ( host && host.match(/[a-zA-Z]/) ) { - global.environment.sqlapi.domain = host; - } -} - // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ 'user', diff --git a/lib/cartodb/sql/sql_api.js b/lib/cartodb/sql/sql_api.js deleted file mode 100644 index 32885e57..00000000 --- a/lib/cartodb/sql/sql_api.js +++ /dev/null @@ -1,66 +0,0 @@ -var _ = require('underscore'), - request = require('request'); - -module.exports.query = function (username, api_key, sql, callback) { - var api = global.environment.sqlapi; - - // build up api string - var sqlapihostname = username; - if ( api.domain ) sqlapihostname += '.' + api.domain; - - var sqlapi = api.protocol + '://'; - if ( api.host && api.host != api.domain ) sqlapi += api.host; - else sqlapi += sqlapihostname; - sqlapi += ':' + api.port + '/api/' + api.version + '/sql'; - - var qs = { q: sql }; - - // add api_key if given - if (_.isString(api_key) && api_key !== '') { qs.api_key = api_key; } - - // call sql api - // - // NOTE: using POST to avoid size limits: - // See http://github.com/CartoDB/Windshaft-cartodb/issues/111 - // - // NOTE: uses "host" header to allow IP based specification - // of sqlapi address (and avoid a DNS lookup) - // - // NOTE: allows for keeping up to "maxConnections" concurrent - // sockets opened per SQL-API host. - // See http://nodejs.org/api/http.html#http_agent_maxsockets - // - var maxSockets = global.environment.maxConnections || 128; - var maxGetLen = api.max_get_sql_length || 2048; - var maxSQLTime = api.timeout || 100; // 1/10 of a second by default - var reqSpec = { - url:sqlapi, - json:true, - headers:{host: sqlapihostname}, - // http://nodejs.org/api/http.html#http_agent_maxsockets - pool:{maxSockets:maxSockets}, - // timeout in milliseconds - timeout:maxSQLTime - }; - if ( sql.length > maxGetLen ) { - reqSpec.method = 'POST'; - reqSpec.body = qs; - } else { - reqSpec.method = 'GET'; - reqSpec.qs = qs; - } - request(reqSpec, function(err, res, body) { - if (err){ - console.log('ERROR connecting to SQL API on ' + sqlapi + ': ' + err); - callback(err); - return; - } - if (res.statusCode != 200) { - var msg = res.body.error ? res.body.error : res.body; - callback(new Error(msg)); - console.log('unexpected response status (' + res.statusCode + ') for sql query: ' + sql + ': ' + msg); - return; - } - callback(null, body.rows); - }); -}; From d9ab1e8810b35f275fdff9ca1bf0c7593f9305a9 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 15:54:45 +0100 Subject: [PATCH 15/59] Deprecates old config URLs: /tiles/template and /tiles/layergroup Moves all tests to run on new URLs Deprecated base_url_legacy in config, it will keep working tho --- config/environments/development.js.example | 6 +- config/environments/production.js.example | 6 +- config/environments/staging.js.example | 6 +- config/environments/test.js.example | 6 +- .../cache/surrogate_keys_invalidation.js | 6 +- test/acceptance/multilayer.js | 8 +- test/acceptance/named_layers.js | 20 +-- test/acceptance/templates.js | 136 +++++++++--------- 8 files changed, 94 insertions(+), 100 deletions(-) diff --git a/config/environments/development.js.example b/config/environments/development.js.example index edc45308..0636aa03 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -14,13 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/map/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)' // Base url for the Detached Maps API // "maps" is the the new API, // "tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' - // Base url for the Inline Maps and Table Maps API - ,base_url_legacy: '/tiles/:table' + ,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)' // Maximum number of connections for one process // 128 is a good value with a limit of 1024 open file descriptors diff --git a/config/environments/production.js.example b/config/environments/production.js.example index fecc6e9a..f8029935 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -14,13 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/map/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)' // Base url for the Detached Maps API // "maps" is the the new API, // "tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' - // Base url for the Inline Maps and Table Maps API - ,base_url_legacy: '/tiles/:table' + ,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)' // Maximum number of connections for one process // 128 is a good value with a limit of 1024 open file descriptors diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 3f125e55..b2251b84 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -14,13 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/maps/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)' // Base url for the Detached Maps API // "/api/v1/maps" is the the new API, // "/tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' - // Base url for the Inline Maps and Table Maps API - ,base_url_legacy: '/tiles/:table' + ,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)' // Maximum number of connections for one process // 128 is a good value with a limit of 1024 open file descriptors diff --git a/config/environments/test.js.example b/config/environments/test.js.example index ca209751..2ea3071d 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -14,13 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/map/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)' // Base url for the Detached Maps API // "maps" is the the new API, // "tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' - // Base url for the Inline Maps and Table Maps API - ,base_url_legacy: '/tiles/:table' + ,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)' // Maximum number of connections for one process // 128 is a good value with a limit of 1024 open file descriptors diff --git a/test/acceptance/cache/surrogate_keys_invalidation.js b/test/acceptance/cache/surrogate_keys_invalidation.js index 118c6a63..01299585 100644 --- a/test/acceptance/cache/surrogate_keys_invalidation.js +++ b/test/acceptance/cache/surrogate_keys_invalidation.js @@ -56,7 +56,7 @@ suite('templates surrogate keys', function() { function createTemplate(callback) { var postTemplateRequest = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: { host: templateOwner, @@ -109,7 +109,7 @@ suite('templates surrogate keys', function() { throw err; } var updateTemplateRequest = { - url: '/tiles/template/' + expectedTemplateId + '/?api_key=1234', + url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234', method: 'PUT', headers: { host: templateOwner, @@ -174,7 +174,7 @@ suite('templates surrogate keys', function() { throw err; } var deleteTemplateRequest = { - url: '/tiles/template/' + expectedTemplateId + '/?api_key=1234', + url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234', method: 'DELETE', headers: { host: templateOwner, diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index d9382d9c..c94d8380 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -22,7 +22,7 @@ serverOptions = ServerOptions(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -['/tiles/layergroup', '/u/localhost/tiles/layergroup'].forEach(function(layergroup_url) { +['/api/v1/map', '/u/localhost/api/v1/map'].forEach(function(layergroup_url) { var suiteName = 'multilayer:postgres=layergroup_url=' + layergroup_url; suite(suiteName, function() { @@ -962,7 +962,7 @@ suite(suiteName, function() { }; assert.response(server, { - url: '/tiles/layergroup?', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -995,7 +995,7 @@ suite(suiteName, function() { }; assert.response(server, { - url: '/tiles/layergroup?', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -1018,7 +1018,7 @@ suite(suiteName, function() { ] }; assert.response(server, { - url: '/tiles/layergroup?', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) diff --git a/test/acceptance/named_layers.js b/test/acceptance/named_layers.js index 992d1981..9e2be330 100644 --- a/test/acceptance/named_layers.js +++ b/test/acceptance/named_layers.js @@ -96,6 +96,7 @@ suite('named_layers', function() { }; suiteSetup(function(done) { + global.environment.enabledFeatures = {cdbQueryTablesFromPostgres: true}; templateMaps.addTemplate(username, nestedNamedMapTemplate, function(err) { if (err) { return done(err); @@ -129,7 +130,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -182,7 +183,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -239,7 +240,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -292,7 +293,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -372,7 +373,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -407,7 +408,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup/' + layergroupId + '/0/0/0.png', + url: '/api/v1/map/' + layergroupId + '/0/0/0.png', method: 'GET', headers: { host: 'localhost' @@ -500,7 +501,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -535,7 +536,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup/' + layergroupId + '/0/0/0.png', + url: '/api/v1/map/' + layergroupId + '/0/0/0.png', method: 'GET', headers: { host: 'localhost' @@ -601,7 +602,7 @@ suite('named_layers', function() { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: '/api/v1/map', method: 'POST', headers: { host: 'localhost', @@ -636,6 +637,7 @@ suite('named_layers', function() { suiteTeardown(function(done) { + global.environment.enabledFeatures = {cdbQueryTablesFromPostgres: false}; templateMaps.delTemplate(username, nestedNamedMapTemplateName, function(err) { if (err) { return done(err); diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index 7d6b301a..13923b4d 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -84,7 +84,7 @@ suite('template_api', function() { var expected_failure = false; var expected_tpl_id = "localhost@acceptance1"; var post_request_1 = { - url: '/tiles/template', + url: '/api/v1/map/named', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance1) @@ -171,7 +171,7 @@ suite('template_api', function() { broken_template.auth.method = 'token'; delete broken_template.auth.tokens; var post_request_1 = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(broken_template) @@ -201,7 +201,7 @@ suite('template_api', function() { broken_template.auth.method = 'token'; broken_template.auth.tokens = []; var post_request_1 = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(broken_template) @@ -228,7 +228,7 @@ suite('template_api', function() { var broken_template = JSON.parse(JSON.stringify(template_acceptance1)); broken_template.name = 'broken1'; var post_request_1 = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(broken_template) @@ -252,7 +252,7 @@ suite('template_api', function() { broken_template.auth.method = 'token'; broken_template.auth.tokens = []; var put_request_1 = { - url: '/tiles/template/' + tpl_id + '/?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234', method: 'PUT', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(broken_template) @@ -273,7 +273,7 @@ suite('template_api', function() { 'Error for invalid authentication on PUT does not match ' + re + ': ' + parsed.error); var del_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost'} } @@ -309,7 +309,7 @@ suite('template_api', function() { Step(function postTemplate1(err, res) { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost.localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance1) @@ -318,7 +318,7 @@ suite('template_api', function() { }, function testCORS() { assert.response(server, { - url: '/tiles/template/acceptance1', + url: '/api/v1/map/named/acceptance1', method: 'OPTIONS' },{ status: 200, @@ -338,7 +338,7 @@ suite('template_api', function() { Step(function postTemplate1(err, res) { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(tmpl) @@ -350,7 +350,7 @@ suite('template_api', function() { function testCORS() { var next = this; assert.response(server, { - url: '/tiles/template/' + tmpl.name, + url: '/api/v1/map/named/' + tmpl.name, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, },{ @@ -364,7 +364,7 @@ suite('template_api', function() { function deleteTemplate(err) { if ( err ) throw err; var del_request = { - url: '/tiles/template/' + tmpl.name + '?api_key=1234', + url: '/api/v1/map/named/' + tmpl.name + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost', 'Content-Type': 'application/json' } } @@ -387,7 +387,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance1) @@ -408,7 +408,7 @@ suite('template_api', function() { var backup_name = template_acceptance1.name; template_acceptance1.name += '_new'; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance1) @@ -427,7 +427,7 @@ suite('template_api', function() { tplid2 = parsed.template_id; var next = this; var get_request = { - url: '/tiles/template', + url: '/api/v1/map/named', method: 'GET', headers: {host: 'localhost'} } @@ -445,7 +445,7 @@ suite('template_api', function() { assert.ok(err.match(/authenticated user/), err); var next = this; var get_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'GET', headers: {host: 'localhost'} } @@ -504,7 +504,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(makeTemplate()) @@ -523,7 +523,7 @@ suite('template_api', function() { var backup_name = template_acceptance1.name; template_acceptance1.name = 'changed_name'; var put_request = { - url: '/tiles/template/' + tpl_id + '/?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234', method: 'PUT', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance1) @@ -542,7 +542,7 @@ suite('template_api', function() { assert.ok(parsedBody.error.match(/cannot update name/i), 'Unexpected error for invalid update: ' + parsedBody.error); var put_request = { - url: '/tiles/template/unexistent/?api_key=1234', + url: '/api/v1/map/named/unexistent/?api_key=1234', method: 'PUT', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(makeTemplate()) @@ -560,7 +560,7 @@ suite('template_api', function() { assert.ok(parsedBody.error.match(/cannot update name/i), 'Unexpected error for invalid update: ' + parsedBody.error); var put_request = { - url: '/tiles/template/' + tpl_id + '/?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234', method: 'PUT', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(makeTemplate()) @@ -616,7 +616,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(makeTemplate()) @@ -633,7 +633,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var get_request = { - url: '/tiles/template/' + tpl_id, + url: '/api/v1/map/named/' + tpl_id, method: 'GET', headers: {host: 'localhost'} } @@ -650,7 +650,7 @@ suite('template_api', function() { assert.ok(parsedBody.error.match(/only.*authenticated.*user/i), 'Unexpected error for unauthenticated template get: ' + parsedBody.error); var get_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'GET', headers: {host: 'localhost'} } @@ -705,7 +705,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(makeTemplate()) @@ -722,7 +722,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var get_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'GET', headers: {host: 'localhost'} } @@ -739,7 +739,7 @@ suite('template_api', function() { "Missing 'template' from response body: " + res.body); assert.deepEqual(extendDefaultsTemplate(makeTemplate()), parsed.template); var del_request = { - url: '/tiles/template/' + tpl_id, + url: '/api/v1/map/named/' + tpl_id, method: 'DELETE', headers: {host: 'localhost'} } @@ -757,7 +757,7 @@ suite('template_api', function() { assert.ok(parsed.error.match(/only.*authenticated.*user/i), 'Unexpected error for unauthenticated template get: ' + parsed.error); var del_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost'} } @@ -771,7 +771,7 @@ suite('template_api', function() { assert.equal(res.statusCode, 204, res.statusCode + ': ' + res.body); assert.ok(!res.body, 'Unexpected body in DELETE /template response'); var get_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'GET', headers: {host: 'localhost'} } @@ -849,7 +849,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance2) @@ -866,7 +866,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id, + url: '/api/v1/map/named/' + tpl_id, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -887,7 +887,7 @@ suite('template_api', function() { assert.ok(parsed.error.match(/unauthorized/i), 'Unexpected error for unauthorized instance : ' + parsed.error); var post_request = { - url: '/tiles/template/' + tpl_id + '?auth_token=valid2', + url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', headers: {host: 'foreign', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -906,7 +906,7 @@ suite('template_api', function() { assert.ok(parsed.error.match(/cannot instanciate/i), 'Unexpected error for forbidden instance : ' + parsed.error); var post_request = { - url: '/tiles/template/' + tpl_id + '?auth_token=valid2', + url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -930,7 +930,7 @@ suite('template_api', function() { "Missing 'last_updated' from response body: " + res.body); // TODO: check value of last_updated ? var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb0/0/0/0.png', + url: '/api/v1/map/' + layergroupid + ':cb0/0/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -950,7 +950,7 @@ suite('template_api', function() { 'Unexpected error for unauthorized instance ' + '(expected /permission denied/): ' + parsed.error); var get_request = { - url: '/tiles/layergroup/' + layergroupid + '/0/0/0.png?auth_token=valid1', + url: '/api/v1/map/' + layergroupid + '/0/0/0.png?auth_token=valid1', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -972,7 +972,7 @@ suite('template_api', function() { if ( err ) throw err; var foreignsigned = layergroupid.replace(/[^@]*@/, 'foreign@'); var get_request = { - url: '/tiles/layergroup/' + foreignsigned + '/0/0/0.png?auth_token=valid1', + url: '/api/v1/map/' + foreignsigned + '/0/0/0.png?auth_token=valid1', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -998,7 +998,7 @@ suite('template_api', function() { { if ( err ) throw err; var del_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost'} } @@ -1011,7 +1011,7 @@ suite('template_api', function() { assert.equal(res.statusCode, 204, 'Deleting template: ' + res.statusCode + ':' + res.body); var get_request = { - url: '/tiles/layergroup/' + layergroupid + '/0/0/0.png?auth_token=valid1', + url: '/api/v1/map/' + layergroupid + '/0/0/0.png?auth_token=valid1', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1083,7 +1083,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template) @@ -1100,7 +1100,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id, + url: '/api/v1/map/named/' + tpl_id, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1121,7 +1121,7 @@ suite('template_api', function() { assert.ok(parsed.error.match(/unauthorized/i), 'Unexpected error for unauthorized instance : ' + parsed.error); var post_request = { - url: '/tiles/template/' + tpl_id + '?auth_token=valid2', + url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1145,7 +1145,7 @@ suite('template_api', function() { "Missing 'last_updated' from response body: " + res.body); // TODO: check value of last_updated ? var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb0/0/0/0/0.json.torque', + url: '/api/v1/map/' + layergroupid + ':cb0/0/0/0/0.json.torque', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1165,7 +1165,7 @@ suite('template_api', function() { 'Unexpected error for unauthorized instance ' + '(expected /permission denied): ' + parsed.error); var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb1/0/0/0/0.json.torque?auth_token=valid1', + url: '/api/v1/map/' + layergroupid + ':cb1/0/0/0/0.json.torque?auth_token=valid1', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1187,7 +1187,7 @@ suite('template_api', function() { serverOptions = ServerOptions(); // need to clean channel cache server = new CartodbWindshaft(serverOptions); var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb1/0/0/0/1.json.torque?auth_token=valid1', + url: '/api/v1/map/' + layergroupid + ':cb1/0/0/0/1.json.torque?auth_token=valid1', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1211,7 +1211,7 @@ suite('template_api', function() { { if ( err ) throw err; var del_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost'} } @@ -1224,7 +1224,7 @@ suite('template_api', function() { assert.equal(res.statusCode, 204, 'Deleting template: ' + res.statusCode + ':' + res.body); var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb2/0/0/0/0.json.torque?auth_token=valid1', + url: '/api/v1/map/' + layergroupid + ':cb2/0/0/0/0.json.torque?auth_token=valid1', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1298,7 +1298,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template) @@ -1315,7 +1315,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id, + url: '/api/v1/map/named/' + tpl_id, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1336,7 +1336,7 @@ suite('template_api', function() { assert.ok(parsed.error.match(/unauthorized/i), 'Unexpected error for unauthorized instance : ' + parsed.error); var post_request = { - url: '/tiles/template/' + tpl_id + '?auth_token=valid2', + url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1360,7 +1360,7 @@ suite('template_api', function() { "Missing 'last_updated' from response body: " + res.body); // TODO: check value of last_updated ? var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb0/0/attributes/5', + url: '/api/v1/map/' + layergroupid + ':cb0/0/attributes/5', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1380,7 +1380,7 @@ suite('template_api', function() { 'Unexpected error for unauthorized getAttributes ' + '(expected /permission denied/): ' + parsed.error); var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb1/0/attributes/5?auth_token=valid2', + url: '/api/v1/map/' + layergroupid + ':cb1/0/attributes/5?auth_token=valid2', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1401,7 +1401,7 @@ suite('template_api', function() { { if ( err ) throw err; var del_request = { - url: '/tiles/template/' + tpl_id + '?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost'} } @@ -1414,7 +1414,7 @@ suite('template_api', function() { assert.equal(res.statusCode, 204, 'Deleting template: ' + res.statusCode + ':' + res.body); var get_request = { - url: '/tiles/layergroup/' + layergroupid + ':cb2/0/attributes/5?auth_token=valid2', + url: '/api/v1/map/' + layergroupid + ':cb2/0/attributes/5?auth_token=valid2', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1488,7 +1488,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance_open) @@ -1505,7 +1505,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id, + url: '/api/v1/map/named/' + tpl_id, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1557,7 +1557,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance_open) @@ -1574,7 +1574,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id + "/jsonp?callback=test", + url: '/api/v1/map/named/' + tpl_id + "/jsonp?callback=test", method: 'GET', headers: {host: 'localhost' } } @@ -1631,7 +1631,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance_open) @@ -1648,7 +1648,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id + "/jsonp?callback=test%config=" + JSON.stringify('{color:blue}'), + url: '/api/v1/map/named/' + tpl_id + "/jsonp?callback=test%config=" + JSON.stringify('{color:blue}'), method: 'GET', headers: {host: 'localhost' } } @@ -1709,7 +1709,7 @@ suite('template_api', function() { { if ( err ) throw err; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template) @@ -1723,7 +1723,7 @@ suite('template_api', function() { assert.equal(res.statusCode, 200, res.body); template_id = JSON.parse(res.body).template_id; var post_request = { - url: '/tiles/template/' + template_id, + url: '/api/v1/map/named/' + template_id, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify({}) @@ -1758,7 +1758,7 @@ suite('template_api', function() { { if ( err ) throw err; var del_request = { - url: '/tiles/template/' + template_id + '?api_key=1234', + url: '/api/v1/map/named/' + template_id + '?api_key=1234', method: 'DELETE', headers: {host: 'localhost'} } @@ -1811,7 +1811,7 @@ suite('template_api', function() { { var next = this; var post_request = { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_acceptance2) @@ -1828,7 +1828,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); tpl_id = parsed.template_id; var post_request = { - url: '/tiles/template/' + tpl_id + '?auth_token=valid2', + url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1855,7 +1855,7 @@ suite('template_api', function() { var changedTemplate = JSON.parse(JSON.stringify(template_acceptance2)); changedTemplate.auth.method = 'open'; var post_request = { - url: '/tiles/template/' + tpl_id + '/?api_key=1234', + url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234', method: 'PUT', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(changedTemplate) @@ -1873,7 +1873,7 @@ suite('template_api', function() { "Missing 'template_id' from response body: " + res.body); assert.equal(tpl_id, parsed.template_id); var post_request = { - url: '/tiles/template/' + tpl_id + '?auth_token=valid2', + url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(template_params) @@ -1968,7 +1968,7 @@ suite('template_api', function() { assert.response( server, { - url: '/tiles/template?api_key=1234', + url: '/api/v1/map/named?api_key=1234', method: 'POST', headers: { host: username, @@ -1993,7 +1993,7 @@ suite('template_api', function() { assert.response( server, { - url: '/tiles/template/' + expectedTemplateId, + url: '/api/v1/map/named/' + expectedTemplateId, method: 'POST', headers: { host: username, @@ -2022,7 +2022,7 @@ suite('template_api', function() { assert.response( server, { - url: '/tiles/layergroup/' + layergroupid + '/all/0/0/0.png', + url: '/api/v1/map/' + layergroupid + '/all/0/0/0.png', method: 'GET', headers: { host: username @@ -2052,7 +2052,7 @@ suite('template_api', function() { assert.response( server, { - url: '/tiles/template/' + expectedTemplateId + '?api_key=1234', + url: '/api/v1/map/named/' + expectedTemplateId + '?api_key=1234', method: 'DELETE', headers: { host: username From 09b3f0a8629b8b6bc3cd167be7de696119144da4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 17:27:24 +0100 Subject: [PATCH 16/59] Skip server suite for now until we decide what tests we should port --- test/acceptance/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 6702a603..4b9b19c6 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -18,7 +18,7 @@ server.setMaxListeners(0); var cdbQueryTablesFromPostgresEnabledValue = true; -suite('server', function() { +suite.skip('server', function() { var redis_client = redis.createClient(global.environment.redis.port); var sqlapi_server; From f5f7be627f904512a422c6198798b638288fe65c Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 17:35:09 +0100 Subject: [PATCH 17/59] Move userByReq to its own model --- lib/cartodb/controllers/template_maps.js | 14 +++++---- lib/cartodb/models/cdb_request.js | 26 +++++++++++++++ lib/cartodb/server_options.js | 40 ++++++------------------ 3 files changed, 43 insertions(+), 37 deletions(-) create mode 100644 lib/cartodb/models/cdb_request.js diff --git a/lib/cartodb/controllers/template_maps.js b/lib/cartodb/controllers/template_maps.js index 452f7225..e071d8a0 100644 --- a/lib/cartodb/controllers/template_maps.js +++ b/lib/cartodb/controllers/template_maps.js @@ -1,5 +1,6 @@ var step = require('step'); var _ = require('underscore'); +var CdbRequest = require('../models/cdb_request'); function TemplateMapsController(app, serverOptions, templateMaps, metadataBackend, templateBaseUrl, surrogateKeysCache, NamedMapsCacheEntry, pgConnection) { @@ -15,6 +16,7 @@ function TemplateMapsController(app, serverOptions, templateMaps, metadataBacken module.exports = TemplateMapsController; +var cdbRequest = new CdbRequest(); TemplateMapsController.prototype.register = function(app) { app.get(this.templateBaseUrl + '/:template_id/jsonp', this.jsonp.bind(this)); @@ -33,7 +35,7 @@ TemplateMapsController.prototype.create = function(req, res) { this.app.doCORS(res); - var cdbuser = self.serverOptions.userByReq(req); + var cdbuser = cdbRequest.userByReq(req); step( function checkPerms(){ @@ -80,7 +82,7 @@ TemplateMapsController.prototype.update = function(req, res) { this.app.doCORS(res); - var cdbuser = this.serverOptions.userByReq(req); + var cdbuser = cdbRequest.userByReq(req); var template; var tpl_id; step( @@ -140,7 +142,7 @@ TemplateMapsController.prototype.retrieve = function(req, res) { this.app.doCORS(res); - var cdbuser = this.serverOptions.userByReq(req); + var cdbuser = cdbRequest.userByReq(req); var tpl_id; step( function checkPerms(){ @@ -201,7 +203,7 @@ TemplateMapsController.prototype.destroy = function(req, res) { } this.app.doCORS(res); - var cdbuser = this.serverOptions.userByReq(req); + var cdbuser = cdbRequest.userByReq(req); var tpl_id; step( function checkPerms(){ @@ -254,7 +256,7 @@ TemplateMapsController.prototype.list = function(req, res) { } this.app.doCORS(res); - var cdbuser = this.serverOptions.userByReq(req); + var cdbuser = cdbRequest.userByReq(req); step( function checkPerms(){ @@ -353,7 +355,7 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa var template; var layergroup; var fakereq; // used for call to createLayergroup - var cdbuser = self.serverOptions.userByReq(req); + var cdbuser = cdbRequest.userByReq(req); // Format of template_id: []@ var tpl_id = req.params.template_id.split('@'); if ( tpl_id.length > 1 ) { diff --git a/lib/cartodb/models/cdb_request.js b/lib/cartodb/models/cdb_request.js new file mode 100644 index 00000000..ec2da747 --- /dev/null +++ b/lib/cartodb/models/cdb_request.js @@ -0,0 +1,26 @@ +function CdbRequest() { +} + +module.exports = CdbRequest; + +var RE_USER_FROM_HOST = new RegExp(global.environment.user_from_host || + '^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com" +); + +CdbRequest.prototype.userByReq = function(req) { + var host = req.headers.host; + if (req.params.user) { + return req.params.user; + } + var mat = host.match(RE_USER_FROM_HOST); + if ( ! mat ) { + console.error("Pattern '" + RE_USER_FROM_HOST + "' does not match hostname '" + host + "'"); + return; + } + // console.log("Matches: "); console.dir(mat); + if ( mat.length !== 2 ) { + console.error("Pattern '" + RE_USER_FROM_HOST + "' gave unexpected matches against '" + host + "': ", mat); + return; + } + return mat[1]; +}; diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index da3e6156..38d0668b 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -6,6 +6,7 @@ var crypto = require('crypto'); var LZMA = require('lzma').LZMA; var TemplateMaps = require('./template_maps.js'); var MapConfigNamedLayersAdapter = require('./models/mapconfig_named_layers_adapter'); +var CdbRequest = require('./models/cdb_request'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ @@ -33,7 +34,8 @@ module.exports = function(redisPool) { var cartoData = require('cartodb-redis')({ pool: redisPool }), lzmaWorker = new LZMA(), pgConnection = new PgConnection(cartoData), - queryTablesApi = new QueryTablesApi(pgConnection, cartoData); + queryTablesApi = new QueryTablesApi(pgConnection, cartoData), + cdbRequest = new CdbRequest(); var rendererConfig = _.defaults(global.environment.renderer || {}, { cache_ttl: 60000, // milliseconds @@ -201,7 +203,7 @@ module.exports = function(redisPool) { return [req.params.table]; } - queryTablesApi.getAffectedTablesInQuery(that.userByReq(req), sql, this); // in addCacheChannel + queryTablesApi.getAffectedTablesInQuery(cdbRequest.userByReq(req), sql, this); // in addCacheChannel }, function buildCacheChannel(err, tableNames) { if ( err ) throw err; @@ -273,7 +275,7 @@ module.exports = function(redisPool) { }; me.beforeLayergroupCreate = function(req, requestMapConfig, callback) { - mapConfigNamedLayersAdapter.getLayers(this.userByReq(req), requestMapConfig.layers, pgConnection, + mapConfigNamedLayersAdapter.getLayers(cdbRequest.userByReq(req), requestMapConfig.layers, pgConnection, function(err, layers, datasource) { if (err) { return callback(err); @@ -288,7 +290,7 @@ module.exports = function(redisPool) { me.afterLayergroupCreate = function(req, mapconfig, response, callback) { var token = response.layergroupid; - var username = this.userByReq(req); + var username = cdbRequest.userByReq(req); var tasksleft = 2; // redis key and affectedTables var errors = []; @@ -362,30 +364,6 @@ module.exports = function(redisPool) { /* X-Cache-Channel generation } */ - me.re_userFromHost = new RegExp( - global.environment.user_from_host || - '^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com" - ); - - me.userByReq = function(req) { - var host = req.headers.host; - if (req.params.user) { - return req.params.user; - } - var mat = host.match(this.re_userFromHost); - if ( ! mat ) { - console.error("ERROR: user pattern '" + this.re_userFromHost + "' does not match hostname '" + host + "'"); - return; - } - // console.log("Matches: "); console.dir(mat); - if ( mat.length !== 2 ) { - console.error("ERROR: pattern '" + this.re_userFromHost + "' gave unexpected matches against '" + host + "': " + - mat); - return; - } - return mat[1]; - }; - // Check if a request is authorized by a signer // // @param req express request object @@ -441,7 +419,7 @@ module.exports = function(redisPool) { return; } //console.log("given ApiKey: " + givenKey); - var user = me.userByReq(req); + var user = cdbRequest.userByReq(req); step( function (){ cartoData.getUserMapKey(user, this); @@ -464,7 +442,7 @@ module.exports = function(redisPool) { */ me.authorize = function(req, callback) { var that = this; - var user = me.userByReq(req); + var user = cdbRequest.userByReq(req); step( function (){ @@ -589,7 +567,7 @@ module.exports = function(redisPool) { _.each(bad_query, function(key){ delete req.query[key]; }); req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object - var user = me.userByReq(req); + var user = cdbRequest.userByReq(req); if ( req.params.token ) { //console.log("Request parameters include token " + req.params.token); From c19f652ff371d4c9045bcdb3b49eed229a97970d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 17:54:37 +0100 Subject: [PATCH 18/59] Remove some old accepted query params --- lib/cartodb/server_options.js | 8 ----- test/unit/cartodb/req2params.test.js | 54 ++++++++++++++++------------ 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 38d0668b..1af0634c 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -12,17 +12,12 @@ var CdbRequest = require('./models/cdb_request'); var REQUEST_QUERY_PARAMS_WHITELIST = [ 'user', 'sql', - 'geom_type', 'cache_buster', 'cache_policy', 'callback', - 'interactivity', 'map_key', 'api_key', 'auth_token', - 'style', - 'style_version', - 'style_convert', 'config', 'scale_factor' ]; @@ -531,9 +526,6 @@ module.exports = function(redisPool) { if ( req.query.lzma ) { - // TODO: check ? - //console.log("type of req.query.lzma is " + typeof(req.query.lzma)); - // Decode (from base64) var lzma = new Buffer(req.query.lzma, 'base64') .toString('binary') diff --git a/test/unit/cartodb/req2params.test.js b/test/unit/cartodb/req2params.test.js index 90b96169..7e2c1360 100644 --- a/test/unit/cartodb/req2params.test.js +++ b/test/unit/cartodb/req2params.test.js @@ -1,8 +1,6 @@ -var assert = require('assert') - , _ = require('underscore') - , redis = require('redis') - , test_helper = require('../../support/test_helper') - , tests = module.exports = {}; +var assert = require('assert'); +var _ = require('underscore'); +var test_helper = require('../../support/test_helper'); suite('req2params', function() { @@ -65,23 +63,35 @@ suite('req2params', function() { }); test('it should extend params with decoded lzma', function(done) { - var qo = { - style: 'test', - style_version: '2.1.0', - cache_buster: 5 - }; - test_helper.lzma_compress_to_base64(JSON.stringify(qo), 1, function(err, data) { - opts.req2params({ headers: { host:'localhost' }, query: { non_included: 'toberemoved', api_key: 'test', style: 'override', lzma: data }}, function(err, req) { - if ( err ) { done(err); return; } - var query = req.params - assert.equal(qo.style, query.style) - assert.equal(qo.style_version, query.style_version) - assert.equal(qo.cache_buster, query.cache_buster) - assert.equal('test', query.api_key) - assert.equal(undefined, query.non_included) - done(); + var qo = { + style: 'test', + style_version: '2.1.0', + cache_buster: 5 + }; + test_helper.lzma_compress_to_base64(JSON.stringify(qo), 1, function(err, data) { + console.log(data); + var req = { + headers: { + host:'localhost' + }, + query: { + non_included: 'toberemoved', + api_key: 'test', + style: 'override', + lzma: data + } + }; + opts.req2params(req, function(err, req) { + if ( err ) { + return done(err); + } + var query = req.params; + assert.equal(qo.cache_buster, query.cache_buster); + assert.equal('test', query.api_key); + assert.equal(undefined, query.non_included); + done(); + }); }); - }); }); - + }); From 415d0c42d5336fc71bb2c7d391e024fd42107e1d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 17:56:18 +0100 Subject: [PATCH 19/59] jshint --- lib/cartodb/server_options.js | 83 ++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 1af0634c..c2264c1d 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -7,6 +7,7 @@ var LZMA = require('lzma').LZMA; var TemplateMaps = require('./template_maps.js'); var MapConfigNamedLayersAdapter = require('./models/mapconfig_named_layers_adapter'); var CdbRequest = require('./models/cdb_request'); +var assert = require('assert'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ @@ -233,10 +234,14 @@ module.exports = function(redisPool) { me.addCacheChannel = function(app, req, cb) { // skip non-GET requests, or requests for which there's no response if ( req.method != 'GET' || ! req.res ) { cb(null, null); return; } - if (req.profiler) req.profiler.start('addCacheChannel'); + if (req.profiler) { + req.profiler.start('addCacheChannel'); + } var res = req.res; var cache_policy = req.query.cache_policy; - if ( req.params.token ) cache_policy = 'persist'; + if ( req.params.token ) { + cache_policy = 'persist'; + } if ( cache_policy == 'persist' ) { res.header('Cache-Control', 'public,max-age=31536000'); // 1 year } else { @@ -256,8 +261,10 @@ module.exports = function(redisPool) { res.header('Last-Modified', lastUpdated.toUTCString()); me.generateCacheChannel(app, req, function(err, channel){ - if (req.profiler) req.profiler.done('generateCacheChannel'); - if (req.profiler) req.profiler.end(); + if (req.profiler) { + req.profiler.done('generateCacheChannel'); + req.profiler.end(); + } if ( ! err ) { res.header('X-Cache-Channel', channel); cb(null, channel); @@ -312,8 +319,12 @@ module.exports = function(redisPool) { // take place before proceeding. Error will be logged // asyncronously cartoData.incMapviewCount(username, mapconfig.stat_tag, function(err) { - if (req.profiler) req.profiler.done('incMapviewCount'); - if ( err ) console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err); + if (req.profiler) { + req.profiler.done('incMapviewCount'); + } + if ( err ) { + console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err); + } done(); }); @@ -329,8 +340,10 @@ module.exports = function(redisPool) { queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this); }, function handleAffectedTablesAndLastUpdatedTime(err, result) { - if (req.profiler) req.profiler.done('queryTablesAndLastUpdated'); - if ( err ) throw err; + if (req.profiler) { + req.profiler.done('queryTablesAndLastUpdated'); + } + assert.ifError(err); var cacheChannel = me.buildCacheChannel(dbName, result.affectedTables); me.channelCache[cacheKey] = cacheChannel; @@ -420,7 +433,7 @@ module.exports = function(redisPool) { cartoData.getUserMapKey(user, this); }, function checkApiKey(err, val){ - if (err) throw err; + assert.ifError(err); return ( val && givenKey == val ) ? 1 : 0; }, function finish(err, authorized) { @@ -444,8 +457,10 @@ module.exports = function(redisPool) { that.authorizedByAPIKey(req, this); }, function checkApiKey(err, authorized){ - if (req.profiler) req.profiler.done('authorizedByAPIKey'); - if (err) throw err; + if (req.profiler) { + req.profiler.done('authorizedByAPIKey'); + } + assert.ifError(err); // if not authorized by api_key, continue if (authorized !== 1) { @@ -463,7 +478,7 @@ module.exports = function(redisPool) { }); }, function checkSignAuthorized(err, signed_by){ - if (err) throw err; + assert.ifError(err); if (req.profiler) { if ( req.params._authorizedByApiKey ) { req.profiler.done('setDBAuth'); @@ -476,7 +491,9 @@ module.exports = function(redisPool) { // request not authorized by signer. // if table was given, continue to check table privacy - if ( req.params.table ) return null; + if ( req.params.table ) { + return null; + } // if no signer name was given, let dbparams and // PostgreSQL do the rest. @@ -494,22 +511,28 @@ module.exports = function(redisPool) { // Authorized by "signed_by" ! _.extend(req.params, { _authorizedBySigner: signed_by }); pgConnection.setDBAuth(signed_by, req.params, function(err) { - if (req.profiler) req.profiler.done('setDBAuth'); + if (req.profiler) { + req.profiler.done('setDBAuth'); + } callback(err, true); // authorized (or error) }); }, function getDatabase(err){ - if (err) throw err; + assert.ifError(err); // NOTE: only used to get to table privacy cartoData.getUserDBName(user, this); }, function getPrivacy(err, dbname){ - if (err) throw err; - if (req.profiler) req.profiler.done('tablePrivacy_getUserDBName'); + assert.ifError(err); + if (req.profiler) { + req.profiler.done('tablePrivacy_getUserDBName'); + } cartoData.getTablePrivacy(dbname, req.params.table, this); }, function(err, privacy){ - if (req.profiler) req.profiler.done('getTablePrivacy'); + if (req.profiler) { + req.profiler.done('getTablePrivacy'); + } callback(err, privacy !== "0"); } ); @@ -538,7 +561,9 @@ module.exports = function(redisPool) { lzmaWorker.decompress( lzma, function(result) { - if (req.profiler) req.profiler.done('LZMA decompress'); + if (req.profiler) { + req.profiler.done('LZMA decompress'); + } try { delete req.query.lzma; _.extend(req.query, JSON.parse(result)); @@ -565,11 +590,15 @@ module.exports = function(redisPool) { //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]; + 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; + 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 database of user "' + user + '"'); @@ -591,15 +620,19 @@ module.exports = function(redisPool) { // for cartodb, ensure interactivity is cartodb_id or user specified req.params.interactivity = req.params.interactivity || 'cartodb_id'; - if (req.profiler) req.profiler.done('req2params.setup'); + if (req.profiler) { + req.profiler.done('req2params.setup'); + } step( function getPrivacy(){ me.authorize(req, this); }, function gatekeep(err, authorized){ - if (req.profiler) req.profiler.done('authorize'); - if(err) throw err; + 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; @@ -608,7 +641,7 @@ module.exports = function(redisPool) { return null; }, function getDatabase(err){ - if(err) throw err; + assert.ifError(err); pgConnection.setDBConn(user, req.params, this); }, function finishSetup(err) { From ea3d2124dc9647f1bb7d3e5f1cccdd601db09f64 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 17:56:51 +0100 Subject: [PATCH 20/59] No sql param in generateCacheChannel --- lib/cartodb/server_options.js | 161 ++++++++++++++-------------------- 1 file changed, 66 insertions(+), 95 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index c2264c1d..1af80410 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -2,7 +2,6 @@ var _ = require('underscore'); var step = require('step'); var QueryTablesApi = require('./api/query_tables_api'); var PgConnection = require('./backends/pg_connection'); -var crypto = require('crypto'); var LZMA = require('lzma').LZMA; var TemplateMaps = require('./template_maps.js'); var MapConfigNamedLayersAdapter = require('./models/mapconfig_named_layers_adapter'); @@ -120,106 +119,78 @@ module.exports = function(redisPool) { return dbName + ':' + tableNames.join(','); }; - me.generateMD5 = function(data){ - var hash = crypto.createHash('md5'); - hash.update(data); - return hash.digest('hex'); - }; - me.generateCacheChannel = function(app, req, callback){ + // Build channelCache key + var dbName = req.params.dbname; + var cacheKey = [ dbName, req.params.token ].join(':'); - // Build channelCache key - var dbName = req.params.dbname; - var cacheKey = [ dbName ]; - if ( req.params.token ) cacheKey.push(req.params.token); - else if ( req.params.sql ) cacheKey.push( me.generateMD5(req.params.sql) ); - cacheKey = cacheKey.join(':'); + step( + function checkCached() { + if ( me.channelCache.hasOwnProperty(cacheKey) ) { + return callback(null, me.channelCache[cacheKey]); + } + return null; + }, + function extractSQL(err) { + assert.ifError(err); - var that = this; + // TODO: cached cache channel for token-based access should + // be constructed at renderer cache creation time + // See http://github.com/CartoDB/Windshaft-cartodb/issues/152 + if ( ! app.mapStore ) { + throw new Error('missing channel cache for token ' + req.params.token); + } + var next = this; + var mapStore = app.mapStore; + step( + function loadFromStore() { + mapStore.load(req.params.token, this); + }, + function getSQL(err, mapConfig) { + if (req.profiler) { + req.profiler.done('mapStore_load'); + } + assert.ifError(err); - step ( - function checkCached() { - if ( me.channelCache.hasOwnProperty(cacheKey) ) { - callback(null, me.channelCache[cacheKey]); - return; - } - return null; - }, - function extractSQL(err) { - if ( err ) throw err; + return mapConfig.obj().layers.map(function(lyr) { + return lyr.options.sql; + }).join(';'); + }, + function finish(err, sql) { + next(err, sql); + } + ); + }, + function findAffectedTables(err, sql) { + assert.ifError(err); + if ( ! sql ) { + if ( ! req.params.table ) { + throw new Error("this request doesn't need an X-Cache-Channel generated"); + } + return [req.params.table]; + } - if ( req.params.token ) { - // TODO: cached cache channel for token-based access should - // be constructed at renderer cache creation time - // See http://github.com/CartoDB/Windshaft-cartodb/issues/152 - if ( ! app.mapStore ) { - throw new Error('missing channel cache for token ' + req.params.token); + queryTablesApi.getAffectedTablesInQuery(cdbRequest.userByReq(req), sql, this); // in addCacheChannel + }, + function buildCacheChannel(err, tableNames) { + assert.ifError(err); + + if (req.profiler && ! req.params.table ) { + req.profiler.done('affectedTables'); + } + + var cacheChannel = me.buildCacheChannel(dbName,tableNames); + // store for caching from me.generateCacheChannel + // (not worth when table was specified in params) + if ( ! req.params.table ) { + me.channelCache[cacheKey] = cacheChannel; + } + return cacheChannel; + }, + function finish(err, cacheChannel) { + callback(err, cacheChannel); } - var next = this; - var mapStore = app.mapStore; - step( - function loadFromStore() { - mapStore.load(req.params.token, this); - }, - function getSQL(err, mapConfig) { - if (req.profiler) req.profiler.done('mapStore_load'); - if ( err ) throw err; - var sql = []; - _.each(mapConfig.obj().layers, function(lyr) { - sql.push(lyr.options.sql); - }); - sql = sql.join(';'); - return sql; - }, - function finish(err, sql) { - next(err, sql); - } - ); - return; - } - - if ( ! req.params.sql ) { - return null; // no sql - } - - // We have sql, and no token... - - // strip out windshaft/mapnik inserted sql if present - var sql = req.params.sql.match(/^\((.*)\)\sas\scdbq$/); - sql = (sql !== null) ? sql[1] : req.params.sql; - - return sql; - }, - function findAffectedTables(err, sql) { - if ( err ) throw err; - if ( ! sql ) { - if ( ! req.params.table ) { - throw new Error("this request doesn't need an X-Cache-Channel generated"); - } - return [req.params.table]; - } - - queryTablesApi.getAffectedTablesInQuery(cdbRequest.userByReq(req), sql, this); // in addCacheChannel - }, - function buildCacheChannel(err, tableNames) { - if ( err ) throw err; - if (req.profiler && ! req.params.table ) { - req.profiler.done('affectedTables'); - } - - var dbName = req.params.dbname; - var cacheChannel = me.buildCacheChannel(dbName,tableNames); - // store for caching from me.generateCacheChannel - // (not worth when table was specified in params) - if ( ! req.params.table ) { - me.channelCache[cacheKey] = cacheChannel; - } - return cacheChannel; - }, - function finish(err, cacheChannel) { - callback(err, cacheChannel); - } - ); + ); }; // Set the cache chanel info to invalidate the cache on the frontend server From e1e5f8712308b11700bcd5fad73a222d5ff9dfbc Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 18:02:41 +0100 Subject: [PATCH 21/59] No longer possible to set sql param --- lib/cartodb/server_options.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 1af80410..5712d760 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -11,7 +11,6 @@ var assert = require('assert'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ 'user', - 'sql', 'cache_buster', 'cache_policy', 'callback', From 36ea58e750ab6c6f4779dca36914e695dc3bf24c Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 18:03:19 +0100 Subject: [PATCH 22/59] no longer possible to set cache_buster request param --- lib/cartodb/server_options.js | 1 - test/unit/cartodb/req2params.test.js | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 5712d760..d19dccb2 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -11,7 +11,6 @@ var assert = require('assert'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ 'user', - 'cache_buster', 'cache_policy', 'callback', 'map_key', diff --git a/test/unit/cartodb/req2params.test.js b/test/unit/cartodb/req2params.test.js index 7e2c1360..7bc4f9ac 100644 --- a/test/unit/cartodb/req2params.test.js +++ b/test/unit/cartodb/req2params.test.js @@ -64,12 +64,11 @@ suite('req2params', function() { test('it should extend params with decoded lzma', function(done) { var qo = { - style: 'test', - style_version: '2.1.0', - cache_buster: 5 + config: { + version: '1.3.0' + } }; test_helper.lzma_compress_to_base64(JSON.stringify(qo), 1, function(err, data) { - console.log(data); var req = { headers: { host:'localhost' @@ -86,7 +85,7 @@ suite('req2params', function() { return done(err); } var query = req.params; - assert.equal(qo.cache_buster, query.cache_buster); + assert.deepEqual(qo.config, query.config); assert.equal('test', query.api_key); assert.equal(undefined, query.non_included); done(); From d5e20ef558d182e99f58eaf2c644d2d67670cc4d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 18:40:59 +0100 Subject: [PATCH 23/59] Remove cache_policy query param --- lib/cartodb/server_options.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index d19dccb2..c6afe11e 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -11,7 +11,6 @@ var assert = require('assert'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ 'user', - 'cache_policy', 'callback', 'map_key', 'api_key', @@ -207,11 +206,7 @@ module.exports = function(redisPool) { req.profiler.start('addCacheChannel'); } var res = req.res; - var cache_policy = req.query.cache_policy; if ( req.params.token ) { - cache_policy = 'persist'; - } - if ( cache_policy == 'persist' ) { res.header('Cache-Control', 'public,max-age=31536000'); // 1 year } else { var ttl = global.environment.varnish.ttl || 86400; @@ -318,12 +313,8 @@ module.exports = function(redisPool) { if (req.res && req.method == 'GET') { var res = req.res; - if ( req.query && req.query.cache_policy == 'persist' ) { - res.header('Cache-Control', 'public,max-age=31536000'); // 1 year - } else { - var ttl = global.environment.varnish.layergroupTtl || 86400; - res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate'); - } + var ttl = global.environment.varnish.layergroupTtl || 86400; + res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate'); res.header('Last-Modified', (new Date()).toUTCString()); res.header('X-Cache-Channel', cacheChannel); } From 1d433bf5b22ca86d8f4b01c49ee1d8b3983c3859 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 18:58:57 +0100 Subject: [PATCH 24/59] Remove table param from generateCacheChannel --- lib/cartodb/server_options.js | 37 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index c6afe11e..1c191871 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -121,6 +121,11 @@ module.exports = function(redisPool) { var dbName = req.params.dbname; var cacheKey = [ dbName, req.params.token ].join(':'); + // no token means no tables associated + if (!req.params.token) { + return callback(null, this.buildCacheChannel(dbName, [])); + } + step( function checkCached() { if ( me.channelCache.hasOwnProperty(cacheKey) ) { @@ -137,7 +142,6 @@ module.exports = function(redisPool) { if ( ! app.mapStore ) { throw new Error('missing channel cache for token ' + req.params.token); } - var next = this; var mapStore = app.mapStore; step( function loadFromStore() { @@ -149,22 +153,24 @@ module.exports = function(redisPool) { } assert.ifError(err); - return mapConfig.obj().layers.map(function(lyr) { - return lyr.options.sql; - }).join(';'); + var queries = mapConfig.getLayers() + .map(function(lyr) { + return lyr.options.sql; + }) + .filter(function(sql) { + return !!sql; + }); + + return queries.length ? queries.join(';') : null; }, - function finish(err, sql) { - next(err, sql); - } + this ); }, function findAffectedTables(err, sql) { assert.ifError(err); + if ( ! sql ) { - if ( ! req.params.table ) { - throw new Error("this request doesn't need an X-Cache-Channel generated"); - } - return [req.params.table]; + throw new Error("this request doesn't need an X-Cache-Channel generated"); } queryTablesApi.getAffectedTablesInQuery(cdbRequest.userByReq(req), sql, this); // in addCacheChannel @@ -172,16 +178,13 @@ module.exports = function(redisPool) { function buildCacheChannel(err, tableNames) { assert.ifError(err); - if (req.profiler && ! req.params.table ) { + if (req.profiler) { req.profiler.done('affectedTables'); } var cacheChannel = me.buildCacheChannel(dbName,tableNames); - // store for caching from me.generateCacheChannel - // (not worth when table was specified in params) - if ( ! req.params.table ) { - me.channelCache[cacheKey] = cacheChannel; - } + me.channelCache[cacheKey] = cacheChannel; + return cacheChannel; }, function finish(err, cacheChannel) { From 07bc281e25e21f1cf4bbfe994adfc5c52ed72c08 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 19:19:46 +0100 Subject: [PATCH 25/59] Remove check table privacy --- lib/cartodb/server_options.js | 66 ++++++++++------------------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 1c191871..af00223d 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -342,34 +342,27 @@ module.exports = function(redisPool) { // null if the request is not signed by anyone // or will be a string cartodb username otherwise. // - me.authorizedBySigner = function(req, callback) - { - if ( ! req.params.token || ! req.params.signer ) { - //console.log("No signature provided"); // debugging - callback(null, null); // no signer requested - return; - } - - var signer = req.params.signer; - var layergroup_id = req.params.token; - var auth_token = req.params.auth_token; - - //console.log("Checking authorization from signer " + signer + " for resource " + layergroup_id + - // " with auth_token " + auth_token); - var mapStore = req.app.mapStore; - if (!mapStore) { - throw new Error('Unable to retrieve map configuration token'); - } - - mapStore.load(layergroup_id, function(err, mapConfig) { - if (err) { - throw err; + me.authorizedBySigner = function(req, callback) { + if ( ! req.params.token || ! req.params.signer ) { + return callback(null, null); // no signer requested } - var authorized = me.templateMaps.isAuthorized(mapConfig.obj().template, auth_token); - callback(null, authorized ? signer : null); - }); + var signer = req.params.signer; + var layergroup_id = req.params.token; + var auth_token = req.params.auth_token; + var mapStore = req.app.mapStore; + if (!mapStore) { + throw new Error('Unable to retrieve map configuration token'); + } + + mapStore.load(layergroup_id, function(err, mapConfig) { + assert.ifError(err); + + var authorized = me.templateMaps.isAuthorized(mapConfig.obj().template, auth_token); + + return callback(null, authorized ? signer : null); + }); }; // Check if a request is authorized by api_key @@ -452,11 +445,6 @@ module.exports = function(redisPool) { if ( ! signed_by ) { // request not authorized by signer. - - // if table was given, continue to check table privacy - if ( req.params.table ) { - return null; - } // if no signer name was given, let dbparams and // PostgreSQL do the rest. @@ -479,24 +467,6 @@ module.exports = function(redisPool) { } callback(err, true); // authorized (or error) }); - }, - function getDatabase(err){ - assert.ifError(err); - // NOTE: only used to get to table privacy - cartoData.getUserDBName(user, this); - }, - function getPrivacy(err, dbname){ - assert.ifError(err); - if (req.profiler) { - req.profiler.done('tablePrivacy_getUserDBName'); - } - cartoData.getTablePrivacy(dbname, req.params.table, this); - }, - function(err, privacy){ - if (req.profiler) { - req.profiler.done('getTablePrivacy'); - } - callback(err, privacy !== "0"); } ); }; From 985973dfda49c027f9ff32fccda0335646fc0ae3 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 23 Mar 2015 19:28:34 +0100 Subject: [PATCH 26/59] Split old api and basic endpoints --- test/acceptance/server.js | 83 ++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 4b9b19c6..0b04eada 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -18,46 +18,7 @@ server.setMaxListeners(0); var cdbQueryTablesFromPostgresEnabledValue = true; -suite.skip('server', function() { - - var redis_client = redis.createClient(global.environment.redis.port); - var sqlapi_server; - - var mapnik_version = global.environment.mapnik_version || server.getVersion().mapnik; - var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; - var default_style; - if ( semver.satisfies(mapnik_version, '<2.1.0') ) { - // 2.0.0 default - default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;marker-line-color: white;' + - 'marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ' + - 'ellipse;marker-allow-overlap: true;}'; - } - else if ( semver.satisfies(mapnik_version, '<2.2.0') ) { - // 2.1.0 default - default_style = '#<%= table %>[mapnik-geometry-type=1] {marker-fill: #FF6600;marker-opacity: 1;' + - 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + - 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + - '#<%= table %>[mapnik-geometry-type=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + - '#<%= table %>[mapnik-geometry-type=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + - ' line-color: #FFFFFF;}'; - } - else { - // 2.2.0+ default - default_style = '#<%= table %>["mapnik::geometry_type"=1] {marker-fill: #FF6600;marker-opacity: 1;' + - 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + - 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + - '#<%= table %>["mapnik::geometry_type"=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + - '#<%= table %>["mapnik::geometry_type"=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + - ' line-color: #FFFFFF;}'; - } - - // A couple of styles to use during testing - var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; - var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - - suiteSetup(function(done){ - sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); - }); +suite('server', function() { ///////////////////////////////////////////////////////////////////////////////// // @@ -116,6 +77,48 @@ suite.skip('server', function() { done(); }); }); +}); + +suite.skip('server old_api', function() { + + var redis_client = redis.createClient(global.environment.redis.port); + var sqlapi_server; + + var mapnik_version = global.environment.mapnik_version || server.getVersion().mapnik; + var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; + var default_style; + if ( semver.satisfies(mapnik_version, '<2.1.0') ) { + // 2.0.0 default + default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;marker-line-color: white;' + + 'marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ' + + 'ellipse;marker-allow-overlap: true;}'; + } + else if ( semver.satisfies(mapnik_version, '<2.2.0') ) { + // 2.1.0 default + default_style = '#<%= table %>[mapnik-geometry-type=1] {marker-fill: #FF6600;marker-opacity: 1;' + + 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + + 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + + '#<%= table %>[mapnik-geometry-type=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + + '#<%= table %>[mapnik-geometry-type=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + + ' line-color: #FFFFFF;}'; + } + else { + // 2.2.0+ default + default_style = '#<%= table %>["mapnik::geometry_type"=1] {marker-fill: #FF6600;marker-opacity: 1;' + + 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + + 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + + '#<%= table %>["mapnik::geometry_type"=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + + '#<%= table %>["mapnik::geometry_type"=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + + ' line-color: #FFFFFF;}'; + } + + // A couple of styles to use during testing + var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; + var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; + + suiteSetup(function(done){ + sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); + }); ///////////////////////////////////////////////////////////////////////////////// // From f683e39aea84d89e062e5699e80d27ee84075f00 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 24 Mar 2015 10:38:14 +0100 Subject: [PATCH 27/59] Remove api sql emulator --- .../cache/surrogate_keys_invalidation.js | 21 ++--- test/acceptance/multilayer.js | 8 +- test/acceptance/server.js | 10 +-- test/acceptance/templates.js | 9 +-- test/support/SQLAPIEmu.js | 81 ------------------- 5 files changed, 12 insertions(+), 117 deletions(-) delete mode 100644 test/support/SQLAPIEmu.js diff --git a/test/acceptance/cache/surrogate_keys_invalidation.js b/test/acceptance/cache/surrogate_keys_invalidation.js index 01299585..83b2dca2 100644 --- a/test/acceptance/cache/surrogate_keys_invalidation.js +++ b/test/acceptance/cache/surrogate_keys_invalidation.js @@ -1,10 +1,8 @@ +require(__dirname + '/../../support/test_helper'); + var assert = require('../../support/assert'); var redis = require('redis'); -var Step = require('step'); - -var helper = require(__dirname + '/../../support/test_helper'); - -var SqlApiEmulator = require(__dirname + '/../../support/SQLAPIEmu.js'); +var step = require('step'); var NamedMapsCacheEntry = require(__dirname + '/../../../lib/cartodb/cache/model/named_maps_entry'); var SurrogateKeysCache = require(__dirname + '/../../../lib/cartodb/cache/surrogate_keys_cache'); @@ -16,7 +14,6 @@ var serverOptions = ServerOptions(); suite('templates surrogate keys', function() { - var sqlApiServer; var redisClient = redis.createClient(global.environment.redis.port); // Enable Varnish purge for tests @@ -48,10 +45,6 @@ suite('templates surrogate keys', function() { }, expectedBody = { template_id: expectedTemplateId }; - suiteSetup(function(done) { - sqlApiServer = new SqlApiEmulator(global.environment.sqlapi.port, done); - }); - var surrogateKeysCacheInvalidateFn = SurrogateKeysCache.prototype.invalidate; function createTemplate(callback) { @@ -65,7 +58,7 @@ suite('templates surrogate keys', function() { data: JSON.stringify(template) }; - Step( + step( function postTemplate() { var next = this; assert.response(server, @@ -100,7 +93,7 @@ suite('templates surrogate keys', function() { surrogateKeysCacheInvalidateMethodInvoked = true; }; - Step( + step( function createTemplateToUpdate() { createTemplate(this); }, @@ -165,7 +158,7 @@ suite('templates surrogate keys', function() { surrogateKeysCacheInvalidateMethodInvoked = true; }; - Step( + step( function createTemplateToDelete() { createTemplate(this); }, @@ -212,7 +205,7 @@ suite('templates surrogate keys', function() { SurrogateKeysCache.prototype.invalidate = surrogateKeysCacheInvalidateFn; // Enable Varnish purge for tests serverOptions.varnish_purge_enabled = false; - sqlApiServer.close(done); + done(); }); }); diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index c94d8380..e0b12507 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -6,7 +6,6 @@ var querystring = require('querystring'); var semver = require('semver'); var Step = require('step'); var strftime = require('strftime'); -var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js'); var redis_stats_db = 5; var helper = require(__dirname + '/../support/test_helper'); @@ -35,13 +34,8 @@ suite(suiteName, function() { var expected_last_updated = new Date(expected_last_updated_epoch).toISOString(); var test_user = _.template(global.environment.postgres_auth_user, {user_id:1}); - var test_pubuser = global.environment.postgres.user; var test_database = test_user + '_db'; - suiteSetup(function(done){ - sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); - }); - test("layergroup with 2 layers, each with its style", function(done) { var layergroup = { @@ -1432,7 +1426,7 @@ suite(suiteName, function() { redis_client.select(5, function(err, matches) { redis_client.keys("user:localhost:mapviews*", function(err, matches) { redis_client.del(matches, function(err) { - sqlapi_server.close(done); + done(); }); }); }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 0b04eada..84ad2b1e 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -4,7 +4,6 @@ var redis = require('redis'); var querystring = require('querystring'); var semver = require('semver'); var step = require('step'); -var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js'); var helper = require(__dirname + '/../support/test_helper'); @@ -116,10 +115,6 @@ suite.skip('server old_api', function() { var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - suiteSetup(function(done){ - sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); - }); - ///////////////////////////////////////////////////////////////////////////////// // // POST STYLE @@ -1086,8 +1081,9 @@ suite.skip('server old_api', function() { // This test will add map_style records, like // 'map_style|null|publicuser|my_table', redis_client.keys("map_style|*", function(err, matches) { - _.each(matches, function(k) { redis_client.del(k); }); - sqlapi_server.close(done); + redis_client.del(matches, function() { + done(); + }); }); }); diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index 13923b4d..70339e6e 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -6,7 +6,6 @@ var semver = require('semver'); var Step = require('step'); var strftime = require('strftime'); var NamedMapsCacheEntry = require(__dirname + '/../../lib/cartodb/cache/model/named_maps_entry'); -var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js'); var redis_stats_db = 5; // Pollute the PG environment to make sure @@ -29,15 +28,9 @@ suite('template_api', function() { serverOptions.channelCache = {}; var redis_client = redis.createClient(global.environment.redis.port); - var sqlapi_server; var expected_last_updated_epoch = 1234567890123; // this is hard-coded into SQLAPIEmu var expected_last_updated = new Date(expected_last_updated_epoch).toISOString(); - suiteSetup(function(done){ - sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done); - // TODO: check redis is clean ? - }); - var template_acceptance1 = { version: '0.0.1', name: 'acceptance1', @@ -2108,7 +2101,7 @@ suite('template_api', function() { redis_client.select(5, function(err) { redis_client.keys("user:localhost:mapviews*", function(err, keys) { redis_client.del(keys, function(err) { - sqlapi_server.close(done); + done(); }); }); }); diff --git a/test/support/SQLAPIEmu.js b/test/support/SQLAPIEmu.js deleted file mode 100644 index 074e7ada..00000000 --- a/test/support/SQLAPIEmu.js +++ /dev/null @@ -1,81 +0,0 @@ -var http = require('http'); -var url = require('url'); -var _ = require('underscore'); - -var SQLAPIEmulator = function(port, cb) { - - this.queries = []; - var that = this; - this.requests = []; - - this.sqlapi_server = http.createServer(function(req,res) { - //console.log("server got request with method " + req.method); - var query; - - that.requests.push(req); - - if ( req.method == 'GET' ) { - query = url.parse(req.url, true).query; - that.handleQuery(query, res); - } - else if ( req.method == 'POST') { - var data = ''; - req.on('data', function(chunk) { - //console.log("GOT Chunk " + chunk); - data += chunk; - }); - req.on('end', function() { - //console.log("Data is: "); console.dir(data); - query = JSON.parse(data); - //console.log("handleQuery is " + that.handleQuery); - that.handleQuery(query, res); - }); - } - else { - that.handleQuery('SQLAPIEmu does not support method' + req.method, res); - } - }).listen(port, cb); -}; - -SQLAPIEmulator.prototype.handleQuery = function(query, res) { - this.queries.push(query); - if ( query.q.match('SQLAPIERROR') ) { - res.statusCode = 400; - res.write(JSON.stringify({'error':'Some error occurred'})); - } else if ( query.q.match('SQLAPINOANSWER') ) { - console.log("SQLAPIEmulator will never respond, on request"); - return; - } else if (query.q.match('tablenames')) { - var tableNames = JSON.stringify(query); - res.write(queryResult({tablenames: '{' + tableNames + '}', max: 1234567890.123})); - } else if ( query.q.match('EPOCH.* as max') ) { - // This is the structure of the known query sent by tiler - res.write(queryResult({max: 1234567890.123})); - } else { - if ( query.q.match('_private_') && query.api_key === undefined) { - res.statusCode = 403; - res.write(JSON.stringify({'error':'forbidden: ' + JSON.stringify(query)})); - } else { - var qs = JSON.stringify(query); - res.write(queryResult({cdb_querytables: '{' + qs + '}', max: 1234567890.123})); - } - } - res.end(); - }; - -SQLAPIEmulator.prototype.close = function(cb) { - this.sqlapi_server.close(cb); -}; - -SQLAPIEmulator.prototype.getLastRequest = function() { - return this.requests.pop(); -}; - -function queryResult(row) { - return JSON.stringify({ - rows: [row] - }); -} - -module.exports = SQLAPIEmulator; - From 3012b99e155fbe4a9a313a913af598904ac066be Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 24 Mar 2015 10:39:23 +0100 Subject: [PATCH 28/59] Remove varnish emu --- test/support/VarnishEmu.js | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 test/support/VarnishEmu.js diff --git a/test/support/VarnishEmu.js b/test/support/VarnishEmu.js deleted file mode 100644 index 6cd636d0..00000000 --- a/test/support/VarnishEmu.js +++ /dev/null @@ -1,25 +0,0 @@ -var net = require('net'); - -module.exports = function(on_cmd_recieved, test_callback) { - var self = this; - var welcome_msg = 'hi, im a varnish emu, right?'; - - self.commands_recieved = []; - - var server = net.createServer(function (socket) { - var command = ''; - socket.write("200 " + welcome_msg.length + "\n"); - socket.write(welcome_msg); - socket.on('data', function(data) { - self.commands_recieved.push(data); - on_cmd_recieved && on_cmd_recieved(self.commands_recieved); - socket.write('200 0\n'); - }); - }); - server.listen(1337, "127.0.0.1"); - - server.on('listening', function(){ - test_callback(); - }); -}; - From 4be0a7036280c6d718809f13745df6f4fbe451b7 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 26 Mar 2015 13:05:35 +0100 Subject: [PATCH 29/59] Do not append interactivity to params, it is no longer it will be used from mapconfig layer definition --- lib/cartodb/server_options.js | 3 --- test/unit/cartodb/req2params.test.js | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index af00223d..d1dbb11c 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -550,9 +550,6 @@ module.exports = function(redisPool) { // bring all query values onto req.params object _.extend(req.params, req.query); - // for cartodb, ensure interactivity is cartodb_id or user specified - req.params.interactivity = req.params.interactivity || 'cartodb_id'; - if (req.profiler) { req.profiler.done('req2params.setup'); } diff --git a/test/unit/cartodb/req2params.test.js b/test/unit/cartodb/req2params.test.js index 7bc4f9ac..932bec05 100644 --- a/test/unit/cartodb/req2params.test.js +++ b/test/unit/cartodb/req2params.test.js @@ -22,7 +22,7 @@ suite('req2params', function() { assert.ok(_.isObject(req.query), 'request has query'); assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query'); assert.ok(req.hasOwnProperty('params'), 'request has params'); - assert.ok(req.params.hasOwnProperty('interactivity'), 'request params have interactivity'); + assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity'); assert.equal(req.params.dbname, test_database, 'could forge dbname: '+ req.params.dbname); assert.ok(req.params.dbuser === test_pubuser, 'could inject dbuser ('+req.params.dbuser+')'); done(); @@ -36,7 +36,7 @@ suite('req2params', function() { assert.ok(_.isObject(req.query), 'request has query'); assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query'); assert.ok(req.hasOwnProperty('params'), 'request has params'); - assert.ok(req.params.hasOwnProperty('interactivity'), 'request params have interactivity'); + assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity'); assert.equal(req.params.dbname, test_database); assert.ok(req.params.dbuser === test_pubuser, 'could inject dbuser ('+req.params.dbuser+')'); done(); @@ -50,7 +50,7 @@ suite('req2params', function() { assert.ok(_.isObject(req.query), 'request has query'); assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query'); assert.ok(req.hasOwnProperty('params'), 'request has params'); - assert.ok(req.params.hasOwnProperty('interactivity'), 'request params have interactivity'); + assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity'); assert.equal(req.params.dbname, test_database); assert.equal(req.params.dbuser, test_user); From d210643d63cc47fb67c76a970b14b637417ec180 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 26 Mar 2015 17:19:16 +0100 Subject: [PATCH 30/59] Only required query params --- lib/cartodb/server_options.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index d1dbb11c..e595d26b 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -10,13 +10,11 @@ var assert = require('assert'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ - 'user', - 'callback', + 'config', 'map_key', 'api_key', 'auth_token', - 'config', - 'scale_factor' + 'callback' ]; module.exports = function(redisPool) { @@ -495,7 +493,7 @@ module.exports = function(redisPool) { lzma, function(result) { if (req.profiler) { - req.profiler.done('LZMA decompress'); + req.profiler.done('lzma'); } try { delete req.query.lzma; @@ -504,18 +502,13 @@ module.exports = function(redisPool) { } catch (err) { callback(new Error('Error parsing lzma as JSON: ' + err)); } - }, - function(/*percent*/) { // progress - //console.log("LZMA decompression " + percent + "%"); } ); return; } - var bad_query = _.difference(_.keys(req.query), REQUEST_QUERY_PARAMS_WHITELIST); - - _.each(bad_query, function(key){ delete req.query[key]; }); - req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object + 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 = cdbRequest.userByReq(req); From 1f538847229b61c32828540096925c3b4749e96e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 27 Mar 2015 17:57:46 +0100 Subject: [PATCH 31/59] Remove metrics for authorizedBy* --- docs/metrics.md | 2 -- lib/cartodb/server_options.js | 11 ----------- 2 files changed, 13 deletions(-) diff --git a/docs/metrics.md b/docs/metrics.md index ba356a48..0d641ac6 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -25,9 +25,7 @@ Again, each inner timer may have several inner timers. - **TemplateMaps_instance**: time to retrieve a map template instance, see *getTemplate* and *authorizedByCert* - **affectedTables**: time to check what are the affected tables for adding the cache channel, see *addCacheChannel* - **authorize**: time to authorize a request, see *authorizedByAPIKey*, *authorizedByCert*, *authorizedBySigner* -- **authorizedByAPIKey**: time to authorize using an API KEY - **authorizedByCert**: time to authorize a template instantiation -- **authorizedBySigner**: time to authorize a request with auth_token - **findLastUpdated**: time to retrieve the last update time for a list of tables, see *affectedTables* - **generateCacheChannel**: time to generate the headers for the cache channel based on the request, see *addCacheChannel* - **getSignerMapKey**: time to retrieve from redis the authorized user for a template map diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index e595d26b..e1957fbb 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -424,8 +424,6 @@ module.exports = function(redisPool) { return; } - _.extend(req.params, { _authorizedByApiKey: true }); - // authorized by api key, login as the given username and stop pgConnection.setDBAuth(user, req.params, function(err) { callback(err, true); // authorized (or error) @@ -433,13 +431,6 @@ module.exports = function(redisPool) { }, function checkSignAuthorized(err, signed_by){ assert.ifError(err); - if (req.profiler) { - if ( req.params._authorizedByApiKey ) { - req.profiler.done('setDBAuth'); - } else { - req.profiler.done('authorizedBySigner'); - } - } if ( ! signed_by ) { // request not authorized by signer. @@ -457,8 +448,6 @@ module.exports = function(redisPool) { return; } - // Authorized by "signed_by" ! - _.extend(req.params, { _authorizedBySigner: signed_by }); pgConnection.setDBAuth(signed_by, req.params, function(err) { if (req.profiler) { req.profiler.done('setDBAuth'); From d0313a42287e56e3bcab77ab4cef8b91ff07937d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 27 Mar 2015 17:59:55 +0100 Subject: [PATCH 32/59] Remove gc_prob as it is no longer used in grainstore --- lib/cartodb/server_options.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index e1957fbb..e7f8b855 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -57,8 +57,7 @@ module.exports = function(redisPool) { cachedir: global.environment.millstone.cache_basedir, mapnik_version: global.environment.mapnik_version, mapnik_tile_format: global.environment.mapnik_tile_format || 'png', - default_layergroup_ttl: global.environment.mapConfigTTL || 7200, - gc_prob: 0.01 // @deprecated since Windshaft-1.8.0 + default_layergroup_ttl: global.environment.mapConfigTTL || 7200 }, mapnik: { poolSize: rendererConfig.poolSize, From da4b1d5a0f8554375247da3e91d6bbcd88502db4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:13:59 +0200 Subject: [PATCH 33/59] jshint --- test/acceptance/multilayer.js | 243 ++++++++++++++-------------------- test/acceptance/server.js | 6 +- 2 files changed, 106 insertions(+), 143 deletions(-) diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index e0b12507..e2fe35f3 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -1,10 +1,7 @@ var assert = require('../support/assert'); -var tests = module.exports = {}; var _ = require('underscore'); var redis = require('redis'); -var querystring = require('querystring'); -var semver = require('semver'); -var Step = require('step'); +var step = require('step'); var strftime = require('strftime'); var redis_stats_db = 5; @@ -16,9 +13,8 @@ var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20; var IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL = 25; var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft'); -var ServerOptions = require(__dirname + '/../../lib/cartodb/server_options'); -serverOptions = ServerOptions(); -var server = new CartodbWindshaft(serverOptions); +var serverOptions = require(__dirname + '/../../lib/cartodb/server_options'); +var server = new CartodbWindshaft(serverOptions()); server.setMaxListeners(0); ['/api/v1/map', '/u/localhost/api/v1/map'].forEach(function(layergroup_url) { @@ -26,7 +22,7 @@ server.setMaxListeners(0); var suiteName = 'multilayer:postgres=layergroup_url=' + layergroup_url; suite(suiteName, function() { - var cdbQueryTablesFromPostgresEnabledValue = true + var cdbQueryTablesFromPostgresEnabledValue = true; var redis_client = redis.createClient(global.environment.redis.port); var sqlapi_server; @@ -42,13 +38,15 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2', + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2', cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }', cartocss_version: '2.0.1', interactivity: 'cartodb_id' } }, { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, -5e6, 0) as the_geom_webmercator from test_table limit 2 offset 2', + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, -5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2 offset 2', cartocss: '#layer { marker-fill:blue; marker-allow-overlap:true; }', cartocss_version: '2.0.2', interactivity: 'cartodb_id' @@ -57,7 +55,7 @@ suite(suiteName, function() { }; var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7"; - Step( + step( function do_post() { var next = this; @@ -69,14 +67,6 @@ suite(suiteName, function() { }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); - var expectedBody = { layergroupid: expected_token }; - // check last modified - var qTables = JSON.stringify({ - 'q': 'SELECT CDB_QueryTables($windshaft$' - + layergroup.layers[0].options.sql + ';' - + layergroup.layers[1].options.sql - + '$windshaft$)' - }); assert.equal(parsedBody.last_updated, expected_last_updated); if ( expected_token ) { assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch); @@ -110,19 +100,23 @@ suite(suiteName, function() { if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API var jsonquery = cc.substring(dbname.length + 1); var sentquery = JSON.parse(jsonquery); - var expectedQuery = [layergroup.layers[0].options.sql, ';', layergroup.layers[1].options.sql].join(''); - assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' - + expectedQuery - + '$windshaft$) as tablenames )' - + ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' - + ' FROM CDB_TableMetadata m' - + ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])'); + var expectedQuery = [ + layergroup.layers[0].options.sql, ';', + layergroup.layers[1].options.sql + ].join(''); + assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' + + expectedQuery + + '$windshaft$) as tablenames )' + + ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' + + ' FROM CDB_TableMetadata m' + + ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])'); } - assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png', IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL, - function(err, similarity) { - next(err); - }); + assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png', + IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + next(err); + } + ); }); }, // See https://github.com/CartoDB/Windshaft-cartodb/issues/170 @@ -148,15 +142,14 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/0/0/0/0.grid.json', + url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['content-type'], "application/json; charset=utf-8"); assert.utfgridEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.layer0.grid.json', 2, - function(err, similarity) { + function(err/*, similarity*/) { next(err); }); }); @@ -166,15 +159,14 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/1/0/0/0.grid.json', + url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['content-type'], "application/json; charset=utf-8"); assert.utfgridEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.layer1.grid.json', 2, - function(err, similarity) { + function(err/*, similarity*/) { next(err); }); }); @@ -200,20 +192,20 @@ suite(suiteName, function() { test("should include serverMedata in the response", function(done) { - global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } } + global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } }; var layergroup = { version: '1.0.0', layers: [ { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2', + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2', cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }', cartocss_version: '2.0.1' } } ] }; - var expected_token; - Step( + step( function do_create_get() { var next = this; @@ -228,7 +220,7 @@ suite(suiteName, function() { assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url)); done(); } - ) + ); }); @@ -238,7 +230,8 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2', + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2', cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }', cartocss_version: '2.0.1' } } @@ -246,7 +239,7 @@ suite(suiteName, function() { }; var expected_token; - Step( + step( function do_create_get() { var next = this; @@ -310,7 +303,8 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2', + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2', cartocss: '#layer { invalid-rule:red; }', cartocss_version: '2.0.1' } } @@ -333,8 +327,8 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select 1 as cartodb_id, ' - + 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator from test_table limit 1', + sql: 'select 1 as cartodb_id, ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!))' + + ' as the_geom_webmercator from test_table limit 1', cartocss: '#layer { polygon-fill:red; }', cartocss_version: '2.0.1', interactivity: 'cartodb_id' @@ -343,7 +337,7 @@ suite(suiteName, function() { }; var expected_token; // = "6d8e4ad5458e2d25cf0eef38e38717a6"; - Step( + step( function do_post() { var next = this; @@ -355,13 +349,6 @@ suite(suiteName, function() { }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); - var expectedBody = { layergroupid: expected_token }; - // check last modified - var qTables = JSON.stringify({ - 'q': 'SELECT CDB_QueryTables($windshaft$' - + layergroup.layers[0].options.sql - + '$windshaft$)' - }); assert.equal(parsedBody.last_updated, expected_last_updated); if ( expected_token ) { assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch); @@ -395,16 +382,16 @@ suite(suiteName, function() { .replace(/!bbox!/g, 'ST_MakeEnvelope(0,0,0,0)') .replace(/!pixel_width!/g, '1') .replace(/!pixel_height!/g, '1'); - assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' - + expectedQuery - + '$windshaft$) as tablenames )' - + ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' - + ' FROM CDB_TableMetadata m' - + ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])'); + assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' + + expectedQuery + + '$windshaft$) as tablenames )' + + ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' + + ' FROM CDB_TableMetadata m' + + ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])'); } assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { + function(err/*, similarity*/) { next(err); }); }); @@ -434,16 +421,16 @@ suite(suiteName, function() { .replace('!bbox!', 'ST_MakeEnvelope(0,0,0,0)') .replace('!pixel_width!', '1') .replace('!pixel_height!', '1'); - assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' - + expectedQuery - + '$windshaft$) as tablenames )' - + ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' - + ' FROM CDB_TableMetadata m' - + ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])'); + assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' + + expectedQuery + + '$windshaft$) as tablenames )' + + ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' + + ' FROM CDB_TableMetadata m' + + ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])'); } assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { + function(err/*, similarity*/) { next(err); }); }); @@ -453,15 +440,14 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/0/1/0/0.grid.json', + url: layergroup_url + "/" + expected_token + '/0/1/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['content-type'], "application/json; charset=utf-8"); assert.utfgridEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.grid.json', 2, - function(err, similarity) { + function(err/*, similarity*/) { next(err); }); }); @@ -471,15 +457,14 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/0/4/0/0.grid.json', + url: layergroup_url + "/" + expected_token + '/0/4/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['content-type'], "application/json; charset=utf-8"); assert.utfgridEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.grid.json', 2, - function(err, similarity) { + function(err/*, similarity*/) { next(err); }); }); @@ -509,8 +494,8 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select 1 as cartodb_id, !pixel_height! as h, ' - + 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator', + sql: 'select 1 as cartodb_id, !pixel_height! as h,' + + ' ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator', cartocss: '#layer { polygon-fill:red; }', cartocss_version: '2.0.1' } } @@ -521,7 +506,7 @@ suite(suiteName, function() { var expected_token; // will be set on first post and checked on second var now = strftime("%Y%m%d", new Date()); var errors = []; - Step( + step( function clean_stats() { var next = this; @@ -547,14 +532,13 @@ suite(suiteName, function() { }, function check_global_stats_1(err, val) { if ( err ) throw err; - assert.equal(val, 1, "Expected score of " + now + " in " - + statskey + ":global to be 1, got " + val); + assert.equal(val, 1, "Expected score of " + now + " in " + statskey + ":global to be 1, got " + val); redis_stats_client.zscore(statskey+':stat_tag:random_tag', now, this); }, function check_tag_stats_1_do_post_2(err, val) { if ( err ) throw err; - assert.equal(val, 1, "Expected score of " + now + " in " - + statskey + ":stat_tag:" + layergroup.stat_tag + " to be 1, got " + val); + assert.equal(val, 1, "Expected score of " + now + " in " + statskey + ":stat_tag:" + layergroup.stat_tag + + " to be 1, got " + val); var next = this; assert.response(server, { url: layergroup_url, @@ -570,15 +554,14 @@ suite(suiteName, function() { function check_global_stats_2(err, val) { if ( err ) throw err; - assert.equal(val, 2, "Expected score of " + now + " in " - + statskey + ":global to be 2, got " + val); + assert.equal(val, 2, "Expected score of " + now + " in " + statskey + ":global to be 2, got " + val); redis_stats_client.zscore(statskey+':stat_tag:' + layergroup.stat_tag, now, this); }, function check_tag_stats_2(err, val) { if ( err ) throw err; - assert.equal(val, 2, "Expected score of " + now + " in " - + statskey + ":stat_tag:" + layergroup.stat_tag + " to be 2, got " + val); + assert.equal(val, 2, "Expected score of " + now + " in " + statskey + ":stat_tag:" + layergroup.stat_tag + + " to be 2, got " + val); return 1; }, function cleanup_map_style(err) { @@ -608,8 +591,8 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select 1 as cartodb_id, !pixel_height! as h' - + 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator', + sql: 'select 1 as cartodb_id, !pixel_height! as h' + + 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator', cartocss: '#layer { polygon-fit:red; }', cartocss_version: '2.0.1' } } @@ -679,7 +662,7 @@ suite(suiteName, function() { }; var expected_token; // = "b4ed64d93a411a59f330ab3d798e4009"; - Step( + step( function do_post() { var next = this; @@ -691,14 +674,6 @@ suite(suiteName, function() { }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); - var expectedBody = { layergroupid: expected_token }; - // check last modified - var qTables = JSON.stringify({ - 'q': 'SELECT CDB_QueryTables($windshaft$' - + layergroup.layers[0].options.sql + ';' - + layergroup.layers[1].options.sql - + '$windshaft$)' - }); assert.equal(parsedBody.last_updated, expected_last_updated); if ( expected_token ) { assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch); @@ -733,8 +708,7 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/0/0/0/0.grid.json?map_key=1234', + url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json?map_key=1234', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { @@ -747,8 +721,7 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/1/0/0/0.grid.json?map_key=1234', + url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json?map_key=1234', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { @@ -768,7 +741,7 @@ suite(suiteName, function() { encoding: 'binary' }, {}, function(res) { assert.equal(res.statusCode, 403); - var re = RegExp('permission denied'); + var re = new RegExp('permission denied'); assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body); next(err); }); @@ -778,13 +751,12 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/0/0/0/0.grid.json', + url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { assert.equal(res.statusCode, 403); - var re = RegExp('permission denied'); + var re = new RegExp('permission denied'); assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body); next(err); }); @@ -794,13 +766,12 @@ suite(suiteName, function() { if ( err ) throw err; var next = this; assert.response(server, { - url: layergroup_url + "/" + expected_token - + '/1/0/0/0.grid.json', + url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' }, {}, function(res) { assert.equal(res.statusCode, 403); - var re = RegExp('permission denied'); + var re = new RegExp('permission denied'); assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body); next(err); }); @@ -840,7 +811,7 @@ suite(suiteName, function() { }; var expected_token; // = "b4ed64d93a411a59f330ab3d798e4009"; - Step( + step( function do_post() { var next = this; @@ -855,13 +826,6 @@ suite(suiteName, function() { if ( err ) throw err; assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); - var expectedBody = { layergroupid: expected_token }; - // check last modified - var qTables = JSON.stringify({ - 'q': 'SELECT CDB_QueryTables($windshaft$' - + layergroup.layers[0].options.sql - + '$windshaft$)' - }); assert.equal(parsedBody.last_updated, expected_last_updated); if ( expected_token ) { assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch); @@ -892,11 +856,10 @@ suite(suiteName, function() { assert.equal(cc.substring(0, dbname.length), dbname); return null; }, - function do_restart_server(err, res) { + function do_restart_server(err/*, res*/) { if ( err ) throw err; // hack simulating restart... - serverOptions = ServerOptions(); - server = new CartodbWindshaft(serverOptions); + server = new CartodbWindshaft(serverOptions()); return null; }, function do_get1(err) @@ -950,7 +913,7 @@ suite(suiteName, function() { { options: { sql: "select 1 as cartodb_id, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator", cartocss: '#sample { text-name: cartodb_id; text-face-name: "Dejagnu"; }', - cartocss_version: '2.1.0', + cartocss_version: '2.1.0' } } ] }; @@ -978,12 +941,12 @@ suite(suiteName, function() { { options: { sql: "select 'single''quote' as n, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator", cartocss: '#s [n="single\'quote" ] { marker-fill:red; }', - cartocss_version: '2.1.0', + cartocss_version: '2.1.0' } }, { options: { sql: "select 'double\"quote' as n, 'SRID=3857;POINT(2 0)'::geometry as the_geom_webmercator", cartocss: '#s [n="double\\"quote" ] { marker-fill:red; }', - cartocss_version: '2.1.0', + cartocss_version: '2.1.0' } } ] }; @@ -1007,7 +970,7 @@ suite(suiteName, function() { { options: { sql: "select .4 as n, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator", cartocss: '#s [n<=.2e-2] { marker-fill:red; }', - cartocss_version: '2.1.0', + cartocss_version: '2.1.0' } } ] }; @@ -1035,7 +998,7 @@ suite(suiteName, function() { ] }; var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7"; - Step( + step( function do_post() { var next = this; @@ -1047,7 +1010,6 @@ suite(suiteName, function() { }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); - var expectedBody = { layergroupid: expected_token }; if ( expected_token ) { assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch); } @@ -1071,10 +1033,11 @@ suite(suiteName, function() { }, {}, function(res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['content-type'], "image/png"); - assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, - function(err, similarity) { - next(err); - }); + assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png', + IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { + next(err); + } + ); }); }, function finish(err) { @@ -1111,7 +1074,7 @@ suite(suiteName, function() { ] }; var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7"; - Step( + step( function do_post() { var next = this; @@ -1150,7 +1113,6 @@ suite(suiteName, function() { }, function check_get_tile(err, res) { if ( err ) throw err; - var next = this; assert.equal(res.statusCode, 200, res.body); return null; }, @@ -1182,10 +1144,10 @@ suite(suiteName, function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/111 test("sql string can be very long", function(done){ var long_val = 'pretty'; - for (var i=0; i<1024; ++i) long_val += ' long' + for (var i=0; i<1024; ++i) long_val += ' long'; long_val += ' string'; var sql = "SELECT "; - for (var i=0; i<16; ++i) + for (i=0; i<16; ++i) sql += "'" + long_val + "'::text as pretty_long_field_name_" + i + ", "; sql += "cartodb_id, the_geom_webmercator FROM gadm4 g"; var layergroup = { @@ -1200,7 +1162,7 @@ suite(suiteName, function() { }; var errors = []; var expected_token; - Step( + step( function do_post() { var data = JSON.stringify(layergroup); @@ -1253,13 +1215,14 @@ suite(suiteName, function() { version: '1.0.0', layers: [ { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2', + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2', interactivity: 'cartodb_id' } } ] }; - Step( + step( function do_post() { var next = this; @@ -1301,7 +1264,7 @@ suite(suiteName, function() { ] }; - Step( + step( function do_post() { var next = this; @@ -1409,7 +1372,7 @@ suite(suiteName, function() { { status: 403 }, - function(res, err) { + function(res) { assert.ok(res.body.match(/permission denied for relation test_table_private_1/)); done(); } @@ -1422,10 +1385,10 @@ suite(suiteName, function() { // This test will add map_style records, like // 'map_style|null|publicuser|my_table', redis_client.keys("map_style|*", function(err, matches) { - redis_client.del(matches, function(err) { - redis_client.select(5, function(err, matches) { + redis_client.del(matches, function() { + redis_client.select(5, function() { redis_client.keys("user:localhost:mapviews*", function(err, matches) { - redis_client.del(matches, function(err) { + redis_client.del(matches, function() { done(); }); }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 84ad2b1e..ee6144ef 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -88,9 +88,9 @@ suite.skip('server old_api', function() { var default_style; if ( semver.satisfies(mapnik_version, '<2.1.0') ) { // 2.0.0 default - default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;marker-line-color: white;' + - 'marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;marker-type: ' + - 'ellipse;marker-allow-overlap: true;}'; + default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;' + + 'marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;' + + 'marker-type: ellipse;marker-allow-overlap: true;}'; } else if ( semver.satisfies(mapnik_version, '<2.2.0') ) { // 2.1.0 default From 848bfacc2d3d4b12e62808f454d6f5976eb5923b Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:15:26 +0200 Subject: [PATCH 34/59] no need to check it used post for long queries --- test/acceptance/multilayer.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index e2fe35f3..5ba35ca7 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -25,7 +25,6 @@ suite(suiteName, function() { var cdbQueryTablesFromPostgresEnabledValue = true; var redis_client = redis.createClient(global.environment.redis.port); - var sqlapi_server; var expected_last_updated_epoch = 1234567890123; // this is hard-coded into SQLAPIEmu var expected_last_updated = new Date(expected_last_updated_epoch).toISOString(); @@ -1181,10 +1180,6 @@ suite(suiteName, function() { var parsedBody = JSON.parse(res.body); var token_components = parsedBody.layergroupid.split(':'); expected_token = token_components[0]; - if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API - var last_request = sqlapi_server.getLastRequest(); - assert.equal(last_request.method, 'POST'); - } return null; }, function cleanup(err) { From ff515f8c1260479cec2711ffd88a9b24cd9840b4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:20:04 +0200 Subject: [PATCH 35/59] No need to have a test for empty cartocss --- test/acceptance/server.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index ee6144ef..9d6b1b39 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -121,20 +121,6 @@ suite.skip('server old_api', function() { // ///////////////////////////////////////////////////////////////////////////////// - test("post'ing no style returns 400 with errors", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table/style', - method: 'POST' - },{ - body: '{"error":"must send style information"}' - }, function(res) { - assert.equal(res.statusCode, 400); - assert.ok(!res.headers.hasOwnProperty('cache-control')); - done(); - }); - }); - test("post'ing bad style returns 400 with error", function(done){ assert.response(server, { url: '/tiles/my_table3/style?map_key=1234', From 000a248ab40f7392157c0abe19f800a9ba86bc4b Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:24:40 +0200 Subject: [PATCH 36/59] Removes test as is covered in "layergroup creation fails if CartoCSS is bogus" --- test/acceptance/server.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 9d6b1b39..b275e73d 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -120,18 +120,6 @@ suite.skip('server old_api', function() { // POST STYLE // ///////////////////////////////////////////////////////////////////////////////// - - test("post'ing bad style returns 400 with error", function(done){ - assert.response(server, { - url: '/tiles/my_table3/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: '#my_table3{backgxxxxxround-color:#fff;}'}) - },{ - status: 400, - body: /Unrecognized rule: backgxxxxxround-color/ - }, function() { done(); }); - }); test("post'ing unparseable style returns 400 with error", function(done){ assert.response(server, { From ada616ee6a3c928e17fab03e32bc4fe0de4febf6 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:31:44 +0200 Subject: [PATCH 37/59] jshint adds mocha globals --- .jshintrc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.jshintrc b/.jshintrc index e8d605fc..4aedb3cf 100644 --- a/.jshintrc +++ b/.jshintrc @@ -84,6 +84,10 @@ // Custom Globals "globals" : { // additional predefined global variables + "describe": true, + "before": true, + "after": true, + "it": true, "suite": true, "suiteSetup": true, "test": true, From e7544e84c23ec2cf208b84197a2d0d6602005310 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:32:09 +0200 Subject: [PATCH 38/59] Replace server test with multilayer one --- test/acceptance/multilayer_server.js | 56 ++++++++++++++++++++++++++++ test/acceptance/server.js | 13 ------- 2 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 test/acceptance/multilayer_server.js diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js new file mode 100644 index 00000000..84e7174c --- /dev/null +++ b/test/acceptance/multilayer_server.js @@ -0,0 +1,56 @@ +require(__dirname + '/../support/test_helper'); + +var assert = require('../support/assert'); + +var redis = require('redis'); + +var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft'); +var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')(); +var server = new CartodbWindshaft(serverOptions); +server.setMaxListeners(0); + +describe('tests from old api translated to multilayer', function() { + + var layergroupUrl = '/api/v1/map'; + + var redisClient = redis.createClient(global.environment.redis.port); + after(function(done) { + // This test will add map_style records, like + // 'map_style|null|publicuser|my_table', + redisClient.keys("map_style|*", function(err, matches) { + redisClient.del(matches, function() { + done(); + }); + }); + }); + + test("layergroup creation fails if CartoCSS is bogus", function(done) { + var layergroup = { + stat_tag: 'random_tag', + version: '1.0.0', + layers: [ + { + type: 'mapnik', + options: { + sql: 'select 1 as cartodb_id, null::geometry as the_geom_webmercator', + cartocss: '#my_table3{', + cartocss_version: '2.0.1' + } + } + ] + }; + assert.response(server, { + url: layergroupUrl, + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(layergroup) + }, {}, function(res) { + assert.equal(res.statusCode, 400, res.body); + var parsed = JSON.parse(res.body); + assert.ok(parsed.errors[0].match(/^style0/)); + assert.ok(parsed.errors[0].match(/missing closing/)); + done(); + }); + }); + +}); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index b275e73d..692d11a3 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -121,19 +121,6 @@ suite.skip('server old_api', function() { // ///////////////////////////////////////////////////////////////////////////////// - test("post'ing unparseable style returns 400 with error", function(done){ - assert.response(server, { - url: '/tiles/my_table3/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: '#my_table3{'}) - },{}, function(res) { - assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); - assert.ok( new RegExp(/missing closing/i).test(res.body) ); - done(); - }); - }); - test("post'ing multiple bad styles returns 400 with error array", function(done){ assert.response(server, { url: '/tiles/my_table4/style?map_key=1234', From 4ea1199014e7befe0828f00294dfd54111f66a08 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:32:48 +0200 Subject: [PATCH 39/59] it instead of test --- test/acceptance/multilayer_server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 84e7174c..24640631 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -24,7 +24,7 @@ describe('tests from old api translated to multilayer', function() { }); }); - test("layergroup creation fails if CartoCSS is bogus", function(done) { + it("layergroup creation fails if CartoCSS is bogus", function(done) { var layergroup = { stat_tag: 'random_tag', version: '1.0.0', From ecc67b1d0fe4ff2768a736679615b3dde4f70371 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:41:34 +0200 Subject: [PATCH 40/59] Replace test for multiple cartocss errors --- test/acceptance/multilayer_server.js | 32 ++++++++++++++++++++++++---- test/acceptance/server.js | 22 ------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 24640631..ee013eeb 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -24,21 +24,27 @@ describe('tests from old api translated to multilayer', function() { }); }); - it("layergroup creation fails if CartoCSS is bogus", function(done) { - var layergroup = { + var wadusSql = 'select 1 as cartodb_id, null::geometry as the_geom_webmercator'; + + function singleLayergroupConfig(sql, cartocss) { + return { stat_tag: 'random_tag', version: '1.0.0', layers: [ { type: 'mapnik', options: { - sql: 'select 1 as cartodb_id, null::geometry as the_geom_webmercator', - cartocss: '#my_table3{', + sql: sql, + cartocss: cartocss, cartocss_version: '2.0.1' } } ] }; + } + + it("layergroup creation fails if CartoCSS is bogus", function(done) { + var layergroup = singleLayergroupConfig(wadusSql, '#my_table3{'); assert.response(server, { url: layergroupUrl, method: 'POST', @@ -53,4 +59,22 @@ describe('tests from old api translated to multilayer', function() { }); }); + it("multiple bad styles returns 400 with all errors", function(done) { + var layergroup = singleLayergroupConfig(wadusSql, '#my_table4{backgxxxxxround-color:#fff;foo:bar}'); + assert.response(server, { + url: layergroupUrl, + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(layergroup) + }, {}, function(res) { + assert.equal(res.statusCode, 400, res.body); + var parsed = JSON.parse(res.body); + assert.equal(parsed.errors.length, 1); + assert.ok(parsed.errors[0].match(/^style0/)); + assert.ok(parsed.errors[0].match(/Unrecognized rule: backgxxxxxround-color/)); + assert.ok(parsed.errors[0].match(/Unrecognized rule: foo/)); + done(); + }); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 692d11a3..528d9641 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -115,28 +115,6 @@ suite.skip('server old_api', function() { var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - ///////////////////////////////////////////////////////////////////////////////// - // - // POST STYLE - // - ///////////////////////////////////////////////////////////////////////////////// - - test("post'ing multiple bad styles returns 400 with error array", function(done){ - assert.response(server, { - url: '/tiles/my_table4/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: '#my_table4{backgxxxxxround-color:#fff;foo:bar}'}) - },{ - status: 400 - }, function(res) { - var parsed = JSON.parse(res.body); - assert.equal(parsed.length, 2); - assert.ok( new RegExp(/Unrecognized rule: backgxxxxxround-color/).test(parsed[0]) ); - assert.ok( new RegExp(/Unrecognized rule: foo/).test(parsed[1]) ); - done(); - }); - }); test("post'ing good style returns 200", function(done){ assert.response(server, { From ec2fcad2e0b796ae34fecd4a19688e0e9ec8eef1 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:42:15 +0200 Subject: [PATCH 41/59] No need to test good style cases --- test/acceptance/server.js | 126 -------------------------------------- 1 file changed, 126 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 528d9641..b8f6fc61 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -116,132 +116,6 @@ suite.skip('server old_api', function() { var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - test("post'ing good style returns 200", function(done){ - assert.response(server, { - url: '/tiles/my_table5/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: 'Map { background-color:#fff; }'}) - },{ - }, function(res) { - assert.equal(res.statusCode, 200, res.body); - done(); - }); - }); - - // See https://github.com/Vizzuality/Windshaft-cartodb/issues/38 - test("post'ing good style with auth passed as api_key returns 200", function(done){ - assert.response(server, { - url: '/tiles/my_table5/style?api_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: 'Map { background-color:#fff; }'}) - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - done(); - }); - }); - - // See https://github.com/Vizzuality/cartodb-management/issues/155 - test("post'ing good style with no authentication returns an error", function(done){ - assert.response(server, { - url: '/tiles/my_table5/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: 'Map { background-color:#fff; }'}) - },{ - }, function(res) { - assert.equal(res.statusCode, 200, res.body); - assert.response(server, { - url: '/tiles/my_table5/style', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: 'Map { background-color:#aaa; }'}) - },{}, function(res) { - // FIXME: should be 403 Forbidden - assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); - assert.ok(res.body.indexOf('map state cannot be changed by unauthenticated request') != -1, res.body); - - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style', - method: 'GET' - },{ - status: 200 - }, function(res) { - var parsed = JSON.parse(res.body); - assert.equal(parsed.style, 'Map { background-color:#fff; }'); - assert.equal(parsed.style_version, '2.0.0'); - done(); - }); - - }); - }); - }); - - test("post'ing good style returns 200 then getting returns original style", function(done){ - var style = 'Map { background-color:#fff; }'; - assert.response(server, { - url: '/tiles/my_table5/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: style, style_version: '2.0.2'}) - },{}, function(res) { - - assert.equal(res.statusCode, 200, res.body); - - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - var parsed = JSON.parse(res.body); - assert.equal(parsed.style, style); - assert.equal(parsed.style_version, '2.0.2'); - - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style?style_convert=true', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - var parsed = JSON.parse(res.body); - assert.equal(parsed.style, style); - assert.equal(parsed.style_version, mapnik_version); - done(); - }); - }); - - }); - - }); - - test("post'ing good style with style_convert returns 200 then getting returns converted style", function(done){ - var style = 'Map { background-color:#fff; }'; - assert.response(server, { - url: '/tiles/my_table5/style?map_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: style, style_version: '2.0.2', style_convert: true}) - },{}, function(res) { - - assert.equal(res.statusCode, 200, res.body); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - var parsed = JSON.parse(res.body); - // NOTE: no transform expected for the specific style - assert.equal(parsed.style, style); - assert.equal(parsed.style_version, mapnik_version); - done(); - }); - }); - }); - ///////////////////////////////////////////////////////////////////////////////// // // DELETE STYLE From 41521b67768b5816446cf1883c9a2e52b4004c8a Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 12:42:57 +0200 Subject: [PATCH 42/59] No need to test style deletion --- test/acceptance/server.js | 80 --------------------------------------- 1 file changed, 80 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index b8f6fc61..bacdb0b9 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -116,86 +116,6 @@ suite.skip('server old_api', function() { var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - ///////////////////////////////////////////////////////////////////////////////// - // - // DELETE STYLE - // - ///////////////////////////////////////////////////////////////////////////////// - - // Test that unauthenticated DELETE should fail - // See https://github.com/Vizzuality/cartodb-management/issues/155 - test("delete'ing style with no authentication returns an error", function(done){ - assert.response(server, { - url: '/tiles/my_table5/style', - method: 'DELETE', - headers: {host: 'localhost'} - },{}, function(res) { - // FIXME: should be 403 Forbidden - assert.equal(res.statusCode, 400, res.body); - assert.ok(res.body.indexOf('map state cannot be changed by unauthenticated request') != -1, res.body); - // check that the style wasn't really deleted ! - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style?map_key=1234', - method: 'GET' - },{ - status: 200 - }, function(res) { - var parsed = JSON.parse(res.body); - assert.equal(parsed.style, 'Map { background-color:#fff; }'); - //assert.equal(parsed.version, '2.0.0'); - done(); - }); - }); - }); - - test("delete'ing style returns 200 then getting returns default style", function(done){ - // this is the default style - var style = _.template(default_style, {table: 'my_table5'}); - assert.response(server, { - url: '/tiles/my_table5/style?map_key=1234', - method: 'DELETE', - headers: {host: 'localhost'} - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - - // Retrive style with authenticated request - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style?map_key=1234', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - assert.deepEqual(JSON.parse(res.body).style, style); - - // Now retrive style with unauthenticated request - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/my_table5/style', - method: 'GET' - }, {}, function(res) { - assert.equal(res.statusCode, 200, res.body); - assert.deepEqual(JSON.parse(res.body).style, style); - - done(); - }); - }); - - }); - }); - - // See https://github.com/Vizzuality/Windshaft-cartodb/issues/38 - test("delete'ing style with api_key is accepted", function(done){ - assert.response(server, { - url: '/tiles/my_table5/style?api_key=1234', - method: 'DELETE', - headers: {host: 'localhost'} - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - done(); - }); - }); - ///////////////////////////////////////////////////////////////////////////////// // // GET GRID From 2161bbf8e9f61e7c7a832ea7d40a88c199f8d116 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 13:30:44 +0200 Subject: [PATCH 43/59] Remove comments --- test/acceptance/server.js | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index bacdb0b9..7d65022c 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -2,7 +2,6 @@ var assert = require('../support/assert'); var _ = require('underscore'); var redis = require('redis'); var querystring = require('querystring'); -var semver = require('semver'); var step = require('step'); var helper = require(__dirname + '/../support/test_helper'); @@ -19,12 +18,6 @@ var cdbQueryTablesFromPostgresEnabledValue = true; suite('server', function() { - ///////////////////////////////////////////////////////////////////////////////// - // - // GET UNSUPPORTED - // - ///////////////////////////////////////////////////////////////////////////////// - // TODO: I guess this should be a 404 instead... test("get call to server returns 200", function(done){ step( @@ -48,12 +41,6 @@ suite('server', function() { ); }); - ///////////////////////////////////////////////////////////////////////////////// - // - // GET VERSION - // - ///////////////////////////////////////////////////////////////////////////////// - test("get call to server returns 200", function(done){ assert.response(server, { url: '/version', @@ -83,33 +70,7 @@ suite.skip('server old_api', function() { var redis_client = redis.createClient(global.environment.redis.port); var sqlapi_server; - var mapnik_version = global.environment.mapnik_version || server.getVersion().mapnik; var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; - var default_style; - if ( semver.satisfies(mapnik_version, '<2.1.0') ) { - // 2.0.0 default - default_style = '#<%= table %>{marker-fill: #FF6600;marker-opacity: 1;marker-width: 8;' + - 'marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;marker-placement: point;' + - 'marker-type: ellipse;marker-allow-overlap: true;}'; - } - else if ( semver.satisfies(mapnik_version, '<2.2.0') ) { - // 2.1.0 default - default_style = '#<%= table %>[mapnik-geometry-type=1] {marker-fill: #FF6600;marker-opacity: 1;' + - 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + - 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + - '#<%= table %>[mapnik-geometry-type=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + - '#<%= table %>[mapnik-geometry-type=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + - ' line-color: #FFFFFF;}'; - } - else { - // 2.2.0+ default - default_style = '#<%= table %>["mapnik::geometry_type"=1] {marker-fill: #FF6600;marker-opacity: 1;' + - 'marker-width: 16;marker-line-color: white;marker-line-width: 3;marker-line-opacity: 0.9;' + - 'marker-placement: point;marker-type: ellipse;marker-allow-overlap: true;}' + - '#<%= table %>["mapnik::geometry_type"=2] {line-color:#FF6600; line-width:1; line-opacity: 0.7;}' + - '#<%= table %>["mapnik::geometry_type"=3] {polygon-fill:#FF6600; polygon-opacity: 0.7; line-opacity:1;' + - ' line-color: #FFFFFF;}'; - } // A couple of styles to use during testing var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; From 70d1a30c64079dbf881c2d3e83f00542dcb46c02 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 13:30:57 +0200 Subject: [PATCH 44/59] style --- test/acceptance/multilayer_server.js | 73 ++++++++++++++++------------ 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index ee013eeb..7c6d6a92 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -1,16 +1,19 @@ require(__dirname + '/../support/test_helper'); -var assert = require('../support/assert'); +var assert = require('../support/assert'); -var redis = require('redis'); +var redis = require('redis'); +var _ = require('underscore'); -var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft'); -var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')(); +var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); +var serverOptions = require('../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); describe('tests from old api translated to multilayer', function() { + var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; + var layergroupUrl = '/api/v1/map'; var redisClient = redis.createClient(global.environment.redis.port); @@ -45,36 +48,46 @@ describe('tests from old api translated to multilayer', function() { it("layergroup creation fails if CartoCSS is bogus", function(done) { var layergroup = singleLayergroupConfig(wadusSql, '#my_table3{'); - assert.response(server, { - url: layergroupUrl, - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(layergroup) - }, {}, function(res) { - assert.equal(res.statusCode, 400, res.body); - var parsed = JSON.parse(res.body); - assert.ok(parsed.errors[0].match(/^style0/)); - assert.ok(parsed.errors[0].match(/missing closing/)); - done(); - }); + assert.response(server, + { + url: layergroupUrl, + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(layergroup) + }, + { + status: 400 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.errors[0].match(/^style0/)); + assert.ok(parsed.errors[0].match(/missing closing/)); + done(); + } + ); }); it("multiple bad styles returns 400 with all errors", function(done) { var layergroup = singleLayergroupConfig(wadusSql, '#my_table4{backgxxxxxround-color:#fff;foo:bar}'); - assert.response(server, { - url: layergroupUrl, - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(layergroup) - }, {}, function(res) { - assert.equal(res.statusCode, 400, res.body); - var parsed = JSON.parse(res.body); - assert.equal(parsed.errors.length, 1); - assert.ok(parsed.errors[0].match(/^style0/)); - assert.ok(parsed.errors[0].match(/Unrecognized rule: backgxxxxxround-color/)); - assert.ok(parsed.errors[0].match(/Unrecognized rule: foo/)); - done(); - }); + assert.response(server, + { + url: layergroupUrl, + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(layergroup) + }, + { + status: 400 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.equal(parsed.errors.length, 1); + assert.ok(parsed.errors[0].match(/^style0/)); + assert.ok(parsed.errors[0].match(/Unrecognized rule: backgxxxxxround-color/)); + assert.ok(parsed.errors[0].match(/Unrecognized rule: foo/)); + done(); + } + ); }); }); From 2b9f2ee66c23a6918f47de39770687f0239b444d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 13:35:20 +0200 Subject: [PATCH 45/59] Removes tests as they are covered in multilayer suite --- test/acceptance/server.js | 442 -------------------------------------- 1 file changed, 442 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 7d65022c..a9711f95 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -76,292 +76,6 @@ suite.skip('server old_api', function() { var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - - ///////////////////////////////////////////////////////////////////////////////// - // - // GET GRID - // - ///////////////////////////////////////////////////////////////////////////////// - - test("get'ing a json with default style should return an grid", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.grid.json', - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'application/json; charset=utf-8', - 'X-Cache-Channel': test_database+':gadm4' } - }, function() { done(); }); - }); - - test("get'ing a json with default style should return an grid", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.grid.json', - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'application/json; charset=utf-8' } - }, function() { done(); }); - }); - - test("get'ing a json with default style and sql should return a constrained grid", function(done){ - var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08'"}); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.grid.json?' + sql, - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'application/json; charset=utf-8' } - }, function() { done(); }); - }); - - test("get'ing the grid of a private table should fail when unauthenticated", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/6/31/24.grid.json', - method: 'GET' - },{}, function(res) { - // 403 Forbidden - assert.equal(res.statusCode, 403, res.statusCode + ': ' + res.body); - done(); - }); - }); - - // See http://github.com/CartoDB/Windshaft-cartodb/issues/186 - test("get'ing the grid of a private table should fail when unauthenticated (jsonp)", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/6/31/24.grid.json?callback=x', - method: 'GET' - },{}, function(res) { - // It's forbidden, but jsonp calls for status = 200 - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - // Still, we do NOT want to add caching headers here - // See https://github.com/CartoDB/Windshaft-cartodb/issues/186 - assert.ok(!res.headers.hasOwnProperty('cache-control'), - "Unexpected Cache-Control: " + res.headers['cache-control']); - done(); - }); - }); - - // See http://github.com/Vizzuality/Windshaft-cartodb/issues/55 - test("get'ing grid of private table should fail on unknown username", - function(done) { - assert.response(server, { - headers: {host: 'unknown_user'}, - url: '/tiles/test_table_private_1/6/31/24.grid.json', - method: 'GET' - },{ - }, function(res) { - // FIXME: should be 403 Forbidden - assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); - assert.deepEqual(JSON.parse(res.body), - {error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"}); - done(); - }); - }); - - test("get'ing the grid of a private table should succeed when authenticated", - function(done) { - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table_private_1/6/31/24.grid.json?map_key=1234', - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.body); - done(); - }); - }); - - ///////////////////////////////////////////////////////////////////////////////// - // - // GET TILE - // - ///////////////////////////////////////////////////////////////////////////////// - - test("should send Cache-Control header with short expiration by default", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png', - method: 'GET' - },{ - status: 200 - }, function(res) { - var cc = res.headers['cache-control']; - assert.ok(cc); - //assert.equal(cc, 'public,max-age=31536000'); // 1 year - assert.ok(cc.match('no-cache'), cc); - assert.ok(cc.match('must-revalidate'), cc); - assert.ok(cc.match('public'), cc); - done(); - }); - }); - - test("should send Cache-Control header with long expiration when requested", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?cache_policy=persist', - method: 'GET' - },{ - status: 200 - }, function(res) { - var cc = res.headers['cache-control']; - assert.ok(cc); - assert.equal(cc, 'public,max-age=31536000'); // 1 year - done(); - }); - }); - - test("get'ing a tile with default style should return an image", function(done){ - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?geom_type=polygon', - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'image/png', 'X-Cache-Channel': test_database+':gadm4' } - }, function() { done(); }); - }); - - test("get'ing a tile with default style and sql should return a constrained image", function(done){ - var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08'"}); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'image/png' } - }, function() { done(); }); - }); - - - test("get'ing a tile with default style and complex sql should return a constrained image", function(done){ - var sql = querystring.stringify({sql: "SELECT * FROM gadm4 WHERE codineprov = '08' AND codccaa > 60"}); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'image/png' } - }, function() { done(); }); - }); - - test("get'ing a tile with data from private table should succeed when authenticated", function(done){ - // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft - var sql = querystring.stringify({sql: "SELECT * FROM test_table_private_1", map_key: 1234}); - assert.response(server, { - headers: {host: 'localhost'}, - // NOTE: we encode a public table in the URL ! - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'image/png' } - }, function() { done(); }); - }); - - // See https://github.com/Vizzuality/Windshaft-cartodb/issues/38 - test("get'ing a tile with data from private table should succeed when authenticated with api_key", function(done){ - // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft - var sql = querystring.stringify({sql: "SELECT * FROM test_table_private_1", api_key: 1234}); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - status: 200, - headers: { 'Content-Type': 'image/png' } - }, function() { done(); }); - }); - - test("get'ing a tile with data from private table should fail when unauthenticated", function(done){ - var sql = querystring.stringify({ - sql: "SELECT * FROM test_table_private_1", - cache_buster:2 // this is to avoid getting the cached response - }); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - }, function(res) { - // 403 Forbidden - assert.equal(res.statusCode, 403, res.statusCode + ': ' + res.body); - done(); - }); - }); - - test("get'ing a tile with data from private table should fail on unknown username", function(done){ - var sql = querystring.stringify({ - sql: "SELECT * FROM test_table_private_1", - cache_buster:2 // this is to avoid getting the cached response - }); - assert.response(server, { - headers: {host: 'unknown_user'}, - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - }, function(res) { - // FIXME: should be 403 Forbidden - assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); - assert.deepEqual(JSON.parse(res.body), - {error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"}); - assert.ok(!res.headers.hasOwnProperty('cache-control'), - "Unexpected Cache-Control: " + res.headers['cache-control']); - done(); - }); - }); - - test("get'ing a tile with data from private table should fail when unauthenticated (uses old redis key)", - function(done) { - var sql = querystring.stringify({ - sql: "SELECT * FROM test_table_private_1", - cache_buster:3, - // 1235 is written in rails:users:localhost:map_key SET - // See https://github.com/Vizzuality/Windshaft-cartodb/issues/39 - map_key: 1235 - }); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + sql, - method: 'GET' - },{ - }, function(res) { - // 403 Forbidden - assert.equal(res.statusCode, 403, res.statusCode + ': ' + res.body); - // Failed in 1.6.0 of https://github.com/CartoDB/Windshaft-cartodb/issues/107 - assert.ok(!res.headers.hasOwnProperty('cache-control'), - "Unexpected Cache-Control: " + res.headers['cache-control']); - done(); - }); - }); - - test("get'ing a tile with url specified 2.0.0 style should return an expected tile", function(done){ - var style = querystring.stringify({style: test_style_black_200, style_version: '2.0.0'}); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png?cache_buster=4&' + style, // madrid - method: 'GET', - encoding: 'binary' - },{}, function(res){ - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { - if (err) throw err; - done(); - }); - }); - }); - // See https://github.com/CartoDB/Windshaft-cartodb/issues/88 test("get'ing a tile from a user-specific database should return an expected tile", function(done){ var style = querystring.stringify({style: test_style_black_200, style_version: '2.0.0'}); @@ -434,25 +148,6 @@ suite.skip('server old_api', function() { ); }); - test("get'ing a tile with url specified 2.1.0 style should return an expected tile", function(done){ - var style = querystring.stringify({style: test_style_black_210, style_version: '2.1.0'}); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png?cache_buster=4&' + style, // madrid - method: 'GET', - encoding: 'binary' - },{}, function(res){ - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { - if (err) throw err; - done(); - }); - }); - }); - test("get'ing a tile with url specified 2.1.0 style (lzma version)", function(done){ var qo = { style: test_style_black_210, @@ -492,143 +187,6 @@ suite.skip('server old_api', function() { ); }); - // See http://github.com/Vizzuality/Windshaft-cartodb/issues/57 - test("GET'ing a tile as anonymous with style set by POST", function(done){ - step ( - function postStyle1() { - var next = this; - assert.response(server, { - method: 'POST', - url: '/tiles/test_table/style', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: 'Map { background-color:#fff; }', map_key: 1234}) - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - next(); - }); - }, - // Load the new cache with results from Style1 above - function getTileAnon1(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png', - method: 'GET', - encoding: 'binary' - },{}, function(res){ - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/blank.png', IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL, - function(err/*, similarity*/) { - if (err) next(err); - else next(); - }); - }); - }, - // Get again with authentication - function getTileAuth1(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png?map_key=1234', - method: 'GET', - encoding: 'binary' - },{}, function(res){ - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/blank.png', IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL, - function(err/*, similarity*/) { - if (err) next(err); - else next(); - }); - }); - }, - // Change the style - function postStyle2(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - method: 'POST', - url: '/tiles/test_table/style', - headers: {host: 'localhost', 'Content-Type': 'application/x-www-form-urlencoded' }, - data: querystring.stringify({style: test_style_black_200, map_key: 1234}) - },{}, function(res) { - try { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - next(); - } - catch (err) { next(err); } - }); - }, - // Verify the Style2 is applied. NOTE: pass the SAME cache_buster as before! - function getTileAnon2(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png', - method: 'GET', - encoding: 'binary' - },{}, function(res){ - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { - // NOTE: we expect them to be EQUAL here - if (err) { next(err); return; } - next(); - }); - }); - }, - // Delete the style - function delStyle(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - method: 'DELETE', - url: '/tiles/test_table/style?map_key=1234', - headers: {host: 'localhost'} - },{}, function(res) { - try { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - next(); - } - catch (err) { next(err); } - }); - }, - // Verify the default style is applied. - function getTileAnon3(err) { - if ( err ) throw err; - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png?cache_buster=2314', - method: 'GET', - encoding: 'binary' - },{}, function(res){ - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { - // NOTE: we expect them to be different here - if (err) next(); - else next(new Error('Last posted style still in effect after delete')); - } - ); - }); - }, - function finish(err) { - done(err); - } - ); - }); - test("uses sqlapi to figure source data of query", function(done){ var qo = { sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator" + From 124133ceca22cda016ea3d466f1202f10c02c6e0 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 13:38:34 +0200 Subject: [PATCH 46/59] Replace zoom test with multilayer one --- test/acceptance/multilayer_server.js | 26 ++++++++++++++++++++++++++ test/acceptance/server.js | 20 +------------------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 7c6d6a92..69a7397b 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -90,4 +90,30 @@ describe('tests from old api translated to multilayer', function() { ); }); + // Zoom is a special variable + it("Specifying zoom level in CartoCSS does not need a 'zoom' variable in SQL output", function(done){ + // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft + var sql = "SELECT 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator, 1::int as cartodb_id"; + var cartocss = '#gadm4 [ zoom>=3] { marker-fill:red; }'; + + var layergroup = singleLayergroupConfig(sql, cartocss); + + assert.response(server, + { + url: layergroupUrl, + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(layergroup) + }, + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + done(); + } + ); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index a9711f95..474b22ec 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -6,8 +6,7 @@ var step = require('step'); var helper = require(__dirname + '/../support/test_helper'); -var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20, - IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL = 0; +var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20; var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft'); var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')(); @@ -292,23 +291,6 @@ suite.skip('server old_api', function() { }); } - // Zoom is a special variable - test("Specifying zoom level in CartoCSS does not need a 'zoom' variable in SQL output", function(done){ - // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft - var query = querystring.stringify({ - sql: "SELECT 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator, 1::int as cartodb_id", - style: '#gadm4 [ zoom>=3] { marker-fill:red; }' - }); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/0/0/0.png?' + query, - method: 'GET' - },{}, function(res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - done(); - }); - }); - // See https://github.com/CartoDB/Windshaft-cartodb/issues/115 test.skip("get'ing tile with not-strictly-valid style", function(done) { var style = querystring.stringify({style: '#test_table{line-color:black}}', style_version: '2.0.0'}); From 55a78899a497fa6117e24569ad8eb4d2492559f7 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 13:39:47 +0200 Subject: [PATCH 47/59] Removes sql api specific test --- test/acceptance/server.js | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 474b22ec..f5ad4d50 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -67,7 +67,6 @@ suite('server', function() { suite.skip('server old_api', function() { var redis_client = redis.createClient(global.environment.redis.port); - var sqlapi_server; var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; @@ -225,39 +224,6 @@ suite.skip('server old_api', function() { ); }); - if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was a post if it's using the SQL API - test("passes hostname header to sqlapi", function(done){ - var qo = { - sql: "SELECT * from gadm4", - map_key: 1234 - }; - step( - function sendRequest() { - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + querystring.stringify(qo), - method: 'GET' - },{}, function(res) { next(null, res); }); - }, - function checkResponse(err, res) { - if ( err ) throw err; - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var last_request = sqlapi_server.getLastRequest(); - assert.ok(last_request); - var host = last_request.headers.host; - assert.ok(host); - assert.equal(last_request.method, 'GET'); - assert.equal(host, 'localhost.donot_look_this_up'); - return null; - }, - function finish(err) { - done(err); - } - ); - }); - } - if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API test("requests to skip cache on sqlapi error", function(done){ var qo = { From 434d6d4110720b4217067f2f5b71d8d51c6c2034 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 13:42:59 +0200 Subject: [PATCH 48/59] Extract request function --- test/acceptance/multilayer_server.js | 33 +++++++++++++--------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 69a7397b..e0bf8460 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -46,15 +46,22 @@ describe('tests from old api translated to multilayer', function() { }; } + function createRequest(layergroup, userHost) { + return { + url: layergroupUrl, + method: 'POST', + headers: { + host: userHost || 'localhost', + 'Content-Type': 'application/json' + }, + data: JSON.stringify(layergroup) + }; + } + it("layergroup creation fails if CartoCSS is bogus", function(done) { var layergroup = singleLayergroupConfig(wadusSql, '#my_table3{'); assert.response(server, - { - url: layergroupUrl, - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(layergroup) - }, + createRequest(layergroup), { status: 400 }, @@ -70,12 +77,7 @@ describe('tests from old api translated to multilayer', function() { it("multiple bad styles returns 400 with all errors", function(done) { var layergroup = singleLayergroupConfig(wadusSql, '#my_table4{backgxxxxxround-color:#fff;foo:bar}'); assert.response(server, - { - url: layergroupUrl, - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(layergroup) - }, + createRequest(layergroup), { status: 400 }, @@ -99,12 +101,7 @@ describe('tests from old api translated to multilayer', function() { var layergroup = singleLayergroupConfig(sql, cartocss); assert.response(server, - { - url: layergroupUrl, - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(layergroup) - }, + createRequest(layergroup), { status: 200 }, From d6ef0b7457e4cd6e4482d42328b8b447cba68299 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 14:39:26 +0200 Subject: [PATCH 49/59] Replaces server tests for user db connection with multilayer --- test/acceptance/multilayer_server.js | 63 ++++++++++++++++++++---- test/acceptance/server.js | 73 ---------------------------- 2 files changed, 53 insertions(+), 83 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index e0bf8460..d7b2c16b 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -12,8 +12,6 @@ server.setMaxListeners(0); describe('tests from old api translated to multilayer', function() { - var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; - var layergroupUrl = '/api/v1/map'; var redisClient = redis.createClient(global.environment.redis.port); @@ -28,6 +26,7 @@ describe('tests from old api translated to multilayer', function() { }); var wadusSql = 'select 1 as cartodb_id, null::geometry as the_geom_webmercator'; + var pointSql = "SELECT 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator, 1::int as cartodb_id"; function singleLayergroupConfig(sql, cartocss) { return { @@ -46,9 +45,13 @@ describe('tests from old api translated to multilayer', function() { }; } - function createRequest(layergroup, userHost) { + function createRequest(layergroup, userHost, apiKey) { + var url = layergroupUrl; + if (apiKey) { + url += '?api_key=' + apiKey; + } return { - url: layergroupUrl, + url: url, method: 'POST', headers: { host: userHost || 'localhost', @@ -93,12 +96,8 @@ describe('tests from old api translated to multilayer', function() { }); // Zoom is a special variable - it("Specifying zoom level in CartoCSS does not need a 'zoom' variable in SQL output", function(done){ - // NOTE: may fail if grainstore < 0.3.0 is used by Windshaft - var sql = "SELECT 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator, 1::int as cartodb_id"; - var cartocss = '#gadm4 [ zoom>=3] { marker-fill:red; }'; - - var layergroup = singleLayergroupConfig(sql, cartocss); + it("Specifying zoom level in CartoCSS does not need a 'zoom' variable in SQL output", function(done) { + var layergroup = singleLayergroupConfig(pointSql, '#gadm4 [ zoom>=3] { marker-fill:red; }'); assert.response(server, createRequest(layergroup), @@ -113,4 +112,48 @@ describe('tests from old api translated to multilayer', function() { ); }); + // See https://github.com/CartoDB/Windshaft-cartodb/issues/88 + it("getting a tile from a user-specific database should return an expected tile", function(done) { + var layergroup = singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }'); + + var backupDBHost = global.environment.postgres.host; + global.environment.postgres.host = '6.6.6.6'; + + assert.response(server, + createRequest(layergroup, 'cartodb250user'), + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + + global.environment.postgres.host = backupDBHost; + done(); + } + ); + }); + + // See https://github.com/CartoDB/Windshaft-cartodb/issues/89 + it("getting a tile with a user-specific database password", function(done) { + var layergroup = singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }'); + + var backupDBPass = global.environment.postgres_auth_pass; + global.environment.postgres_auth_pass = '<%= user_password %>'; + + assert.response(server, + createRequest(layergroup, 'cartodb250user', '4321'), + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + + global.environment.postgres_auth_pass = backupDBPass; + done(); + } + ); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index f5ad4d50..33fd9817 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -71,81 +71,8 @@ suite.skip('server old_api', function() { var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; // A couple of styles to use during testing - var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:10}"; var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - // See https://github.com/CartoDB/Windshaft-cartodb/issues/88 - test("get'ing a tile from a user-specific database should return an expected tile", function(done){ - var style = querystring.stringify({style: test_style_black_200, style_version: '2.0.0'}); - var backupDBHost = global.environment.postgres.host; - global.environment.postgres.host = '6.6.6.6'; - step ( - function() { - var next = this; - assert.response(server, { - headers: {host: 'cartodb250user'}, - url: '/tiles/test_table/15/16046/12354.png?cache_buster=4.10&' + style, - method: 'GET', - encoding: 'binary' - },{}, function(res){ - next(null, res); - }); - }, - function checkRes(err, res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, - './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, this); - }, - function checkImage(err/*, similarity*/) { - if (err) throw err; - return null; - }, - function finish(err) { - global.environment.postgres.host = backupDBHost; - done(err); - } - ); - }); - - // See https://github.com/CartoDB/Windshaft-cartodb/issues/89 - test("get'ing a tile with a user-specific database password", function(done){ - var style = querystring.stringify({style: test_style_black_200, style_version: '2.0.0'}); - var backupDBPass = global.environment.postgres_auth_pass; - global.environment.postgres_auth_pass = '<%= user_password %>'; - step ( - function() { - var next = this; - assert.response(server, { - headers: {host: 'cartodb250user'}, - url: '/tiles/test_table/15/16046/12354.png?' + 'cache_buster=4.20&api_key=4321&' + style, - method: 'GET', - encoding: 'binary' - },{}, function(res){ - next(null, res); - }); - }, - function checkRes(err, res) { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, - './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, this); - }, - function checkImage(err/*, similarity*/) { - if (err) throw err; - return null; - }, - function finish(err) { - global.environment.postgres_auth_pass = backupDBPass; - done(err); - } - ); - }); - test("get'ing a tile with url specified 2.1.0 style (lzma version)", function(done){ var qo = { style: test_style_black_210, From c92e786a5f91dd9697856faed7d80f0d1a091226 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 15:01:17 +0200 Subject: [PATCH 50/59] Replace lzma test with multilayer --- test/acceptance/multilayer_server.js | 35 ++++++++++++++++++++-- test/acceptance/server.js | 44 +--------------------------- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index d7b2c16b..0adf29cb 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -1,9 +1,8 @@ -require(__dirname + '/../support/test_helper'); +var testHelper = require(__dirname + '/../support/test_helper'); var assert = require('../support/assert'); var redis = require('redis'); -var _ = require('underscore'); var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); var serverOptions = require('../../lib/cartodb/server_options')(); @@ -156,4 +155,36 @@ describe('tests from old api translated to multilayer', function() { ); }); + it("creating a layergroup from lzma param", function(done){ + + var params = { + config: JSON.stringify(singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }')) + }; + + testHelper.lzma_compress_to_base64(JSON.stringify(params), 1, function(err, lzma) { + if (err) { + return done(err); + } + assert.response(server, + { + url: layergroupUrl + '?lzma=' + encodeURIComponent(lzma), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + + done(); + } + ); + }); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 33fd9817..ce77619a 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -64,54 +64,12 @@ suite('server', function() { }); }); -suite.skip('server old_api', function() { +suite('server old_api', function() { var redis_client = redis.createClient(global.environment.redis.port); var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; - // A couple of styles to use during testing - var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:red;marker-width:20}"; - - test("get'ing a tile with url specified 2.1.0 style (lzma version)", function(done){ - var qo = { - style: test_style_black_210, - style_version: '2.1.0', - cache_buster: 5 - }; - step ( - function compressQuery () { - //console.log("Compressing starts"); - helper.lzma_compress_to_base64(JSON.stringify(qo), 1, this); - }, - function sendRequest(err, lzma) { - if ( err ) throw err; - var next = this; - //console.log("Compressing ends: " + typeof(lzma) + " - " + lzma); - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/test_table/15/16046/12354.png?lzma=' + encodeURIComponent(lzma), - method: 'GET', - encoding: 'binary' - },{}, function(res) { next(null, res); }); - }, - function checkResponse(err, res) { - if ( err ) throw err; - var next = this; - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', - IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) { - next(err); - }); - }, - function finish(err) { - done(err); - } - ); - }); - test("uses sqlapi to figure source data of query", function(done){ var qo = { sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator" + From 7df3658d4173f4a0c37d6de8cb8c97e33dba4daf Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 15:06:00 +0200 Subject: [PATCH 51/59] Invalid json lzma test --- test/acceptance/multilayer_server.js | 32 ++++++++++++++++++++++++++++ test/acceptance/server.js | 2 +- test/support/prepare_db.sh | 4 ++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 0adf29cb..b27a9629 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -187,4 +187,36 @@ describe('tests from old api translated to multilayer', function() { }); }); + it("creating a layergroup from lzma param, invalid json input", function(done){ + + var params = { + config: 'WADUS' + }; + + testHelper.lzma_compress_to_base64(JSON.stringify(params), 1, function(err, lzma) { + if (err) { + return done(err); + } + assert.response(server, + { + url: layergroupUrl + '?lzma=' + encodeURIComponent(lzma), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 400 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.deepEqual(parsed, { errors: [ 'Unexpected token W' ] }); + + done(); + } + ); + }); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index ce77619a..7d256fbd 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -64,7 +64,7 @@ suite('server', function() { }); }); -suite('server old_api', function() { +suite.skip('server old_api', function() { var redis_client = redis.createClient(global.environment.redis.port); diff --git a/test/support/prepare_db.sh b/test/support/prepare_db.sh index 8185da4d..dba10043 100755 --- a/test/support/prepare_db.sh +++ b/test/support/prepare_db.sh @@ -79,8 +79,8 @@ if test x"$PREPARE_PGSQL" = xyes; then psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 psql -c "CREATE EXTENSION plpythonu;" ${TEST_DB} - curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryStatements.sql -o sql/CDB_QueryStatements.sql - curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryTables.sql -o sql/CDB_QueryTables.sql +# curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryStatements.sql -o sql/CDB_QueryStatements.sql +# curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryTables.sql -o sql/CDB_QueryTables.sql cat sql/CDB_QueryStatements.sql sql/CDB_QueryTables.sql | psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 From 85804f9854bc8f242cd56d0b8ad204a41576bcf0 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 15:07:49 +0200 Subject: [PATCH 52/59] Fixes jshint --- test/acceptance/server.js | 29 ++++------------------------- test/support/prepare_db.sh | 4 ++-- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/test/acceptance/server.js b/test/acceptance/server.js index 7d256fbd..f99442a6 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -1,15 +1,12 @@ +require(__dirname + '/../support/test_helper'); + var assert = require('../support/assert'); var _ = require('underscore'); -var redis = require('redis'); var querystring = require('querystring'); var step = require('step'); -var helper = require(__dirname + '/../support/test_helper'); - -var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20; - -var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft'); -var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')(); +var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); +var serverOptions = require('../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); @@ -66,8 +63,6 @@ suite('server', function() { suite.skip('server old_api', function() { - var redis_client = redis.createClient(global.environment.redis.port); - var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; test("uses sqlapi to figure source data of query", function(done){ @@ -156,20 +151,4 @@ suite.skip('server old_api', function() { }); }); - ///////////////////////////////////////////////////////////////////////////////// - // - // Tear down - // - ///////////////////////////////////////////////////////////////////////////////// - - suiteTeardown(function(done) { - // This test will add map_style records, like - // 'map_style|null|publicuser|my_table', - redis_client.keys("map_style|*", function(err, matches) { - redis_client.del(matches, function() { - done(); - }); - }); - }); - }); diff --git a/test/support/prepare_db.sh b/test/support/prepare_db.sh index dba10043..8185da4d 100755 --- a/test/support/prepare_db.sh +++ b/test/support/prepare_db.sh @@ -79,8 +79,8 @@ if test x"$PREPARE_PGSQL" = xyes; then psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 psql -c "CREATE EXTENSION plpythonu;" ${TEST_DB} -# curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryStatements.sql -o sql/CDB_QueryStatements.sql -# curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryTables.sql -o sql/CDB_QueryTables.sql + curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryStatements.sql -o sql/CDB_QueryStatements.sql + curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryTables.sql -o sql/CDB_QueryTables.sql cat sql/CDB_QueryStatements.sql sql/CDB_QueryTables.sql | psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 From b599e67c35fd44ee9455a525cb3245810bd858ef Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 15:27:40 +0200 Subject: [PATCH 53/59] Replaces affected tables test with multilayer one --- test/acceptance/multilayer_server.js | 37 +++++++++++++++++++++++-- test/acceptance/server.js | 41 ---------------------------- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index b27a9629..c39d2903 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -3,6 +3,7 @@ var testHelper = require(__dirname + '/../support/test_helper'); var assert = require('../support/assert'); var redis = require('redis'); +var _ = require('underscore'); var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); var serverOptions = require('../../lib/cartodb/server_options')(); @@ -156,7 +157,6 @@ describe('tests from old api translated to multilayer', function() { }); it("creating a layergroup from lzma param", function(done){ - var params = { config: JSON.stringify(singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }')) }; @@ -187,8 +187,7 @@ describe('tests from old api translated to multilayer', function() { }); }); - it("creating a layergroup from lzma param, invalid json input", function(done){ - + it("creating a layergroup from lzma param, invalid json input", function(done) { var params = { config: 'WADUS' }; @@ -219,4 +218,36 @@ describe('tests from old api translated to multilayer', function() { }); }); + it("uses queries postgresql to figure affected tables in query", function(done) { + var tableName = 'gadm4'; + var expectedCacheChannel = _.template('<%= databaseName %>:public.<%= tableName %>', { + databaseName: _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db', + tableName: tableName + }); + + var layergroup = singleLayergroupConfig('select * from ' + tableName, '#gadm4 { marker-fill: red; }'); + + assert.response(server, + { + url: layergroupUrl + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), + method: 'GET', + headers: { + host: 'localhost' + } + }, + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + + assert.ok(res.headers.hasOwnProperty('x-cache-channel')); + assert.equal(res.headers['x-cache-channel'], expectedCacheChannel); + + done(); + } + ); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index f99442a6..dd83de50 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -63,47 +63,6 @@ suite('server', function() { suite.skip('server old_api', function() { - var test_database = _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db'; - - test("uses sqlapi to figure source data of query", function(done){ - var qo = { - sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator" + - " FROM gadm4 g, test_table t" + - " WHERE g.cartodb_id = t.cartodb_id", - map_key: 1234 - }; - step( - function sendRequest() { - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + querystring.stringify(qo), - method: 'GET' - },{}, function(res) { next(null, res); }); - }, - function checkResponse(err, res) { - if ( err ) throw err; - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - var cc = res.headers['x-cache-channel']; - assert(cc, 'Missing X-Cache-Channel'); - var dbname = test_database; - assert.equal(cc.substring(0, dbname.length), dbname); - if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API - var jsonquery = cc.substring(dbname.length + 1); - var sentquery = JSON.parse(jsonquery); - assert.equal(sentquery.api_key, qo.map_key); - assert.equal(sentquery.q, 'SELECT CDB_QueryTables($windshaft$' + qo.sql + '$windshaft$)'); - } - return null; - }, - function finish(err) { - done(err); - } - ); - }); - if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API test("requests to skip cache on sqlapi error", function(done){ var qo = { From 1fc0545b5ab48796057e882ddb704ab805e7055f Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 15:57:53 +0200 Subject: [PATCH 54/59] Replace affected tables tests with multilayer ones --- test/acceptance/multilayer_server.js | 87 +++++++++++++++++++++++++++- test/acceptance/server.js | 39 +------------ 2 files changed, 87 insertions(+), 39 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index c39d2903..c7c37de2 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -1,10 +1,12 @@ -var testHelper = require(__dirname + '/../support/test_helper'); +var testHelper = require('../support/test_helper'); var assert = require('../support/assert'); var redis = require('redis'); var _ = require('underscore'); + +var QueryTablesApi = require('../../lib/cartodb/api/query_tables_api'); var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); var serverOptions = require('../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); @@ -30,7 +32,6 @@ describe('tests from old api translated to multilayer', function() { function singleLayergroupConfig(sql, cartocss) { return { - stat_tag: 'random_tag', version: '1.0.0', layers: [ { @@ -250,4 +251,86 @@ describe('tests from old api translated to multilayer', function() { ); }); + it("creates layergroup fails when postgresql queries fail to figure affected tables in query", function(done) { + + var runQueryFn = QueryTablesApi.prototype.runQuery; + QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) { + return callback(new Error('failed to query database for affected tables')); + }; + + var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }'); + + assert.response(server, + { + url: layergroupUrl + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), + method: 'GET', + headers: { + host: 'localhost' + } + }, + { + status: 400 + }, + function(res) { + QueryTablesApi.prototype.runQuery = runQueryFn; + + assert.ok(!res.headers.hasOwnProperty('x-cache-channel')); + + var parsed = JSON.parse(res.body); + assert.deepEqual(parsed, {"errors":["Error: failed to query database for affected tables"]}); + + done(); + } + ); + }); + + it("tile requests works when postgresql queries fail to figure affected tables in query", function(done) { + var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }'); + assert.response(server, + { + url: layergroupUrl + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), + method: 'GET', + headers: { + host: 'localhost' + } + }, + { + status: 200 + }, + function(res) { + var runQueryFn = QueryTablesApi.prototype.runQuery; + QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) { + return callback(new Error('failed to query database for affected tables')); + }; + + // reset internal cacheChannel cache + serverOptions.channelCache = {}; + + assert.response(server, + { + url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { + layergroupId: JSON.parse(res.body).layergroupid, + z: 0, + x: 0, + y: 0 + }), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 200 + }, + function(res) { + assert.ok(!res.headers.hasOwnProperty('x-cache-channel')); + QueryTablesApi.prototype.runQuery = runQueryFn; + done(); + } + ); + } + ); + }); + }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index dd83de50..ffb32fe4 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -1,7 +1,6 @@ -require(__dirname + '/../support/test_helper'); +require('../support/test_helper'); var assert = require('../support/assert'); -var _ = require('underscore'); var querystring = require('querystring'); var step = require('step'); @@ -10,7 +9,6 @@ var serverOptions = require('../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -var cdbQueryTablesFromPostgresEnabledValue = true; suite('server', function() { @@ -61,40 +59,7 @@ suite('server', function() { }); }); -suite.skip('server old_api', function() { - - if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API - test("requests to skip cache on sqlapi error", function(done){ - var qo = { - sql: "SELECT g.cartodb_id, g.codineprov, t.the_geom_webmercator, 'SQLAPIERROR' is not null" + - " FROM gadm4 g, test_table t" + - " WHERE g.cartodb_id = t.cartodb_id", - map_key: 1234 - }; - step( - function sendRequest() { - var next = this; - assert.response(server, { - headers: {host: 'localhost'}, - url: '/tiles/gadm4/6/31/24.png?' + querystring.stringify(qo), - method: 'GET' - },{}, function(res) { next(null, res); }); - }, - function checkResponse(err, res) { - if ( err ) throw err; - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - var ct = res.headers['content-type']; - assert.equal(ct, 'image/png'); - // does NOT send an x-cache-channel - assert.ok(!res.headers.hasOwnProperty('x-cache-channel')); - return null; - }, - function finish(err) { - done(err); - } - ); - }); - } +suite('server old_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/115 test.skip("get'ing tile with not-strictly-valid style", function(done) { From f1e8c9a709bebcd893cc2b5b66cd0a3e2bed2e38 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 16:28:37 +0200 Subject: [PATCH 55/59] Tests for cdb request --- lib/cartodb/models/cdb_request.js | 12 +++--- test/unit/cartodb/cdb_request.test.js | 60 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 test/unit/cartodb/cdb_request.test.js diff --git a/lib/cartodb/models/cdb_request.js b/lib/cartodb/models/cdb_request.js index ec2da747..db5c93ea 100644 --- a/lib/cartodb/models/cdb_request.js +++ b/lib/cartodb/models/cdb_request.js @@ -1,25 +1,25 @@ function CdbRequest() { + this.RE_USER_FROM_HOST = new RegExp(global.environment.user_from_host || + '^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com" + ); } module.exports = CdbRequest; -var RE_USER_FROM_HOST = new RegExp(global.environment.user_from_host || - '^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com" -); CdbRequest.prototype.userByReq = function(req) { var host = req.headers.host; if (req.params.user) { return req.params.user; } - var mat = host.match(RE_USER_FROM_HOST); + var mat = host.match(this.RE_USER_FROM_HOST); if ( ! mat ) { - console.error("Pattern '" + RE_USER_FROM_HOST + "' does not match hostname '" + host + "'"); + console.error("Pattern '" + this.RE_USER_FROM_HOST + "' does not match hostname '" + host + "'"); return; } // console.log("Matches: "); console.dir(mat); if ( mat.length !== 2 ) { - console.error("Pattern '" + RE_USER_FROM_HOST + "' gave unexpected matches against '" + host + "': ", mat); + console.error("Pattern '" + this.RE_USER_FROM_HOST + "' gave unexpected matches against '" + host + "': ", mat); return; } return mat[1]; diff --git a/test/unit/cartodb/cdb_request.test.js b/test/unit/cartodb/cdb_request.test.js new file mode 100644 index 00000000..04b2c1b9 --- /dev/null +++ b/test/unit/cartodb/cdb_request.test.js @@ -0,0 +1,60 @@ +require('../../support/test_helper'); +var assert = require('assert'); + +var CdbRequest = require('../../../lib/cartodb/models/cdb_request'); + +describe('req2params', function() { + + function createRequest(host, userParam) { + var req = { + params: {}, + headers: { + host: host + } + }; + + if (userParam) { + req.params.user = userParam; + } + + return req; + } + + it('extracts name from host header', function() { + var cdbRequest = new CdbRequest(); + var user = cdbRequest.userByReq(createRequest('localhost')); + + assert.equal(user, 'localhost'); + }); + + it('extracts name from subdomain host header in case of no config', function() { + var userFromHostConfig = global.environment.user_from_host; + global.environment.user_from_host = null; + + var cdbRequest = new CdbRequest(); + var user = cdbRequest.userByReq(createRequest('development.localhost.lan')); + + global.environment.user_from_host = userFromHostConfig; + + assert.equal(user, 'development'); + }); + + it('considers user param before headers', function() { + var cdbRequest = new CdbRequest(); + var user = cdbRequest.userByReq(createRequest('localhost', 'development')); + + assert.equal(user, 'development'); + }); + + it('returns undefined when it cannot extract username', function() { + var userFromHostConfig = global.environment.user_from_host; + global.environment.user_from_host = null; + + var cdbRequest = new CdbRequest(); + var user = cdbRequest.userByReq(createRequest('localhost')); + + global.environment.user_from_host = userFromHostConfig; + + assert.equal(user, undefined); + }); +}); From 69f99daa60c9e1c5279554fe2012ad1261e0e60d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 16:28:58 +0200 Subject: [PATCH 56/59] Mock better query tables api --- test/acceptance/multilayer_server.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index c7c37de2..79b59a3c 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -255,7 +255,7 @@ describe('tests from old api translated to multilayer', function() { var runQueryFn = QueryTablesApi.prototype.runQuery; QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) { - return callback(new Error('failed to query database for affected tables')); + return queryHandler(new Error('fake error message'), [], callback); }; var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }'); @@ -277,7 +277,9 @@ describe('tests from old api translated to multilayer', function() { assert.ok(!res.headers.hasOwnProperty('x-cache-channel')); var parsed = JSON.parse(res.body); - assert.deepEqual(parsed, {"errors":["Error: failed to query database for affected tables"]}); + assert.deepEqual(parsed, { + errors: ["Error: could not fetch affected tables and last updated time: fake error message"] + }); done(); } @@ -300,7 +302,7 @@ describe('tests from old api translated to multilayer', function() { function(res) { var runQueryFn = QueryTablesApi.prototype.runQuery; QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) { - return callback(new Error('failed to query database for affected tables')); + return queryHandler(new Error('failed to query database for affected tables'), [], callback); }; // reset internal cacheChannel cache From a2ac1c23f114d0b8c12237338bdd37988029404a Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 17:51:17 +0200 Subject: [PATCH 57/59] Tests for surrogate keys invalidation - uses nock to mock request - a bit hacky because tests keep environment inconsistent * for intance I had to mock cartocdn to not fail in other suite --- package.json | 1 + .../cache/surrogate_keys_invalidation.js | 127 +++++++++++++----- 2 files changed, 98 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 23cf68e2..21e43740 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "devDependencies": { "istanbul": "~0.3.6", "mocha": "~1.21.4", + "nock": "~1.3.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 83b2dca2..8b626701 100644 --- a/test/acceptance/cache/surrogate_keys_invalidation.js +++ b/test/acceptance/cache/surrogate_keys_invalidation.js @@ -5,20 +5,20 @@ var redis = require('redis'); var step = require('step'); var NamedMapsCacheEntry = require(__dirname + '/../../../lib/cartodb/cache/model/named_maps_entry'); -var SurrogateKeysCache = require(__dirname + '/../../../lib/cartodb/cache/surrogate_keys_cache'); - var CartodbWindshaft = require(__dirname + '/../../../lib/cartodb/cartodb_windshaft'); -var ServerOptions = require(__dirname + '/../../../lib/cartodb/server_options'); -var serverOptions = ServerOptions(); -suite('templates surrogate keys', function() { +describe('templates surrogate keys', function() { var redisClient = redis.createClient(global.environment.redis.port); // Enable Varnish purge for tests - serverOptions.varnish_purge_enabled = true; + var varnishHost = global.environment.varnish.host; + global.environment.varnish.host = '127.0.0.1'; + var varnishPurgeEnabled = global.environment.varnish.purge_enabled; + global.environment.varnish.purge_enabled = true; + var serverOptions = require('../../../lib/cartodb/server_options')(); var server = new CartodbWindshaft(serverOptions); var templateOwner = 'localhost', @@ -45,7 +45,24 @@ suite('templates surrogate keys', function() { }, expectedBody = { template_id: expectedTemplateId }; - var surrogateKeysCacheInvalidateFn = SurrogateKeysCache.prototype.invalidate; + var varnishHttpUrl = [ + 'http://', global.environment.varnish.host, ':', global.environment.varnish.http_port + ].join(''); + + var cacheEntryKey = new NamedMapsCacheEntry(templateOwner, templateName).key(); + var invalidationMatchHeader = '\\b' + cacheEntryKey + '\\b'; + + var nock = require('nock'); + nock.enableNetConnect(/(127.0.0.1:5555|cartocdn.com)/); + + after(function(done) { + serverOptions.varnish_purge_enabled = false; + global.environment.varnish.host = varnishHost; + global.environment.varnish.purge_enabled = varnishPurgeEnabled; + + nock.restore(); + done(); + }); function createTemplate(callback) { var postTemplateRequest = { @@ -85,13 +102,12 @@ suite('templates surrogate keys', function() { ); } - test("update template calls surrogate keys invalidation", function(done) { - var cacheEntryKey; - var surrogateKeysCacheInvalidateMethodInvoked = false; - SurrogateKeysCache.prototype.invalidate = function(cacheEntry) { - cacheEntryKey = cacheEntry.key(); - surrogateKeysCacheInvalidateMethodInvoked = true; - }; + it("invalidates surrogate keys on template update", function(done) { + + var scope = nock(varnishHttpUrl) + .intercept('/key', 'PURGE') + .matchHeader('Invalidation-Match', invalidationMatchHeader) + .reply(204, ''); step( function createTemplateToUpdate() { @@ -128,8 +144,7 @@ suite('templates surrogate keys', function() { var parsedBody = JSON.parse(res.body); assert.deepEqual(parsedBody, expectedBody); - assert.ok(surrogateKeysCacheInvalidateMethodInvoked); - assert.equal(cacheEntryKey, new NamedMapsCacheEntry(templateOwner, templateName).key()); + assert.equal(scope.pendingMocks().length, 0); return null; }, @@ -149,14 +164,12 @@ suite('templates surrogate keys', function() { ); }); - test("delete template calls surrogate keys invalidation", function(done) { + it("invalidates surrogate on template deletion", function(done) { - var cacheEntryKey; - var surrogateKeysCacheInvalidateMethodInvoked = false; - SurrogateKeysCache.prototype.invalidate = function(cacheEntry) { - cacheEntryKey = cacheEntry.key(); - surrogateKeysCacheInvalidateMethodInvoked = true; - }; + var scope = nock(varnishHttpUrl) + .intercept('/key', 'PURGE') + .matchHeader('Invalidation-Match', invalidationMatchHeader) + .reply(204, ''); step( function createTemplateToDelete() { @@ -190,8 +203,7 @@ suite('templates surrogate keys', function() { throw err; } - assert.ok(surrogateKeysCacheInvalidateMethodInvoked); - assert.equal(cacheEntryKey, new NamedMapsCacheEntry(templateOwner, templateName).key()); + assert.equal(scope.pendingMocks().length, 0); return null; }, @@ -201,11 +213,66 @@ suite('templates surrogate keys', function() { ); }); - suiteTeardown(function(done) { - SurrogateKeysCache.prototype.invalidate = surrogateKeysCacheInvalidateFn; - // Enable Varnish purge for tests - serverOptions.varnish_purge_enabled = false; - done(); + it("should update template even if surrogate key invalidation fails", function(done) { + + var scope = nock(varnishHttpUrl) + .intercept('/key', 'PURGE') + .matchHeader('Invalidation-Match', invalidationMatchHeader) + .reply(503, ''); + + step( + function createTemplateToUpdate() { + createTemplate(this); + }, + function putValidTemplate(err) { + if (err) { + throw err; + } + var updateTemplateRequest = { + url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234', + method: 'PUT', + headers: { + host: templateOwner, + 'Content-Type': 'application/json' + }, + data: JSON.stringify(template) + }; + var next = this; + assert.response(server, + updateTemplateRequest, + { + status: 200 + }, + function(res) { + next(null, res); + } + ); + }, + function checkValidUpdate(err, res) { + if (err) { + throw err; + } + var parsedBody = JSON.parse(res.body); + assert.deepEqual(parsedBody, expectedBody); + + assert.equal(scope.pendingMocks().length, 0); + + return null; + }, + function finish(err) { + if ( err ) { + return done(err); + } + redisClient.keys("map_*|localhost", function(err, keys) { + if ( err ) { + return done(err); + } + redisClient.del(keys, function(err) { + return done(err); + }); + }); + } + ); }); }); From cd79fc606b0de642ba68bc275360eae9a9395e9f Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 17:57:27 +0200 Subject: [PATCH 58/59] Regenerate npm-shrinkwrap.json --- npm-shrinkwrap.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a96a981c..b2678e6d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -116,11 +116,6 @@ "from": "lzma@~1.3.7", "resolved": "https://registry.npmjs.org/lzma/-/lzma-1.3.7.tgz" }, - "node-varnish": { - "version": "0.3.0", - "from": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0", - "resolved": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0" - }, "queue-async": { "version": "1.0.7", "from": "queue-async@~1.0.7", @@ -2384,8 +2379,8 @@ }, "abaculus": { "version": "1.1.0", - "from": "https://github.com/CartoDB/abaculus/tarball/cdb", - "resolved": "https://github.com/CartoDB/abaculus/tarball/cdb" + "from": "https://github.com/CartoDB/abaculus/tarball/cdb-stats", + "resolved": "https://github.com/CartoDB/abaculus/tarball/cdb-stats" }, "sphericalmercator": { "version": "1.0.2", From e0413c33020b3434be96c377a3724054a44db6b8 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 30 Mar 2015 18:44:44 +0200 Subject: [PATCH 59/59] Prepared next release --- NEWS.md | 443 +++++++++++++++++++++++++++----------------- npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 277 insertions(+), 170 deletions(-) diff --git a/NEWS.md b/NEWS.md index eb5dd295..cfc7d9d3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,58 +1,90 @@ -1.30.1 -- 2015-mm-dd --------------------- +# Changelog -1.30.0 -- 2015-03-11 --------------------- +## 2.0.0 + +Released 2015-mm-dd + +Announcements: + - Major release with **BREAKING CHANGES**: + * Removes `/:table/infowindow`, `/:table/map_metadata` and `/:table/flush_cache` endpoints + * Sample configuration removes `/tiles/template` and `/tiles/layergroup` + * URLs to use from now on are: `/api/v1/map/named` and `/api/v1/map` + * No more state changes for styles + * No more dump stats for renderers: SIGUSR1 and SIGUSR2 signals + * Removes query params: + - sql + - geom_type + - cache_buster + - cache_policy + - interactivity + - style + - style_version + - style_convert + - scale_factor + * Affected tables for x-cache-channel will use direct connection to postgresql + * Removes some metrics: authorized times ones + + +## 1.30.0 + +Released 2015-03-11 Announcements: - Upgrades windshaft to [0.40.0](https://github.com/CartoDB/Windshaft/releases/tag/0.40.0) -1.29.0 -- 2015-03-09 --------------------- +## 1.29.0 + +Released 2015-03-09 Announcements: - Upgrades windshaft to [0.39.0](https://github.com/CartoDB/Windshaft/releases/tag/0.39.0) -1.28.5 -- 2015-02-20 --------------------- +## 1.28.5 + +Released 2015-02-20 Announcements: - Upgrades windshaft to [0.37.5](https://github.com/CartoDB/Windshaft/releases/tag/0.37.5) -1.28.4 -- 2015-02-18 --------------------- +## 1.28.4 + +Released 2015-02-18 Announcements: - Upgrades windshaft to [0.37.4](https://github.com/CartoDB/Windshaft/releases/tag/0.37.4) -1.28.3 -- 2015-02-17 --------------------- +## 1.28.3 + +Released 2015-02-17 Announcements: - Upgrades windshaft to [0.37.3](https://github.com/CartoDB/Windshaft/releases/tag/0.37.3) -1.28.2 -- 2015-02-17 --------------------- +## 1.28.2 + +Released 2015-02-17 Announcements: - Upgrades windshaft to [0.37.2](https://github.com/CartoDB/Windshaft/releases/tag/0.37.2) -1.28.1 -- 2015-02-17 --------------------- +## 1.28.1 + +Released 2015-02-17 Announcements: - Upgrades windshaft to [0.37.1](https://github.com/CartoDB/Windshaft/releases/tag/0.37.1) -1.28.0 -- 2015-02-17 --------------------- +## 1.28.0 + +Released 2015-02-17 Announcements: - Upgrades windshaft to [0.37.0](https://github.com/CartoDB/Windshaft/releases/tag/0.37.0) @@ -62,8 +94,9 @@ New features: tables last update (#253) -1.27.0 -- 2015-02-16 --------------------- +## 1.27.0 + +Released 2015-02-16 Announcements: - Adds default image placeholder for http renderer to use as fallback @@ -76,29 +109,33 @@ Bugfixes: - Fixes tests with beforeEach and afterEach triggers -1.26.2 -- 2015-01-28 --------------------- +## 1.26.2 + +Released 2015-01-28 Bugfixes: - Accept 'open' string in templates' `auth` as authorized. -1.26.1 -- 2015-01-28 --------------------- +## 1.26.1 + +Released 2015-01-28 Announcements: - Upgrades windshaft to 0.35.1, see https://github.com/CartoDB/Windshaft/pull/254 -1.26.0 -- 2015-01-27 --------------------- +## 1.26.0 + +Released 2015-01-27 Announcements: - Upgrades windshaft to 0.35.0, supports mapconfig version `1.3.0` -1.25.0 -- 2015-01-26 --------------------- +## 1.25.0 + +Released 2015-01-26 Announcements: - No more signed maps (#227 and #238) @@ -134,22 +171,25 @@ New features: - SurrogateKeysCache is subscribed to TemplateMaps events to do the invalidations -1.24.0 -- 2015-01-15 --------------------- +## 1.24.0 + +Released 2015-01-15 Announcements: - Upgrades windshaft to 0.34.0 for retina support -1.23.1 -- 2015-01-14 --------------------- +## 1.23.1 + +Released 2015-01-14 Announcements: - Regenerate npm-shrinkwrap.json -1.23.0 -- 2015-01-14 --------------------- +## 1.23.0 + +Released 2015-01-14 Announcements: - Upgrades windshaft to 0.33.0 @@ -158,22 +198,25 @@ New features: - Sets HTTP renderer configuration in server_options -1.22.0 -- 2015-01-13 --------------------- +## 1.22.0 + +Released 2015-01-13 New features: - Health check endpoint -1.21.2 -- 2014-12-15 --------------------- +## 1.21.2 + +Released 2014-12-15 Announcements: - Upgrades windshaft to 0.32.4 -1.21.1 -- 2014-12-11 --------------------- +## 1.21.1 + +Released 2014-12-11 Announcements: - Upgrades windshaft to 0.32.2 @@ -183,29 +226,33 @@ Bugfixes: -1.21.0 -- 2014-10-24 --------------------- +## 1.21.0 + +Released 2014-10-24 New features: - Allow a different cache-control max-age for layergroup responses -1.20.2 -- 2014-10-20 --------------------- +## 1.20.2 + +Released 2014-10-20 Announcements: - Upgrades windshaft to 0.31.0 -1.20.1 -- 2014-10-17 --------------------- +## 1.20.1 + +Released 2014-10-17 Announcements: - Upgrades redis-mpool to 0.3.0 -1.20.0 -- 2014-10-15 --------------------- +## 1.20.0 + +Released 2014-10-15 New features: - Report to statsd the status of redis pools @@ -215,8 +262,9 @@ Enhancements: - Share one redis-mpool across the application -1.19.0 -- 2014-10-14 --------------------- +## 1.19.0 + +Released 2014-10-14 Announcements: - Dropping support for npm <1.2.1 @@ -225,8 +273,9 @@ Announcements: - Generates npm-shrinkwrap.json with npm >1.2.0 -1.18.2 -- 2014-10-13 --------------------- +## 1.18.2 + +Released 2014-10-13 Bug fixes: - Defaults resultSet to object if undefined in QueryTablesApi @@ -235,29 +284,33 @@ Announcements: - Upgrades windshaft to 0.28.1 -1.18.1 -- 2014-10-13 --------------------- +## 1.18.1 + +Released 2014-10-13 New features: - Allow to add more node.js' threadpool workers via process.env.UV_THREADPOOL_SIZE -1.18.0 -- 2014-10-03 --------------------- +## 1.18.0 + +Released 2014-10-03 Announcements: - Comes back to use mapnik 2.3.x based on cartodb/node-mapnik@1.4.15-cdb from windshaft@0.28.0 -1.17.2 -- 2014-10-01 --------------------- +## 1.17.2 + +Released 2014-10-01 Announcements: - Upgrades windshaft to 0.27.2 which downgrades node-mapnik to 0.7.26-cdb1 -1.17.1 -- 2014-09-30 --------------------- +## 1.17.1 + +Released 2014-09-30 Announcements: - Upgrades windshaft to 0.27.1 which downgrades node-mapnik to 1.4.10 @@ -267,8 +320,9 @@ Enhancements: - Upgrades mocha -1.17.0 -- 2014-09-25 --------------------- +## 1.17.0 + +Released 2014-09-25 New features: - Starts using mapnik 2.3.x @@ -279,14 +333,16 @@ Enhancements: - Metrics revamp: removes and adds some metrics - Adds poolSize configuration for mapnik -1.16.1 -- 2014-08-19 --------------------- +## 1.16.1 + +Released 2014-08-19 Enhancements: - Upgrades cartodb-redis -1.16.0 -- 2014-08-18 --------------------- +## 1.16.0 + +Released 2014-08-18 New features: - Configurable QueryTablesAPI to call directly postgresql using cartodb-psql @@ -302,8 +358,9 @@ Enhancements: - windshaft - request -1.15.0 -- 2014-08-13 --------------------- +## 1.15.0 + +Released 2014-08-13 Enhancements: - Upgrades dependencies: - redis-mpool @@ -313,8 +370,9 @@ Enhancements: - Slow pool configuration in example configurations -1.14.0 -- 2014-08-07 --------------------- +## 1.14.0 + +Released 2014-08-07 Enhancements: - SQL API requests moved to its own entity @@ -326,43 +384,49 @@ New features: dependencies for this matter -1.13.1 -- 2014-08-04 --------------------- +## 1.13.1 + +Released 2014-08-04 Enhancements: - Profiler header sent as JSON string -1.13.0 -- 2014-07-30 --------------------- +## 1.13.0 + +Released 2014-07-30 New features: - Support for postgresql schemas - Use public user from redis - Support for several auth tokens -1.12.1 -- 2014-06-24 --------------------- +## 1.12.1 + +Released 2014-06-24 Enhancements: - Caches layergroup and sets X-Cache-Channel in GET requests also in named maps -1.12.0 -- 2014-06-24 --------------------- +## 1.12.0 + +Released 2014-06-24 New features: - Caches layergroup and sets X-Cache-Channel in GET requests -1.11.1 -- 2014-05-07 --------------------- +## 1.11.1 + +Released 2014-05-07 Enhancements: - Upgrade Windshaft to 0.21.0, see http://github.com/CartoDB/Windshaft/blob/0.21.0/NEWS -1.11.0 -- 2014-04-28 --------------------- +## 1.11.0 + +Released 2014-04-28 New features: @@ -373,23 +437,26 @@ Enhancements: - Set default PostgreSQL application name to "cartodb_tiler" -1.10.2 -- 2014-04-08 --------------------- +## 1.10.2 + +Released 2014-04-08 Bug fixes: - Fix show_style tool broken since 1.8.1 - Fix X-Cache-Channel of tiles accessed via signed token (#188) -1.10.1 -- 2014-03-21 --------------------- +## 1.10.1 + +Released 2014-03-21 Bug fixes: - Do not cache non-success jsonp responses (#186) -1.10.0 -- 2014-03-20 --------------------- +## 1.10.0 + +Released 2014-03-20 New features: @@ -410,15 +477,17 @@ Other changes: - Switch to 3-clause BSD license (#184) -1.9.0 -- 2014-03-10 -------------------- +## 1.9.0 + +Released 2014-03-10 New features: - Allow to set server related configuration in serverMetadata (#182) -1.8.5 -- 2014-03-10 -------------------- +## 1.8.5 + +Released 2014-03-10 Enhancements: @@ -436,8 +505,9 @@ Bug fixes: - Do not cache map creation responses (#176) -1.8.4 -- 2014-03-03 -------------------- +## 1.8.4 + +Released 2014-03-03 Enhancements: @@ -454,8 +524,9 @@ Bug fixes: - Fix database connection settings on template instanciation (#174) -1.8.3 -- 2014-02-27 -------------------- +## 1.8.3 + +Released 2014-02-27 Enhancements: @@ -468,8 +539,9 @@ Enhancements: [ new sqlapi.timeout directive, defaults to 100 ms ] - Do not query CDB_TableMetadata for queries affected by no tables (#168) -1.8.2 -- 2014-02-25 -------------------- +## 1.8.2 + +Released 2014-02-25 Enhancements: @@ -483,8 +555,9 @@ Bug fixes: * Fix munin plugin after log format changes (#154) -1.8.1 -- 2014-02-19 -------------------- +## 1.8.1 + +Released 2014-02-19 Enhancements: @@ -494,8 +567,9 @@ Bug fixes: * Always generate X-Cache-Channel for token-based tile responses (#152) -1.8.0 -- 2014-02-18 -------------------- +## 1.8.0 + +Released 2014-02-18 Enhancements: @@ -510,16 +584,18 @@ Enhancements: * Allow limiting number of templates for each user (#136) * Allow configuring TTL of mapConfigs via "mapConfigTTL" -1.7.1 -- 2014-02-11 -------------------- +## 1.7.1 + +Released 2014-02-11 Enhancements: * Disable debug logging unless "debug" config param evaluates to true (#137) * Require windshaft 0.17.2 for further reducing log noise (#137) -1.7.0 -- 2014-02-11 -------------------- +## 1.7.0 + +Released 2014-02-11 New features: @@ -540,8 +616,9 @@ Bug fixes: * Allow passing numbers as values for numeric template variables (#130) -1.6.3 -- 2014-01-30 -------------------- +## 1.6.3 + +Released 2014-01-30 Bug fixes: @@ -556,8 +633,9 @@ Enhancements: * Stop processing XML on renderer creation, not needed anymore since 1.6.1 introduced on-demand XML generation. -1.6.2 -- 2014-01-23 -------------------- +## 1.6.2 + +Released 2014-01-23 Bug fixes: @@ -569,16 +647,18 @@ Enhancements: print XML style now it is not in redis anymore (#110) * Support CORS in template instanciation endpoint (#113) -1.6.1 -- 2014-01-15 -------------------- +## 1.6.1 + +Released 2014-01-15 Bug fixes: * Drop cache headers from error responses (#107) * Localize external CartoCSS resources at renderer creation time (#108) -1.6.0 -- 2014-01-10 -------------------- +## 1.6.0 + +Released 2014-01-10 New features: @@ -591,24 +671,27 @@ Other changes: * Update cartodb-redis dependency to "~0.3.0" * Update redis-server dependency to "2.4.0+" -1.5.2 -- 2013-12-05 -------------------- +## 1.5.2 + +Released 2013-12-05 Bug fixes: * Fix configuration-level compatibility with versions prior to 1.5 (#96) * Fix use of old layergroups on mapnik upgrade (#97) -1.5.1 -- 2013-11-28 -------------------- +## 1.5.1 + +Released 2013-11-28 Bug fixes: * Survive presence of malformed CartoCSS in redis (#94) * Accept useless point-transform:scale directives (#93) -1.5.0 -- 2013-11-19 -------------------- +## 1.5.0 + +Released 2013-11-19 NOTE: new configuration directives `postgres_auth_pass` and `postgres.password` added; see config/environments/*.example @@ -632,24 +715,28 @@ Other changes: * CartoDB redis interaction delegated to "cartodb-redis" module -1.4.1 -- 2013-11-08 -------------------- +## 1.4.1 + +Released 2013-11-08 * Fix support for exponential notation in CartoCSS filter values (#87) -1.4.0 -- 2013-10-31 -------------------- +## 1.4.0 + +Released 2013-10-31 * Add Support for Mapnik-2.2.0 (#78) -1.3.6 -- 2013-10-11 -------------------- +## 1.3.6 + +Released 2013-10-11 * Restore support for node-0.8.9 accidentally dropped by 1.3.5 NOTE: needs removing node_modules/windshaft and re-running npm install -1.3.5 -- 2013-10-03 -------------------- +## 1.3.5 + +Released 2013-10-03 * Fixing apostrophes in CartoCSS * Fix "sql/table must contain zoom variable" error when using @@ -658,8 +745,8 @@ Other changes: * Fix error for invalid text-name in CartoCSS (#81) * Do not let anonymous requests use authorized renderer caches -1.3.4 ------- +## 1.3.4 + NOTE: configuration sqlapi.host renamed to sqlapi.domain (support for "sqlapi.host" is retained for backward compatibility) @@ -668,38 +755,38 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * Improve invalid mapnik-geometry-type CSS error message * Fix race condition in localization of network resources -1.3.3 ------- +## 1.3.3 + * Set Last-Modified header to allow for 304 responses * Add profiling support (needs useProfiler in env config file) * Fix double-checking for layergroups with no interactivity * Log full layergroup config at creation time (#76) -1.3.2 ------- +## 1.3.2 + * Set default layergroup TTL to 2 hours * Serve multilayer tiles and grid with persistent cache control -1.3.1 ------- +## 1.3.1 + * Fix deadlock on new style creation * Fix database authentication with multi-table layergroups * Add tile and grid fetching checks at layergroup creation time * Fix SQL error reporting to NOT split on newline * Fix support for CartoCSS attachments -1.3.0 ------- +## 1.3.0 + * Change stats format for multilayer map token request, see http://github.com/Vizzuality/Windshaft-cartodb/wiki/Redis-stats-format -1.2.1 ------- +## 1.2.1 + * Fix multilayer post from firefox * Fix multilayer cartocss layer name handling -1.2.0 ------- +## 1.2.0 + * Multilayer API changes * Layers passed by index in grid fetching url * Interactivity only specified in layergroup config @@ -707,14 +794,14 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * Use ISO format for last_modified timestamp * Expected LZMA encoding changed to base64 -1.1.10 ------- +## 1.1.10 + * Fix regression with default interactivity parameter (#74) * More verbose logging for SQL api connection errors * Write stats for multilayer map token request -1.1.9 ------ +## 1.1.9 + * Handle SQL API errors by requesting no Varnish cache * Fix X-Cache-Channel for multilayer (by token) responses * Add last_modified field to layergroup creation response (#72) @@ -723,18 +810,22 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * Add support for LZMA compressed GET parameters * Add support for creating layergroups via GET -1.1.8 ------ +## 1.1.8 + * Require Windshaft-0.9.1, to reduce harmfulness of cache_buster param -1.1.7 (DD//MM//YY) ------ +## 1.1.7 + +Released DD//MM//YY + * Do not let /etc/services confuse FD checker (munin plugin) * Multilayer support (#72) * Expose renderer settings in the environment config files -1.1.6 (19//02//13) ------ +## 1.1.6 + +Released 19//02//13 + * Require windshaft 0.8.5, fixing some stability issues and providing cache info on request * Require grainstore 0.10.9, fixing an issue with multi-geom markers @@ -743,20 +834,26 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * Survive connection refusals from redis * Add maxConnection environment configuration, default to 128 -1.1.5 (DD//MM//YY) ------ +## 1.1.5 + +Released DD//MM//YY + * Fix bogus cached return of utf grid for fully contained tiles (#67) -1.1.4 (DD//MM//YY) ------ +## 1.1.4 + +Released DD//MM//YY + * Reduce default extent to allow for consistent proj4 round-tripping * Enhance reset_styles script to use full configuration (#62) * Have reset_styles script also drop extended keys (#58) * Fix example postgis parameter for simplifying input geoms (#63) * Add row_limit to example config (#64) -1.1.3 (30//11//12) ------ +## 1.1.3 + +Released 30//11//12 + * Fix reset_styles script to really skip extended keys * CartoCSS versioning * Mapnik-version dependent default styles @@ -764,16 +861,20 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * styles with conditional markers * scale arrow markers by 50% -1.1.2 (DD//MM//YY) ------ +## 1.1.2 + +Released DD//MM//YY + * CartoCSS versioning * Fix use of "style_version" with GET (inline styles) * Enhance 2.0 -> 2.1 transforms: * styles with no semicolon * markers shift due to geometry clipping -1.1.1 (DD//MM//YY) ------ +## 1.1.1 + +Released DD//MM//YY + * Add support for persistent client cache headers * Fix crash on unknown user (#55) * Add /version entry point @@ -782,8 +883,10 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * Support style_version and style_convert parameters in POST /style request * Support style_version in GET /:z/:x/:y request -1.1.0 (30/10/12) -======= +## 1.1.0 + +Released (30/10/12) + * Add /version entry point * CartoCSS versioning * Include version in GET /style response @@ -800,12 +903,16 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain * Replaced environment configs by .example ones * Fixed some issues with cluster2 -1.0.0 (03/10/12) ------ +## 1.0.0 + +Released 03/10/12 + * Migrated to node 0.8.x. -0.9.0 (25/09/12) ------ +## 0.9.0 + +Released 25/09/12 + * External resources in CartoCSS * Added X-Cache-Channel header in all the tiler GET requests * Small fixes diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index b2678e6d..e9d23060 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "windshaft-cartodb", - "version": "1.30.1", + "version": "2.0.0", "dependencies": { "cartodb-psql": { "version": "0.4.0", diff --git a/package.json b/package.json index 21e43740..55414e65 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "windshaft-cartodb", - "version": "1.30.1", + "version": "2.0.0", "description": "A map tile server for CartoDB", "keywords": [ "cartodb"