Refactor req2params to make setting db credential easier

This commit is contained in:
Sandro Santilli 2013-12-06 13:32:37 +01:00
parent 6f689745c0
commit 38342a7f5f
2 changed files with 88 additions and 53 deletions

View File

@ -250,7 +250,7 @@ module.exports = function(){
me.afterLayergroupCreate = function(req, mapconfig, response, callback) {
var token = response.layergroupid;
var username = cartoData.userFromHostname(req.headers.host);
var username = this.dbOwnerByReq(req); // cartoData.userFromHostname(req.headers.host);
var tasksleft = 2; // redis key and affectedTables
var errors = [];
@ -305,69 +305,94 @@ module.exports = function(){
/* X-Cache-Channel generation } */
me.dbOwnerByReq = function(req) {
return cartoData.userFromHostname(req.headers.host);
}
// Set db authentication parameters to those of the given username
//
// @param username the cartodb username, mapped to a database username
// via CartodbRedis metadata records
//
// @param params the parameters to set auth options into
// added params are: "dbuser" and "dbpassword"
//
// @param callback function(err)
//
me.setDBAuth = function(username, params, callback) {
var user_params = {};
var auth_user = global.environment.postgres_auth_user;
var auth_pass = global.environment.postgres_auth_pass;
Step(
function getId() {
cartoData.getUserId(username, this);
},
function(err, user_id) {
if (err) throw err;
user_params['user_id'] = user_id;
var dbuser = _.template(auth_user, user_params);
_.extend(params, {dbuser:dbuser});
// skip looking up user_password if postgres_auth_pass
// doesn't contain the "user_password" label
if (!auth_pass || ! auth_pass.match(/\buser_password\b/) ) return null;
cartoData.getUserDBPass(username, this);
},
function(err, user_password) {
if (err) throw err;
user_params['user_password'] = user_password;
if ( auth_pass ) {
var dbpass = _.template(auth_pass, user_params);
_.extend(params, {dbpassword:dbpass});
}
return true;
},
function finish(err) {
callback(err);
}
);
}
/**
* Get privacy for cartodb table
* Check access authorization
*
* @param req - standard req object. Importantly contains table and host information
* @param callback - is the table private or not?
* @param callback function(err, allowed) is access allowed not?
*/
me.authorize= function(req, callback) {
me.authorize = function(req, callback) {
var that = this;
var dbowner = me.dbOwnerByReq(req);
Step(
function(){
cartoData.checkMapKey(req, this);
},
function checkIfInternal(err, check_result){
function checkApiKey(err, check_result){
if (err) throw err;
// if unauthorized continue to check table privacy
if (check_result !== 1) return true;
// if not authorized by api_key, continue
if (check_result !== 1) return null;
// authorized by key, login as db owner
var user_params = {};
var auth_user = global.environment.postgres_auth_user;
var auth_pass = global.environment.postgres_auth_pass;
Step(
function getId() {
cartoData.getId(req, this);
},
function(err, user_id) {
if (err) throw err;
user_params['user_id'] = user_id;
var dbuser = _.template(auth_user, user_params);
_.extend(req.params, {dbuser:dbuser});
// skip looking up user_password if postgres_auth_pass
// doesn't contain the "user_password" label
if (!auth_pass || ! auth_pass.match(/\buser_password\b/) ) return null;
cartoData.getDatabasePassword(req, this);
},
function(err, user_password) {
if (err) throw err;
user_params['user_password'] = user_password;
if ( auth_pass ) {
var dbpass = _.template(auth_pass, user_params);
_.extend(req.params, {dbpassword:dbpass});
}
return true;
},
function finish(err) {
callback(err, true); // authorized (or error)
}
);
}
,function getDatabase(err, data){
if (err) throw err;
cartoData.getDatabase(req, this);
// authorized by api key, login as db owner and stop
that.setDBAuth(dbowner, req.params, function(err) {
callback(err, true); // authorized (or error)
});
},
function getPrivacy(err, data){
// TODO: check if authorized by layergroup signature
// should only be done for GET /layergroup
function getDatabase(err){
if (err) throw err;
cartoData.getTablePrivacy(data, req.params.table, this);
// NOTE: only used to get to table privacy
cartoData.getUserDBName(dbowner, this);
},
function(err, data){
callback(err, data);
function getPrivacy(err, dbname){
if (err) throw err;
cartoData.getTablePrivacy(dbname, req.params.table, this);
},
function(err, privacy){
callback(err, privacy);
}
);
};
@ -415,11 +440,19 @@ module.exports = function(){
_.each(bad_query, function(key){ delete req.query[key]; });
req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object
var signer = null;
if ( req.params.token ) {
//console.log("Request parameters include token " + req.params.token);
var tksplit = req.params.token.split(':');
req.params.token = tksplit[0];
if ( tksplit.length > 1 ) req.params.cache_buster= tksplit[1];
tksplit = req.params.token.split('@');
if ( tksplit.length > 1 ) {
// signer name defaults to the domain user
req.params.signer = tksplit[0] || req.headers.host.split('.')[0];
req.params.token = tksplit[1];
}
}
// bring all query values onto req.params object
@ -452,12 +485,14 @@ module.exports = function(){
if (req.profiler) req.profiler.done('req2params.setup');
var dbowner = me.dbOwnerByReq(req);
Step(
function getPrivacy(){
me.authorize(req, this);
},
function gatekeep(err, data){
if (req.profiler) req.profiler.done('cartoData.authorize');
if (req.profiler) req.profiler.done('authorize');
if(err) throw err;
if(data === "0") throw new Error("Sorry, you are unauthorized (permission denied)");
return data;
@ -465,21 +500,21 @@ module.exports = function(){
function getDatabaseHost(err, data){
if(err) throw err;
cartoData.getDatabaseHost(req, this);
cartoData.getUserDBHost(dbowner, this);
},
function getDatabase(err, data){
if (req.profiler) req.profiler.done('cartoData.getDatabaseHost');
if(err) throw err;
if ( data ) _.extend(req.params, {dbhost:data});
cartoData.getDatabase(req, this);
cartoData.getUserDBName(dbowner, this);
},
function getGeometryType(err, data){
if (req.profiler) req.profiler.done('cartoData.getDatabase');
if (err) throw err;
_.extend(req.params, {dbname:data});
cartoData.getGeometryType(req, this);
cartoData.getTableGeometryType(data, req.params.table, this);
},
function finishSetup(err, data){
if (req.profiler) req.profiler.done('cartoData.getGeometryType');

View File

@ -27,7 +27,7 @@
"windshaft" : "~0.14.5",
"step": "0.0.x",
"request": "2.9.202",
"cartodb-redis": "~0.1.0",
"cartodb-redis": "~0.2.0",
"mapnik": "~0.7.22",
"lzma": "~1.2.3"
},