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] 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); - }); -};