Adds named maps mapconfig provider

starts using it in named map instantiation
This commit is contained in:
Raul Ochoa
2015-07-09 14:39:25 +02:00
parent ae2a72a810
commit 23d1109910
3 changed files with 178 additions and 62 deletions
+23 -62
View File
@@ -6,11 +6,14 @@ var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
var cors = require('../middleware/cors');
var MapStoreMapConfigProvider = require('windshaft').model.provider.MapStoreMapConfig;
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
function NamedMapsController(app, mapStore, templateMaps, metadataBackend, mapBackend, tileBackend, previewBackend,
templateBaseUrl, surrogateKeysCache, layergroupRequestDecorator, tablesExtentApi) {
function NamedMapsController(app, pgConnection, mapStore, templateMaps, metadataBackend, mapBackend, tileBackend,
previewBackend, templateBaseUrl, surrogateKeysCache, layergroupRequestDecorator,
tablesExtentApi) {
this.app = app;
this.mapStore = mapStore;
this.pgConnection = pgConnection;
this.templateMaps = templateMaps;
this.metadataBackend = metadataBackend;
this.mapBackend = mapBackend;
@@ -398,76 +401,34 @@ NamedMapsController.prototype.instantiateTemplate = function(req, res, template_
}
};
var template;
var layergroup;
var cdbuser = req.context.user;
var params = {
user: req.params.user
};
// Format of template_id: [<template_owner>]@<template_id>
var tpl_id = templateName(req.params.template_id);
var auth_token = req.query.auth_token;
var mapConfigProvider = new NamedMapMapConfigProvider(
this.templateMaps,
this.pgConnection,
cdbuser,
req.params.template_id,
template_params,
req.query.auth_token,
req.params
);
step(
function getTemplate(){
self.templateMaps.getTemplate(cdbuser, tpl_id, this);
mapConfigProvider.getMapConfig(this);
},
function checkAuthorized(err, templateValue) {
if ( req.profiler ) req.profiler.done('getTemplate');
if ( err ) throw err;
if ( ! templateValue ) {
err = new Error("Template '" + tpl_id + "' of user '" + cdbuser + "' not found");
err.http_status = 404;
throw err;
}
template = templateValue;
var authorized = false;
try {
authorized = self.templateMaps.isAuthorized(template, auth_token);
} catch (err) {
// we catch to add http_status
err.http_status = 403;
throw err;
}
if ( ! authorized ) {
err = new Error('Unauthorized template instantiation');
err.http_status = 403;
throw err;
}
if (req.profiler) {
req.profiler.done('authorizedByCert');
}
return self.templateMaps.instance(template, template_params);
},
function prepareParams(err, instance){
if ( req.profiler ) req.profiler.done('TemplateMaps_instance');
if ( err ) throw err;
layergroup = instance;
self.app.setDBParams(cdbuser, params, this);
},
function setApiKey(err){
if ( req.profiler ) req.profiler.done('setDBParams');
if ( err ) throw err;
self.metadataBackend.getUserMapKey(cdbuser, this);
},
function createLayergroup(err, val) {
if ( req.profiler ) req.profiler.done('getUserMapKey');
if ( err ) throw err;
params.api_key = val;
self.mapBackend.createLayergroup(layergroup, params, layergroupDecorator, this);
function createLayergroup(err, mapConfig, rendererParams/*, context*/) {
assert.ifError(err);
self.mapBackend.createLayergroup(mapConfig, rendererParams, layergroupDecorator, this);
},
function prepareResponse(err, layergroup) {
if ( err ) {
if (err) {
return callback(err, { errors: [''+err] });
}
var tplhash = self.templateMaps.fingerPrint(template).substring(0,8);
layergroup.layergroupid = cdbuser + '@' + tplhash + '@' + layergroup.layergroupid;
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0,8);
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
res.header('X-Layergroup-Id', layergroup.layergroupid);
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, template.name));
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.template.name));
callback(null, layergroup);
}
@@ -0,0 +1,154 @@
var _ = require('underscore');
var assert = require('assert');
var step = require('step');
var templateName = require('../../backends/template_maps').templateName;
function NamedMapMapConfigProvider(templateMaps, pgConnection, owner, templateId, config, authToken, params) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.owner = owner;
this.templateId = templateId;
this.config = config;
this.authToken = authToken;
this.params = params;
// use template after call to mapConfig
this.template = null;
// providing
this.err = null;
this.mapConfig = null;
this.rendererParams = null;
this.context = null;
}
module.exports = NamedMapMapConfigProvider;
NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
if (this.err !== null || this.mapConfig !== null) {
return callback(this.err, this.mapConfig, this.rendererParams, this.context);
}
var self = this;
var mapConfig;
var rendererParams;
var context = {};
step(
function getTemplate(err) {
assert.ifError(err);
self.templateMaps.getTemplate(self.owner, templateName(self.templateId), this);
},
function checkExists(err, tpl) {
assert.ifError(err);
if (!tpl) {
var notFoundErr = new Error(
"Template '" + templateName(self.templateId) + "' of user '" + self.owner + "' not found"
);
notFoundErr.http_status = 404;
throw notFoundErr;
}
return tpl;
},
function checkAuthorized(err, tpl) {
assert.ifError(err);
var authorized = false;
try {
authorized = self.templateMaps.isAuthorized(tpl, self.authToken);
} catch (err) {
// we catch to add http_status
var authorizationFailedErr = new Error('Failed to authorize template');
authorizationFailedErr.http_status = 403;
throw authorizationFailedErr;
}
if ( ! authorized ) {
var unauthorizedErr = new Error('Unauthorized template instantiation');
unauthorizedErr.http_status = 403;
throw unauthorizedErr;
}
return tpl;
},
function prepareParams(err, tpl) {
assert.ifError(err);
self.template = tpl;
var templateParams = {};
if (self.config) {
try {
templateParams = _.isString(self.config) ? JSON.parse(self.config) : self.config;
} catch (e) {
throw new Error('malformed config parameter, should be a valid JSON');
}
}
return templateParams;
},
function instantiateTemplate(err, templateParams) {
assert.ifError(err);
return self.templateMaps.instance(self.template, templateParams);
},
function prepareLayergroup(err, layergroup) {
assert.ifError(err);
mapConfig = layergroup;
rendererParams = _.extend({}, self.params, {
user: self.owner
});
self.setDBParams(self.owner, rendererParams, this);
},
function cacheAndReturnMapConfig(err) {
self.err = err;
self.mapConfig = mapConfig;
self.rendererParams = rendererParams;
self.context = context;
return callback(self.err, self.mapConfig, self.rendererParams, self.context);
}
);
};
NamedMapMapConfigProvider.prototype.getKey = function() {
return createKey(this.params);
};
NamedMapMapConfigProvider.prototype.getCacheBuster = function() {
return 0;
};
NamedMapMapConfigProvider.prototype.filter = function(key) {
var regex = new RegExp('^' + createKey(this.params, true) + '.*');
return key && key.match(regex);
};
// Configure bases for cache keys suitable for string interpolation
var baseKey = '<%= dbname %>:<%= owner %>:<%= templateName %>';
var renderKey = baseKey + ':<%= authToken %>:<%= configHash %>:<%= layer %>:<%= scale_factor %>';
// Create a string ID/key from a set of params
function createKey(params, base) {
return _.template(base ? baseKey : renderKey, _.defaults({}, params, {
dbname: '',
owner: '',
templateName: '',
authToken: '',
configHash: '',
scale_factor: 1
}));
}
NamedMapMapConfigProvider.prototype.setDBParams = function(cdbuser, params, callback) {
var self = this;
step(
function setAuth() {
self.pgConnection.setDBAuth(cdbuser, params, this);
},
function setConn(err) {
if ( err ) throw err;
self.pgConnection.setDBConn(cdbuser, params, this);
},
function finish(err) {
callback(err);
}
);
};
+1
View File
@@ -321,6 +321,7 @@ module.exports = function(serverOptions) {
new controller.NamedMaps(
app,
pgConnection,
mapStore,
templateMaps,
metadataBackend,