Merge branch 'middlewarify' into stats-middleware

This commit is contained in:
Daniel García Aubert 2017-10-09 17:54:32 +02:00
commit a81e98995a
18 changed files with 176 additions and 144 deletions

View File

@ -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)
});

View File

@ -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);

View File

@ -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) {

View File

@ -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');

View File

@ -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;

View File

@ -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
);
});

View File

@ -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(){

View File

@ -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();
};
};

View File

@ -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);

View File

@ -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();
};
};

View File

@ -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);
});
};

View File

@ -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),

View File

@ -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) {

View File

@ -0,0 +1,8 @@
const _ = require('underscore');
module.exports = function localsMiddleware(req, res, next) {
_.extend(res.locals, req.params);
next();
};

View File

@ -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();
};

View File

@ -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);
}

View File

@ -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;

View File

@ -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);