2018-03-10 00:02:13 +08:00
|
|
|
const _ = require('underscore');
|
2018-03-28 18:39:39 +08:00
|
|
|
const ResourceLocator = require('../../models/resource-locator');
|
|
|
|
const cleanUpQueryParams = require('../../middleware/clean-up-query-params');
|
|
|
|
const credentials = require('../../middleware/credentials');
|
|
|
|
const dbConnSetup = require('../../middleware/db-conn-setup');
|
|
|
|
const authorize = require('../../middleware/authorize');
|
2018-03-28 18:45:03 +08:00
|
|
|
const initProfiler = require('./middlewares/init-profiler');
|
2018-03-28 18:49:11 +08:00
|
|
|
const checkJsonContentType = require('./middlewares/check-json-content-type');
|
2018-03-28 19:01:23 +08:00
|
|
|
const incrementMapViewCount = require('./middlewares/increment-map-view-count');
|
2018-03-28 19:10:47 +08:00
|
|
|
const augmentLayergroupData = require('./middlewares/augment-layergroup-data');
|
2018-03-28 18:39:39 +08:00
|
|
|
const cacheControlHeader = require('../../middleware/cache-control-header');
|
|
|
|
const cacheChannelHeader = require('../../middleware/cache-channel-header');
|
|
|
|
const surrogateKeyHeader = require('../../middleware/surrogate-key-header');
|
|
|
|
const lastModifiedHeader = require('../../middleware/last-modified-header');
|
2018-03-28 19:27:01 +08:00
|
|
|
const lastUpdatedTimeLayergroup = require('./middlewares/last-updated-time-layergroup');
|
2018-03-28 19:31:37 +08:00
|
|
|
const layerStats = require('./middlewares/layer-stats');
|
2018-03-28 19:41:41 +08:00
|
|
|
const layergroupIdHeader = require('./middlewares/layergroup-id-header');
|
2018-03-28 18:39:39 +08:00
|
|
|
const sendResponse = require('../../middleware/send-response');
|
|
|
|
const NamedMapMapConfigProvider = require('../../models/mapconfig/provider/named-map-provider');
|
|
|
|
const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provider/create-layergroup-provider');
|
|
|
|
const LayergroupMetadata = require('../../utils/layergroup-metadata');
|
|
|
|
const rateLimit = require('../../middleware/rate-limit');
|
2018-02-27 23:52:27 +08:00
|
|
|
const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit;
|
2017-05-10 23:17:01 +08:00
|
|
|
|
2015-07-05 02:41:22 +08:00
|
|
|
/**
|
2015-09-16 22:18:26 +08:00
|
|
|
* @param {AuthApi} authApi
|
2015-07-10 07:30:38 +08:00
|
|
|
* @param {PgConnection} pgConnection
|
|
|
|
* @param {TemplateMaps} templateMaps
|
2015-07-05 02:41:22 +08:00
|
|
|
* @param {MapBackend} mapBackend
|
2015-07-10 17:24:32 +08:00
|
|
|
* @param metadataBackend
|
|
|
|
* @param {SurrogateKeysCache} surrogateKeysCache
|
2015-07-14 19:40:41 +08:00
|
|
|
* @param {UserLimitsApi} userLimitsApi
|
|
|
|
* @param {LayergroupAffectedTables} layergroupAffectedTables
|
2016-05-24 05:35:42 +08:00
|
|
|
* @param {MapConfigAdapter} mapConfigAdapter
|
2017-05-09 18:31:16 +08:00
|
|
|
* @param {StatsBackend} statsBackend
|
2015-07-05 02:41:22 +08:00
|
|
|
* @constructor
|
|
|
|
*/
|
2018-03-28 18:39:39 +08:00
|
|
|
function NamedMapController (
|
2018-03-20 18:01:13 +08:00
|
|
|
pgConnection,
|
|
|
|
templateMaps,
|
|
|
|
mapBackend,
|
|
|
|
metadataBackend,
|
|
|
|
surrogateKeysCache,
|
|
|
|
userLimitsApi,
|
|
|
|
layergroupAffectedTables,
|
|
|
|
mapConfigAdapter,
|
|
|
|
statsBackend,
|
|
|
|
authApi
|
|
|
|
) {
|
2015-07-10 07:30:38 +08:00
|
|
|
this.pgConnection = pgConnection;
|
|
|
|
this.templateMaps = templateMaps;
|
2015-07-09 02:51:36 +08:00
|
|
|
this.mapBackend = mapBackend;
|
2015-07-10 17:24:32 +08:00
|
|
|
this.metadataBackend = metadataBackend;
|
|
|
|
this.surrogateKeysCache = surrogateKeysCache;
|
2015-07-11 01:10:55 +08:00
|
|
|
this.userLimitsApi = userLimitsApi;
|
2015-07-14 19:40:41 +08:00
|
|
|
this.layergroupAffectedTables = layergroupAffectedTables;
|
2015-07-14 17:55:49 +08:00
|
|
|
|
2016-05-24 05:35:42 +08:00
|
|
|
this.mapConfigAdapter = mapConfigAdapter;
|
2018-03-09 19:58:05 +08:00
|
|
|
const resourceLocator = new ResourceLocator(global.environment);
|
|
|
|
this.layergroupMetadata = new LayergroupMetadata(resourceLocator);
|
2017-05-09 00:42:40 +08:00
|
|
|
|
2017-05-09 18:31:16 +08:00
|
|
|
this.statsBackend = statsBackend;
|
2018-03-16 01:48:29 +08:00
|
|
|
this.authApi = authApi;
|
2015-07-05 02:41:22 +08:00
|
|
|
}
|
|
|
|
|
2018-03-28 18:39:39 +08:00
|
|
|
module.exports = NamedMapController;
|
2018-03-16 23:42:47 +08:00
|
|
|
|
2018-03-28 18:39:39 +08:00
|
|
|
NamedMapController.prototype.register = function (templateRouter) {
|
2018-03-28 00:46:54 +08:00
|
|
|
templateRouter.get(
|
|
|
|
`/:template_id/jsonp`,
|
2018-03-28 18:39:39 +08:00
|
|
|
this.composeInstantiateTemplateMiddleware()
|
2018-02-20 18:26:09 +08:00
|
|
|
);
|
2018-03-20 18:01:13 +08:00
|
|
|
|
2018-03-28 00:46:54 +08:00
|
|
|
templateRouter.post(
|
|
|
|
`/:template_id`,
|
2018-03-28 18:39:39 +08:00
|
|
|
this.composeInstantiateTemplateMiddleware()
|
2018-02-20 18:26:09 +08:00
|
|
|
);
|
2015-07-05 02:41:22 +08:00
|
|
|
};
|
|
|
|
|
2018-03-28 18:39:39 +08:00
|
|
|
NamedMapController.prototype.composeInstantiateTemplateMiddleware = function () {
|
|
|
|
const isTemplateInstantiation = true;
|
|
|
|
const useTemplateHash = true;
|
|
|
|
const includeQuery = false;
|
|
|
|
const label = 'NAMED MAP LAYERGROUP';
|
|
|
|
const addContext = false;
|
2017-11-03 02:03:20 +08:00
|
|
|
|
|
|
|
return [
|
2018-03-16 02:38:11 +08:00
|
|
|
credentials(),
|
2018-03-16 01:48:29 +08:00
|
|
|
authorize(this.authApi),
|
2018-03-15 22:33:20 +08:00
|
|
|
dbConnSetup(this.pgConnection),
|
2018-03-28 18:39:39 +08:00
|
|
|
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED),
|
2018-03-24 00:37:06 +08:00
|
|
|
cleanUpQueryParams(['aggregation']),
|
2018-03-08 02:09:52 +08:00
|
|
|
initProfiler(isTemplateInstantiation),
|
2018-03-08 02:11:03 +08:00
|
|
|
checkJsonContentType(),
|
2018-03-28 18:39:39 +08:00
|
|
|
checkInstantiteLayergroup(),
|
|
|
|
getTemplate(
|
|
|
|
this.templateMaps,
|
|
|
|
this.pgConnection,
|
|
|
|
this.metadataBackend,
|
|
|
|
this.userLimitsApi,
|
|
|
|
this.mapConfigAdapter,
|
|
|
|
this.layergroupAffectedTables
|
|
|
|
),
|
|
|
|
instantiateLayergroup(
|
|
|
|
this.mapBackend,
|
|
|
|
this.userLimitsApi,
|
|
|
|
this.pgConnection,
|
|
|
|
this.layergroupAffectedTables
|
|
|
|
),
|
2018-03-08 19:16:24 +08:00
|
|
|
incrementMapViewCount(this.metadataBackend),
|
|
|
|
augmentLayergroupData(),
|
2018-03-21 23:38:37 +08:00
|
|
|
cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }),
|
2018-03-21 21:11:54 +08:00
|
|
|
cacheChannelHeader(),
|
|
|
|
surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }),
|
2018-03-21 21:43:00 +08:00
|
|
|
lastModifiedHeader({ now: true }),
|
2018-03-28 19:27:01 +08:00
|
|
|
lastUpdatedTimeLayergroup(),
|
2018-03-28 19:31:37 +08:00
|
|
|
layerStats(this.pgConnection, this.statsBackend),
|
2018-03-28 19:41:41 +08:00
|
|
|
layergroupIdHeader(this.templateMaps ,useTemplateHash),
|
2018-03-09 19:58:05 +08:00
|
|
|
setDataviewsAndWidgetsUrlsToLayergroupMetadata(this.layergroupMetadata),
|
|
|
|
setAnalysesMetadataToLayergroup(this.layergroupMetadata, includeQuery),
|
|
|
|
setTurboCartoMetadataToLayergroup(this.layergroupMetadata),
|
|
|
|
setAggregationMetadataToLayergroup(this.layergroupMetadata),
|
|
|
|
setTilejsonMetadataToLayergroup(this.layergroupMetadata),
|
2018-03-08 19:16:24 +08:00
|
|
|
sendResponse(),
|
|
|
|
augmentError({ label, addContext })
|
2017-11-03 02:24:33 +08:00
|
|
|
];
|
|
|
|
};
|
|
|
|
|
2018-03-08 19:16:24 +08:00
|
|
|
function checkInstantiteLayergroup () {
|
2017-11-06 02:13:56 +08:00
|
|
|
return function checkInstantiteLayergroupMiddleware(req, res, next) {
|
|
|
|
if (req.method === 'GET') {
|
|
|
|
const { callback, config } = req.query;
|
|
|
|
|
|
|
|
if (callback === undefined || callback.length === 0) {
|
|
|
|
return next(new Error('callback parameter should be present and be a function name'));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config) {
|
|
|
|
try {
|
|
|
|
req.body = JSON.parse(config);
|
|
|
|
} catch(e) {
|
|
|
|
return next(new Error('Invalid config parameter, should be a valid JSON'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-08 21:27:35 +08:00
|
|
|
req.profiler.done('checkInstantiteLayergroup');
|
|
|
|
|
2017-11-06 02:13:56 +08:00
|
|
|
return next();
|
|
|
|
};
|
2018-03-08 19:16:24 +08:00
|
|
|
}
|
2017-11-06 02:13:56 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
function getTemplate (
|
|
|
|
templateMaps,
|
|
|
|
pgConnection,
|
|
|
|
metadataBackend,
|
|
|
|
userLimitsApi,
|
|
|
|
mapConfigAdapter,
|
|
|
|
affectedTablesCache
|
|
|
|
) {
|
2017-11-06 02:13:56 +08:00
|
|
|
return function getTemplateMiddleware (req, res, next) {
|
|
|
|
const templateParams = req.body;
|
2018-03-23 01:57:26 +08:00
|
|
|
const { user, dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;
|
|
|
|
const { template_id } = req.params;
|
|
|
|
const { auth_token } = req.query;
|
|
|
|
|
|
|
|
const params = { dbuser, dbname, dbpassword, dbhost, dbport };
|
2017-11-02 00:57:35 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
const mapConfigProvider = new NamedMapMapConfigProvider(
|
2018-03-08 19:16:24 +08:00
|
|
|
templateMaps,
|
|
|
|
pgConnection,
|
|
|
|
metadataBackend,
|
|
|
|
userLimitsApi,
|
|
|
|
mapConfigAdapter,
|
2018-03-21 21:11:54 +08:00
|
|
|
affectedTablesCache,
|
2017-11-06 02:13:56 +08:00
|
|
|
user,
|
2018-03-23 01:57:26 +08:00
|
|
|
template_id,
|
2017-11-06 02:13:56 +08:00
|
|
|
templateParams,
|
2018-03-23 01:57:26 +08:00
|
|
|
auth_token,
|
|
|
|
params
|
2017-11-06 02:13:56 +08:00
|
|
|
);
|
2017-11-02 00:57:35 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
mapConfigProvider.getMapConfig((err, mapConfig, rendererParams) => {
|
2017-11-08 21:08:27 +08:00
|
|
|
req.profiler.done('named.getMapConfig');
|
2017-11-06 02:13:56 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
2017-11-03 16:37:01 +08:00
|
|
|
}
|
2017-11-02 00:57:35 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
res.locals.mapConfig = mapConfig;
|
2017-11-06 02:13:56 +08:00
|
|
|
res.locals.rendererParams = rendererParams;
|
2018-03-21 21:11:54 +08:00
|
|
|
res.locals.mapConfigProvider = mapConfigProvider;
|
2017-11-06 02:13:56 +08:00
|
|
|
|
|
|
|
next();
|
|
|
|
});
|
2018-03-08 19:16:24 +08:00
|
|
|
};
|
|
|
|
}
|
2017-11-02 00:57:35 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
function instantiateLayergroup (mapBackend, userLimitsApi, pgConnection, affectedTablesCache) {
|
2017-11-03 22:06:15 +08:00
|
|
|
return function instantiateLayergroupMiddleware (req, res, next) {
|
2018-03-21 21:11:54 +08:00
|
|
|
const { user, mapConfig, rendererParams } = res.locals;
|
|
|
|
const mapConfigProvider = new CreateLayergroupMapConfigProvider(
|
|
|
|
mapConfig,
|
|
|
|
user,
|
|
|
|
userLimitsApi,
|
|
|
|
pgConnection,
|
|
|
|
affectedTablesCache,
|
|
|
|
rendererParams
|
|
|
|
);
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
mapBackend.createLayergroup(mapConfig, rendererParams, mapConfigProvider, (err, layergroup) => {
|
2017-11-08 17:52:25 +08:00
|
|
|
req.profiler.done('createLayergroup');
|
2017-11-03 22:06:15 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2017-11-02 02:02:07 +08:00
|
|
|
|
2018-03-20 02:16:18 +08:00
|
|
|
res.body = layergroup;
|
2017-10-31 20:36:17 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
const { mapConfigProvider } = res.locals;
|
2017-11-02 02:02:07 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
res.locals.analysesResults = mapConfigProvider.analysesResults;
|
|
|
|
res.locals.template = mapConfigProvider.template;
|
|
|
|
res.locals.context = mapConfigProvider.context;
|
2017-11-02 02:27:01 +08:00
|
|
|
|
2017-11-03 22:06:15 +08:00
|
|
|
next();
|
|
|
|
});
|
2018-03-08 19:16:24 +08:00
|
|
|
};
|
|
|
|
}
|
2017-11-02 02:02:07 +08:00
|
|
|
|
2018-03-09 19:58:05 +08:00
|
|
|
function setDataviewsAndWidgetsUrlsToLayergroupMetadata (layergroupMetadata) {
|
2017-11-03 22:06:15 +08:00
|
|
|
return function setDataviewsAndWidgetsUrlsToLayergroupMetadataMiddleware (req, res, next) {
|
2018-03-21 21:11:54 +08:00
|
|
|
const { user, mapConfig } = res.locals;
|
2018-03-20 02:16:18 +08:00
|
|
|
const layergroup = res.body;
|
2017-11-01 01:02:23 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
layergroupMetadata.addDataviewsAndWidgetsUrls(user, layergroup, mapConfig.obj());
|
2017-11-01 01:02:23 +08:00
|
|
|
|
2017-11-03 22:06:15 +08:00
|
|
|
next();
|
2018-03-08 19:16:24 +08:00
|
|
|
};
|
|
|
|
}
|
2017-11-01 01:02:23 +08:00
|
|
|
|
2018-03-09 19:58:05 +08:00
|
|
|
function setAnalysesMetadataToLayergroup (layergroupMetadata, includeQuery) {
|
2017-11-06 02:13:56 +08:00
|
|
|
return function setAnalysesMetadataToLayergroupMiddleware (req, res, next) {
|
2018-03-20 02:16:18 +08:00
|
|
|
const { user, analysesResults = [] } = res.locals;
|
|
|
|
const layergroup = res.body;
|
2017-11-01 02:49:12 +08:00
|
|
|
|
2018-03-09 19:58:05 +08:00
|
|
|
layergroupMetadata.addAnalysesMetadata(user, layergroup, analysesResults, includeQuery);
|
2017-11-01 02:49:12 +08:00
|
|
|
|
2017-11-03 22:06:15 +08:00
|
|
|
next();
|
2018-03-08 19:16:24 +08:00
|
|
|
};
|
|
|
|
}
|
2017-11-01 02:49:12 +08:00
|
|
|
|
2018-03-09 19:58:05 +08:00
|
|
|
function setTurboCartoMetadataToLayergroup (layergroupMetadata) {
|
2017-11-06 02:13:56 +08:00
|
|
|
return function setTurboCartoMetadataToLayergroupMiddleware (req, res, next) {
|
2018-03-21 21:11:54 +08:00
|
|
|
const { mapConfig, context } = res.locals;
|
2018-03-20 02:16:18 +08:00
|
|
|
const layergroup = res.body;
|
2016-06-02 20:14:11 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
layergroupMetadata.addTurboCartoContextMetadata(layergroup, mapConfig.obj(), context);
|
2016-03-19 01:09:17 +08:00
|
|
|
|
2017-11-06 02:13:56 +08:00
|
|
|
next();
|
|
|
|
};
|
2018-03-08 19:16:24 +08:00
|
|
|
}
|
2016-03-19 01:09:17 +08:00
|
|
|
|
2018-03-09 19:58:05 +08:00
|
|
|
function setAggregationMetadataToLayergroup (layergroupMetadata) {
|
2017-12-04 19:40:53 +08:00
|
|
|
return function setAggregationMetadataToLayergroupMiddleware (req, res, next) {
|
2018-03-21 21:11:54 +08:00
|
|
|
const { mapConfig, context } = res.locals;
|
2018-03-20 02:16:18 +08:00
|
|
|
const layergroup = res.body;
|
2017-12-04 19:40:53 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
layergroupMetadata.addAggregationContextMetadata(layergroup, mapConfig.obj(), context);
|
2017-12-04 19:40:53 +08:00
|
|
|
|
|
|
|
next();
|
|
|
|
};
|
2018-03-08 19:16:24 +08:00
|
|
|
}
|
2017-12-04 19:40:53 +08:00
|
|
|
|
2018-03-09 19:58:05 +08:00
|
|
|
function setTilejsonMetadataToLayergroup (layergroupMetadata) {
|
2018-03-08 19:16:24 +08:00
|
|
|
return function augmentLayergroupTilejsonMiddleware (req, res, next) {
|
2018-03-21 21:11:54 +08:00
|
|
|
const { user, mapConfig } = res.locals;
|
2018-03-20 02:16:18 +08:00
|
|
|
const layergroup = res.body;
|
2018-03-08 19:16:24 +08:00
|
|
|
|
2018-03-21 21:11:54 +08:00
|
|
|
layergroupMetadata.addTileJsonMetadata(layergroup, user, mapConfig);
|
2018-03-08 19:16:24 +08:00
|
|
|
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function augmentError (options) {
|
2017-11-03 01:38:34 +08:00
|
|
|
const { addContext = false, label = 'MAPS CONTROLLER' } = options;
|
2017-11-01 03:49:26 +08:00
|
|
|
|
2017-11-03 22:06:15 +08:00
|
|
|
return function augmentErrorMiddleware (err, req, res, next) {
|
2017-11-08 17:52:25 +08:00
|
|
|
req.profiler.done('error');
|
2018-03-21 21:11:54 +08:00
|
|
|
const { mapConfig } = res.locals;
|
2017-11-01 03:49:26 +08:00
|
|
|
|
2017-11-03 15:48:13 +08:00
|
|
|
if (addContext) {
|
2018-03-21 21:11:54 +08:00
|
|
|
err = Number.isFinite(err.layerIndex) ? populateError(err, mapConfig) : err;
|
2017-11-01 03:49:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
err.label = label;
|
|
|
|
|
|
|
|
next(err);
|
|
|
|
};
|
2018-03-08 19:16:24 +08:00
|
|
|
}
|
2017-11-01 03:49:26 +08:00
|
|
|
|
|
|
|
function populateError(err, mapConfig) {
|
|
|
|
var error = new Error(err.message);
|
|
|
|
error.http_status = err.http_status;
|
|
|
|
|
|
|
|
if (!err.http_status && err.message.indexOf('column "the_geom_webmercator" does not exist') >= 0) {
|
|
|
|
error.http_status = 400;
|
|
|
|
}
|
|
|
|
|
|
|
|
error.type = 'layer';
|
|
|
|
error.subtype = err.message.indexOf('Postgis Plugin') >= 0 ? 'query' : undefined;
|
|
|
|
error.layer = {
|
|
|
|
id: mapConfig.getLayerId(err.layerIndex),
|
|
|
|
index: err.layerIndex,
|
|
|
|
type: mapConfig.layerType(err.layerIndex)
|
|
|
|
};
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|