2015-07-10 17:24:32 +08:00
|
|
|
var _ = require('underscore');
|
2015-07-05 02:41:22 +08:00
|
|
|
var assert = require('assert');
|
|
|
|
var step = require('step');
|
2015-07-10 17:24:32 +08:00
|
|
|
var windshaft = require('windshaft');
|
2016-02-23 02:11:54 +08:00
|
|
|
var QueryTables = require('cartodb-query-tables');
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-09-16 22:18:26 +08:00
|
|
|
var util = require('util');
|
|
|
|
var BaseController = require('./base');
|
|
|
|
|
2015-07-08 19:27:56 +08:00
|
|
|
var cors = require('../middleware/cors');
|
2015-09-30 23:17:01 +08:00
|
|
|
var userMiddleware = require('../middleware/user');
|
2015-07-08 19:27:56 +08:00
|
|
|
|
2015-07-10 07:30:38 +08:00
|
|
|
var MapConfig = windshaft.model.MapConfig;
|
|
|
|
var Datasource = windshaft.model.Datasource;
|
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
|
|
|
|
|
2016-05-23 19:16:34 +08:00
|
|
|
var MapConfigNamedLayersAdapter = require('../models/mapconfig/adapter/mapconfig-named-layers-adapter');
|
2016-05-23 19:10:52 +08:00
|
|
|
var AnalysisMapConfigAdapter = require('../models/mapconfig/adapter/analysis-mapconfig-adapter');
|
2016-05-23 19:32:28 +08:00
|
|
|
var NamedMapMapConfigProvider = require('../models/mapconfig/provider/named-map-provider');
|
2016-05-23 19:28:11 +08:00
|
|
|
var CreateLayergroupMapConfigProvider = require('../models/mapconfig/provider/create-layergroup-provider');
|
2016-05-19 19:32:32 +08:00
|
|
|
var SqlWrapMapConfigAdapter = require('../models/mapconfig/adapter/sql-wrap-mapconfig-adapter');
|
2015-07-09 02:51:36 +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-04-14 23:09:07 +08:00
|
|
|
* @param {MapConfigOverviewsAdapter} overviewsAdapter
|
2016-04-26 21:59:41 +08:00
|
|
|
* @param {TurboCartoAdapter} turboCartoAdapter
|
2016-04-14 23:09:07 +08:00
|
|
|
* @param {AnalysisBackend} analysisBackend
|
2015-07-05 02:41:22 +08:00
|
|
|
* @constructor
|
|
|
|
*/
|
2016-01-26 18:49:41 +08:00
|
|
|
function MapController(authApi, pgConnection, templateMaps, mapBackend, metadataBackend,
|
2016-04-01 00:33:41 +08:00
|
|
|
surrogateKeysCache, userLimitsApi, layergroupAffectedTables,
|
2016-04-26 21:59:41 +08:00
|
|
|
overviewsAdapter, turboCartoAdapter, analysisBackend) {
|
2015-09-16 22:18:26 +08:00
|
|
|
|
|
|
|
BaseController.call(this, authApi, pgConnection);
|
|
|
|
|
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;
|
2016-04-26 21:59:41 +08:00
|
|
|
this.turboCartoAdapter = turboCartoAdapter;
|
2015-07-14 17:55:49 +08:00
|
|
|
|
2016-04-14 23:09:07 +08:00
|
|
|
this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter(analysisBackend);
|
2016-05-24 00:03:45 +08:00
|
|
|
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps, pgConnection);
|
2016-04-01 00:33:41 +08:00
|
|
|
this.overviewsAdapter = overviewsAdapter;
|
2016-05-19 19:32:32 +08:00
|
|
|
this.sqlWrapMapConfigAdapter = new SqlWrapMapConfigAdapter();
|
2015-07-05 02:41:22 +08:00
|
|
|
}
|
|
|
|
|
2015-09-16 22:18:26 +08:00
|
|
|
util.inherits(MapController, BaseController);
|
|
|
|
|
2015-07-05 02:41:22 +08:00
|
|
|
module.exports = MapController;
|
|
|
|
|
|
|
|
|
|
|
|
MapController.prototype.register = function(app) {
|
2015-09-30 23:17:01 +08:00
|
|
|
app.get(app.base_url_mapconfig, cors(), userMiddleware, this.createGet.bind(this));
|
|
|
|
app.post(app.base_url_mapconfig, cors(), userMiddleware, this.createPost.bind(this));
|
|
|
|
app.get(app.base_url_templated + '/:template_id/jsonp', cors(), userMiddleware, this.jsonp.bind(this));
|
|
|
|
app.post(app.base_url_templated + '/:template_id', cors(), userMiddleware, this.instantiate.bind(this));
|
2015-07-10 17:24:32 +08:00
|
|
|
app.options(app.base_url_mapconfig, cors('Content-Type'));
|
2015-07-05 02:41:22 +08:00
|
|
|
};
|
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
MapController.prototype.createGet = function(req, res){
|
|
|
|
req.profiler.start('windshaft.createmap_get');
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
this.create(req, res, function createGet$prepareConfig(err, req) {
|
|
|
|
assert.ifError(err);
|
|
|
|
if ( ! req.params.config ) {
|
|
|
|
throw new Error('layergroup GET needs a "config" parameter');
|
|
|
|
}
|
|
|
|
return JSON.parse(req.params.config);
|
|
|
|
});
|
|
|
|
};
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
MapController.prototype.createPost = function(req, res) {
|
|
|
|
req.profiler.start('windshaft.createmap_post');
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
this.create(req, res, function createPost$prepareConfig(err, req) {
|
|
|
|
assert.ifError(err);
|
|
|
|
if (!req.is('application/json')) {
|
|
|
|
throw new Error('layergroup POST data must be of type application/json');
|
|
|
|
}
|
|
|
|
return req.body;
|
|
|
|
});
|
|
|
|
};
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
MapController.prototype.instantiate = function(req, res) {
|
|
|
|
if (req.profiler) {
|
|
|
|
req.profiler.start('windshaft-cartodb.instance_template_post');
|
|
|
|
}
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
this.instantiateTemplate(req, res, function prepareTemplateParams(callback) {
|
|
|
|
if (!req.is('application/json')) {
|
|
|
|
return callback(new Error('Template POST data must be of type application/json'));
|
|
|
|
}
|
|
|
|
return callback(null, req.body);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
MapController.prototype.jsonp = function(req, res) {
|
|
|
|
if (req.profiler) {
|
|
|
|
req.profiler.start('windshaft-cartodb.instance_template_get');
|
|
|
|
}
|
|
|
|
|
|
|
|
this.instantiateTemplate(req, res, function prepareJsonTemplateParams(callback) {
|
|
|
|
var err = null;
|
|
|
|
if ( req.query.callback === undefined || req.query.callback.length === 0) {
|
|
|
|
err = new Error('callback parameter should be present and be a function name');
|
|
|
|
}
|
|
|
|
|
|
|
|
var templateParams = {};
|
|
|
|
if (req.query.config) {
|
|
|
|
try {
|
|
|
|
templateParams = JSON.parse(req.query.config);
|
|
|
|
} catch(e) {
|
|
|
|
err = new Error('Invalid config parameter, should be a valid JSON');
|
2015-07-05 02:41:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
return callback(err, templateParams);
|
|
|
|
});
|
2015-07-05 02:41:22 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
MapController.prototype.create = function(req, res, prepareConfigFn) {
|
|
|
|
var self = this;
|
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var mapConfig;
|
2016-04-07 23:58:12 +08:00
|
|
|
var analysesResults = [];
|
2015-07-10 17:24:32 +08:00
|
|
|
|
2016-05-23 22:20:42 +08:00
|
|
|
var user = req.context.user;
|
|
|
|
var context = {};
|
|
|
|
|
2015-07-05 02:41:22 +08:00
|
|
|
step(
|
|
|
|
function setupParams(){
|
2015-09-16 22:18:26 +08:00
|
|
|
self.req2params(req, this);
|
2015-07-05 02:41:22 +08:00
|
|
|
},
|
|
|
|
prepareConfigFn,
|
2016-05-19 19:32:32 +08:00
|
|
|
function prepareSqlWrap(err, requestMapConfig) {
|
|
|
|
assert.ifError(err);
|
2016-05-23 22:44:14 +08:00
|
|
|
self.sqlWrapMapConfigAdapter.getMapConfig(user, requestMapConfig, req.params, context, this);
|
2016-05-19 19:32:32 +08:00
|
|
|
},
|
2016-02-13 01:38:06 +08:00
|
|
|
function prepareAnalysisLayers(err, requestMapConfig) {
|
|
|
|
assert.ifError(err);
|
2016-05-23 22:44:14 +08:00
|
|
|
context.analysisConfiguration = {
|
2016-02-20 00:13:28 +08:00
|
|
|
db: {
|
|
|
|
host: req.params.dbhost,
|
|
|
|
port: req.params.dbport,
|
|
|
|
dbname: req.params.dbname,
|
|
|
|
user: req.params.dbuser,
|
|
|
|
pass: req.params.dbpassword
|
|
|
|
},
|
|
|
|
batch: {
|
|
|
|
username: req.context.user,
|
|
|
|
apiKey: req.params.api_key
|
|
|
|
}
|
|
|
|
};
|
2016-05-23 22:44:14 +08:00
|
|
|
self.analysisMapConfigAdapter.getMapConfig(user, requestMapConfig, req.params, context, this);
|
2016-02-13 01:38:06 +08:00
|
|
|
},
|
2016-04-07 23:58:12 +08:00
|
|
|
function beforeLayergroupCreate(err, requestMapConfig, _analysesResults) {
|
2015-07-10 07:30:38 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
var next = this;
|
2016-04-07 23:58:12 +08:00
|
|
|
analysesResults = _analysesResults;
|
2016-05-24 00:03:45 +08:00
|
|
|
self.namedLayersAdapter.getMapConfig(user, requestMapConfig, req.params, context,
|
2016-05-23 21:39:11 +08:00
|
|
|
function(err, requestMapConfig, datasource) {
|
2015-07-10 07:30:38 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return next(null, requestMapConfig, datasource);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2016-01-20 02:31:43 +08:00
|
|
|
function addOverviewsInformation(err, requestMapConfig, datasource) {
|
2016-03-10 01:05:17 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
var next = this;
|
2016-05-24 00:35:16 +08:00
|
|
|
context.analysesResults = analysesResults;
|
|
|
|
self.overviewsAdapter.getMapConfig(req.context.user, requestMapConfig, req.params, context,
|
2016-05-23 21:52:31 +08:00
|
|
|
function(err, requestMapConfig) {
|
2016-05-12 22:20:34 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2016-03-10 01:05:17 +08:00
|
|
|
|
2016-05-12 22:20:34 +08:00
|
|
|
return next(null, requestMapConfig, datasource);
|
|
|
|
}
|
|
|
|
);
|
2016-01-20 02:31:43 +08:00
|
|
|
},
|
2016-04-26 21:59:41 +08:00
|
|
|
function parseTurboCarto(err, requestMapConfig, datasource) {
|
2016-03-08 21:34:57 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
2016-05-23 22:50:26 +08:00
|
|
|
self.turboCartoAdapter.getMapConfig(req.context.user, requestMapConfig, req.params, context,
|
|
|
|
function (err, requestMapConfig) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2016-03-08 21:34:57 +08:00
|
|
|
|
2016-05-23 22:50:26 +08:00
|
|
|
return next(null, requestMapConfig, datasource);
|
|
|
|
}
|
|
|
|
);
|
2016-01-20 02:31:43 +08:00
|
|
|
},
|
2015-07-10 07:30:38 +08:00
|
|
|
function createLayergroup(err, requestMapConfig, datasource) {
|
2015-07-05 02:41:22 +08:00
|
|
|
assert.ifError(err);
|
2015-07-10 17:24:32 +08:00
|
|
|
mapConfig = new MapConfig(requestMapConfig, datasource || Datasource.EmptyDatasource());
|
2015-07-11 01:10:55 +08:00
|
|
|
self.mapBackend.createLayergroup(
|
|
|
|
mapConfig, req.params,
|
|
|
|
new CreateLayergroupMapConfigProvider(mapConfig, req.context.user, self.userLimitsApi, req.params),
|
|
|
|
this
|
|
|
|
);
|
2015-07-10 17:24:32 +08:00
|
|
|
},
|
|
|
|
function afterLayergroupCreate(err, layergroup) {
|
|
|
|
assert.ifError(err);
|
2016-04-07 23:58:12 +08:00
|
|
|
self.afterLayergroupCreate(req, res, mapConfig, analysesResults, layergroup, this);
|
2015-07-05 02:41:22 +08:00
|
|
|
},
|
2015-07-10 07:30:38 +08:00
|
|
|
function finish(err, layergroup) {
|
2015-07-05 02:41:22 +08:00
|
|
|
if (err) {
|
2015-09-17 03:54:56 +08:00
|
|
|
self.sendError(req, res, err, 'ANONYMOUS LAYERGROUP');
|
2015-07-05 02:41:22 +08:00
|
|
|
} else {
|
2016-02-22 22:06:39 +08:00
|
|
|
addWidgetsUrl(req.context.user, layergroup);
|
|
|
|
|
2015-09-17 08:05:25 +08:00
|
|
|
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
|
|
|
self.send(req, res, layergroup, 200);
|
2015-07-05 02:41:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn) {
|
|
|
|
var self = this;
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var cdbuser = req.context.user;
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var mapConfigProvider;
|
|
|
|
var mapConfig;
|
2015-07-05 02:41:22 +08:00
|
|
|
|
|
|
|
step(
|
2015-07-13 22:15:34 +08:00
|
|
|
function setupParams(){
|
2015-09-16 22:18:26 +08:00
|
|
|
self.req2params(req, this);
|
2015-07-13 22:15:34 +08:00
|
|
|
},
|
2015-07-10 17:24:32 +08:00
|
|
|
function getTemplateParams() {
|
|
|
|
prepareParamsFn(this);
|
2015-07-05 02:41:22 +08:00
|
|
|
},
|
2015-07-10 17:24:32 +08:00
|
|
|
function getTemplate(err, templateParams) {
|
|
|
|
assert.ifError(err);
|
|
|
|
mapConfigProvider = new NamedMapMapConfigProvider(
|
|
|
|
self.templateMaps,
|
|
|
|
self.pgConnection,
|
2016-04-07 22:18:48 +08:00
|
|
|
self.metadataBackend,
|
2015-07-11 01:10:55 +08:00
|
|
|
self.userLimitsApi,
|
2015-09-24 00:44:11 +08:00
|
|
|
self.namedLayersAdapter,
|
2016-04-01 00:33:41 +08:00
|
|
|
self.overviewsAdapter,
|
2016-04-26 21:59:41 +08:00
|
|
|
self.turboCartoAdapter,
|
2016-04-07 22:18:48 +08:00
|
|
|
self.analysisMapConfigAdapter,
|
2015-07-10 17:24:32 +08:00
|
|
|
cdbuser,
|
|
|
|
req.params.template_id,
|
|
|
|
templateParams,
|
|
|
|
req.query.auth_token,
|
|
|
|
req.params
|
|
|
|
);
|
|
|
|
mapConfigProvider.getMapConfig(this);
|
2015-07-05 02:41:22 +08:00
|
|
|
},
|
2016-01-21 01:36:06 +08:00
|
|
|
function createLayergroup(err, mapConfig_, rendererParams) {
|
2015-07-10 17:24:32 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
mapConfig = mapConfig_;
|
2015-07-11 01:10:55 +08:00
|
|
|
self.mapBackend.createLayergroup(
|
|
|
|
mapConfig, rendererParams,
|
|
|
|
new CreateLayergroupMapConfigProvider(mapConfig, cdbuser, self.userLimitsApi, rendererParams),
|
|
|
|
this
|
|
|
|
);
|
2015-07-05 02:41:22 +08:00
|
|
|
},
|
2015-07-10 17:24:32 +08:00
|
|
|
function afterLayergroupCreate(err, layergroup) {
|
|
|
|
assert.ifError(err);
|
2016-04-18 20:48:14 +08:00
|
|
|
self.afterLayergroupCreate(req, res, mapConfig, [], layergroup, this);
|
2015-07-10 17:24:32 +08:00
|
|
|
},
|
|
|
|
function finishTemplateInstantiation(err, layergroup) {
|
|
|
|
if (err) {
|
2015-09-17 03:54:56 +08:00
|
|
|
self.sendError(req, res, err, 'NAMED MAP LAYERGROUP');
|
2015-07-10 17:24:32 +08:00
|
|
|
} else {
|
|
|
|
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
|
|
|
|
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
|
|
|
|
|
2016-04-21 23:03:41 +08:00
|
|
|
addWidgetsUrl(cdbuser, layergroup);
|
|
|
|
addDataviewsUrls(cdbuser, layergroup, mapConfig.obj());
|
|
|
|
addAnalysesMetadata(cdbuser, layergroup, mapConfigProvider.analysesResults);
|
2016-02-22 22:06:39 +08:00
|
|
|
|
2015-09-17 08:03:09 +08:00
|
|
|
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
2015-07-10 17:24:32 +08:00
|
|
|
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName()));
|
|
|
|
|
2015-09-17 08:05:25 +08:00
|
|
|
self.send(req, res, layergroup, 200);
|
2015-07-05 02:41:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-04-07 23:58:12 +08:00
|
|
|
MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, analysesResults, layergroup, callback) {
|
2015-07-10 17:24:32 +08:00
|
|
|
var self = this;
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var username = req.context.user;
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var tasksleft = 2; // redis key and affectedTables
|
|
|
|
var errors = [];
|
2015-07-05 02:41:22 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var done = function(err) {
|
|
|
|
if ( err ) {
|
|
|
|
errors.push('' + err);
|
|
|
|
}
|
|
|
|
if ( ! --tasksleft ) {
|
|
|
|
err = errors.length ? new Error(errors.join('\n')) : null;
|
|
|
|
callback(err, layergroup);
|
|
|
|
}
|
|
|
|
};
|
2015-07-09 02:51:36 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
// include in layergroup response the variables in serverMedata
|
|
|
|
// those variables are useful to send to the client information
|
|
|
|
// about how to reach this server or information about it
|
|
|
|
_.extend(layergroup, global.environment.serverMetadata);
|
|
|
|
|
|
|
|
// Don't wait for the mapview count increment to
|
|
|
|
// take place before proceeding. Error will be logged
|
|
|
|
// asynchronously
|
|
|
|
this.metadataBackend.incMapviewCount(username, mapconfig.obj().stat_tag, function(err) {
|
|
|
|
if (req.profiler) {
|
|
|
|
req.profiler.done('incMapviewCount');
|
|
|
|
}
|
|
|
|
if ( err ) {
|
2015-09-18 23:12:53 +08:00
|
|
|
global.logger.log("ERROR: failed to increment mapview count for user '" + username + "': " + err);
|
2015-07-10 17:24:32 +08:00
|
|
|
}
|
|
|
|
done();
|
2015-07-09 02:51:36 +08:00
|
|
|
});
|
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var sql = mapconfig.getLayers().map(function(layer) {
|
|
|
|
return layer.options.sql;
|
|
|
|
}).join(';');
|
2015-07-09 02:51:36 +08:00
|
|
|
|
2015-07-10 17:24:32 +08:00
|
|
|
var dbName = req.params.dbname;
|
2015-07-14 19:40:41 +08:00
|
|
|
var layergroupId = layergroup.layergroupid;
|
2015-07-09 02:51:36 +08:00
|
|
|
|
|
|
|
step(
|
2016-03-04 02:01:58 +08:00
|
|
|
function getPgConnection() {
|
|
|
|
self.pgConnection.getConnection(username, this);
|
2015-07-14 19:40:41 +08:00
|
|
|
},
|
2016-03-04 02:01:58 +08:00
|
|
|
function getAffectedTablesAndLastUpdatedTime(err, connection) {
|
2015-07-14 19:40:41 +08:00
|
|
|
assert.ifError(err);
|
2016-03-04 02:01:58 +08:00
|
|
|
QueryTables.getAffectedTablesFromQuery(connection, sql, this);
|
2015-07-09 02:51:36 +08:00
|
|
|
},
|
2015-07-10 17:24:32 +08:00
|
|
|
function handleAffectedTablesAndLastUpdatedTime(err, result) {
|
|
|
|
if (req.profiler) {
|
|
|
|
req.profiler.done('queryTablesAndLastUpdated');
|
2015-07-09 02:51:36 +08:00
|
|
|
}
|
2015-07-10 17:24:32 +08:00
|
|
|
assert.ifError(err);
|
2016-03-04 02:01:21 +08:00
|
|
|
// feed affected tables cache so it can be reused from, for instance, layergroup controller
|
2016-02-22 18:40:25 +08:00
|
|
|
self.layergroupAffectedTables.set(dbName, layergroupId, result);
|
2015-07-10 17:24:32 +08:00
|
|
|
|
|
|
|
// last update for layergroup cache buster
|
2016-02-22 18:40:25 +08:00
|
|
|
layergroup.layergroupid = layergroup.layergroupid + ':' + result.getLastUpdatedAt();
|
|
|
|
layergroup.last_updated = new Date(result.getLastUpdatedAt()).toISOString();
|
2015-07-10 17:24:32 +08:00
|
|
|
|
2016-01-16 00:02:09 +08:00
|
|
|
// TODO this should take into account several URL patterns
|
2015-10-26 21:35:51 +08:00
|
|
|
addWidgetsUrl(username, layergroup);
|
2016-03-19 01:09:17 +08:00
|
|
|
addDataviewsUrls(username, layergroup, mapconfig.obj());
|
2016-04-21 23:03:41 +08:00
|
|
|
addAnalysesMetadata(username, layergroup, analysesResults, true);
|
2015-07-13 22:15:34 +08:00
|
|
|
if (req.method === 'GET') {
|
|
|
|
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
2015-09-17 08:03:09 +08:00
|
|
|
res.set('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
|
|
|
res.set('Last-Modified', (new Date()).toUTCString());
|
2016-02-22 18:40:25 +08:00
|
|
|
res.set('X-Cache-Channel', result.getCacheChannel());
|
|
|
|
if (result.tables && result.tables.length > 0) {
|
|
|
|
self.surrogateKeysCache.tag(res, result);
|
2015-07-09 02:51:36 +08:00
|
|
|
}
|
|
|
|
}
|
2015-07-10 17:24:32 +08:00
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
done(err);
|
2015-07-09 02:51:36 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
2015-10-26 21:35:51 +08:00
|
|
|
|
2016-04-21 23:03:41 +08:00
|
|
|
function addAnalysesMetadata(username, layergroup, analysesResults, includeQuery) {
|
|
|
|
includeQuery = includeQuery || false;
|
2016-04-07 23:58:12 +08:00
|
|
|
analysesResults = analysesResults || [];
|
2016-04-21 23:03:41 +08:00
|
|
|
layergroup.metadata.analyses = [];
|
2016-04-07 23:58:12 +08:00
|
|
|
|
2016-04-14 17:08:39 +08:00
|
|
|
analysesResults.forEach(function(analysis) {
|
2016-04-14 00:02:28 +08:00
|
|
|
var nodes = analysis.getSortedNodes();
|
2016-04-07 23:58:12 +08:00
|
|
|
layergroup.metadata.analyses.push({
|
|
|
|
nodes: nodes.reduce(function(nodesIdMap, node) {
|
|
|
|
if (node.params.id) {
|
2016-04-14 17:08:39 +08:00
|
|
|
var nodeResource = layergroup.layergroupid + '/analysis/node/' + node.id();
|
2016-04-07 23:58:12 +08:00
|
|
|
nodesIdMap[node.params.id] = {
|
2016-04-12 00:49:43 +08:00
|
|
|
status: node.getStatus(),
|
2016-04-07 23:58:12 +08:00
|
|
|
url: getUrls(username, nodeResource)
|
|
|
|
};
|
2016-04-21 23:03:41 +08:00
|
|
|
if (includeQuery) {
|
|
|
|
nodesIdMap[node.params.id].query = node.getQuery();
|
|
|
|
}
|
2016-04-07 23:58:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return nodesIdMap;
|
|
|
|
}, {})
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-03-19 01:09:17 +08:00
|
|
|
function addDataviewsUrls(username, layergroup, mapConfig) {
|
|
|
|
layergroup.metadata.dataviews = layergroup.metadata.dataviews || {};
|
|
|
|
var dataviews = mapConfig.dataviews || {};
|
|
|
|
|
|
|
|
Object.keys(dataviews).forEach(function(dataviewName) {
|
|
|
|
var resource = layergroup.layergroupid + '/dataview/' + dataviewName;
|
|
|
|
layergroup.metadata.dataviews[dataviewName] = {
|
|
|
|
url: getUrls(username, resource)
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-10-26 21:35:51 +08:00
|
|
|
function addWidgetsUrl(username, layergroup) {
|
|
|
|
|
|
|
|
if (layergroup.metadata && Array.isArray(layergroup.metadata.layers)) {
|
|
|
|
layergroup.metadata.layers = layergroup.metadata.layers.map(function(layer, layerIndex) {
|
|
|
|
if (layer.widgets) {
|
|
|
|
Object.keys(layer.widgets).forEach(function(widgetName) {
|
|
|
|
var resource = layergroup.layergroupid + '/' + layerIndex + '/widget/' + widgetName;
|
|
|
|
layer.widgets[widgetName].url = getUrls(username, resource);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return layer;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function getUrls(username, resource) {
|
|
|
|
var cdnUrl = global.environment.serverMetadata && global.environment.serverMetadata.cdn_url;
|
|
|
|
if (cdnUrl) {
|
|
|
|
return {
|
2015-10-27 00:50:50 +08:00
|
|
|
http: 'http://' + cdnUrl.http + '/' + username + '/api/v1/map/' + resource,
|
|
|
|
https: 'https://' + cdnUrl.https + '/' + username + '/api/v1/map/' + resource
|
2015-10-26 21:35:51 +08:00
|
|
|
};
|
|
|
|
} else {
|
|
|
|
var port = global.environment.port;
|
|
|
|
return {
|
2015-10-27 00:50:50 +08:00
|
|
|
http: 'http://' + username + '.' + 'localhost.lan:' + port + '/api/v1/map/' + resource
|
2015-10-26 21:35:51 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|