From 72d8a26ede0b5fcd0f35252b81623b78a31f38f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 12:14:27 +0200 Subject: [PATCH 01/21] Use ES6 class --- .../api/map/anonymous-map-controller.js | 158 +++++++++--------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/lib/cartodb/api/map/anonymous-map-controller.js b/lib/cartodb/api/map/anonymous-map-controller.js index 21049437..b16e2c00 100644 --- a/lib/cartodb/api/map/anonymous-map-controller.js +++ b/lib/cartodb/api/map/anonymous-map-controller.js @@ -22,88 +22,88 @@ const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provid const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -/** - * @param {AuthBackend} authBackend - * @param {PgConnection} pgConnection - * @param {TemplateMaps} templateMaps - * @param {MapBackend} mapBackend - * @param metadataBackend - * @param {SurrogateKeysCache} surrogateKeysCache - * @param {UserLimitsBackend} userLimitsBackend - * @param {LayergroupAffectedTables} layergroupAffectedTables - * @param {MapConfigAdapter} mapConfigAdapter - * @param {StatsBackend} statsBackend - * @constructor - */ -function AnonymousMapController ( - pgConnection, - templateMaps, - mapBackend, - metadataBackend, - surrogateKeysCache, - userLimitsBackend, - layergroupAffectedTables, - mapConfigAdapter, - statsBackend, - authBackend, - layergroupMetadata -) { - this.pgConnection = pgConnection; - this.templateMaps = templateMaps; - this.mapBackend = mapBackend; - this.metadataBackend = metadataBackend; - this.surrogateKeysCache = surrogateKeysCache; - this.userLimitsBackend = userLimitsBackend; - this.layergroupAffectedTables = layergroupAffectedTables; - this.mapConfigAdapter = mapConfigAdapter; - this.statsBackend = statsBackend; - this.authBackend = authBackend; - this.layergroupMetadata = layergroupMetadata; -} +module.exports = class AnonymousMapController { + /** + * @param {AuthBackend} authBackend + * @param {PgConnection} pgConnection + * @param {TemplateMaps} templateMaps + * @param {MapBackend} mapBackend + * @param metadataBackend + * @param {SurrogateKeysCache} surrogateKeysCache + * @param {UserLimitsBackend} userLimitsBackend + * @param {LayergroupAffectedTables} layergroupAffectedTables + * @param {MapConfigAdapter} mapConfigAdapter + * @param {StatsBackend} statsBackend + * @constructor + */ + constructor ( + pgConnection, + templateMaps, + mapBackend, + metadataBackend, + surrogateKeysCache, + userLimitsBackend, + layergroupAffectedTables, + mapConfigAdapter, + statsBackend, + authBackend, + layergroupMetadata + ) { + this.pgConnection = pgConnection; + this.templateMaps = templateMaps; + this.mapBackend = mapBackend; + this.metadataBackend = metadataBackend; + this.surrogateKeysCache = surrogateKeysCache; + this.userLimitsBackend = userLimitsBackend; + this.layergroupAffectedTables = layergroupAffectedTables; + this.mapConfigAdapter = mapConfigAdapter; + this.statsBackend = statsBackend; + this.authBackend = authBackend; + this.layergroupMetadata = layergroupMetadata; + } -module.exports = AnonymousMapController; + register (mapRouter) { + mapRouter.options('/'); + mapRouter.get('/', this.composeCreateMapMiddleware()); + mapRouter.post('/', this.composeCreateMapMiddleware()); + } -AnonymousMapController.prototype.register = function (mapRouter) { - mapRouter.options('/'); - mapRouter.get('/', this.composeCreateMapMiddleware()); - mapRouter.post('/', this.composeCreateMapMiddleware()); -}; + composeCreateMapMiddleware () { + const isTemplateInstantiation = false; + const useTemplateHash = false; + const includeQuery = true; + const label = 'ANONYMOUS LAYERGROUP'; + const addContext = true; -AnonymousMapController.prototype.composeCreateMapMiddleware = function () { - const isTemplateInstantiation = false; - const useTemplateHash = false; - const includeQuery = true; - const label = 'ANONYMOUS LAYERGROUP'; - const addContext = true; - - return [ - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS), - cleanUpQueryParams(['aggregation']), - initProfiler(isTemplateInstantiation), - checkJsonContentType(), - checkCreateLayergroup(), - prepareAdapterMapConfig(this.mapConfigAdapter), - createLayergroup ( - this.mapBackend, - this.userLimitsBackend, - this.pgConnection, - this.layergroupAffectedTables - ), - incrementMapViewCount(this.metadataBackend), - augmentLayergroupData(), - cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader({ now: true }), - lastUpdatedTimeLayergroup(), - layerStats(this.pgConnection, this.statsBackend), - layergroupIdHeader(this.templateMaps, useTemplateHash), - layergroupMetadata(this.layergroupMetadata, includeQuery), - mapError({ label, addContext }) - ]; + return [ + credentials(), + authorize(this.authBackend), + dbConnSetup(this.pgConnection), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS), + cleanUpQueryParams(['aggregation']), + initProfiler(isTemplateInstantiation), + checkJsonContentType(), + checkCreateLayergroup(), + prepareAdapterMapConfig(this.mapConfigAdapter), + createLayergroup ( + this.mapBackend, + this.userLimitsBackend, + this.pgConnection, + this.layergroupAffectedTables + ), + incrementMapViewCount(this.metadataBackend), + augmentLayergroupData(), + cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }), + cacheChannelHeader(), + surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), + lastModifiedHeader({ now: true }), + lastUpdatedTimeLayergroup(), + layerStats(this.pgConnection, this.statsBackend), + layergroupIdHeader(this.templateMaps, useTemplateHash), + layergroupMetadata(this.layergroupMetadata, includeQuery), + mapError({ label, addContext }) + ]; + } }; function checkCreateLayergroup () { From d86a8392652ed8138347b53ce69e20229fb61d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 12:22:50 +0200 Subject: [PATCH 02/21] Blank line --- lib/cartodb/api/map/analysis-layergroup-controller.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/cartodb/api/map/analysis-layergroup-controller.js b/lib/cartodb/api/map/analysis-layergroup-controller.js index 96f46d70..8a22dd09 100644 --- a/lib/cartodb/api/map/analysis-layergroup-controller.js +++ b/lib/cartodb/api/map/analysis-layergroup-controller.js @@ -26,7 +26,6 @@ module.exports = class AnalysisLayergroupController { cleanUpQueryParams(), analysisNodeStatus(this.analysisStatusBackend) ); - } }; From 07dec2e64138760a12ccd0a1b80d99858230a4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 12:38:52 +0200 Subject: [PATCH 03/21] Create .middlwares() to return a set of middlewares to be mounted --- lib/cartodb/api/map/analysis-layergroup-controller.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/map/analysis-layergroup-controller.js b/lib/cartodb/api/map/analysis-layergroup-controller.js index 8a22dd09..41acf819 100644 --- a/lib/cartodb/api/map/analysis-layergroup-controller.js +++ b/lib/cartodb/api/map/analysis-layergroup-controller.js @@ -16,8 +16,11 @@ module.exports = class AnalysisLayergroupController { } register (mapRouter) { - mapRouter.get( - `/:token/analysis/node/:nodeId`, + mapRouter.get('/:token/analysis/node/:nodeId', this.middlewares()); + } + + middlewares () { + return [ layergroupToken(), credentials(), authorize(this.authBackend), @@ -25,7 +28,7 @@ module.exports = class AnalysisLayergroupController { rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS), cleanUpQueryParams(), analysisNodeStatus(this.analysisStatusBackend) - ); + ]; } }; From 1bc017eac99a6bb5f60014e171ac1a16547882d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 12:42:17 +0200 Subject: [PATCH 04/21] Rename function --- lib/cartodb/api/map/anonymous-map-controller.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/map/anonymous-map-controller.js b/lib/cartodb/api/map/anonymous-map-controller.js index b16e2c00..6bbacd37 100644 --- a/lib/cartodb/api/map/anonymous-map-controller.js +++ b/lib/cartodb/api/map/anonymous-map-controller.js @@ -64,11 +64,11 @@ module.exports = class AnonymousMapController { register (mapRouter) { mapRouter.options('/'); - mapRouter.get('/', this.composeCreateMapMiddleware()); - mapRouter.post('/', this.composeCreateMapMiddleware()); + mapRouter.get('/', this.middlewares()); + mapRouter.post('/', this.middlewares()); } - composeCreateMapMiddleware () { + middlewares () { const isTemplateInstantiation = false; const useTemplateHash = false; const includeQuery = true; From a77dd9a11fe6879147b7c5ac1f4dda45877867e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 13:20:05 +0200 Subject: [PATCH 05/21] Create .middlewares() method to be mounted in dataview controller --- .../api/map/dataview-layergroup-controller.js | 78 +++---------------- 1 file changed, 11 insertions(+), 67 deletions(-) diff --git a/lib/cartodb/api/map/dataview-layergroup-controller.js b/lib/cartodb/api/map/dataview-layergroup-controller.js index 710c5cd4..18392b01 100644 --- a/lib/cartodb/api/map/dataview-layergroup-controller.js +++ b/lib/cartodb/api/map/dataview-layergroup-controller.js @@ -5,6 +5,7 @@ const dbConnSetup = require('../middlewares/db-conn-setup'); const authorize = require('../middlewares/authorize'); const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; +const { DATAVIEW: DATAVIEW_GROUP, DATAVIEW_SEARCH: DATAVIEW_SEARCH_GROUP } = RATE_LIMIT_ENDPOINTS_GROUPS; const createMapStoreMapConfigProvider = require('../middlewares/map-store-map-config-provider'); const cacheControlHeader = require('../middlewares/cache-control-header'); const cacheChannelHeader = require('../middlewares/cache-channel-header'); @@ -49,34 +50,19 @@ module.exports = class DataviewLayergroupController { // Undocumented/non-supported API endpoint methods. // Use at your own peril. - mapRouter.get( - `/:token/dataview/:dataviewName`, - layergroupToken(), - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW), - cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), - createMapStoreMapConfigProvider( - this.mapStore, - this.userLimitsBackend, - this.pgConnection, - this.layergroupAffectedTablesCache - ), - getDataview(this.dataviewBackend), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader() - ); + mapRouter.get('/:token/dataview/:dataviewName', this.middlewares('get', DATAVIEW_GROUP)); + mapRouter.get('/:token/:layer/widget/:dataviewName', this.middlewares('get', DATAVIEW_GROUP)); + mapRouter.get('/:token/dataview/:dataviewName/search', this.middlewares('search', DATAVIEW_SEARCH_GROUP)); + mapRouter.get('/:token/:layer/widget/:dataviewName/search', this.middlewares('search', DATAVIEW_SEARCH_GROUP)); + } - mapRouter.get( - `/:token/:layer/widget/:dataviewName`, + middlewares ({ action, rateLimitGroup }) { + return [ layergroupToken(), credentials(), authorize(this.authBackend), dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW), + rateLimit(this.userLimitsBackend, rateLimitGroup), cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), createMapStoreMapConfigProvider( this.mapStore, @@ -84,54 +70,12 @@ module.exports = class DataviewLayergroupController { this.pgConnection, this.layergroupAffectedTablesCache ), - getDataview(this.dataviewBackend), + action === 'search' ? dataviewSearch(this.dataviewBackend) : getDataview(this.dataviewBackend), cacheControlHeader(), cacheChannelHeader(), surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), lastModifiedHeader() - ); - - mapRouter.get( - `/:token/dataview/:dataviewName/search`, - layergroupToken(), - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH), - cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), - createMapStoreMapConfigProvider( - this.mapStore, - this.userLimitsBackend, - this.pgConnection, - this.layergroupAffectedTablesCache - ), - dataviewSearch(this.dataviewBackend), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader() - ); - - mapRouter.get( - `/:token/:layer/widget/:dataviewName/search`, - layergroupToken(), - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH), - cleanUpQueryParams(ALLOWED_DATAVIEW_QUERY_PARAMS), - createMapStoreMapConfigProvider( - this.mapStore, - this.userLimitsBackend, - this.pgConnection, - this.layergroupAffectedTablesCache - ), - dataviewSearch(this.dataviewBackend), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader() - ); + ]; } }; From 69505974fea40eb09c3538db95e29be6f9484ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 13:29:50 +0200 Subject: [PATCH 06/21] Pass object instead of argument list --- .../api/map/dataview-layergroup-controller.js | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/cartodb/api/map/dataview-layergroup-controller.js b/lib/cartodb/api/map/dataview-layergroup-controller.js index 18392b01..1fad5e77 100644 --- a/lib/cartodb/api/map/dataview-layergroup-controller.js +++ b/lib/cartodb/api/map/dataview-layergroup-controller.js @@ -50,10 +50,25 @@ module.exports = class DataviewLayergroupController { // Undocumented/non-supported API endpoint methods. // Use at your own peril. - mapRouter.get('/:token/dataview/:dataviewName', this.middlewares('get', DATAVIEW_GROUP)); - mapRouter.get('/:token/:layer/widget/:dataviewName', this.middlewares('get', DATAVIEW_GROUP)); - mapRouter.get('/:token/dataview/:dataviewName/search', this.middlewares('search', DATAVIEW_SEARCH_GROUP)); - mapRouter.get('/:token/:layer/widget/:dataviewName/search', this.middlewares('search', DATAVIEW_SEARCH_GROUP)); + mapRouter.get('/:token/dataview/:dataviewName', this.middlewares({ + action: 'get', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW + })); + + mapRouter.get('/:token/:layer/widget/:dataviewName', this.middlewares({ + action: 'get', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW + })); + + mapRouter.get('/:token/dataview/:dataviewName/search', this.middlewares({ + action: 'search', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH + })); + + mapRouter.get('/:token/:layer/widget/:dataviewName/search', this.middlewares({ + action: 'search', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.DATAVIEW_SEARCH + })); } middlewares ({ action, rateLimitGroup }) { From 33af2d37b36ffb67e369277eed962655414b8f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 13:30:25 +0200 Subject: [PATCH 07/21] Remove declared variables but not used --- lib/cartodb/api/map/dataview-layergroup-controller.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/cartodb/api/map/dataview-layergroup-controller.js b/lib/cartodb/api/map/dataview-layergroup-controller.js index 1fad5e77..5fd666ea 100644 --- a/lib/cartodb/api/map/dataview-layergroup-controller.js +++ b/lib/cartodb/api/map/dataview-layergroup-controller.js @@ -5,7 +5,6 @@ const dbConnSetup = require('../middlewares/db-conn-setup'); const authorize = require('../middlewares/authorize'); const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -const { DATAVIEW: DATAVIEW_GROUP, DATAVIEW_SEARCH: DATAVIEW_SEARCH_GROUP } = RATE_LIMIT_ENDPOINTS_GROUPS; const createMapStoreMapConfigProvider = require('../middlewares/map-store-map-config-provider'); const cacheControlHeader = require('../middlewares/cache-control-header'); const cacheChannelHeader = require('../middlewares/cache-channel-header'); From 1cfeda8fe5ee3b891f8776c5f0e0a4db4b6c2f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 13:38:51 +0200 Subject: [PATCH 08/21] Create .middlewares() method to mount corresponding set of middlewares --- lib/cartodb/api/map/attributes-layergroup-controller.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/map/attributes-layergroup-controller.js b/lib/cartodb/api/map/attributes-layergroup-controller.js index 632cca9f..2723ebd0 100644 --- a/lib/cartodb/api/map/attributes-layergroup-controller.js +++ b/lib/cartodb/api/map/attributes-layergroup-controller.js @@ -31,8 +31,11 @@ module.exports = class AttributesLayergroupController { } register (mapRouter) { - mapRouter.get( - `/:token/:layer/attributes/:fid`, + mapRouter.get('/:token/:layer/attributes/:fid', this.middlewares()); + } + + middlewares () { + return [ layergroupToken(), credentials(), authorize(this.authBackend), @@ -50,7 +53,7 @@ module.exports = class AttributesLayergroupController { cacheChannelHeader(), surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), lastModifiedHeader() - ); + ]; } }; From 242224396d53615ae9b9e0ff2af8f90c9a611b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 14:05:41 +0200 Subject: [PATCH 09/21] Create .middlewares() method to compose controller actions --- .../api/map/preview-layergroup-controller.js | 52 +++++++++---------- lib/cartodb/api/middlewares/noop.js | 5 ++ 2 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 lib/cartodb/api/middlewares/noop.js diff --git a/lib/cartodb/api/map/preview-layergroup-controller.js b/lib/cartodb/api/map/preview-layergroup-controller.js index 29db8729..9e84f8d9 100644 --- a/lib/cartodb/api/map/preview-layergroup-controller.js +++ b/lib/cartodb/api/map/preview-layergroup-controller.js @@ -2,6 +2,7 @@ const layergroupToken = require('../middlewares/layergroup-token'); const coordinates = require('../middlewares/coordinates'); const cleanUpQueryParams = require('../middlewares/clean-up-query-params'); const credentials = require('../middlewares/credentials'); +const noop = require('../middlewares/noop'); const dbConnSetup = require('../middlewares/db-conn-setup'); const authorize = require('../middlewares/authorize'); const rateLimit = require('../middlewares/rate-limit'); @@ -32,34 +33,33 @@ module.exports = class PreviewLayergroupController { } register (mapRouter) { + mapRouter.get('/static/center/:token/:z/:lat/:lng/:width/:height.:format', this.middlewares({ + validateZoom: true, + previewType: 'centered' + })); + + mapRouter.get('/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format', this.middlewares({ + validateZoom: false, + previewType: 'bbox' + })); + } + + middlewares ({ validateZoom, previewType }) { const forcedFormat = 'png'; - mapRouter.get( - `/static/center/:token/:z/:lat/:lng/:width/:height.:format`, - layergroupToken(), - coordinates({ z: true, x: false, y: false }), - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC), - cleanUpQueryParams(['layer']), - createMapStoreMapConfigProvider( - this.mapStore, - this.userLimitsBackend, - this.pgConnection, - this.layergroupAffectedTablesCache, - forcedFormat - ), - getPreviewImageByCenter(this.previewBackend), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader() - ); + let getPreviewImage; - mapRouter.get( - `/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format`, + if (previewType === 'centered') { + getPreviewImage = getPreviewImageByCenter; + } + + if (previewType === 'bbox') { + getPreviewImage = getPreviewImageByBoundingBox; + } + + return [ layergroupToken(), + validateZoom ? coordinates({ z: true, x: false, y: false }) : noop(), credentials(), authorize(this.authBackend), dbConnSetup(this.pgConnection), @@ -72,12 +72,12 @@ module.exports = class PreviewLayergroupController { this.layergroupAffectedTablesCache, forcedFormat ), - getPreviewImageByBoundingBox(this.previewBackend), + getPreviewImage(this.previewBackend), cacheControlHeader(), cacheChannelHeader(), surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), lastModifiedHeader() - ); + ]; } }; diff --git a/lib/cartodb/api/middlewares/noop.js b/lib/cartodb/api/middlewares/noop.js new file mode 100644 index 00000000..16ceabbe --- /dev/null +++ b/lib/cartodb/api/middlewares/noop.js @@ -0,0 +1,5 @@ +module.exports = function noop () { + return function noopMiddleware (req, res, next) { + next(); + }; +}; From 3d7231929c265b24b7743d4fa3fddaeaf742478f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 15:34:10 +0200 Subject: [PATCH 10/21] Create .middlewares() method to return the middlewares to process the request --- .../api/map/preview-template-controller.js | 95 ++++++++++--------- .../api/map/tile-layergroup-controller.js | 14 ++- 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/lib/cartodb/api/map/preview-template-controller.js b/lib/cartodb/api/map/preview-template-controller.js index 9f5257a3..385b954d 100644 --- a/lib/cartodb/api/map/preview-template-controller.js +++ b/lib/cartodb/api/map/preview-template-controller.js @@ -22,54 +22,57 @@ function numMapper(n) { return +n; } -function PreviewTemplateController ( - namedMapProviderCache, - previewBackend, - surrogateKeysCache, - tablesExtentBackend, - metadataBackend, - pgConnection, - authBackend, - userLimitsBackend -) { - this.namedMapProviderCache = namedMapProviderCache; - this.previewBackend = previewBackend; - this.surrogateKeysCache = surrogateKeysCache; - this.tablesExtentBackend = tablesExtentBackend; - this.metadataBackend = metadataBackend; - this.pgConnection = pgConnection; - this.authBackend = authBackend; - this.userLimitsBackend = userLimitsBackend; -} +module.exports = class PreviewTemplateController { + constructor ( + namedMapProviderCache, + previewBackend, + surrogateKeysCache, + tablesExtentBackend, + metadataBackend, + pgConnection, + authBackend, + userLimitsBackend + ) { + this.namedMapProviderCache = namedMapProviderCache; + this.previewBackend = previewBackend; + this.surrogateKeysCache = surrogateKeysCache; + this.tablesExtentBackend = tablesExtentBackend; + this.metadataBackend = metadataBackend; + this.pgConnection = pgConnection; + this.authBackend = authBackend; + this.userLimitsBackend = userLimitsBackend; + } -module.exports = PreviewTemplateController; + register (mapRouter) { + mapRouter.get('/static/named/:template_id/:width/:height.:format', this.middlewares()); + } -PreviewTemplateController.prototype.register = function (mapRouter) { - mapRouter.get( - `/static/named/:template_id/:width/:height.:format`, - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC_NAMED), - cleanUpQueryParams(['layer', 'zoom', 'lon', 'lat', 'bbox']), - namedMapProvider({ - namedMapProviderCache: this.namedMapProviderCache, - label: 'STATIC_VIZ_MAP', forcedFormat: 'png' - }), - getTemplate({ label: 'STATIC_VIZ_MAP' }), - prepareLayerFilterFromPreviewLayers({ - namedMapProviderCache: this.namedMapProviderCache, - label: 'STATIC_VIZ_MAP' - }), - getStaticImageOptions({ tablesExtentBackend: this.tablesExtentBackend }), - getImage({ previewBackend: this.previewBackend, label: 'STATIC_VIZ_MAP' }), - setContentTypeHeader(), - incrementMapViews({ metadataBackend: this.metadataBackend }), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader() - ); + middlewares () { + return [ + credentials(), + authorize(this.authBackend), + dbConnSetup(this.pgConnection), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC_NAMED), + cleanUpQueryParams(['layer', 'zoom', 'lon', 'lat', 'bbox']), + namedMapProvider({ + namedMapProviderCache: this.namedMapProviderCache, + label: 'STATIC_VIZ_MAP', forcedFormat: 'png' + }), + getTemplate({ label: 'STATIC_VIZ_MAP' }), + prepareLayerFilterFromPreviewLayers({ + namedMapProviderCache: this.namedMapProviderCache, + label: 'STATIC_VIZ_MAP' + }), + getStaticImageOptions({ tablesExtentBackend: this.tablesExtentBackend }), + getImage({ previewBackend: this.previewBackend, label: 'STATIC_VIZ_MAP' }), + setContentTypeHeader(), + incrementMapViews({ metadataBackend: this.metadataBackend }), + cacheControlHeader(), + cacheChannelHeader(), + surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), + lastModifiedHeader() + ]; + } }; function getTemplate ({ label }) { diff --git a/lib/cartodb/api/map/tile-layergroup-controller.js b/lib/cartodb/api/map/tile-layergroup-controller.js index f882d13c..229f5d00 100644 --- a/lib/cartodb/api/map/tile-layergroup-controller.js +++ b/lib/cartodb/api/map/tile-layergroup-controller.js @@ -46,10 +46,14 @@ module.exports = class TileLayergroupController { const not = (val) => `(?!${val})([^\/]+?)`; mapRouter.get([ - `/:token/:z/:x/:y@:scale_factor?x.:format`, - `/:token/:z/:x/:y.:format`, - `/:token${not('static')}/:layer/:z/:x/:y.(:format)` - ], + `/:token/:z/:x/:y@:scale_factor?x.:format`, + `/:token/:z/:x/:y.:format`, + `/:token${not('static')}/:layer/:z/:x/:y.(:format)` + ], this.middlewares()); + } + + middlewares () { + return [ layergroupToken(), coordinates(), credentials(), @@ -72,7 +76,7 @@ module.exports = class TileLayergroupController { incrementErrorMetrics(global.statsClient), tileError(), vectorError() - ); + ]; } }; From 1f717617b0b01e4a0140e468ab4b49c0eea98431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:07:25 +0200 Subject: [PATCH 11/21] Add .middlewares() method to build middleware stack to be mounted --- .../api/template/admin-template-controller.js | 128 ++++++++++-------- 1 file changed, 74 insertions(+), 54 deletions(-) diff --git a/lib/cartodb/api/template/admin-template-controller.js b/lib/cartodb/api/template/admin-template-controller.js index b45ebca7..b2087685 100644 --- a/lib/cartodb/api/template/admin-template-controller.js +++ b/lib/cartodb/api/template/admin-template-controller.js @@ -3,70 +3,90 @@ const credentials = require('../middlewares/credentials'); const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -/** - * @param {AuthBackend} authBackend - * @param {PgConnection} pgConnection - * @param {TemplateMaps} templateMaps - * @constructor - */ -function AdminTemplateController(authBackend, templateMaps, userLimitsBackend) { - this.authBackend = authBackend; - this.templateMaps = templateMaps; - this.userLimitsBackend = userLimitsBackend; -} +module.exports = class AdminTemplateController { + /** + * @param {AuthBackend} authBackend + * @param {PgConnection} pgConnection + * @param {TemplateMaps} templateMaps + * @constructor + */ + constructor (authBackend, templateMaps, userLimitsBackend) { + this.authBackend = authBackend; + this.templateMaps = templateMaps; + this.userLimitsBackend = userLimitsBackend; + } -module.exports = AdminTemplateController; + register (templateRouter) { + templateRouter.options(`/:template_id`); -AdminTemplateController.prototype.register = function (templateRouter) { - templateRouter.options(`/:template_id`); + templateRouter.post('/', this.middlewares({ + action: 'create', + label: 'POST TEMPLATE', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_CREATE + })); - templateRouter.post( - `/`, - credentials(), - authorizedByAPIKey({ authBackend: this.authBackend, action: 'create', label: 'POST TEMPLATE' }), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_CREATE), - checkContentType({ action: 'POST', label: 'POST TEMPLATE' }), - createTemplate({ templateMaps: this.templateMaps }) - ); + templateRouter.put('/:template_id', this.middlewares({ + action: 'update', + label: 'PUT TEMPLATE', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_UPDATE + })); - templateRouter.put( - `/:template_id`, - credentials(), - authorizedByAPIKey({ authBackend: this.authBackend, action: 'update', label: 'PUT TEMPLATE' }), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_UPDATE), - checkContentType({ action: 'PUT', label: 'PUT TEMPLATE' }), - updateTemplate({ templateMaps: this.templateMaps }) - ); + templateRouter.get('/:template_id', this.middlewares({ + action: 'get', + label: 'GET TEMPLATE', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_GET + })); - templateRouter.get( - `/:template_id`, - credentials(), - authorizedByAPIKey({ authBackend: this.authBackend, action: 'get', label: 'GET TEMPLATE' }), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_GET), - retrieveTemplate({ templateMaps: this.templateMaps }) - ); + templateRouter.delete('/:template_id', this.middlewares({ + action: 'delete', + label: 'DELETE TEMPLATE', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_DELETE + })); - templateRouter.delete( - `/:template_id`, - credentials(), - authorizedByAPIKey({ authBackend: this.authBackend, action: 'delete', label: 'DELETE TEMPLATE' }), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_DELETE), - destroyTemplate({ templateMaps: this.templateMaps }) - ); + templateRouter.get('/', this.middlewares({ + action: 'list', + label: 'GET TEMPLATE LIST', + rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_LIST + })); + } - templateRouter.get( - `/`, - credentials(), - authorizedByAPIKey({ authBackend: this.authBackend, action: 'list', label: 'GET TEMPLATE LIST' }), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_LIST), - listTemplates({ templateMaps: this.templateMaps }) - ); + middlewares ({ action, label, rateLimitGroup }) { + let template; + + if (action === 'create') { + template = createTemplate; + } + + if (action === 'update') { + template = updateTemplate; + } + + if (action === 'get') { + template = retrieveTemplate; + } + + if (action === 'delete') { + template = destroyTemplate; + } + + if (action === 'list') { + template = listTemplates; + } + + return [ + credentials(), + authorizedByAPIKey({ authBackend: this.authBackend, action, label }), + rateLimit(this.userLimitsBackend, rateLimitGroup), + checkContentType({ action: 'POST', label: 'POST TEMPLATE' }), + template({ templateMaps: this.templateMaps }) + ]; + } }; -function checkContentType ({ action, label }) { +function checkContentType ({ label }) { return function checkContentTypeMiddleware (req, res, next) { - if (!req.is('application/json')) { - const error = new Error(`template ${action} data must be of type application/json`); + if ((req.method === 'POST' || req.method === 'PUT') && !req.is('application/json')) { + const error = new Error(`${req.method} template data must be of type application/json`); error.label = label; return next(error); } From 6eeb75a35ef30ba6265128d13cbac56200c52f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:13:34 +0200 Subject: [PATCH 12/21] Use .middlewares() method to build middleware stack to process the request --- lib/cartodb/api/map/analyses-catalog-controller.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/map/analyses-catalog-controller.js b/lib/cartodb/api/map/analyses-catalog-controller.js index 760c0e80..870d81dc 100644 --- a/lib/cartodb/api/map/analyses-catalog-controller.js +++ b/lib/cartodb/api/map/analyses-catalog-controller.js @@ -17,8 +17,11 @@ function AnalysesController(pgConnection, authBackend, userLimitsBackend) { module.exports = AnalysesController; AnalysesController.prototype.register = function (mapRouter) { - mapRouter.get( - `/analyses/catalog`, + mapRouter.get('/analyses/catalog', this.middlewares()); +}; + +AnalysesController.prototype.middlewares = function () { + return [ credentials(), authorize(this.authBackend), dbConnSetup(this.pgConnection), @@ -30,7 +33,7 @@ AnalysesController.prototype.register = function (mapRouter) { prepareResponse(), cacheControlHeader({ ttl: 10, revalidate: true }), unauthorizedError() - ); + ]; }; function createPGClient () { From 9db6e2161b2a3f9858cf8769d951011de88b0c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:15:33 +0200 Subject: [PATCH 13/21] Use ES6 class syntax --- .../api/map/analyses-catalog-controller.js | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/cartodb/api/map/analyses-catalog-controller.js b/lib/cartodb/api/map/analyses-catalog-controller.js index 870d81dc..2fae5ac2 100644 --- a/lib/cartodb/api/map/analyses-catalog-controller.js +++ b/lib/cartodb/api/map/analyses-catalog-controller.js @@ -8,32 +8,32 @@ const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; const cacheControlHeader = require('../middlewares/cache-control-header'); const dbParamsFromResLocals = require('../../utils/database-params'); -function AnalysesController(pgConnection, authBackend, userLimitsBackend) { - this.pgConnection = pgConnection; - this.authBackend = authBackend; - this.userLimitsBackend = userLimitsBackend; -} +module.exports = class AnalysesController { + constructor (pgConnection, authBackend, userLimitsBackend) { + this.pgConnection = pgConnection; + this.authBackend = authBackend; + this.userLimitsBackend = userLimitsBackend; + } -module.exports = AnalysesController; + register (mapRouter) { + mapRouter.get('/analyses/catalog', this.middlewares()); + } -AnalysesController.prototype.register = function (mapRouter) { - mapRouter.get('/analyses/catalog', this.middlewares()); -}; - -AnalysesController.prototype.middlewares = function () { - return [ - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS_CATALOG), - cleanUpQueryParams(), - createPGClient(), - getDataFromQuery({ queryTemplate: catalogQueryTpl, key: 'catalog' }), - getDataFromQuery({ queryTemplate: tablesQueryTpl, key: 'tables' }), - prepareResponse(), - cacheControlHeader({ ttl: 10, revalidate: true }), - unauthorizedError() - ]; + middlewares () { + return [ + credentials(), + authorize(this.authBackend), + dbConnSetup(this.pgConnection), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS_CATALOG), + cleanUpQueryParams(), + createPGClient(), + getDataFromQuery({ queryTemplate: catalogQueryTpl, key: 'catalog' }), + getDataFromQuery({ queryTemplate: tablesQueryTpl, key: 'tables' }), + prepareResponse(), + cacheControlHeader({ ttl: 10, revalidate: true }), + unauthorizedError() + ]; + } }; function createPGClient () { From 68f5ee7bde138a7589bb9fb8a59e5c67db6cf711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:18:52 +0200 Subject: [PATCH 14/21] Use ES6 class syntax --- .../api/template/named-template-controller.js | 150 +++++++++--------- 1 file changed, 72 insertions(+), 78 deletions(-) diff --git a/lib/cartodb/api/template/named-template-controller.js b/lib/cartodb/api/template/named-template-controller.js index 86613c5e..f85892bd 100644 --- a/lib/cartodb/api/template/named-template-controller.js +++ b/lib/cartodb/api/template/named-template-controller.js @@ -33,88 +33,82 @@ const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; * @param {StatsBackend} statsBackend * @constructor */ -function NamedMapController ( - pgConnection, - templateMaps, - mapBackend, - metadataBackend, - surrogateKeysCache, - userLimitsBackend, - layergroupAffectedTables, - mapConfigAdapter, - statsBackend, - authBackend, - layergroupMetadata -) { - this.pgConnection = pgConnection; - this.templateMaps = templateMaps; - this.mapBackend = mapBackend; - this.metadataBackend = metadataBackend; - this.surrogateKeysCache = surrogateKeysCache; - this.userLimitsBackend = userLimitsBackend; - this.layergroupAffectedTables = layergroupAffectedTables; - this.mapConfigAdapter = mapConfigAdapter; - this.statsBackend = statsBackend; - this.authBackend = authBackend; - this.layergroupMetadata = layergroupMetadata; -} +module.exports = class NamedMapController { + constructor ( + pgConnection, + templateMaps, + mapBackend, + metadataBackend, + surrogateKeysCache, + userLimitsBackend, + layergroupAffectedTables, + mapConfigAdapter, + statsBackend, + authBackend, + layergroupMetadata + ) { + this.pgConnection = pgConnection; + this.templateMaps = templateMaps; + this.mapBackend = mapBackend; + this.metadataBackend = metadataBackend; + this.surrogateKeysCache = surrogateKeysCache; + this.userLimitsBackend = userLimitsBackend; + this.layergroupAffectedTables = layergroupAffectedTables; + this.mapConfigAdapter = mapConfigAdapter; + this.statsBackend = statsBackend; + this.authBackend = authBackend; + this.layergroupMetadata = layergroupMetadata; + } -module.exports = NamedMapController; + register (templateRouter) { + templateRouter.get(`/:template_id/jsonp`, this.composeInstantiateTemplateMiddleware()); -NamedMapController.prototype.register = function (templateRouter) { - templateRouter.get( - `/:template_id/jsonp`, - this.composeInstantiateTemplateMiddleware() - ); + templateRouter.post(`/:template_id`, this.composeInstantiateTemplateMiddleware()); + } - templateRouter.post( - `/:template_id`, - this.composeInstantiateTemplateMiddleware() - ); -}; + composeInstantiateTemplateMiddleware () { + const isTemplateInstantiation = true; + const useTemplateHash = true; + const includeQuery = false; + const label = 'NAMED MAP LAYERGROUP'; + const addContext = false; -NamedMapController.prototype.composeInstantiateTemplateMiddleware = function () { - const isTemplateInstantiation = true; - const useTemplateHash = true; - const includeQuery = false; - const label = 'NAMED MAP LAYERGROUP'; - const addContext = false; - - return [ - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED), - cleanUpQueryParams(['aggregation']), - initProfiler(isTemplateInstantiation), - checkJsonContentType(), - checkInstantiteLayergroup(), - getTemplate( - this.templateMaps, - this.pgConnection, - this.metadataBackend, - this.userLimitsBackend, - this.mapConfigAdapter, - this.layergroupAffectedTables - ), - instantiateLayergroup( - this.mapBackend, - this.userLimitsBackend, - this.pgConnection, - this.layergroupAffectedTables - ), - incrementMapViewCount(this.metadataBackend), - augmentLayergroupData(), - cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader({ now: true }), - lastUpdatedTimeLayergroup(), - layerStats(this.pgConnection, this.statsBackend), - layergroupIdHeader(this.templateMaps ,useTemplateHash), - layergroupMetadata(this.layergroupMetadata, includeQuery), - mapError({ label, addContext }) - ]; + return [ + credentials(), + authorize(this.authBackend), + dbConnSetup(this.pgConnection), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED), + cleanUpQueryParams(['aggregation']), + initProfiler(isTemplateInstantiation), + checkJsonContentType(), + checkInstantiteLayergroup(), + getTemplate( + this.templateMaps, + this.pgConnection, + this.metadataBackend, + this.userLimitsBackend, + this.mapConfigAdapter, + this.layergroupAffectedTables + ), + instantiateLayergroup( + this.mapBackend, + this.userLimitsBackend, + this.pgConnection, + this.layergroupAffectedTables + ), + incrementMapViewCount(this.metadataBackend), + augmentLayergroupData(), + cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }), + cacheChannelHeader(), + surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), + lastModifiedHeader({ now: true }), + lastUpdatedTimeLayergroup(), + layerStats(this.pgConnection, this.statsBackend), + layergroupIdHeader(this.templateMaps ,useTemplateHash), + layergroupMetadata(this.layergroupMetadata, includeQuery), + mapError({ label, addContext }) + ]; + } }; function checkInstantiteLayergroup () { From 3bcf6d7ca09cc72e3965930a19ddde86209a41ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:20:44 +0200 Subject: [PATCH 15/21] Place comment --- .../api/template/named-template-controller.js | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/cartodb/api/template/named-template-controller.js b/lib/cartodb/api/template/named-template-controller.js index f85892bd..5de0a91d 100644 --- a/lib/cartodb/api/template/named-template-controller.js +++ b/lib/cartodb/api/template/named-template-controller.js @@ -20,20 +20,21 @@ const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provid const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -/** - * @param {AuthBackend} authBackend - * @param {PgConnection} pgConnection - * @param {TemplateMaps} templateMaps - * @param {MapBackend} mapBackend - * @param metadataBackend - * @param {SurrogateKeysCache} surrogateKeysCache - * @param {UserLimitsBackend} userLimitsBackend - * @param {LayergroupAffectedTables} layergroupAffectedTables - * @param {MapConfigAdapter} mapConfigAdapter - * @param {StatsBackend} statsBackend - * @constructor - */ module.exports = class NamedMapController { + /** + * @param {PgConnection} pgConnection + * @param {TemplateMaps} templateMaps + * @param {MapBackend} mapBackend + * @param metadataBackend + * @param {SurrogateKeysCache} surrogateKeysCache + * @param {UserLimitsBackend} userLimitsBackend + * @param {LayergroupAffectedTables} layergroupAffectedTables + * @param {MapConfigAdapter} mapConfigAdapter + * @param {StatsBackend} statsBackend + * @param {AuthBackend} authBackend + * @param layergroupMetadata + * @constructor + */ constructor ( pgConnection, templateMaps, @@ -62,7 +63,6 @@ module.exports = class NamedMapController { register (templateRouter) { templateRouter.get(`/:template_id/jsonp`, this.composeInstantiateTemplateMiddleware()); - templateRouter.post(`/:template_id`, this.composeInstantiateTemplateMiddleware()); } From 595d006d5b7ca0287433e01777d9caefe28e154c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:21:57 +0200 Subject: [PATCH 16/21] Rename function --- lib/cartodb/api/template/named-template-controller.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/template/named-template-controller.js b/lib/cartodb/api/template/named-template-controller.js index 5de0a91d..0af1ad65 100644 --- a/lib/cartodb/api/template/named-template-controller.js +++ b/lib/cartodb/api/template/named-template-controller.js @@ -62,11 +62,11 @@ module.exports = class NamedMapController { } register (templateRouter) { - templateRouter.get(`/:template_id/jsonp`, this.composeInstantiateTemplateMiddleware()); - templateRouter.post(`/:template_id`, this.composeInstantiateTemplateMiddleware()); + templateRouter.get('/:template_id/jsonp', this.middlewares()); + templateRouter.post('/:template_id', this.middlewares()); } - composeInstantiateTemplateMiddleware () { + middlewares () { const isTemplateInstantiation = true; const useTemplateHash = true; const includeQuery = false; From 3905ed796e4337cd982a9ea503b09a7e57d9ad5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:24:28 +0200 Subject: [PATCH 17/21] Use ES6 class syntax --- .../api/template/tile-template-controller.js | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/lib/cartodb/api/template/tile-template-controller.js b/lib/cartodb/api/template/tile-template-controller.js index de256ccb..e4d80663 100644 --- a/lib/cartodb/api/template/tile-template-controller.js +++ b/lib/cartodb/api/template/tile-template-controller.js @@ -12,48 +12,48 @@ const vectorError = require('../middlewares/vector-error'); const rateLimit = require('../middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit; -function TileTemplateController ( - namedMapProviderCache, - tileBackend, - surrogateKeysCache, - pgConnection, - authBackend, - userLimitsBackend -) { - this.namedMapProviderCache = namedMapProviderCache; - this.tileBackend = tileBackend; - this.surrogateKeysCache = surrogateKeysCache; - this.pgConnection = pgConnection; - this.authBackend = authBackend; - this.userLimitsBackend = userLimitsBackend; -} +module.exports = class TileTemplateController { + constructor ( + namedMapProviderCache, + tileBackend, + surrogateKeysCache, + pgConnection, + authBackend, + userLimitsBackend + ) { + this.namedMapProviderCache = namedMapProviderCache; + this.tileBackend = tileBackend; + this.surrogateKeysCache = surrogateKeysCache; + this.pgConnection = pgConnection; + this.authBackend = authBackend; + this.userLimitsBackend = userLimitsBackend; + } -module.exports = TileTemplateController; - -TileTemplateController.prototype.register = function (templateRouter) { - templateRouter.get( - `/:template_id/:layer/:z/:x/:y.(:format)`, - coordinates(), - credentials(), - authorize(this.authBackend), - dbConnSetup(this.pgConnection), - rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_TILES), - cleanUpQueryParams(), - namedMapProvider({ - namedMapProviderCache: this.namedMapProviderCache, - label: 'NAMED_MAP_TILE' - }), - getTile({ - tileBackend: this.tileBackend, - label: 'NAMED_MAP_TILE' - }), - setContentTypeHeader(), - cacheControlHeader(), - cacheChannelHeader(), - surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), - lastModifiedHeader(), - vectorError() - ); + register (templateRouter) { + templateRouter.get( + `/:template_id/:layer/:z/:x/:y.(:format)`, + coordinates(), + credentials(), + authorize(this.authBackend), + dbConnSetup(this.pgConnection), + rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_TILES), + cleanUpQueryParams(), + namedMapProvider({ + namedMapProviderCache: this.namedMapProviderCache, + label: 'NAMED_MAP_TILE' + }), + getTile({ + tileBackend: this.tileBackend, + label: 'NAMED_MAP_TILE' + }), + setContentTypeHeader(), + cacheControlHeader(), + cacheChannelHeader(), + surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), + lastModifiedHeader(), + vectorError() + ); + } }; function getTile ({ tileBackend, label }) { From c6babc7dc454c7110d2aae36651409bbc5ea1a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:26:05 +0200 Subject: [PATCH 18/21] Create .middlewares() method to build midlleware stack to perform request --- lib/cartodb/api/template/tile-template-controller.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/template/tile-template-controller.js b/lib/cartodb/api/template/tile-template-controller.js index e4d80663..71a45e6e 100644 --- a/lib/cartodb/api/template/tile-template-controller.js +++ b/lib/cartodb/api/template/tile-template-controller.js @@ -30,8 +30,11 @@ module.exports = class TileTemplateController { } register (templateRouter) { - templateRouter.get( - `/:template_id/:layer/:z/:x/:y.(:format)`, + templateRouter.get('/:template_id/:layer/:z/:x/:y.(:format)', this.middlewares()); + } + + middlewares () { + return [ coordinates(), credentials(), authorize(this.authBackend), @@ -52,7 +55,7 @@ module.exports = class TileTemplateController { surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }), lastModifiedHeader(), vectorError() - ); + ]; } }; From f4d60f963d76e9630e396a893223e0ed91caa375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Fri, 11 May 2018 16:37:02 +0200 Subject: [PATCH 19/21] Add comment --- lib/cartodb/api/map/tile-layergroup-controller.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/map/tile-layergroup-controller.js b/lib/cartodb/api/map/tile-layergroup-controller.js index 229f5d00..311fec45 100644 --- a/lib/cartodb/api/map/tile-layergroup-controller.js +++ b/lib/cartodb/api/map/tile-layergroup-controller.js @@ -42,12 +42,15 @@ module.exports = class TileLayergroupController { } register (mapRouter) { - // REGEXP doesn't match with `val` + // REGEXP: doesn't match with `val` const not = (val) => `(?!${val})([^\/]+?)`; + // Sadly the path that matches 1 also matches with 2 so we need to tell to express + // that performs only the middlewares of the first path that matches + // for that we use one array to group all paths. mapRouter.get([ - `/:token/:z/:x/:y@:scale_factor?x.:format`, - `/:token/:z/:x/:y.:format`, + `/:token/:z/:x/:y@:scale_factor?x.:format`, // 1 + `/:token/:z/:x/:y.:format`, // 2 `/:token${not('static')}/:layer/:z/:x/:y.(:format)` ], this.middlewares()); } From 5a397afd0609611fd8ee6a38a5378aed2d7feaea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Mon, 14 May 2018 11:50:48 +0200 Subject: [PATCH 20/21] In order to extract common middlewares between routers and controlles we need to activate mergeParams options to preserve the req.params from the parent router --- lib/cartodb/api/api-router.js | 2 +- lib/cartodb/api/map/map-router.js | 2 +- lib/cartodb/api/template/template-router.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cartodb/api/api-router.js b/lib/cartodb/api/api-router.js index 9d53285b..b7534559 100644 --- a/lib/cartodb/api/api-router.js +++ b/lib/cartodb/api/api-router.js @@ -191,7 +191,7 @@ module.exports = class ApiRouter { Object.keys(this.serverOptions.routes).forEach(apiVersion => { const routes = this.serverOptions.routes[apiVersion]; - const apiRouter = router(); + const apiRouter = router({ mergeParams: true }); apiRouter.use(logger(this.serverOptions)); apiRouter.use(initializeStatusCode()); diff --git a/lib/cartodb/api/map/map-router.js b/lib/cartodb/api/map/map-router.js index 03f19937..46e2be5e 100644 --- a/lib/cartodb/api/map/map-router.js +++ b/lib/cartodb/api/map/map-router.js @@ -113,7 +113,7 @@ module.exports = class MapRouter { } register (apiRouter, mapPaths) { - const mapRouter = router(); + const mapRouter = router({ mergeParams: true }); this.analysisLayergroupController.register(mapRouter); this.attributesLayergroupController.register(mapRouter); diff --git a/lib/cartodb/api/template/template-router.js b/lib/cartodb/api/template/template-router.js index 9ddcf9fc..4234bb22 100644 --- a/lib/cartodb/api/template/template-router.js +++ b/lib/cartodb/api/template/template-router.js @@ -53,7 +53,7 @@ module.exports = class TemplateRouter { } register (apiRouter, templatePaths) { - const templateRouter = router(); + const templateRouter = router({ mergeParams: true }); this.namedMapController.register(templateRouter); this.tileTemplateController.register(templateRouter); From 63a9d58c6713c065818c09813007c5d87cee7ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Mon, 14 May 2018 12:28:57 +0200 Subject: [PATCH 21/21] Add regression test --- test/acceptance/regressions.js | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/acceptance/regressions.js b/test/acceptance/regressions.js index 698d1401..e49065d3 100644 --- a/test/acceptance/regressions.js +++ b/test/acceptance/regressions.js @@ -1,7 +1,10 @@ require('../support/test_helper'); var assert = require('../support/assert'); +const helper = require('../support/test_helper'); var TestClient = require('../support/test-client'); const LayergroupToken = require('../../lib/cartodb/models/layergroup-token'); +const CartodbWindshaft = require(__dirname + '/../../lib/cartodb/server'); +const serverOptions = require(__dirname + '/../../lib/cartodb/server_options'); describe('regressions', function() { @@ -38,6 +41,49 @@ describe('regressions', function() { }); }); + // See: https://github.com/CartoDB/Windshaft-cartodb/pull/956 + it('"/user/localhost/api/v1/map" should create an anonymous map', function (done) { + const server = new CartodbWindshaft(serverOptions); + const layergroup = { + version: '1.7.0', + layers: [ + { + type: 'mapnik', + options: { + sql: TestClient.SQL.ONE_POINT, + cartocss: TestClient.CARTOCSS.POINTS, + cartocss_version: '2.3.0' + } + } + ] + }; + + const keysToDelete = {}; + + assert.response(server, + { + url: '/user/localhost/api/v1/map', + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify(layergroup) + }, + function(res, err) { + if (err) { + return done(err); + } + + const body = JSON.parse(res.body); + assert.ok(body.layergroupid); + + keysToDelete['map_cfg|' + LayergroupToken.parse(body.layergroupid).token] = 0; + keysToDelete['user:localhost:mapviews:global'] = 5; + helper.deleteRedisKeys(keysToDelete, done); + } + ); + }); + describe('map instantiation', function () { const apikeyToken = 'regular1'; const mapConfig = {