Windshaft-cartodb/lib/api/map/anonymous-map-controller.js

248 lines
8.6 KiB
JavaScript
Raw Normal View History

'use strict';
2018-03-10 00:02:13 +08:00
const windshaft = require('windshaft');
const MapConfig = windshaft.model.MapConfig;
const Datasource = windshaft.model.Datasource;
const cleanUpQueryParams = require('../middlewares/clean-up-query-params');
const credentials = require('../middlewares/credentials');
const dbConnSetup = require('../middlewares/db-conn-setup');
const authorize = require('../middlewares/authorize');
const initProfiler = require('../middlewares/init-profiler');
const checkJsonContentType = require('../middlewares/check-json-content-type');
const incrementMapViewCount = require('../middlewares/increment-map-view-count');
const augmentLayergroupData = require('../middlewares/augment-layergroup-data');
const cacheControlHeader = require('../middlewares/cache-control-header');
const cacheChannelHeader = require('../middlewares/cache-channel-header');
const surrogateKeyHeader = require('../middlewares/surrogate-key-header');
const lastModifiedHeader = require('../middlewares/last-modified-header');
const lastUpdatedTimeLayergroup = require('../middlewares/last-updated-time-layergroup');
const layerStats = require('../middlewares/layer-stats');
const layergroupIdHeader = require('../middlewares/layergroup-id-header');
const layergroupMetadata = require('../middlewares/layergroup-metadata');
const mapError = require('../middlewares/map-error');
const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provider/create-layergroup-provider');
const rateLimit = require('../middlewares/rate-limit');
const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit;
const metrics = require('../middlewares/metrics');
2018-05-11 18:14:27 +08:00
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 (
config,
2018-05-11 18:14:27 +08:00
pgConnection,
templateMaps,
mapBackend,
metadataBackend,
surrogateKeysCache,
userLimitsBackend,
layergroupAffectedTables,
mapConfigAdapter,
statsBackend,
authBackend,
layergroupMetadata,
metricsBackend
2018-05-11 18:14:27 +08:00
) {
this.config = config;
2018-05-11 18:14:27 +08:00
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;
this.metricsBackend = metricsBackend;
2018-05-11 18:14:27 +08:00
}
2019-10-04 18:22:23 +08:00
route (mapRouter) {
2018-05-11 18:14:27 +08:00
mapRouter.options('/');
2018-05-11 18:42:17 +08:00
mapRouter.get('/', this.middlewares());
mapRouter.post('/', this.middlewares());
2018-05-11 18:14:27 +08:00
}
2018-05-11 18:42:17 +08:00
middlewares () {
2018-05-11 18:14:27 +08:00
const isTemplateInstantiation = false;
const useTemplateHash = false;
const includeQuery = true;
const label = 'ANONYMOUS LAYERGROUP';
const addContext = true;
const metricsTags = {
event: 'map_view',
attributes: { map_type: 'anonymous' },
from: {
req: {
query: { client: 'client' }
}
}
};
2017-11-03 02:03:20 +08:00
2018-05-11 18:14:27 +08:00
return [
metrics({
enabled: this.config.pubSubMetrics.enabled,
metricsBackend: this.metricsBackend,
tags: metricsTags
}),
2018-05-11 18:14:27 +08:00
credentials(),
authorize(this.authBackend),
dbConnSetup(this.pgConnection),
rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS),
cleanUpQueryParams(['aggregation']),
initProfiler(isTemplateInstantiation),
checkJsonContentType(),
checkCreateLayergroup(),
prepareAdapterMapConfig(this.mapConfigAdapter),
2019-10-22 01:07:24 +08:00
createLayergroup(
2018-05-11 18:14:27 +08:00
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(),
2018-05-11 18:14:27 +08:00
lastUpdatedTimeLayergroup(),
layerStats(this.pgConnection, this.statsBackend),
layergroupIdHeader(this.templateMaps, useTemplateHash),
layergroupMetadata(this.layergroupMetadata, includeQuery),
mapError({ label, addContext })
];
}
};
function checkCreateLayergroup () {
return function checkCreateLayergroupMiddleware (req, res, next) {
if (req.method === 'GET') {
const { config } = req.query;
if (!config) {
return next(new Error('layergroup GET needs a "config" parameter'));
}
try {
req.body = JSON.parse(config);
} catch (err) {
return next(err);
}
2017-11-03 16:37:01 +08:00
}
2017-11-02 00:57:35 +08:00
2017-11-08 21:27:35 +08:00
req.profiler.done('checkCreateLayergroup');
return next();
};
}
2017-11-02 00:57:35 +08:00
function prepareAdapterMapConfig (mapConfigAdapter) {
2019-10-22 01:07:24 +08:00
return function prepareAdapterMapConfigMiddleware (req, res, next) {
const requestMapConfig = req.body;
2019-11-14 18:36:47 +08:00
const { user, api_key: apiKey } = res.locals;
const { dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;
const params = Object.assign({ dbuser, dbname, dbpassword, dbhost, dbport }, req.query);
const context = {
analysisConfiguration: {
user,
db: {
host: dbhost,
port: dbport,
dbname: dbname,
user: dbuser,
pass: dbpassword
},
batch: {
username: user,
2019-11-14 18:36:47 +08:00
apiKey
}
}
};
mapConfigAdapter.getMapConfig(user,
2019-10-22 01:07:24 +08:00
requestMapConfig,
params,
context,
(err, requestMapConfig, stats = { overviewsAddedToMapconfig: false }) => {
req.profiler.done('anonymous.getMapConfig');
2019-10-22 01:07:24 +08:00
stats.mapType = 'anonymous';
req.profiler.add(stats);
2019-10-22 01:07:24 +08:00
if (err) {
return next(err);
}
2019-10-22 01:07:24 +08:00
req.body = requestMapConfig;
res.locals.context = context;
2019-10-22 01:07:24 +08:00
next();
});
};
}
function createLayergroup (mapBackend, userLimitsBackend, pgConnection, affectedTablesCache) {
return function createLayergroupMiddleware (req, res, next) {
const requestMapConfig = req.body;
const { context } = res.locals;
2019-11-14 18:36:47 +08:00
const { user, cache_buster: cacheBuster, api_key: apiKey } = res.locals;
const { dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;
const params = {
2019-11-14 18:36:47 +08:00
cache_buster: cacheBuster,
api_key: apiKey,
2019-10-22 01:07:24 +08:00
dbuser,
dbname,
dbpassword,
dbhost,
dbport
};
const datasource = context.datasource || Datasource.EmptyDatasource();
const mapConfig = new MapConfig(requestMapConfig, datasource);
const mapConfigProvider = new CreateLayergroupMapConfigProvider(
mapConfig,
user,
userLimitsBackend,
pgConnection,
affectedTablesCache,
params
);
2016-05-23 22:20:42 +08:00
2018-03-23 17:57:35 +08:00
res.locals.mapConfig = mapConfig;
res.locals.mapConfigProvider = mapConfigProvider;
2018-03-23 17:57:35 +08:00
res.locals.analysesResults = context.analysesResults;
2018-03-23 02:37:08 +08:00
const mapParams = { dbuser, dbname, dbpassword, dbhost, dbport };
2018-07-16 22:52:26 +08:00
mapBackend.createLayergroup(mapConfig, mapParams, mapConfigProvider, (err, layergroup, stats = {}) => {
req.profiler.add(stats);
if (err) {
return next(err);
}
res.statusCode = 200;
res.body = layergroup;
2017-11-01 03:10:37 +08:00
next();
});
};
}