From 382089445455366b6a2059dedbb42a728f5328d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 17:00:15 +0200 Subject: [PATCH 01/20] Do not use 'step' --- .../provider/create-layergroup-provider.js | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index bc36d3ae..4d415420 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -33,28 +33,22 @@ function CreateLayergroupMapConfigProvider( module.exports = CreateLayergroupMapConfigProvider; CreateLayergroupMapConfigProvider.prototype.getMapConfig = function(callback) { - var self = this; - if (this.mapConfig && this.params && this.context) { return callback(null, this.mapConfig, this.params, this.context); } var context = {}; - step( - function prepareContextLimits() { - self.userLimitsBackend.getRenderLimits(self.user, self.params.api_key, this); - }, - function handleRenderLimits(err, renderLimits) { - assert.ifError(err); - context.limits = renderLimits; - self.context = context; - return null; - }, - function finish(err) { - return callback(err, self.mapConfig, self.params, context); + this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { + if (err) { + return callback(err); } - ); + + context.limits = renderLimits; + this.context = context; + + return callback(err, this.mapConfig, this.params, context); + }); }; CreateLayergroupMapConfigProvider.prototype.getKey = MapStoreMapConfigProvider.prototype.getKey; From cd0be5f79d27198dab70160833c7cd13cd9d3333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 17:00:45 +0200 Subject: [PATCH 02/20] Do not require 'step' --- .../models/mapconfig/provider/create-layergroup-provider.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index 4d415420..23f0c117 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -1,6 +1,3 @@ -var assert = require('assert'); -var step = require('step'); - var MapStoreMapConfigProvider = require('./map-store-provider'); const QueryTables = require('cartodb-query-tables'); From d8b0d338c0df3a8dee40b1f13520f3b6dcad6bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 17:02:15 +0200 Subject: [PATCH 03/20] Use 'const' instead of 'var' --- .../models/mapconfig/provider/create-layergroup-provider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index 23f0c117..32865b37 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -1,4 +1,4 @@ -var MapStoreMapConfigProvider = require('./map-store-provider'); +const MapStoreMapConfigProvider = require('./map-store-provider'); const QueryTables = require('cartodb-query-tables'); /** @@ -34,7 +34,7 @@ CreateLayergroupMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(null, this.mapConfig, this.params, this.context); } - var context = {}; + const context = {}; this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { if (err) { From 532d50ad7adff6379e43368beaef65a8ef65fe43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 17:09:01 +0200 Subject: [PATCH 04/20] Return 'null' explicitly --- .../provider/create-layergroup-provider.js | 2 +- .../mapconfig/provider/map-store-provider.js | 37 +++++++++---------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index 32865b37..f1e2ac37 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -44,7 +44,7 @@ CreateLayergroupMapConfigProvider.prototype.getMapConfig = function(callback) { context.limits = renderLimits; this.context = context; - return callback(err, this.mapConfig, this.params, context); + return callback(null, this.mapConfig, this.params, context); }); }; diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index 1fd9dadf..0adebde3 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -28,33 +28,30 @@ function MapStoreMapConfigProvider(mapStore, user, userLimitsBackend, pgConnecti module.exports = MapStoreMapConfigProvider; MapStoreMapConfigProvider.prototype.getMapConfig = function(callback) { - var self = this; - if (this.mapConfig !== null) { return callback(null, this.mapConfig, this.params, this.context); } var context = {}; - step( - function prepareContextLimits() { - self.userLimitsBackend.getRenderLimits(self.user, self.params.api_key, this); - }, - function handleRenderLimits(err, renderLimits) { - assert.ifError(err); - context.limits = renderLimits; - return null; - }, - function loadMapConfig(err) { - assert.ifError(err); - self.mapStore.load(self.token, this); - }, - function finish(err, mapConfig) { - self.mapConfig = mapConfig; - self.context = context; - return callback(err, mapConfig, self.params, context); + this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { + if (err) { + return callback(err); } - ); + + context.limits = renderLimits; + + this.mapStore.load(this.token, (err, mapConfig) => { + if (err) { + return callback(err); + } + + this.mapConfig = mapConfig; + this.context = context; + + return callback(null, mapConfig, this.params, context); + }); + }); }; MapStoreMapConfigProvider.prototype.getKey = function() { From 4e28f7bb4e3afbe15d62ce146cbe60cb687c8256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 17:10:18 +0200 Subject: [PATCH 05/20] Do not require assert and step --- lib/cartodb/models/mapconfig/provider/map-store-provider.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index 0adebde3..e621738f 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -1,7 +1,5 @@ var _ = require('underscore'); -var assert = require('assert'); var dot = require('dot'); -var step = require('step'); const QueryTables = require('cartodb-query-tables'); /** From 5cfffcfa83c82256fce3cf6d17f407dc6d59319b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 17:22:02 +0200 Subject: [PATCH 06/20] Use const instead of var --- .../mapconfig/provider/map-store-provider.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index e621738f..3cbff358 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -1,5 +1,5 @@ -var _ = require('underscore'); -var dot = require('dot'); +const _ = require('underscore'); +const dot = require('dot'); const QueryTables = require('cartodb-query-tables'); /** @@ -30,7 +30,7 @@ MapStoreMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(null, this.mapConfig, this.params, this.context); } - var context = {}; + const context = {}; this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { if (err) { @@ -61,19 +61,19 @@ MapStoreMapConfigProvider.prototype.getCacheBuster = function() { }; MapStoreMapConfigProvider.prototype.filter = function(key) { - var regex = new RegExp('^' + this.createKey(true) + '.*'); + const regex = new RegExp('^' + this.createKey(true) + '.*'); return key && key.match(regex); }; // Configure bases for cache keys suitable for string interpolation -var baseKey = '{{=it.dbname}}:{{=it.token}}'; -var rendererKey = baseKey + ':{{=it.dbuser}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; +const baseKey = '{{=it.dbname}}:{{=it.token}}'; +const rendererKey = baseKey + ':{{=it.dbuser}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; -var baseKeyTpl = dot.template(baseKey); -var rendererKeyTpl = dot.template(rendererKey); +const baseKeyTpl = dot.template(baseKey); +const rendererKeyTpl = dot.template(rendererKey); MapStoreMapConfigProvider.prototype.createKey = function(base) { - var tplValues = _.defaults({}, this.params, { + const tplValues = _.defaults({}, this.params, { dbname: '', token: '', dbuser: '', From 1b6a722c0c8b2d51f937c047a92f648c7454364b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 18:15:51 +0200 Subject: [PATCH 07/20] Remove step --- .../mapconfig/provider/named-map-provider.js | 235 +++++++++--------- 1 file changed, 124 insertions(+), 111 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 2d9a88c2..0013e8af 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -1,8 +1,6 @@ var _ = require('underscore'); -var assert = require('assert'); var crypto = require('crypto'); var dot = require('dot'); -var step = require('step'); var MapConfig = require('windshaft').model.MapConfig; var templateName = require('../../../backends/template_maps').templateName; var QueryTables = require('cartodb-query-tables'); @@ -58,135 +56,150 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(this.err, this.mapConfig, this.rendererParams, this.context); } - var self = this; - var mapConfig = null; var rendererParams; var apiKey; var context = {}; - step( - function getTemplate() { - self.getTemplate(this); - }, - function prepareDbParams(err, tpl) { - assert.ifError(err); - self.template = tpl; + this.getTemplate((err, tpl) => { + if (err) { + this.err = err; + return callback(err); + } - rendererParams = _.extend({}, self.params, { - user: self.owner - }); - self.setDBParams(self.owner, rendererParams, this); - }, - function getUserApiKey(err) { - assert.ifError(err); - self.metadataBackend.getUserMapKey(self.owner, this); - }, - function prepareParams(err, _apiKey) { - assert.ifError(err); + this.template = tpl; - apiKey = _apiKey; + rendererParams = _.extend({}, this.params, { + user: this.owner + }); - var templateParams = {}; - if (self.config) { - try { - templateParams = _.isString(self.config) ? JSON.parse(self.config) : self.config; - } catch (e) { - throw new Error('malformed config parameter, should be a valid JSON'); - } + this.setDBParams(this.owner, rendererParams, (err) => { + if (err) { + this.err = err; + return callback(err); } - return templateParams; - }, - function instantiateTemplate(err, templateParams) { - assert.ifError(err); - context.templateParams = templateParams; - return self.templateMaps.instance(self.template, templateParams); - }, - function prepareAdapterMapConfig(err, requestMapConfig) { - assert.ifError(err); - context.analysisConfiguration = { - user: self.owner, - db: { - host: rendererParams.dbhost, - port: rendererParams.dbport, - dbname: rendererParams.dbname, - user: rendererParams.dbuser, - pass: rendererParams.dbpassword - }, - batch: { - username: self.owner, - apiKey: apiKey + this.metadataBackend.getUserMapKey(this.owner, (err, _apiKey) => { + if (err) { + this.err = err; + return callback(err); } - }; - self.mapConfigAdapter.getMapConfig(self.owner, requestMapConfig, rendererParams, context, this); - }, - function prepareContextLimits(err, _mapConfig) { - assert.ifError(err); - mapConfig = _mapConfig; - self.userLimitsBackend.getRenderLimits(self.owner, self.params.api_key, this); - }, - function cacheAndReturnMapConfig(err, renderLimits) { - self.err = err; - self.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); - self.analysesResults = context.analysesResults || []; - self.rendererParams = rendererParams; - self.context = context; - self.context.limits = renderLimits || {}; - return callback(self.err, self.mapConfig, self.rendererParams, self.context); - } - ); + + apiKey = _apiKey; + + var templateParams = {}; + if (this.config) { + try { + templateParams = _.isString(this.config) ? JSON.parse(this.config) : this.config; + } catch (e) { + const error = new Error('malformed config parameter, should be a valid JSON'); + this.err = error; + return callback(err); + } + } + + context.templateParams = templateParams; + + let requestMapConfig; + try { + requestMapConfig = this.templateMaps.instance(this.template, templateParams); + } catch (err) { + this.err = err; + return callback(err); + } + + context.analysisConfiguration = { + user: this.owner, + db: { + host: rendererParams.dbhost, + port: rendererParams.dbport, + dbname: rendererParams.dbname, + user: rendererParams.dbuser, + pass: rendererParams.dbpassword + }, + batch: { + username: this.owner, + apiKey: apiKey + } + }; + + this.mapConfigAdapter.getMapConfig(this.owner, requestMapConfig, rendererParams, context, (err, _mapConfig) => { + if (err) { + this.err = err; + return callback(err); + } + + mapConfig = _mapConfig; + + this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { + if (err) { + this.err = err; + return callback(err); + } + + this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); + this.analysesResults = context.analysesResults || []; + this.rendererParams = rendererParams; + this.context = context; + this.context.limits = renderLimits || {}; + + return callback(null, this.mapConfig, this.rendererParams, this.context); + }); + }); + }); + }); + }); }; NamedMapMapConfigProvider.prototype.getTemplate = function(callback) { - var self = this; - if (!!this.err || this.template !== null) { return callback(this.err, this.template); } - step( - function getTemplate() { - self.templateMaps.getTemplate(self.owner, self.templateName, this); - }, - function checkExists(err, tpl) { - assert.ifError(err); - if (!tpl) { - var notFoundErr = new Error( - "Template '" + self.templateName + "' of user '" + self.owner + "' not found" - ); - notFoundErr.http_status = 404; - throw notFoundErr; - } - return tpl; - }, - function checkAuthorized(err, tpl) { - assert.ifError(err); - - var authorized = false; - try { - authorized = self.templateMaps.isAuthorized(tpl, self.authToken); - } catch (err) { - // we catch to add http_status - var authorizationFailedErr = new Error('Failed to authorize template'); - authorizationFailedErr.http_status = 403; - throw authorizationFailedErr; - } - if ( ! authorized ) { - var unauthorizedErr = new Error('Unauthorized template instantiation'); - unauthorizedErr.http_status = 403; - throw unauthorizedErr; - } - - return tpl; - }, - function cacheAndReturnTemplate(err, template) { - self.err = err; - self.template = template; - return callback(self.err, self.template); + this.templateMaps.getTemplate(this.owner, this.templateName, (err, tpl) => { + if (err) { + this.err = err; + return callback(err); } - ); + + if (!tpl) { + var notFoundErr = new Error( + "Template '" + this.templateName + "' of user '" + this.owner + "' not found" + ); + notFoundErr.http_status = 404; + + this.err = notFoundErr; + + return callback(notFoundErr); + } + + var authorized = false; + + try { + authorized = this.templateMaps.isAuthorized(tpl, this.authToken); + } catch (err) { + // we catch to add http_status + var authorizationFailedErr = new Error('Failed to authorize template'); + authorizationFailedErr.http_status = 403; + + this.err = authorizationFailedErr; + + return callback(authorizationFailedErr); + } + + if (!authorized) { + var unauthorizedErr = new Error('Unauthorized template instantiation'); + unauthorizedErr.http_status = 403; + this.err = unauthorizedErr; + + return callback(unauthorizedErr); + } + + this.template = tpl; + + return callback(null, this.template); + }); }; NamedMapMapConfigProvider.prototype.getKey = function() { From 5fc49ab3c267ee84de0aa3bc1119c6dccfb31562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 18:16:42 +0200 Subject: [PATCH 08/20] Remove duplicated assignment --- lib/cartodb/models/mapconfig/provider/named-map-provider.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 0013e8af..e58e6bb0 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -68,8 +68,6 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(err); } - this.template = tpl; - rendererParams = _.extend({}, this.params, { user: this.owner }); From eabd25ee6a48509370be3d09f3df187112d3f2de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 18:18:42 +0200 Subject: [PATCH 09/20] Use the returned template instead of the cached one --- lib/cartodb/models/mapconfig/provider/named-map-provider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index e58e6bb0..6e9e9aca 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -62,7 +62,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { var context = {}; - this.getTemplate((err, tpl) => { + this.getTemplate((err, template) => { if (err) { this.err = err; return callback(err); @@ -101,7 +101,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { let requestMapConfig; try { - requestMapConfig = this.templateMaps.instance(this.template, templateParams); + requestMapConfig = this.templateMaps.instance(template, templateParams); } catch (err) { this.err = err; return callback(err); From f7c712f6ebe0b53dff59c1f17b506eb6d8ff76ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 18:31:59 +0200 Subject: [PATCH 10/20] Avoid functions with side effects --- .../mapconfig/provider/named-map-provider.js | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 6e9e9aca..5e9de375 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -57,7 +57,6 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { } var mapConfig = null; - var rendererParams; var apiKey; var context = {}; @@ -68,11 +67,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(err); } - rendererParams = _.extend({}, this.params, { - user: this.owner - }); - - this.setDBParams(this.owner, rendererParams, (err) => { + this.getDBParams(this.owner, (err, rendererParams) => { if (err) { this.err = err; return callback(err); @@ -253,19 +248,23 @@ function configHash(config) { module.exports.configHash = configHash; -NamedMapMapConfigProvider.prototype.setDBParams = function(cdbuser, params, callback) { +NamedMapMapConfigProvider.prototype.getDBParams = function(cdbuser, callback) { + const dbParams = _.extend({}, this.params, { + user: this.owner + }); + this.pgConnection.getDatabaseParams(cdbuser, (err, databaseParams) => { if (err) { return callback(err); } - params.dbuser = databaseParams.dbuser; - params.dbpass = databaseParams.dbpass; - params.dbhost = databaseParams.dbhost; - params.dbport = databaseParams.dbport; - params.dbname = databaseParams.dbname; + dbParams.dbuser = databaseParams.dbuser; + dbParams.dbpass = databaseParams.dbpass; + dbParams.dbhost = databaseParams.dbhost; + dbParams.dbport = databaseParams.dbport; + dbParams.dbname = databaseParams.dbname; - callback(); + return callback(null, dbParams); }); }; From 2fb6c087021fab901629eb82045b536def621f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 18:37:11 +0200 Subject: [PATCH 11/20] Remove unnecessary variables --- .../models/mapconfig/provider/named-map-provider.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 5e9de375..2667971d 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -56,9 +56,6 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(this.err, this.mapConfig, this.rendererParams, this.context); } - var mapConfig = null; - var apiKey; - var context = {}; this.getTemplate((err, template) => { @@ -73,14 +70,12 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(err); } - this.metadataBackend.getUserMapKey(this.owner, (err, _apiKey) => { + this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { if (err) { this.err = err; return callback(err); } - apiKey = _apiKey; - var templateParams = {}; if (this.config) { try { @@ -117,14 +112,12 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { } }; - this.mapConfigAdapter.getMapConfig(this.owner, requestMapConfig, rendererParams, context, (err, _mapConfig) => { + this.mapConfigAdapter.getMapConfig(this.owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { if (err) { this.err = err; return callback(err); } - mapConfig = _mapConfig; - this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { if (err) { this.err = err; From 1d0210a372359d50577e90884ec85a380879f90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 19:07:28 +0200 Subject: [PATCH 12/20] Reorder code --- .../mapconfig/provider/named-map-provider.js | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 2667971d..c1386a5e 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -51,44 +51,61 @@ function NamedMapMapConfigProvider( module.exports = NamedMapMapConfigProvider; -NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { +NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { if (!!this.err || this.mapConfig !== null) { return callback(this.err, this.mapConfig, this.rendererParams, this.context); } - var context = {}; - - this.getTemplate((err, template) => { + this.getDBParams(this.owner, (err, rendererParams) => { if (err) { this.err = err; return callback(err); } - this.getDBParams(this.owner, (err, rendererParams) => { + this.rendererParams = rendererParams; + + this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { if (err) { this.err = err; return callback(err); } - this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { + var context = {}; + + context.analysisConfiguration = { + user: this.owner, + db: { + host: rendererParams.dbhost, + port: rendererParams.dbport, + dbname: rendererParams.dbname, + user: rendererParams.dbuser, + pass: rendererParams.dbpassword + }, + batch: { + username: this.owner, + apiKey: apiKey + } + }; + + var templateParams = {}; + if (this.config) { + try { + templateParams = _.isString(this.config) ? JSON.parse(this.config) : this.config; + } catch (e) { + const error = new Error('malformed config parameter, should be a valid JSON'); + this.err = error; + return callback(err); + } + } + + context.templateParams = templateParams; + + this.getTemplate((err, template) => { if (err) { this.err = err; return callback(err); } - var templateParams = {}; - if (this.config) { - try { - templateParams = _.isString(this.config) ? JSON.parse(this.config) : this.config; - } catch (e) { - const error = new Error('malformed config parameter, should be a valid JSON'); - this.err = error; - return callback(err); - } - } - - context.templateParams = templateParams; - let requestMapConfig; try { requestMapConfig = this.templateMaps.instance(template, templateParams); @@ -97,37 +114,22 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { return callback(err); } - context.analysisConfiguration = { - user: this.owner, - db: { - host: rendererParams.dbhost, - port: rendererParams.dbport, - dbname: rendererParams.dbname, - user: rendererParams.dbuser, - pass: rendererParams.dbpassword - }, - batch: { - username: this.owner, - apiKey: apiKey - } - }; - this.mapConfigAdapter.getMapConfig(this.owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { if (err) { this.err = err; return callback(err); } + this.context = context; + this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); + this.analysesResults = context.analysesResults || []; + this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { if (err) { this.err = err; return callback(err); } - this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); - this.analysesResults = context.analysesResults || []; - this.rendererParams = rendererParams; - this.context = context; this.context.limits = renderLimits || {}; return callback(null, this.mapConfig, this.rendererParams, this.context); From 9d415d0dbe8ba49468198fb910e8f4ea8df558a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 19:30:34 +0200 Subject: [PATCH 13/20] Extract method to get and build context --- .../mapconfig/provider/named-map-provider.js | 100 ++++++++++-------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index c1386a5e..924385b6 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -56,17 +56,68 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { return callback(this.err, this.mapConfig, this.rendererParams, this.context); } - this.getDBParams(this.owner, (err, rendererParams) => { + this.getContext((err, context) => { if (err) { this.err = err; return callback(err); } + const { owner, rendererParams } = this; + + var templateParams = {}; + + if (this.config) { + try { + templateParams = _.isString(this.config) ? JSON.parse(this.config) : this.config; + } catch (e) { + const error = new Error('malformed config parameter, should be a valid JSON'); + this.err = error; + return callback(err); + } + } + + context.templateParams = templateParams; + + this.getTemplate((err, template) => { + if (err) { + this.err = err; + return callback(err); + } + + let requestMapConfig; + + try { + requestMapConfig = this.templateMaps.instance(template, templateParams); + } catch (err) { + this.err = err; + return callback(err); + } + + this.mapConfigAdapter.getMapConfig(owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { + if (err) { + this.err = err; + return callback(err); + } + + this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); + this.analysesResults = context.analysesResults || []; + + return callback(null, this.mapConfig, this.rendererParams, this.context); + }); + }); + }); +}; + +NamedMapMapConfigProvider.prototype.getContext = function (callback) { + this.getDBParams(this.owner, (err, rendererParams) => { + if (err) { + return callback(err); + } + this.rendererParams = rendererParams; this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { if (err) { - this.err = err; return callback(err); } @@ -87,54 +138,17 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { } }; - var templateParams = {}; - if (this.config) { - try { - templateParams = _.isString(this.config) ? JSON.parse(this.config) : this.config; - } catch (e) { - const error = new Error('malformed config parameter, should be a valid JSON'); - this.err = error; - return callback(err); - } - } - - context.templateParams = templateParams; - - this.getTemplate((err, template) => { + this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { if (err) { this.err = err; return callback(err); } - let requestMapConfig; - try { - requestMapConfig = this.templateMaps.instance(template, templateParams); - } catch (err) { - this.err = err; - return callback(err); - } + context.limits = renderLimits || {}; - this.mapConfigAdapter.getMapConfig(this.owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { - if (err) { - this.err = err; - return callback(err); - } + this.context = context; - this.context = context; - this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); - this.analysesResults = context.analysesResults || []; - - this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { - if (err) { - this.err = err; - return callback(err); - } - - this.context.limits = renderLimits || {}; - - return callback(null, this.mapConfig, this.rendererParams, this.context); - }); - }); + return callback(null, context); }); }); }); From 16bca85438f9b8d7678a73c8eecd85ff28f5d836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 19:43:23 +0200 Subject: [PATCH 14/20] Do not use underscore --- .../mapconfig/provider/named-map-provider.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 924385b6..b0600afb 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -1,4 +1,3 @@ -var _ = require('underscore'); var crypto = require('crypto'); var dot = require('dot'); var MapConfig = require('windshaft').model.MapConfig; @@ -62,16 +61,17 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { return callback(err); } - const { owner, rendererParams } = this; - var templateParams = {}; if (this.config) { try { - templateParams = _.isString(this.config) ? JSON.parse(this.config) : this.config; + templateParams = Object.prototype.toString.call(this.config) === '[object String]' ? + JSON.parse(this.config) : + this.config; } catch (e) { const error = new Error('malformed config parameter, should be a valid JSON'); this.err = error; + return callback(err); } } @@ -93,6 +93,8 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { return callback(err); } + const { owner, rendererParams } = this; + this.mapConfigAdapter.getMapConfig(owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { if (err) { this.err = err; @@ -236,7 +238,7 @@ var baseKeyTpl = dot.template(baseKey); var rendererKeyTpl = dot.template(rendererKey); NamedMapMapConfigProvider.prototype.createKey = function(base) { - var tplValues = _.defaults({}, this.params, { + var tplValues = Object.assign({ dbname: '', owner: this.owner, templateName: this.templateName, @@ -244,7 +246,8 @@ NamedMapMapConfigProvider.prototype.createKey = function(base) { configHash: configHash(this.config), layer: '', scale_factor: 1 - }); + }, this.params); + return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); }; @@ -258,9 +261,7 @@ function configHash(config) { module.exports.configHash = configHash; NamedMapMapConfigProvider.prototype.getDBParams = function(cdbuser, callback) { - const dbParams = _.extend({}, this.params, { - user: this.owner - }); + const dbParams = Object.assign({ user: this.owner }, this.params); this.pgConnection.getDatabaseParams(cdbuser, (err, databaseParams) => { if (err) { From 7c51895b0f318a86cef696b40084c35ed4bc4b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 19:50:07 +0200 Subject: [PATCH 15/20] Use const and let instead of var --- .../mapconfig/provider/named-map-provider.js | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index b0600afb..fa6038b1 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -1,8 +1,8 @@ -var crypto = require('crypto'); -var dot = require('dot'); -var MapConfig = require('windshaft').model.MapConfig; -var templateName = require('../../../backends/template_maps').templateName; -var QueryTables = require('cartodb-query-tables'); +const crypto = require('crypto'); +const dot = require('dot'); +const MapConfig = require('windshaft').model.MapConfig; +const templateName = require('../../../backends/template_maps').templateName; +const QueryTables = require('cartodb-query-tables'); /** * @constructor @@ -61,7 +61,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { return callback(err); } - var templateParams = {}; + let templateParams = {}; if (this.config) { try { @@ -123,7 +123,7 @@ NamedMapMapConfigProvider.prototype.getContext = function (callback) { return callback(err); } - var context = {}; + const context = {}; context.analysisConfiguration = { user: this.owner, @@ -168,36 +168,33 @@ NamedMapMapConfigProvider.prototype.getTemplate = function(callback) { } if (!tpl) { - var notFoundErr = new Error( - "Template '" + this.templateName + "' of user '" + this.owner + "' not found" - ); - notFoundErr.http_status = 404; + const error = new Error(`Template '${this.templateName}' of user '${this.owner}' not found`); + error.http_status = 404; - this.err = notFoundErr; + this.err = error; - return callback(notFoundErr); + return callback(error); } - var authorized = false; + let authorized = false; try { authorized = this.templateMaps.isAuthorized(tpl, this.authToken); } catch (err) { - // we catch to add http_status - var authorizationFailedErr = new Error('Failed to authorize template'); - authorizationFailedErr.http_status = 403; + const error = new Error('Failed to authorize template'); + error.http_status = 403; - this.err = authorizationFailedErr; + this.err = error; - return callback(authorizationFailedErr); + return callback(error); } if (!authorized) { - var unauthorizedErr = new Error('Unauthorized template instantiation'); - unauthorizedErr.http_status = 403; - this.err = unauthorizedErr; + const error = new Error('Unauthorized template instantiation'); + error.http_status = 403; + this.err = error; - return callback(unauthorizedErr); + return callback(error); } this.template = tpl; @@ -226,19 +223,19 @@ NamedMapMapConfigProvider.prototype.reset = function() { }; NamedMapMapConfigProvider.prototype.filter = function(key) { - var regex = new RegExp('^' + this.createKey(true) + '.*'); + const regex = new RegExp('^' + this.createKey(true) + '.*'); return key && key.match(regex); }; // Configure bases for cache keys suitable for string interpolation -var baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}'; -var rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; +const baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}'; +const rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; -var baseKeyTpl = dot.template(baseKey); -var rendererKeyTpl = dot.template(rendererKey); +const baseKeyTpl = dot.template(baseKey); +const rendererKeyTpl = dot.template(rendererKey); NamedMapMapConfigProvider.prototype.createKey = function(base) { - var tplValues = Object.assign({ + const tplValues = Object.assign({ dbname: '', owner: this.owner, templateName: this.templateName, From 9fe8958e8c95b9577c4b8b387615537085a1d274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 20:02:38 +0200 Subject: [PATCH 16/20] Use ES6 class syntax --- .../mapconfig/provider/named-map-provider.js | 634 +++++++++--------- 1 file changed, 316 insertions(+), 318 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index fa6038b1..f5bfab9c 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -4,229 +4,6 @@ const MapConfig = require('windshaft').model.MapConfig; const templateName = require('../../../backends/template_maps').templateName; const QueryTables = require('cartodb-query-tables'); -/** - * @constructor - * @type {NamedMapMapConfigProvider} - */ -function NamedMapMapConfigProvider( - templateMaps, - pgConnection, - metadataBackend, - userLimitsBackend, - mapConfigAdapter, - affectedTablesCache, - owner, - templateId, - config, - authToken, - params -) { - this.templateMaps = templateMaps; - this.pgConnection = pgConnection; - this.metadataBackend = metadataBackend; - this.userLimitsBackend = userLimitsBackend; - this.mapConfigAdapter = mapConfigAdapter; - - this.owner = owner; - this.templateName = templateName(templateId); - this.config = config; - this.authToken = authToken; - this.params = params; - - this.cacheBuster = Date.now(); - - // use template after call to mapConfig - this.template = null; - - this.affectedTablesCache = affectedTablesCache; - - // providing - this.err = null; - this.mapConfig = null; - this.rendererParams = null; - this.context = {}; - this.analysesResults = []; -} - -module.exports = NamedMapMapConfigProvider; - -NamedMapMapConfigProvider.prototype.getMapConfig = function (callback) { - if (!!this.err || this.mapConfig !== null) { - return callback(this.err, this.mapConfig, this.rendererParams, this.context); - } - - this.getContext((err, context) => { - if (err) { - this.err = err; - return callback(err); - } - - let templateParams = {}; - - if (this.config) { - try { - templateParams = Object.prototype.toString.call(this.config) === '[object String]' ? - JSON.parse(this.config) : - this.config; - } catch (e) { - const error = new Error('malformed config parameter, should be a valid JSON'); - this.err = error; - - return callback(err); - } - } - - context.templateParams = templateParams; - - this.getTemplate((err, template) => { - if (err) { - this.err = err; - return callback(err); - } - - let requestMapConfig; - - try { - requestMapConfig = this.templateMaps.instance(template, templateParams); - } catch (err) { - this.err = err; - return callback(err); - } - - const { owner, rendererParams } = this; - - this.mapConfigAdapter.getMapConfig(owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { - if (err) { - this.err = err; - return callback(err); - } - - this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); - this.analysesResults = context.analysesResults || []; - - return callback(null, this.mapConfig, this.rendererParams, this.context); - }); - }); - }); -}; - -NamedMapMapConfigProvider.prototype.getContext = function (callback) { - this.getDBParams(this.owner, (err, rendererParams) => { - if (err) { - return callback(err); - } - - this.rendererParams = rendererParams; - - this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { - if (err) { - return callback(err); - } - - const context = {}; - - context.analysisConfiguration = { - user: this.owner, - db: { - host: rendererParams.dbhost, - port: rendererParams.dbport, - dbname: rendererParams.dbname, - user: rendererParams.dbuser, - pass: rendererParams.dbpassword - }, - batch: { - username: this.owner, - apiKey: apiKey - } - }; - - this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { - if (err) { - this.err = err; - return callback(err); - } - - context.limits = renderLimits || {}; - - this.context = context; - - return callback(null, context); - }); - }); - }); -}; - -NamedMapMapConfigProvider.prototype.getTemplate = function(callback) { - if (!!this.err || this.template !== null) { - return callback(this.err, this.template); - } - - this.templateMaps.getTemplate(this.owner, this.templateName, (err, tpl) => { - if (err) { - this.err = err; - return callback(err); - } - - if (!tpl) { - const error = new Error(`Template '${this.templateName}' of user '${this.owner}' not found`); - error.http_status = 404; - - this.err = error; - - return callback(error); - } - - let authorized = false; - - try { - authorized = this.templateMaps.isAuthorized(tpl, this.authToken); - } catch (err) { - const error = new Error('Failed to authorize template'); - error.http_status = 403; - - this.err = error; - - return callback(error); - } - - if (!authorized) { - const error = new Error('Unauthorized template instantiation'); - error.http_status = 403; - this.err = error; - - return callback(error); - } - - this.template = tpl; - - return callback(null, this.template); - }); -}; - -NamedMapMapConfigProvider.prototype.getKey = function() { - return this.createKey(false); -}; - -NamedMapMapConfigProvider.prototype.getCacheBuster = function() { - return this.cacheBuster; -}; - -NamedMapMapConfigProvider.prototype.reset = function() { - this.template = null; - - this.affectedTables = null; - - this.err = null; - this.mapConfig = null; - - this.cacheBuster = Date.now(); -}; - -NamedMapMapConfigProvider.prototype.filter = function(key) { - const regex = new RegExp('^' + this.createKey(true) + '.*'); - return key && key.match(regex); -}; - // Configure bases for cache keys suitable for string interpolation const baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}'; const rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; @@ -234,109 +11,330 @@ const rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.forma const baseKeyTpl = dot.template(baseKey); const rendererKeyTpl = dot.template(rendererKey); -NamedMapMapConfigProvider.prototype.createKey = function(base) { - const tplValues = Object.assign({ - dbname: '', - owner: this.owner, - templateName: this.templateName, - authToken: this.authToken || '', - configHash: configHash(this.config), - layer: '', - scale_factor: 1 - }, this.params); +module.exports = class NamedMapMapConfigProvider { + constructor ( + templateMaps, + pgConnection, + metadataBackend, + userLimitsBackend, + mapConfigAdapter, + affectedTablesCache, + owner, + templateId, + config, + authToken, + params + ) { + this.templateMaps = templateMaps; + this.pgConnection = pgConnection; + this.metadataBackend = metadataBackend; + this.userLimitsBackend = userLimitsBackend; + this.mapConfigAdapter = mapConfigAdapter; - return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); + this.owner = owner; + this.templateName = templateName(templateId); + this.config = config; + this.authToken = authToken; + this.params = params; + + this.cacheBuster = Date.now(); + + // use template after call to mapConfig + this.template = null; + + this.affectedTablesCache = affectedTablesCache; + + // providing + this.err = null; + this.mapConfig = null; + this.rendererParams = null; + this.context = {}; + this.analysesResults = []; + } + + getMapConfig (callback) { + if (!!this.err || this.mapConfig !== null) { + return callback(this.err, this.mapConfig, this.rendererParams, this.context); + } + + this.getContext((err, context) => { + if (err) { + this.err = err; + return callback(err); + } + + let templateParams = {}; + + if (this.config) { + try { + templateParams = Object.prototype.toString.call(this.config) === '[object String]' ? + JSON.parse(this.config) : + this.config; + } catch (e) { + const error = new Error('malformed config parameter, should be a valid JSON'); + this.err = error; + + return callback(err); + } + } + + context.templateParams = templateParams; + + this.getTemplate((err, template) => { + if (err) { + this.err = err; + return callback(err); + } + + let requestMapConfig; + + try { + requestMapConfig = this.templateMaps.instance(template, templateParams); + } catch (err) { + this.err = err; + return callback(err); + } + + const { owner, rendererParams } = this; + + this.mapConfigAdapter.getMapConfig( + owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { + if (err) { + this.err = err; + return callback(err); + } + + this.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource); + this.analysesResults = context.analysesResults || []; + + return callback(null, this.mapConfig, this.rendererParams, this.context); + }); + }); + }); + } + + getContext (callback) { + this.getDBParams(this.owner, (err, rendererParams) => { + if (err) { + return callback(err); + } + + this.rendererParams = rendererParams; + + this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { + if (err) { + return callback(err); + } + + const context = {}; + + context.analysisConfiguration = { + user: this.owner, + db: { + host: rendererParams.dbhost, + port: rendererParams.dbport, + dbname: rendererParams.dbname, + user: rendererParams.dbuser, + pass: rendererParams.dbpassword + }, + batch: { + username: this.owner, + apiKey: apiKey + } + }; + + this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { + if (err) { + this.err = err; + return callback(err); + } + + context.limits = renderLimits || {}; + + this.context = context; + + return callback(null, context); + }); + }); + }); + } + + getTemplate (callback) { + if (!!this.err || this.template !== null) { + return callback(this.err, this.template); + } + + this.templateMaps.getTemplate(this.owner, this.templateName, (err, tpl) => { + if (err) { + this.err = err; + return callback(err); + } + + if (!tpl) { + const error = new Error(`Template '${this.templateName}' of user '${this.owner}' not found`); + error.http_status = 404; + + this.err = error; + + return callback(error); + } + + let authorized = false; + + try { + authorized = this.templateMaps.isAuthorized(tpl, this.authToken); + } catch (err) { + const error = new Error('Failed to authorize template'); + error.http_status = 403; + + this.err = error; + + return callback(error); + } + + if (!authorized) { + const error = new Error('Unauthorized template instantiation'); + error.http_status = 403; + this.err = error; + + return callback(error); + } + + this.template = tpl; + + return callback(null, this.template); + }); + } + + getKey () { + return this.createKey(false); + } + + getCacheBuster () { + return this.cacheBuster; + } + + reset () { + this.template = null; + + this.affectedTables = null; + + this.err = null; + this.mapConfig = null; + + this.cacheBuster = Date.now(); + } + + filter (key) { + const regex = new RegExp('^' + this.createKey(true) + '.*'); + return key && key.match(regex); + } + + createKey (base) { + const tplValues = Object.assign({ + dbname: '', + owner: this.owner, + templateName: this.templateName, + authToken: this.authToken || '', + configHash: configHash(this.config), + layer: '', + scale_factor: 1 + }, this.params); + + return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); + } + + getDBParams (cdbuser, callback) { + const dbParams = Object.assign({ user: this.owner }, this.params); + + this.pgConnection.getDatabaseParams(cdbuser, (err, databaseParams) => { + if (err) { + return callback(err); + } + + dbParams.dbuser = databaseParams.dbuser; + dbParams.dbpass = databaseParams.dbpass; + dbParams.dbhost = databaseParams.dbhost; + dbParams.dbport = databaseParams.dbport; + dbParams.dbname = databaseParams.dbname; + + return callback(null, dbParams); + }); + } + + getTemplateName () { + return this.templateName; + } + + createAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.rendererParams; + const token = mapConfig.id(); + + const queries = []; + + mapConfig.getLayers().forEach(layer => { + queries.push(layer.options.sql); + if (layer.options.affected_tables) { + layer.options.affected_tables.map(table => { + queries.push(`SELECT * FROM ${table} LIMIT 0`); + }); + } + }); + + const sql = queries.length ? queries.join(';') : null; + + if (!sql) { + return callback(); + } + + this.pgConnection.getConnection(this.owner, (err, connection) => { + if (err) { + return callback(err); + } + + QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { + if (err) { + return callback(err); + } + + this.affectedTablesCache.set(dbname, token, affectedTables); + + callback(err, affectedTables); + }); + }); + }); + } + + getAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.params; + const token = mapConfig.id(); + + if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { + const affectedTables = this.affectedTablesCache.get(dbname, token); + return callback(null, affectedTables); + } + + return this.createAffectedTables(callback); + }); + } }; function configHash(config) { if (!config) { return ''; } + return crypto.createHash('md5').update(JSON.stringify(config)).digest('hex').substring(0,8); } module.exports.configHash = configHash; - -NamedMapMapConfigProvider.prototype.getDBParams = function(cdbuser, callback) { - const dbParams = Object.assign({ user: this.owner }, this.params); - - this.pgConnection.getDatabaseParams(cdbuser, (err, databaseParams) => { - if (err) { - return callback(err); - } - - dbParams.dbuser = databaseParams.dbuser; - dbParams.dbpass = databaseParams.dbpass; - dbParams.dbhost = databaseParams.dbhost; - dbParams.dbport = databaseParams.dbport; - dbParams.dbname = databaseParams.dbname; - - return callback(null, dbParams); - }); -}; - -NamedMapMapConfigProvider.prototype.getTemplateName = function() { - return this.templateName; -}; - -NamedMapMapConfigProvider.prototype.createAffectedTables = function(callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.rendererParams; - const token = mapConfig.id(); - - const queries = []; - - mapConfig.getLayers().forEach(layer => { - queries.push(layer.options.sql); - if (layer.options.affected_tables) { - layer.options.affected_tables.map(table => { - queries.push(`SELECT * FROM ${table} LIMIT 0`); - }); - } - }); - - const sql = queries.length ? queries.join(';') : null; - - if (!sql) { - return callback(); - } - - this.pgConnection.getConnection(this.owner, (err, connection) => { - if (err) { - return callback(err); - } - - QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { - if (err) { - return callback(err); - } - - this.affectedTablesCache.set(dbname, token, affectedTables); - - callback(err, affectedTables); - }); - }); - }); -}; - -NamedMapMapConfigProvider.prototype.getAffectedTables = function (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { - const affectedTables = this.affectedTablesCache.get(dbname, token); - return callback(null, affectedTables); - } - - return this.createAffectedTables(callback); - }); -}; From c0e6bf1299f9583505317a5f78cca29fc1624377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 20:08:35 +0200 Subject: [PATCH 17/20] Use ES6 class syntax --- .../mapconfig/provider/map-store-provider.js | 233 +++++++++--------- 1 file changed, 117 insertions(+), 116 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index 3cbff358..238d1cb5 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -2,69 +2,6 @@ const _ = require('underscore'); const dot = require('dot'); const QueryTables = require('cartodb-query-tables'); -/** - * @param {MapStore} mapStore - * @param {String} user - * @param {UserLimitsBackend} userLimitsBackend - * @param {Object} params - * @constructor - * @type {MapStoreMapConfigProvider} - */ -function MapStoreMapConfigProvider(mapStore, user, userLimitsBackend, pgConnection, affectedTablesCache, params) { - this.mapStore = mapStore; - this.user = user; - this.userLimitsBackend = userLimitsBackend; - this.pgConnection = pgConnection; - this.affectedTablesCache = affectedTablesCache; - this.token = params.token; - this.cacheBuster = params.cache_buster || 0; - this.mapConfig = null; - this.params = params; - this.context = null; -} - -module.exports = MapStoreMapConfigProvider; - -MapStoreMapConfigProvider.prototype.getMapConfig = function(callback) { - if (this.mapConfig !== null) { - return callback(null, this.mapConfig, this.params, this.context); - } - - const context = {}; - - this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { - if (err) { - return callback(err); - } - - context.limits = renderLimits; - - this.mapStore.load(this.token, (err, mapConfig) => { - if (err) { - return callback(err); - } - - this.mapConfig = mapConfig; - this.context = context; - - return callback(null, mapConfig, this.params, context); - }); - }); -}; - -MapStoreMapConfigProvider.prototype.getKey = function() { - return this.createKey(false); -}; - -MapStoreMapConfigProvider.prototype.getCacheBuster = function() { - return this.cacheBuster; -}; - -MapStoreMapConfigProvider.prototype.filter = function(key) { - const regex = new RegExp('^' + this.createKey(true) + '.*'); - return key && key.match(regex); -}; - // Configure bases for cache keys suitable for string interpolation const baseKey = '{{=it.dbname}}:{{=it.token}}'; const rendererKey = baseKey + ':{{=it.dbuser}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; @@ -72,76 +9,140 @@ const rendererKey = baseKey + ':{{=it.dbuser}}:{{=it.format}}:{{=it.layer}}:{{=i const baseKeyTpl = dot.template(baseKey); const rendererKeyTpl = dot.template(rendererKey); -MapStoreMapConfigProvider.prototype.createKey = function(base) { - const tplValues = _.defaults({}, this.params, { - dbname: '', - token: '', - dbuser: '', - format: '', - layer: '', - scale_factor: 1 - }); - return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); -}; +module.exports = class MapStoreMapConfigProvider { + /** + * @param {MapStore} mapStore + * @param {String} user + * @param {UserLimitsBackend} userLimitsBackend + * @param {Object} params + * @constructor + * @type {MapStoreMapConfigProvider} + */ + constructor (mapStore, user, userLimitsBackend, pgConnection, affectedTablesCache, params) { + this.mapStore = mapStore; + this.user = user; + this.userLimitsBackend = userLimitsBackend; + this.pgConnection = pgConnection; + this.affectedTablesCache = affectedTablesCache; + this.token = params.token; + this.cacheBuster = params.cache_buster || 0; + this.mapConfig = null; + this.params = params; + this.context = null; + } -MapStoreMapConfigProvider.prototype.createAffectedTables = function(callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); + getMapConfig (callback) { + if (this.mapConfig !== null) { + return callback(null, this.mapConfig, this.params, this.context); } - const { dbname } = this.params; - const token = mapConfig.id(); + const context = {}; - const queries = []; - - mapConfig.getLayers().forEach(layer => { - queries.push(layer.options.sql); - if (layer.options.affected_tables) { - layer.options.affected_tables.map(table => { - queries.push(`SELECT * FROM ${table} LIMIT 0`); - }); - } - }); - - const sql = queries.length ? queries.join(';') : null; - - if (!sql) { - return callback(); - } - - this.pgConnection.getConnection(this.user, (err, connection) => { + this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { if (err) { return callback(err); } - QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { + context.limits = renderLimits; + + this.mapStore.load(this.token, (err, mapConfig) => { if (err) { return callback(err); } - this.affectedTablesCache.set(dbname, token, affectedTables); + this.mapConfig = mapConfig; + this.context = context; - callback(err, affectedTables); + return callback(null, mapConfig, this.params, context); }); }); - }); -}; + } -MapStoreMapConfigProvider.prototype.getAffectedTables = function (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } + getKey () { + return this.createKey(false); + } - const { dbname } = this.params; - const token = mapConfig.id(); + getCacheBuster () { + return this.cacheBuster; + } - if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { - const affectedTables = this.affectedTablesCache.get(dbname, token); - return callback(null, affectedTables); - } + filter (key) { + const regex = new RegExp('^' + this.createKey(true) + '.*'); + return key && key.match(regex); + } - return this.createAffectedTables(callback); - }); + createKey (base) { + const tplValues = _.defaults({}, this.params, { + dbname: '', + token: '', + dbuser: '', + format: '', + layer: '', + scale_factor: 1 + }); + + return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); + } + + createAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.params; + const token = mapConfig.id(); + + const queries = []; + + mapConfig.getLayers().forEach(layer => { + queries.push(layer.options.sql); + if (layer.options.affected_tables) { + layer.options.affected_tables.map(table => { + queries.push(`SELECT * FROM ${table} LIMIT 0`); + }); + } + }); + + const sql = queries.length ? queries.join(';') : null; + + if (!sql) { + return callback(); + } + + this.pgConnection.getConnection(this.user, (err, connection) => { + if (err) { + return callback(err); + } + + QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { + if (err) { + return callback(err); + } + + this.affectedTablesCache.set(dbname, token, affectedTables); + + callback(err, affectedTables); + }); + }); + }); + } + + getAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.params; + const token = mapConfig.id(); + + if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { + const affectedTables = this.affectedTablesCache.get(dbname, token); + return callback(null, affectedTables); + } + + return this.createAffectedTables(callback); + }); + } }; From 94a5020faf0f836ac99aa58d5aa8a5afef07d89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 20:10:59 +0200 Subject: [PATCH 18/20] Do not use underscore --- lib/cartodb/models/mapconfig/provider/map-store-provider.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index 238d1cb5..e4e1de1c 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -1,4 +1,3 @@ -const _ = require('underscore'); const dot = require('dot'); const QueryTables = require('cartodb-query-tables'); @@ -72,14 +71,14 @@ module.exports = class MapStoreMapConfigProvider { } createKey (base) { - const tplValues = _.defaults({}, this.params, { + const tplValues = Object.assign({ dbname: '', token: '', dbuser: '', format: '', layer: '', scale_factor: 1 - }); + }, this.params); return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); } From c32dba1ecb81a7e569d1755f08c8780dc791e52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Wed, 30 May 2018 20:28:15 +0200 Subject: [PATCH 19/20] Use ES6 class syntax --- .../provider/create-layergroup-provider.js | 175 ++++++++---------- 1 file changed, 80 insertions(+), 95 deletions(-) diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index f1e2ac37..b7a52710 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -1,119 +1,104 @@ const MapStoreMapConfigProvider = require('./map-store-provider'); const QueryTables = require('cartodb-query-tables'); -/** - * @param {MapConfig} mapConfig - * @param {String} user - * @param {UserLimitsBackend} userLimitsBackend - * @param {Object} params - * @constructor - * @type {CreateLayergroupMapConfigProvider} - */ - -function CreateLayergroupMapConfigProvider( - mapConfig, - user, - userLimitsBackend, - pgConnection, - affectedTablesCache, - params -) { - this.mapConfig = mapConfig; - this.user = user; - this.userLimitsBackend = userLimitsBackend; - this.pgConnection = pgConnection; - this.affectedTablesCache = affectedTablesCache; - this.params = params; - this.cacheBuster = params.cache_buster || 0; -} - -module.exports = CreateLayergroupMapConfigProvider; - -CreateLayergroupMapConfigProvider.prototype.getMapConfig = function(callback) { - if (this.mapConfig && this.params && this.context) { - return callback(null, this.mapConfig, this.params, this.context); +module.exports = class CreateLayergroupMapConfigProvider extends MapStoreMapConfigProvider { + /** + * @param {MapConfig} mapConfig + * @param {String} user + * @param {UserLimitsBackend} userLimitsBackend + * @param {Object} params + * @constructor + * @type {CreateLayergroupMapConfigProvider} + */ + constructor (mapConfig, user, userLimitsBackend, pgConnection, affectedTablesCache, params) { + super(mapConfig, user, userLimitsBackend, pgConnection, affectedTablesCache, params); + this.mapConfig = mapConfig; + this.user = user; + this.userLimitsBackend = userLimitsBackend; + this.pgConnection = pgConnection; + this.affectedTablesCache = affectedTablesCache; + this.params = params; + this.cacheBuster = params.cache_buster || 0; } - const context = {}; - - this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { - if (err) { - return callback(err); + getMapConfig (callback) { + if (this.mapConfig && this.params && this.context) { + return callback(null, this.mapConfig, this.params, this.context); } - context.limits = renderLimits; - this.context = context; + const context = {}; - return callback(null, this.mapConfig, this.params, context); - }); -}; - -CreateLayergroupMapConfigProvider.prototype.getKey = MapStoreMapConfigProvider.prototype.getKey; - -CreateLayergroupMapConfigProvider.prototype.getCacheBuster = MapStoreMapConfigProvider.prototype.getCacheBuster; - -CreateLayergroupMapConfigProvider.prototype.filter = MapStoreMapConfigProvider.prototype.filter; - -CreateLayergroupMapConfigProvider.prototype.createKey = MapStoreMapConfigProvider.prototype.createKey; - -CreateLayergroupMapConfigProvider.prototype.createAffectedTables = function (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - const queries = []; - - this.mapConfig.getLayers().forEach(layer => { - queries.push(layer.options.sql); - if (layer.options.affected_tables) { - layer.options.affected_tables.map(table => { - queries.push(`SELECT * FROM ${table} LIMIT 0`); - }); - } - }); - - const sql = queries.length ? queries.join(';') : null; - - if (!sql) { - return callback(); - } - - this.pgConnection.getConnection(this.user, (err, connection) => { + this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { if (err) { return callback(err); } - QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { + context.limits = renderLimits; + this.context = context; + + return callback(null, this.mapConfig, this.params, context); + }); + } + + createAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.params; + const token = mapConfig.id(); + + const queries = []; + + this.mapConfig.getLayers().forEach(layer => { + queries.push(layer.options.sql); + if (layer.options.affected_tables) { + layer.options.affected_tables.map(table => { + queries.push(`SELECT * FROM ${table} LIMIT 0`); + }); + } + }); + + const sql = queries.length ? queries.join(';') : null; + + if (!sql) { + return callback(); + } + + this.pgConnection.getConnection(this.user, (err, connection) => { if (err) { return callback(err); } - this.affectedTablesCache.set(dbname, token, affectedTables); + QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { + if (err) { + return callback(err); + } - callback(null, affectedTables); + this.affectedTablesCache.set(dbname, token, affectedTables); + + callback(null, affectedTables); + }); }); }); - }); -}; + } -CreateLayergroupMapConfigProvider.prototype.getAffectedTables = function (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } + getAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } - const { dbname } = this.params; - const token = mapConfig.id(); + const { dbname } = this.params; + const token = mapConfig.id(); - if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { - const affectedTables = this.affectedTablesCache.get(dbname, token); - return callback(null, affectedTables); - } + if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { + const affectedTables = this.affectedTablesCache.get(dbname, token); + return callback(null, affectedTables); + } - return this.createAffectedTables(callback); - }); + return this.createAffectedTables(callback); + }); + } }; From ea95050d432f4c2029fb905eaca6fac57aa77a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Thu, 31 May 2018 14:57:34 +0200 Subject: [PATCH 20/20] Extract base class in order to share createAffectedTables and getAffectedTables methods --- .../provider/base-mapconfig-adapter.js | 65 +++++++++++++ .../provider/create-layergroup-provider.js | 79 +-------------- .../mapconfig/provider/map-store-provider.js | 69 +------------- .../mapconfig/provider/named-map-provider.js | 95 ++++--------------- 4 files changed, 87 insertions(+), 221 deletions(-) create mode 100644 lib/cartodb/models/mapconfig/provider/base-mapconfig-adapter.js diff --git a/lib/cartodb/models/mapconfig/provider/base-mapconfig-adapter.js b/lib/cartodb/models/mapconfig/provider/base-mapconfig-adapter.js new file mode 100644 index 00000000..c783bdd4 --- /dev/null +++ b/lib/cartodb/models/mapconfig/provider/base-mapconfig-adapter.js @@ -0,0 +1,65 @@ +const QueryTables = require('cartodb-query-tables'); + +module.exports = class BaseMapConfigProvider { + createAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.params; + const token = mapConfig.id(); + + const queries = []; + + this.mapConfig.getLayers().forEach(layer => { + queries.push(layer.options.sql); + if (layer.options.affected_tables) { + layer.options.affected_tables.map(table => { + queries.push(`SELECT * FROM ${table} LIMIT 0`); + }); + } + }); + + const sql = queries.length ? queries.join(';') : null; + + if (!sql) { + return callback(); + } + + this.pgConnection.getConnection(this.user, (err, connection) => { + if (err) { + return callback(err); + } + + QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { + if (err) { + return callback(err); + } + + this.affectedTablesCache.set(dbname, token, affectedTables); + + callback(null, affectedTables); + }); + }); + }); + } + + getAffectedTables (callback) { + this.getMapConfig((err, mapConfig) => { + if (err) { + return callback(err); + } + + const { dbname } = this.params; + const token = mapConfig.id(); + + if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { + const affectedTables = this.affectedTablesCache.get(dbname, token); + return callback(null, affectedTables); + } + + return this.createAffectedTables(callback); + }); + } +}; diff --git a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js index b7a52710..6d33c912 100644 --- a/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js +++ b/lib/cartodb/models/mapconfig/provider/create-layergroup-provider.js @@ -1,24 +1,9 @@ const MapStoreMapConfigProvider = require('./map-store-provider'); -const QueryTables = require('cartodb-query-tables'); module.exports = class CreateLayergroupMapConfigProvider extends MapStoreMapConfigProvider { - /** - * @param {MapConfig} mapConfig - * @param {String} user - * @param {UserLimitsBackend} userLimitsBackend - * @param {Object} params - * @constructor - * @type {CreateLayergroupMapConfigProvider} - */ constructor (mapConfig, user, userLimitsBackend, pgConnection, affectedTablesCache, params) { - super(mapConfig, user, userLimitsBackend, pgConnection, affectedTablesCache, params); + super(null, user, userLimitsBackend, pgConnection, affectedTablesCache, params); this.mapConfig = mapConfig; - this.user = user; - this.userLimitsBackend = userLimitsBackend; - this.pgConnection = pgConnection; - this.affectedTablesCache = affectedTablesCache; - this.params = params; - this.cacheBuster = params.cache_buster || 0; } getMapConfig (callback) { @@ -39,66 +24,4 @@ module.exports = class CreateLayergroupMapConfigProvider extends MapStoreMapConf return callback(null, this.mapConfig, this.params, context); }); } - - createAffectedTables (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - const queries = []; - - this.mapConfig.getLayers().forEach(layer => { - queries.push(layer.options.sql); - if (layer.options.affected_tables) { - layer.options.affected_tables.map(table => { - queries.push(`SELECT * FROM ${table} LIMIT 0`); - }); - } - }); - - const sql = queries.length ? queries.join(';') : null; - - if (!sql) { - return callback(); - } - - this.pgConnection.getConnection(this.user, (err, connection) => { - if (err) { - return callback(err); - } - - QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { - if (err) { - return callback(err); - } - - this.affectedTablesCache.set(dbname, token, affectedTables); - - callback(null, affectedTables); - }); - }); - }); - } - - getAffectedTables (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { - const affectedTables = this.affectedTablesCache.get(dbname, token); - return callback(null, affectedTables); - } - - return this.createAffectedTables(callback); - }); - } }; diff --git a/lib/cartodb/models/mapconfig/provider/map-store-provider.js b/lib/cartodb/models/mapconfig/provider/map-store-provider.js index e4e1de1c..abc9eca2 100644 --- a/lib/cartodb/models/mapconfig/provider/map-store-provider.js +++ b/lib/cartodb/models/mapconfig/provider/map-store-provider.js @@ -1,5 +1,5 @@ +const BaseMapConfigProvider = require('./base-mapconfig-adapter'); const dot = require('dot'); -const QueryTables = require('cartodb-query-tables'); // Configure bases for cache keys suitable for string interpolation const baseKey = '{{=it.dbname}}:{{=it.token}}'; @@ -8,7 +8,7 @@ const rendererKey = baseKey + ':{{=it.dbuser}}:{{=it.format}}:{{=it.layer}}:{{=i const baseKeyTpl = dot.template(baseKey); const rendererKeyTpl = dot.template(rendererKey); -module.exports = class MapStoreMapConfigProvider { +module.exports = class MapStoreMapConfigProvider extends BaseMapConfigProvider { /** * @param {MapStore} mapStore * @param {String} user @@ -18,15 +18,16 @@ module.exports = class MapStoreMapConfigProvider { * @type {MapStoreMapConfigProvider} */ constructor (mapStore, user, userLimitsBackend, pgConnection, affectedTablesCache, params) { + super(); this.mapStore = mapStore; this.user = user; this.userLimitsBackend = userLimitsBackend; this.pgConnection = pgConnection; this.affectedTablesCache = affectedTablesCache; + this.params = params; this.token = params.token; this.cacheBuster = params.cache_buster || 0; this.mapConfig = null; - this.params = params; this.context = null; } @@ -82,66 +83,4 @@ module.exports = class MapStoreMapConfigProvider { return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues); } - - createAffectedTables (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - const queries = []; - - mapConfig.getLayers().forEach(layer => { - queries.push(layer.options.sql); - if (layer.options.affected_tables) { - layer.options.affected_tables.map(table => { - queries.push(`SELECT * FROM ${table} LIMIT 0`); - }); - } - }); - - const sql = queries.length ? queries.join(';') : null; - - if (!sql) { - return callback(); - } - - this.pgConnection.getConnection(this.user, (err, connection) => { - if (err) { - return callback(err); - } - - QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { - if (err) { - return callback(err); - } - - this.affectedTablesCache.set(dbname, token, affectedTables); - - callback(err, affectedTables); - }); - }); - }); - } - - getAffectedTables (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { - const affectedTables = this.affectedTablesCache.get(dbname, token); - return callback(null, affectedTables); - } - - return this.createAffectedTables(callback); - }); - } }; diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index f5bfab9c..e3889aff 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -1,17 +1,17 @@ +const BaseMapConfigProvider = require('./base-mapconfig-adapter'); const crypto = require('crypto'); const dot = require('dot'); const MapConfig = require('windshaft').model.MapConfig; const templateName = require('../../../backends/template_maps').templateName; -const QueryTables = require('cartodb-query-tables'); // Configure bases for cache keys suitable for string interpolation -const baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}'; +const baseKey = '{{=it.dbname}}:{{=it.user}}:{{=it.templateName}}'; const rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}'; const baseKeyTpl = dot.template(baseKey); const rendererKeyTpl = dot.template(rendererKey); -module.exports = class NamedMapMapConfigProvider { +module.exports = class NamedMapMapConfigProvider extends BaseMapConfigProvider { constructor ( templateMaps, pgConnection, @@ -19,19 +19,20 @@ module.exports = class NamedMapMapConfigProvider { userLimitsBackend, mapConfigAdapter, affectedTablesCache, - owner, + user, templateId, config, authToken, params ) { + super(); this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.metadataBackend = metadataBackend; this.userLimitsBackend = userLimitsBackend; this.mapConfigAdapter = mapConfigAdapter; - this.owner = owner; + this.user = user; this.templateName = templateName(templateId); this.config = config; this.authToken = authToken; @@ -95,10 +96,10 @@ module.exports = class NamedMapMapConfigProvider { return callback(err); } - const { owner, rendererParams } = this; + const { user, rendererParams } = this; this.mapConfigAdapter.getMapConfig( - owner, requestMapConfig, rendererParams, context, (err, mapConfig) => { + user, requestMapConfig, rendererParams, context, (err, mapConfig) => { if (err) { this.err = err; return callback(err); @@ -114,14 +115,14 @@ module.exports = class NamedMapMapConfigProvider { } getContext (callback) { - this.getDBParams(this.owner, (err, rendererParams) => { + this.getDBParams(this.user, (err, rendererParams) => { if (err) { return callback(err); } this.rendererParams = rendererParams; - this.metadataBackend.getUserMapKey(this.owner, (err, apiKey) => { + this.metadataBackend.getUserMapKey(this.user, (err, apiKey) => { if (err) { return callback(err); } @@ -129,7 +130,7 @@ module.exports = class NamedMapMapConfigProvider { const context = {}; context.analysisConfiguration = { - user: this.owner, + user: this.user, db: { host: rendererParams.dbhost, port: rendererParams.dbport, @@ -138,12 +139,12 @@ module.exports = class NamedMapMapConfigProvider { pass: rendererParams.dbpassword }, batch: { - username: this.owner, + username: this.user, apiKey: apiKey } }; - this.userLimitsBackend.getRenderLimits(this.owner, this.params.api_key, (err, renderLimits) => { + this.userLimitsBackend.getRenderLimits(this.user, this.params.api_key, (err, renderLimits) => { if (err) { this.err = err; return callback(err); @@ -164,14 +165,14 @@ module.exports = class NamedMapMapConfigProvider { return callback(this.err, this.template); } - this.templateMaps.getTemplate(this.owner, this.templateName, (err, tpl) => { + this.templateMaps.getTemplate(this.user, this.templateName, (err, tpl) => { if (err) { this.err = err; return callback(err); } if (!tpl) { - const error = new Error(`Template '${this.templateName}' of user '${this.owner}' not found`); + const error = new Error(`Template '${this.templateName}' of user '${this.user}' not found`); error.http_status = 404; this.err = error; @@ -233,7 +234,7 @@ module.exports = class NamedMapMapConfigProvider { createKey (base) { const tplValues = Object.assign({ dbname: '', - owner: this.owner, + user: this.user, templateName: this.templateName, authToken: this.authToken || '', configHash: configHash(this.config), @@ -245,7 +246,7 @@ module.exports = class NamedMapMapConfigProvider { } getDBParams (cdbuser, callback) { - const dbParams = Object.assign({ user: this.owner }, this.params); + const dbParams = Object.assign({ user: this.user }, this.params); this.pgConnection.getDatabaseParams(cdbuser, (err, databaseParams) => { if (err) { @@ -265,68 +266,6 @@ module.exports = class NamedMapMapConfigProvider { getTemplateName () { return this.templateName; } - - createAffectedTables (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.rendererParams; - const token = mapConfig.id(); - - const queries = []; - - mapConfig.getLayers().forEach(layer => { - queries.push(layer.options.sql); - if (layer.options.affected_tables) { - layer.options.affected_tables.map(table => { - queries.push(`SELECT * FROM ${table} LIMIT 0`); - }); - } - }); - - const sql = queries.length ? queries.join(';') : null; - - if (!sql) { - return callback(); - } - - this.pgConnection.getConnection(this.owner, (err, connection) => { - if (err) { - return callback(err); - } - - QueryTables.getAffectedTablesFromQuery(connection, sql, (err, affectedTables) => { - if (err) { - return callback(err); - } - - this.affectedTablesCache.set(dbname, token, affectedTables); - - callback(err, affectedTables); - }); - }); - }); - } - - getAffectedTables (callback) { - this.getMapConfig((err, mapConfig) => { - if (err) { - return callback(err); - } - - const { dbname } = this.params; - const token = mapConfig.id(); - - if (this.affectedTablesCache.hasAffectedTables(dbname, token)) { - const affectedTables = this.affectedTablesCache.get(dbname, token); - return callback(null, affectedTables); - } - - return this.createAffectedTables(callback); - }); - } }; function configHash(config) {