Merge branch 'middlewarify' into stats-middleware
This commit is contained in:
commit
a81e98995a
@ -19,22 +19,22 @@ function AuthApi(pgConnection, metadataBackend, mapStore, templateMaps) {
|
||||
|
||||
module.exports = AuthApi;
|
||||
|
||||
// Check if a request is authorized by a signer
|
||||
// Check if the user is authorized by a signer
|
||||
//
|
||||
// @param req express request object
|
||||
// @param res express response object
|
||||
// @param callback function(err, signed_by) signed_by will be
|
||||
// null if the request is not signed by anyone
|
||||
// or will be a string cartodb username otherwise.
|
||||
//
|
||||
AuthApi.prototype.authorizedBySigner = function(req, callback) {
|
||||
if ( ! req.params.token || ! req.params.signer ) {
|
||||
AuthApi.prototype.authorizedBySigner = function(res, callback) {
|
||||
if ( ! res.locals.token || ! res.locals.signer ) {
|
||||
return callback(null, false); // no signer requested
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
var layergroup_id = req.params.token;
|
||||
var auth_token = req.params.auth_token;
|
||||
var layergroup_id = res.locals.token;
|
||||
var auth_token = res.locals.auth_token;
|
||||
|
||||
this.mapStore.load(layergroup_id, function(err, mapConfig) {
|
||||
if (err) {
|
||||
@ -84,11 +84,12 @@ AuthApi.prototype.authorizedByAPIKey = function(user, req, callback) {
|
||||
* Check access authorization
|
||||
*
|
||||
* @param req - standard req object. Importantly contains table and host information
|
||||
* @param res - standard res object. Contains the auth parameters in locals
|
||||
* @param callback function(err, allowed) is access allowed not?
|
||||
*/
|
||||
AuthApi.prototype.authorize = function(req, callback) {
|
||||
AuthApi.prototype.authorize = function(req, res, callback) {
|
||||
var self = this;
|
||||
var user = req.context.user;
|
||||
var user = res.locals.user;
|
||||
|
||||
step(
|
||||
function () {
|
||||
@ -101,11 +102,11 @@ AuthApi.prototype.authorize = function(req, callback) {
|
||||
// if not authorized by api_key, continue
|
||||
if (!authorized) {
|
||||
// not authorized by api_key, check if authorized by signer
|
||||
return self.authorizedBySigner(req, this);
|
||||
return self.authorizedBySigner(res, this);
|
||||
}
|
||||
|
||||
// authorized by api key, login as the given username and stop
|
||||
self.pgConnection.setDBAuth(user, req.params, function(err) {
|
||||
self.pgConnection.setDBAuth(user, res.locals, function(err) {
|
||||
callback(err, true); // authorized (or error)
|
||||
});
|
||||
},
|
||||
@ -120,7 +121,7 @@ AuthApi.prototype.authorize = function(req, callback) {
|
||||
// if no signer name was given, let dbparams and
|
||||
// PostgreSQL do the rest.
|
||||
//
|
||||
if ( ! req.params.signer ) {
|
||||
if ( ! res.locals.signer ) {
|
||||
return callback(null, true); // authorized so far
|
||||
}
|
||||
|
||||
@ -128,7 +129,7 @@ AuthApi.prototype.authorize = function(req, callback) {
|
||||
return callback(null, false);
|
||||
}
|
||||
|
||||
self.pgConnection.setDBAuth(user, req.params, function(err) {
|
||||
self.pgConnection.setDBAuth(user, res.locals, function(err) {
|
||||
req.profiler.done('setDBAuth');
|
||||
callback(err, true); // authorized (or error)
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ module.exports = DataviewBackend;
|
||||
|
||||
DataviewBackend.prototype.getDataview = function (mapConfigProvider, user, params, callback) {
|
||||
|
||||
var dataviewName = params.dataviewName;
|
||||
var dataviewName = params.dataviewName;
|
||||
step(
|
||||
function getMapConfig() {
|
||||
mapConfigProvider.getMapConfig(this);
|
||||
@ -113,9 +113,7 @@ function getOverrideParams(params, ownFilter) {
|
||||
return overrideParams;
|
||||
}
|
||||
|
||||
DataviewBackend.prototype.search = function (mapConfigProvider, user, params, callback) {
|
||||
var dataviewName = params.dataviewName;
|
||||
|
||||
DataviewBackend.prototype.search = function (mapConfigProvider, user, dataviewName, params, callback) {
|
||||
step(
|
||||
function getMapConfig() {
|
||||
mapConfigProvider.getMapConfig(this);
|
||||
|
@ -37,11 +37,11 @@ AnalysesController.prototype.sendResponse = function(req, res, resource) {
|
||||
|
||||
AnalysesController.prototype.catalog = function (req, res, next) {
|
||||
var self = this;
|
||||
var username = req.context.user;
|
||||
var username = res.locals.user;
|
||||
|
||||
step(
|
||||
function catalogQuery() {
|
||||
var pg = new PSQL(dbParamsFromReqParams(req.params));
|
||||
var pg = new PSQL(dbParamsFromReqParams(res.locals));
|
||||
getMetadata(username, pg, this);
|
||||
},
|
||||
function prepareResponse(err, results) {
|
||||
|
@ -169,7 +169,7 @@ LayergroupController.prototype.analysisNodeStatus = function(req, res, next) {
|
||||
|
||||
step(
|
||||
function retrieveNodeStatus() {
|
||||
self.analysisStatusBackend.getNodeStatus(req.params, this);
|
||||
self.analysisStatusBackend.getNodeStatus(res.locals, this);
|
||||
},
|
||||
function finish(err, nodeStatus, stats) {
|
||||
req.profiler.add(stats || {});
|
||||
@ -193,9 +193,14 @@ LayergroupController.prototype.dataview = function(req, res, next) {
|
||||
step(
|
||||
function retrieveDataview() {
|
||||
var mapConfigProvider = new MapStoreMapConfigProvider(
|
||||
self.mapStore, req.context.user, self.userLimitsApi, req.params
|
||||
self.mapStore, res.locals.user, self.userLimitsApi, res.locals
|
||||
);
|
||||
self.dataviewBackend.getDataview(
|
||||
mapConfigProvider,
|
||||
res.locals.user,
|
||||
res.locals,
|
||||
this
|
||||
);
|
||||
self.dataviewBackend.getDataview(mapConfigProvider, req.context.user, req.params, this);
|
||||
},
|
||||
function finish(err, dataview, stats) {
|
||||
req.profiler.add(stats || {});
|
||||
@ -216,9 +221,9 @@ LayergroupController.prototype.dataviewSearch = function(req, res, next) {
|
||||
step(
|
||||
function searchDataview() {
|
||||
var mapConfigProvider = new MapStoreMapConfigProvider(
|
||||
self.mapStore, req.context.user, self.userLimitsApi, req.params
|
||||
self.mapStore, res.locals.user, self.userLimitsApi, res.locals
|
||||
);
|
||||
self.dataviewBackend.search(mapConfigProvider, req.context.user, req.params, this);
|
||||
self.dataviewBackend.search(mapConfigProvider, res.locals.user, req.params.dataviewName, res.locals, this);
|
||||
},
|
||||
function finish(err, searchResult, stats) {
|
||||
req.profiler.add(stats || {});
|
||||
@ -242,9 +247,9 @@ LayergroupController.prototype.attributes = function(req, res, next) {
|
||||
step(
|
||||
function retrieveFeatureAttributes() {
|
||||
var mapConfigProvider = new MapStoreMapConfigProvider(
|
||||
self.mapStore, req.context.user, self.userLimitsApi, req.params
|
||||
self.mapStore, res.locals.user, self.userLimitsApi, res.locals
|
||||
);
|
||||
self.attributesBackend.getFeatureAttributes(mapConfigProvider, req.params, false, this);
|
||||
self.attributesBackend.getFeatureAttributes(mapConfigProvider, res.locals, false, this);
|
||||
},
|
||||
function finish(err, tile, stats) {
|
||||
req.profiler.add(stats || {});
|
||||
@ -278,7 +283,7 @@ LayergroupController.prototype.tileOrLayer = function (req, res, next) {
|
||||
step(
|
||||
function mapController$getTileOrGrid() {
|
||||
self.tileBackend.getTile(
|
||||
new MapStoreMapConfigProvider(self.mapStore, req.context.user, self.userLimitsApi, req.params),
|
||||
new MapStoreMapConfigProvider(self.mapStore, res.locals.user, self.userLimitsApi, res.locals),
|
||||
req.params, this
|
||||
);
|
||||
},
|
||||
@ -350,8 +355,8 @@ LayergroupController.prototype.center = function(req, res, next) {
|
||||
|
||||
LayergroupController.prototype.staticMap = function(req, res, width, height, zoom /* bounds */, center, next) {
|
||||
var format = req.params.format === 'jpg' ? 'jpeg' : 'png';
|
||||
req.params.layer = req.params.layer || 'all';
|
||||
req.params.format = req.params.format || 'png';
|
||||
res.locals.layer = res.locals.layer || 'all';
|
||||
|
||||
var self = this;
|
||||
|
||||
@ -359,11 +364,11 @@ LayergroupController.prototype.staticMap = function(req, res, width, height, zoo
|
||||
function getImage() {
|
||||
if (center) {
|
||||
self.previewBackend.getImage(
|
||||
new MapStoreMapConfigProvider(self.mapStore, req.context.user, self.userLimitsApi, req.params),
|
||||
new MapStoreMapConfigProvider(self.mapStore, res.locals.user, self.userLimitsApi, res.locals),
|
||||
format, width, height, zoom, center, this);
|
||||
} else {
|
||||
self.previewBackend.getImage(
|
||||
new MapStoreMapConfigProvider(self.mapStore, req.context.user, self.userLimitsApi, req.params),
|
||||
new MapStoreMapConfigProvider(self.mapStore, res.locals.user, self.userLimitsApi, res.locals),
|
||||
format, width, height, zoom /* bounds */, this);
|
||||
}
|
||||
},
|
||||
@ -391,18 +396,18 @@ LayergroupController.prototype.sendResponse = function(req, res, body, status, h
|
||||
|
||||
// Set Last-Modified header
|
||||
var lastUpdated;
|
||||
if (req.params.cache_buster) {
|
||||
if (res.locals.cache_buster) {
|
||||
// Assuming cache_buster is a timestamp
|
||||
lastUpdated = new Date(parseInt(req.params.cache_buster));
|
||||
lastUpdated = new Date(parseInt(res.locals.cache_buster));
|
||||
} else {
|
||||
lastUpdated = new Date();
|
||||
}
|
||||
res.set('Last-Modified', lastUpdated.toUTCString());
|
||||
|
||||
var dbName = req.params.dbname;
|
||||
var dbName = res.locals.dbname;
|
||||
step(
|
||||
function getAffectedTables() {
|
||||
self.getAffectedTables(req.context.user, dbName, req.params.token, this);
|
||||
self.getAffectedTables(res.locals.user, dbName, res.locals.token, this);
|
||||
},
|
||||
function sendResponse(err, affectedTables) {
|
||||
req.profiler.done('affectedTables');
|
||||
|
@ -94,11 +94,11 @@ MapController.prototype.register = function(app) {
|
||||
MapController.prototype.createGet = function(req, res, next){
|
||||
req.profiler.start('windshaft.createmap_get');
|
||||
|
||||
this.create(req, res, function createGet$prepareConfig(req) {
|
||||
if ( ! req.params.config ) {
|
||||
this.create(req, res, function createGet$prepareConfig(req, config) {
|
||||
if ( ! config ) {
|
||||
throw new Error('layergroup GET needs a "config" parameter');
|
||||
}
|
||||
return JSON.parse(req.params.config);
|
||||
return JSON.parse(config);
|
||||
}, next);
|
||||
};
|
||||
|
||||
@ -155,34 +155,35 @@ MapController.prototype.create = function(req, res, prepareConfigFn, next) {
|
||||
|
||||
step(
|
||||
function prepareConfig () {
|
||||
const requestMapConfig = prepareConfigFn(req);
|
||||
const requestMapConfig = prepareConfigFn(req, res.locals.config);
|
||||
return requestMapConfig;
|
||||
},
|
||||
function prepareAdapterMapConfig(err, requestMapConfig) {
|
||||
assert.ifError(err);
|
||||
context.analysisConfiguration = {
|
||||
user: req.context.user,
|
||||
user: res.locals.user,
|
||||
db: {
|
||||
host: req.params.dbhost,
|
||||
port: req.params.dbport,
|
||||
dbname: req.params.dbname,
|
||||
user: req.params.dbuser,
|
||||
pass: req.params.dbpassword
|
||||
host: res.locals.dbhost,
|
||||
port: res.locals.dbport,
|
||||
dbname: res.locals.dbname,
|
||||
user: res.locals.dbuser,
|
||||
pass: res.locals.dbpassword
|
||||
},
|
||||
batch: {
|
||||
username: req.context.user,
|
||||
apiKey: req.params.api_key
|
||||
username: res.locals.user,
|
||||
apiKey: res.locals.api_key
|
||||
}
|
||||
};
|
||||
self.mapConfigAdapter.getMapConfig(req.context.user, requestMapConfig, req.params, context, this);
|
||||
self.mapConfigAdapter.getMapConfig(res.locals.user, requestMapConfig, res.locals, context, this);
|
||||
},
|
||||
function createLayergroup(err, requestMapConfig) {
|
||||
assert.ifError(err);
|
||||
var datasource = context.datasource || Datasource.EmptyDatasource();
|
||||
mapConfig = new MapConfig(requestMapConfig, datasource);
|
||||
self.mapBackend.createLayergroup(
|
||||
mapConfig, req.params,
|
||||
new CreateLayergroupMapConfigProvider(mapConfig, req.context.user, self.userLimitsApi, req.params),
|
||||
mapConfig,
|
||||
res.locals,
|
||||
new CreateLayergroupMapConfigProvider(mapConfig, res.locals.user, self.userLimitsApi, res.locals),
|
||||
this
|
||||
);
|
||||
},
|
||||
@ -214,8 +215,8 @@ MapController.prototype.create = function(req, res, prepareConfigFn, next) {
|
||||
next(err);
|
||||
} else {
|
||||
var analysesResults = context.analysesResults || [];
|
||||
self.addDataviewsAndWidgetsUrls(req.context.user, layergroup, mapConfig.obj());
|
||||
self.addAnalysesMetadata(req.context.user, layergroup, analysesResults, true);
|
||||
self.addDataviewsAndWidgetsUrls(res.locals.user, layergroup, mapConfig.obj());
|
||||
self.addAnalysesMetadata(res.locals.user, layergroup, analysesResults, true);
|
||||
addContextMetadata(layergroup, mapConfig.obj(), context);
|
||||
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
||||
self.send(req, res, layergroup, 200);
|
||||
@ -238,7 +239,7 @@ function addContextMetadata(layergroup, mapConfig, context) {
|
||||
MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn, next) {
|
||||
var self = this;
|
||||
|
||||
var cdbuser = req.context.user;
|
||||
var cdbuser = res.locals.user;
|
||||
|
||||
var mapConfigProvider;
|
||||
var mapConfig;
|
||||
@ -257,8 +258,8 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
cdbuser,
|
||||
req.params.template_id,
|
||||
templateParams,
|
||||
req.query.auth_token,
|
||||
req.params
|
||||
res.locals.auth_token,
|
||||
res.locals
|
||||
);
|
||||
mapConfigProvider.getMapConfig(this);
|
||||
},
|
||||
@ -303,7 +304,7 @@ MapController.prototype.afterLayergroupCreate =
|
||||
function(req, res, mapconfig, layergroup, analysesResults, callback) {
|
||||
var self = this;
|
||||
|
||||
var username = req.context.user;
|
||||
var username = res.locals.user;
|
||||
|
||||
var tasksleft = 2; // redis key and affectedTables
|
||||
var errors = [];
|
||||
@ -344,7 +345,7 @@ function(req, res, mapconfig, layergroup, analysesResults, callback) {
|
||||
}
|
||||
});
|
||||
|
||||
var dbName = req.params.dbname;
|
||||
var dbName = res.locals.dbname;
|
||||
var layergroupId = layergroup.layergroupid;
|
||||
var dbConnection;
|
||||
|
||||
|
@ -47,7 +47,7 @@ NamedMapsController.prototype.register = function(app) {
|
||||
};
|
||||
|
||||
NamedMapsController.prototype.sendResponse = function(req, res, resource, headers, namedMapProvider) {
|
||||
this.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(req.context.user, namedMapProvider.getTemplateName()));
|
||||
this.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(res.locals.user, namedMapProvider.getTemplateName()));
|
||||
res.set('Content-Type', headers['content-type'] || headers['Content-Type'] || 'image/png');
|
||||
res.set('Cache-Control', 'public,max-age=7200,must-revalidate');
|
||||
|
||||
@ -87,7 +87,7 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header
|
||||
NamedMapsController.prototype.tile = function(req, res, next) {
|
||||
var self = this;
|
||||
|
||||
var cdbUser = req.context.user;
|
||||
var cdbUser = res.locals.user;
|
||||
|
||||
var namedMapProvider;
|
||||
step(
|
||||
@ -97,7 +97,7 @@ NamedMapsController.prototype.tile = function(req, res, next) {
|
||||
req.params.template_id,
|
||||
req.query.config,
|
||||
req.query.auth_token,
|
||||
req.params,
|
||||
res.locals,
|
||||
this
|
||||
);
|
||||
},
|
||||
@ -121,11 +121,11 @@ NamedMapsController.prototype.tile = function(req, res, next) {
|
||||
NamedMapsController.prototype.staticMap = function(req, res, next) {
|
||||
var self = this;
|
||||
|
||||
var cdbUser = req.context.user;
|
||||
var cdbUser = res.locals.user;
|
||||
|
||||
var format = req.params.format === 'jpg' ? 'jpeg' : 'png';
|
||||
req.params.format = req.params.format || 'png';
|
||||
req.params.layer = req.params.layer || 'all';
|
||||
res.locals.format = req.params.format || 'png';
|
||||
res.locals.layer = res.locals.layer || 'all';
|
||||
|
||||
var namedMapProvider;
|
||||
step(
|
||||
@ -135,7 +135,7 @@ NamedMapsController.prototype.staticMap = function(req, res, next) {
|
||||
req.params.template_id,
|
||||
req.query.config,
|
||||
req.query.auth_token,
|
||||
req.params,
|
||||
res.locals,
|
||||
this
|
||||
);
|
||||
},
|
||||
@ -143,12 +143,12 @@ NamedMapsController.prototype.staticMap = function(req, res, next) {
|
||||
assert.ifError(err);
|
||||
|
||||
namedMapProvider = _namedMapProvider;
|
||||
|
||||
self.prepareLayerFilterFromPreviewLayers(cdbUser, req, namedMapProvider, this);
|
||||
|
||||
self.prepareLayerFilterFromPreviewLayers(cdbUser, req, res.locals, namedMapProvider, this);
|
||||
},
|
||||
function prepareImageOptions(err) {
|
||||
assert.ifError(err);
|
||||
self.getStaticImageOptions(cdbUser, req.params, namedMapProvider, this);
|
||||
self.getStaticImageOptions(cdbUser, res.locals, namedMapProvider, this);
|
||||
},
|
||||
function getImage(err, imageOpts) {
|
||||
assert.ifError(err);
|
||||
@ -191,7 +191,13 @@ NamedMapsController.prototype.staticMap = function(req, res, next) {
|
||||
);
|
||||
};
|
||||
|
||||
NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function (user, req, namedMapProvider, callback) {
|
||||
NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function (
|
||||
user,
|
||||
req,
|
||||
params,
|
||||
namedMapProvider,
|
||||
callback
|
||||
) {
|
||||
var self = this;
|
||||
namedMapProvider.getTemplate(function (err, template) {
|
||||
if (err) {
|
||||
@ -216,7 +222,7 @@ NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function (us
|
||||
}
|
||||
|
||||
// overwrites 'all' default filter
|
||||
req.params.layer = layerVisibilityFilter.join(',');
|
||||
params.layer = layerVisibilityFilter.join(',');
|
||||
|
||||
// recreates the provider
|
||||
self.namedMapProviderCache.get(
|
||||
@ -224,7 +230,7 @@ NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function (us
|
||||
req.params.template_id,
|
||||
req.query.config,
|
||||
req.query.auth_token,
|
||||
req.params,
|
||||
params,
|
||||
callback
|
||||
);
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
NamedMapsAdminController.prototype.create = function(req, res, next) {
|
||||
var self = this;
|
||||
|
||||
var cdbuser = req.context.user;
|
||||
var cdbuser = res.locals.user;
|
||||
|
||||
step(
|
||||
function checkPerms(){
|
||||
@ -95,7 +95,7 @@ NamedMapsAdminController.prototype.create = function(req, res, next) {
|
||||
NamedMapsAdminController.prototype.update = function(req, res, next) {
|
||||
var self = this;
|
||||
|
||||
var cdbuser = req.context.user;
|
||||
var cdbuser = res.locals.user;
|
||||
var template;
|
||||
var tpl_id;
|
||||
|
||||
@ -126,7 +126,7 @@ NamedMapsAdminController.prototype.retrieve = function(req, res, next) {
|
||||
|
||||
req.profiler.start('windshaft-cartodb.get_template');
|
||||
|
||||
var cdbuser = req.context.user;
|
||||
var cdbuser = res.locals.user;
|
||||
var tpl_id;
|
||||
step(
|
||||
function checkPerms(){
|
||||
@ -160,7 +160,7 @@ NamedMapsAdminController.prototype.destroy = function(req, res, next) {
|
||||
|
||||
req.profiler.start('windshaft-cartodb.delete_template');
|
||||
|
||||
var cdbuser = req.context.user;
|
||||
var cdbuser = res.locals.user;
|
||||
var tpl_id;
|
||||
step(
|
||||
function checkPerms(){
|
||||
@ -185,7 +185,7 @@ NamedMapsAdminController.prototype.list = function(req, res, next) {
|
||||
var self = this;
|
||||
req.profiler.start('windshaft-cartodb.get_template_list');
|
||||
|
||||
var cdbuser = req.context.user;
|
||||
var cdbuser = res.locals.user;
|
||||
|
||||
step(
|
||||
function checkPerms(){
|
||||
|
@ -3,7 +3,7 @@ module.exports = function allowQueryParams(params) {
|
||||
throw new Error('allowQueryParams must receive an Array of params');
|
||||
}
|
||||
return function allowQueryParamsMiddleware(req, res, next) {
|
||||
req.context.allowedQueryParams = params;
|
||||
res.locals.allowedQueryParams = params;
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
@ -1,15 +1,8 @@
|
||||
const _ = require('underscore');
|
||||
|
||||
module.exports = function authorizeMiddleware (authApi) {
|
||||
return function (req, res, next) {
|
||||
// FIXME: Temporary hack to share data between middlewares. Express overrides req.params to
|
||||
// parse url params to an object and it's performed after matching path and controller.
|
||||
res.locals = {};
|
||||
_.extend(res.locals, req.params);
|
||||
|
||||
req.profiler.done('req2params.setup');
|
||||
|
||||
authApi.authorize(req, (err, authorized) => {
|
||||
authApi.authorize(req, res, (err, authorized) => {
|
||||
req.profiler.done('authorize');
|
||||
if (err) {
|
||||
return next(err);
|
||||
|
@ -18,15 +18,15 @@ module.exports = function cleanUpQueryParamsMiddleware () {
|
||||
return function cleanUpQueryParams (req, res, next) {
|
||||
var allowedQueryParams = REQUEST_QUERY_PARAMS_WHITELIST;
|
||||
|
||||
if (Array.isArray(req.context.allowedQueryParams)) {
|
||||
allowedQueryParams = allowedQueryParams.concat(req.context.allowedQueryParams);
|
||||
if (Array.isArray(res.locals.allowedQueryParams)) {
|
||||
allowedQueryParams = allowedQueryParams.concat(res.locals.allowedQueryParams);
|
||||
}
|
||||
|
||||
req.query = _.pick(req.query, allowedQueryParams);
|
||||
|
||||
// bring all query values onto req.params object
|
||||
_.extend(req.params, req.query);
|
||||
|
||||
// bring all query values onto res.locals object
|
||||
_.extend(res.locals, req.query);
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
@ -2,11 +2,8 @@ const _ = require('underscore');
|
||||
|
||||
module.exports = function dbConnSetupMiddleware(pgConnection) {
|
||||
return function dbConnSetup(req, res, next) {
|
||||
const user = req.context.user;
|
||||
|
||||
// FIXME: this function shouldn't be able to change `req.params`. It should return an
|
||||
// object with the user's conf and it should be merge with default here.
|
||||
pgConnection.setDBConn(user, req.params, (err) => {
|
||||
const user = res.locals.user;
|
||||
pgConnection.setDBConn(user, res.locals, (err) => {
|
||||
if (err) {
|
||||
if (err.message && -1 !== err.message.indexOf('name not found')) {
|
||||
err.http_status = 404;
|
||||
@ -17,24 +14,17 @@ module.exports = function dbConnSetupMiddleware(pgConnection) {
|
||||
|
||||
// Add default database connection parameters
|
||||
// if none given
|
||||
_.defaults(req.params, {
|
||||
_.defaults(res.locals, {
|
||||
dbuser: global.environment.postgres.user,
|
||||
dbpassword: global.environment.postgres.password,
|
||||
dbhost: global.environment.postgres.host,
|
||||
dbport: global.environment.postgres.port
|
||||
});
|
||||
|
||||
res.set('X-Served-By-DB-Host', req.params.dbhost);
|
||||
|
||||
// FIXME: Temporary hack to share data between middlewares. Express overrides req.params to
|
||||
// parse url params to an object and it's performed after matching path and controller.
|
||||
if (!res.locals) {
|
||||
res.locals = {};
|
||||
}
|
||||
_.defaults(res.locals, req.params);
|
||||
|
||||
res.set('X-Served-By-DB-Host', res.locals.dbhost);
|
||||
|
||||
req.profiler.done('req2params');
|
||||
|
||||
|
||||
next(null);
|
||||
});
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
const locals = require('./locals');
|
||||
const cleanUpQueryParams = require('./clean-up-query-params');
|
||||
const layergroupToken = require('./layergroup-token');
|
||||
const authorize = require('./authorize');
|
||||
@ -5,6 +6,7 @@ const dbConnSetup = require('./db-conn-setup');
|
||||
|
||||
module.exports = function prepareContextMiddleware(authApi, pgConnection) {
|
||||
return [
|
||||
locals,
|
||||
cleanUpQueryParams(),
|
||||
layergroupToken,
|
||||
authorize(authApi),
|
||||
|
@ -1,22 +1,22 @@
|
||||
var LayergroupToken = require('../../models/layergroup-token');
|
||||
|
||||
module.exports = function layergroupTokenMiddleware(req, res, next) {
|
||||
if (!req.params.hasOwnProperty('token')) {
|
||||
if (!res.locals.token) {
|
||||
return next();
|
||||
}
|
||||
|
||||
var user = req.context.user;
|
||||
var user = res.locals.user;
|
||||
|
||||
var layergroupToken = LayergroupToken.parse(req.params.token);
|
||||
req.params.token = layergroupToken.token;
|
||||
req.params.cache_buster = layergroupToken.cacheBuster;
|
||||
var layergroupToken = LayergroupToken.parse(res.locals.token);
|
||||
res.locals.token = layergroupToken.token;
|
||||
res.locals.cache_buster = layergroupToken.cacheBuster;
|
||||
|
||||
if (layergroupToken.signer) {
|
||||
req.params.signer = layergroupToken.signer;
|
||||
if (!req.params.signer) {
|
||||
req.params.signer = user;
|
||||
} else if (req.params.signer !== user) {
|
||||
var err = new Error(`Cannot use map signature of user "${req.params.signer}" on db of user "${user}"`);
|
||||
res.locals.signer = layergroupToken.signer;
|
||||
if (!res.locals.signer) {
|
||||
res.locals.signer = user;
|
||||
} else if (res.locals.signer !== user) {
|
||||
var err = new Error(`Cannot use map signature of user "${res.locals.signer}" on db of user "${user}"`);
|
||||
err.type = 'auth';
|
||||
err.http_status = 403;
|
||||
if (req.query && req.query.callback) {
|
||||
|
8
lib/cartodb/middleware/context/locals.js
Normal file
8
lib/cartodb/middleware/context/locals.js
Normal file
@ -0,0 +1,8 @@
|
||||
const _ = require('underscore');
|
||||
|
||||
module.exports = function localsMiddleware(req, res, next) {
|
||||
_.extend(res.locals, req.params);
|
||||
|
||||
next();
|
||||
};
|
||||
|
@ -2,6 +2,13 @@ var CdbRequest = require('../models/cdb_request');
|
||||
var cdbRequest = new CdbRequest();
|
||||
|
||||
module.exports = function userMiddleware(req, res, next) {
|
||||
req.context.user = cdbRequest.userByReq(req);
|
||||
res.locals.user = cdbRequest.userByReq(req);
|
||||
|
||||
// avoid a req.params.user equals to undefined
|
||||
// overwrites res.locals.user
|
||||
if(!req.params.user) {
|
||||
delete req.params.user;
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
@ -362,8 +362,6 @@ function bootstrap(opts) {
|
||||
app.use(bodyParser.json());
|
||||
|
||||
app.use(function bootstrap$prepareRequestResponse(req, res, next) {
|
||||
req.context = req.context || {};
|
||||
|
||||
if (global.environment && global.environment.api_hostname) {
|
||||
res.set('X-Served-By-Host', global.environment.api_hostname);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ module.exports = _.extend({}, serverOptions, {
|
||||
|
||||
_.extend(req.params, req.query);
|
||||
req.params.user = 'localhost';
|
||||
req.context = {user: 'localhost'};
|
||||
res.locals.user = 'localhost';
|
||||
|
||||
req.params.dbhost = global.environment.postgres.host;
|
||||
req.params.dbport = req.params.dbport || global.environment.postgres.port;
|
||||
@ -74,6 +74,9 @@ module.exports = _.extend({}, serverOptions, {
|
||||
}
|
||||
req.params.dbname = 'test_windshaft_cartodb_user_1_db';
|
||||
|
||||
// add all params to res.locals
|
||||
res.locals = _.extend({}, req.params);
|
||||
|
||||
|
||||
// increment number of calls counter
|
||||
global.req2params_calls = global.req2params_calls ? global.req2params_calls + 1 : 1;
|
||||
|
@ -10,6 +10,7 @@ var TemplateMaps = require('../../../lib/cartodb/backends/template_maps');
|
||||
const cleanUpQueryParamsMiddleware = require('../../../lib/cartodb/middleware/context/clean-up-query-params');
|
||||
const authorizeMiddleware = require('../../../lib/cartodb/middleware/context/authorize');
|
||||
const dbConnSetupMiddleware = require('../../../lib/cartodb/middleware/context/db-conn-setup');
|
||||
const localsMiddleware = require('../../../lib/cartodb/middleware/context/locals');
|
||||
|
||||
var windshaft = require('windshaft');
|
||||
|
||||
@ -47,56 +48,75 @@ describe('prepare-context', function() {
|
||||
req.profiler = {
|
||||
done: function() {}
|
||||
};
|
||||
req.context = { user: 'localhost' };
|
||||
req.params = {};
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
function prepareResponse(res) {
|
||||
if(!res.locals) {
|
||||
res.locals = {};
|
||||
}
|
||||
res.locals.user = 'localhost';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
it('res.locals are created', function(done) {
|
||||
let req = {};
|
||||
let res = {};
|
||||
|
||||
localsMiddleware(prepareRequest(req), prepareResponse(res), function(err) {
|
||||
if ( err ) { done(err); return; }
|
||||
assert.ok(res.hasOwnProperty('locals'), 'response has locals');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cleans up request', function(done){
|
||||
var req = {headers: { host:'localhost' }, query: {dbuser:'hacker',dbname:'secret'}};
|
||||
var res = {};
|
||||
|
||||
cleanUpQueryParams(prepareRequest(req), res, function(err) {
|
||||
cleanUpQueryParams(prepareRequest(req), prepareResponse(res), function(err) {
|
||||
if ( err ) { done(err); return; }
|
||||
assert.ok(_.isObject(req.query), 'request has query');
|
||||
assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query');
|
||||
assert.ok(req.hasOwnProperty('params'), 'request has params');
|
||||
assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.ok(res.hasOwnProperty('locals'), 'response has locals');
|
||||
assert.ok(!res.locals.hasOwnProperty('interactivity'), 'response locals do not have interactivity');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('sets dbname from redis metadata', function(done){
|
||||
var req = {headers: { host:'localhost' }, query: {}, locals: {} };
|
||||
var req = {headers: { host:'localhost' }, query: {} };
|
||||
var res = { set: function () {} };
|
||||
|
||||
dbConnSetup(prepareRequest(req), res, function(err) {
|
||||
if ( err ) { done(err); return; }
|
||||
dbConnSetup(prepareRequest(req), prepareResponse(res), function(err) {
|
||||
if ( err ) { done(err); return; }
|
||||
assert.ok(_.isObject(req.query), 'request has query');
|
||||
assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query');
|
||||
assert.ok(req.hasOwnProperty('params'), 'request has params');
|
||||
assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.equal(req.params.dbname, test_database);
|
||||
assert.ok(req.params.dbuser === test_pubuser, 'could inject dbuser ('+req.params.dbuser+')');
|
||||
assert.ok(res.hasOwnProperty('locals'), 'response has locals');
|
||||
assert.ok(!res.locals.hasOwnProperty('interactivity'), 'response locals do not have interactivity');
|
||||
assert.equal(res.locals.dbname, test_database);
|
||||
assert.ok(res.locals.dbuser === test_pubuser, 'could inject dbuser ('+res.locals.dbuser+')');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('sets also dbuser for authenticated requests', function(done){
|
||||
var req = { headers: { host: 'localhost' }, query: { map_key: '1234' }, locals: {} };
|
||||
var req = { headers: { host: 'localhost' }, query: { map_key: '1234' }};
|
||||
var res = { set: function () {} };
|
||||
|
||||
// FIXME: review authorize-pgconnsetup workflow, It might we are doing authorization twice.
|
||||
authorize(prepareRequest(req), res, function (err) {
|
||||
authorize(prepareRequest(req), prepareResponse(res), function (err) {
|
||||
if (err) { done(err); return; }
|
||||
dbConnSetup(req, res, function(err) {
|
||||
if ( err ) { done(err); return; }
|
||||
assert.ok(_.isObject(req.query), 'request has query');
|
||||
assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query');
|
||||
assert.ok(req.hasOwnProperty('params'), 'request has params');
|
||||
assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.equal(req.params.dbname, test_database);
|
||||
assert.equal(req.params.dbuser, test_user);
|
||||
assert.ok(res.hasOwnProperty('locals'), 'response has locals');
|
||||
assert.ok(!res.locals.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.equal(res.locals.dbname, test_database);
|
||||
assert.equal(res.locals.dbuser, test_user);
|
||||
|
||||
req = {
|
||||
headers: {
|
||||
@ -104,13 +124,14 @@ describe('prepare-context', function() {
|
||||
},
|
||||
query: {
|
||||
map_key: '1235'
|
||||
},
|
||||
locals: {}
|
||||
}
|
||||
};
|
||||
|
||||
dbConnSetup(prepareRequest(req), res, function () {
|
||||
res = { set: function () {} };
|
||||
|
||||
dbConnSetup(prepareRequest(req), prepareResponse(res), function() {
|
||||
// wrong key resets params to no user
|
||||
assert.ok(req.params.dbuser === test_pubuser, 'could inject dbuser ('+req.params.dbuser+')');
|
||||
assert.ok(res.locals.dbuser === test_pubuser, 'could inject dbuser ('+res.locals.dbuser+')');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -130,17 +151,16 @@ describe('prepare-context', function() {
|
||||
api_key: 'test',
|
||||
style: 'override',
|
||||
config: config
|
||||
},
|
||||
locals: {}
|
||||
}
|
||||
};
|
||||
var res = {};
|
||||
|
||||
cleanUpQueryParams(prepareRequest(req), res, function (err) {
|
||||
|
||||
cleanUpQueryParams(prepareRequest(req), prepareResponse(res), function (err) {
|
||||
if ( err ) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var query = req.params;
|
||||
var query = res.locals;
|
||||
assert.deepEqual(config, query.config);
|
||||
assert.equal('test', query.api_key);
|
||||
assert.equal(undefined, query.non_included);
|
||||
|
Loading…
Reference in New Issue
Block a user