CDB-3629 Uses one request to redis to retrieve all connection params
This commit is contained in:
parent
04dd9c709b
commit
e16f278087
@ -32,14 +32,7 @@ var express = require('express')
|
||||
, util = require('util')
|
||||
, Profiler = require('step-profiler')
|
||||
, StatsD = require('node-statsd').StatsD
|
||||
, Meta = require('cartodb-redis')({
|
||||
host: global.settings.redis_host,
|
||||
port: global.settings.redis_port,
|
||||
max: global.settings.redisPool,
|
||||
idleTimeoutMillis: global.settings.redisIdleTimeoutMillis,
|
||||
reapIntervalMillis: global.settings.redisReapIntervalMillis
|
||||
})
|
||||
// global.settings.app_root + '/app/models/metadata')
|
||||
, MetadataDB = require('cartodb-redis')
|
||||
, oAuth = require(global.settings.app_root + '/app/models/oauth')
|
||||
, PSQL = require(global.settings.app_root + '/app/models/psql')
|
||||
, PSQLWrapper = require(global.settings.app_root + '/app/sql/psql_wrapper')
|
||||
@ -50,8 +43,15 @@ var express = require('express')
|
||||
, formats = require(global.settings.app_root + '/app/models/formats')
|
||||
;
|
||||
|
||||
var cdbReq = new CdbRequest(Meta);
|
||||
var apiKeyAuth = new ApiKeyAuth(Meta, cdbReq);
|
||||
var metadataBackend = MetadataDB({
|
||||
host: global.settings.redis_host,
|
||||
port: global.settings.redis_port,
|
||||
max: global.settings.redisPool,
|
||||
idleTimeoutMillis: global.settings.redisIdleTimeoutMillis,
|
||||
reapIntervalMillis: global.settings.redisReapIntervalMillis
|
||||
});
|
||||
var cdbReq = new CdbRequest();
|
||||
var apiKeyAuth = new ApiKeyAuth(metadataBackend, cdbReq);
|
||||
|
||||
// Set default configuration
|
||||
global.settings.db_pubuser = global.settings.db_pubuser || "publicuser";
|
||||
@ -287,6 +287,7 @@ function handleQuery(req, res) {
|
||||
|
||||
if ( req.profiler ) req.profiler.done('init');
|
||||
|
||||
var dbParams;
|
||||
// 1. Get database from redis via the username stored in the host header subdomain
|
||||
// 2. Run the request through OAuth to get R/W user id if signed
|
||||
// 3. Get the list of tables affected by the query
|
||||
@ -295,54 +296,38 @@ function handleQuery(req, res) {
|
||||
Step(
|
||||
function getDatabaseConnectionParams() {
|
||||
checkAborted('getDatabaseConnectionParams');
|
||||
Meta.getUserDBConnectionParams(cdbuser, this);
|
||||
metadataBackend.getAllUserDBParams(cdbuser, this);
|
||||
},
|
||||
function setDBConnectionParams(err, dbParams) {
|
||||
|
||||
function authenticate(err, userDBParams) {
|
||||
if (err) {
|
||||
err.http_status = 404;
|
||||
err.message = "Sorry, we can't find CartoDB user '" + cdbuser
|
||||
+ "'. Please check that you have entered the correct domain.";
|
||||
throw err;
|
||||
}
|
||||
|
||||
dbParams = userDBParams;
|
||||
|
||||
dbopts.host = dbParams.dbhost;
|
||||
dbopts.dbname = dbParams.dbname;
|
||||
dbopts.user = (!!dbParams.dbuser) ? dbParams.dbuser : global.settings.db_pubuser;
|
||||
dbopts.user = (!!dbParams.dbpublicuser) ? dbParams.dbpublicuser : global.settings.db_pubuser;
|
||||
|
||||
return null;
|
||||
},
|
||||
function authenticate(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (api_key) {
|
||||
apiKeyAuth.verifyRequest(req, this);
|
||||
apiKeyAuth.verifyRequest(req, dbParams.apikey, this);
|
||||
} else {
|
||||
oAuth.verifyRequest(req, this, requestProtocol);
|
||||
}
|
||||
},
|
||||
function setUserGetDBPassword(err, userId) {
|
||||
function setDBAuth(err, isAuthenticated) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
authenticated = userId !== null;
|
||||
if (authenticated) {
|
||||
user_id = userId;
|
||||
dbopts.user = _.template(global.settings.db_user, {user_id: userId});
|
||||
Meta.getUserDBPass(cdbuser, this);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
function setPassword(err, password) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if ( authenticated ) {
|
||||
if (_.isBoolean(isAuthenticated) && isAuthenticated) {
|
||||
dbopts.user = _.template(global.settings.db_user, {user_id: dbParams.dbuser});
|
||||
if ( global.settings.hasOwnProperty('db_user_pass') ) {
|
||||
dbopts.pass = _.template(global.settings.db_user_pass, {
|
||||
user_id: user_id,
|
||||
user_password: password
|
||||
user_id: dbParams.dbuser,
|
||||
user_password: dbParams.dbpass
|
||||
});
|
||||
} else {
|
||||
delete dbopts.pass;
|
||||
|
@ -1,87 +1,34 @@
|
||||
/**
|
||||
* this module allows to auth user using an pregenerated api key
|
||||
*/
|
||||
|
||||
var _ = require('underscore')
|
||||
, Step = require('step');
|
||||
|
||||
function ApikeyAuth(cartodb_redis, cartodb_request) {
|
||||
if ( ! cartodb_redis ) throw new Error("Cannot initialize ApikeyAuth with no cartodb_request");
|
||||
if ( ! cartodb_request ) throw new Error("Cannot initialize ApikeyAuth with no cartodb-redis");
|
||||
this.cdbRedis = cartodb_redis;
|
||||
this.cdbRequest = cartodb_request;
|
||||
function ApikeyAuth() {
|
||||
}
|
||||
|
||||
module.exports = ApikeyAuth;
|
||||
|
||||
var o = ApikeyAuth.prototype;
|
||||
|
||||
o.userByReq = function(req) {
|
||||
return this.cdbRequest.userByReq(req)
|
||||
};
|
||||
|
||||
// Check if a request is authorized by api_key
|
||||
//
|
||||
// @param req express request object
|
||||
// @param callback function(err, authorized)
|
||||
//
|
||||
o.authorizedByAPIKey = function(req, callback)
|
||||
{
|
||||
var user = this.userByReq(req);
|
||||
var that = this;
|
||||
Step(
|
||||
function (){
|
||||
that.cdbRedis.getUserMapKey(user, this);
|
||||
},
|
||||
function checkApiKey(err, val){
|
||||
if (err) throw err;
|
||||
|
||||
var valid = 0;
|
||||
if ( val ) {
|
||||
if ( val == req.query.map_key ) valid = 1;
|
||||
else if ( val == req.query.api_key ) valid = 1;
|
||||
// check also in request body
|
||||
else if ( req.body && req.body.map_key && val == req.body.map_key ) valid = 1;
|
||||
else if ( req.body && req.body.api_key && val == req.body.api_key ) valid = 1;
|
||||
}
|
||||
|
||||
return valid;
|
||||
},
|
||||
function finish(err, authorized) {
|
||||
callback(err, authorized);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get id of authorized user
|
||||
*
|
||||
* @param req - standard req object. Importantly contains table and host information
|
||||
* @param callback - err, user_id (null if no auth)
|
||||
* @param {Object} req - standard req object. Importantly contains table and host information
|
||||
* @param {String} requiredApi - the API associated to the user, req must contain it
|
||||
* @param {Function} callback - err, boolean (whether the request is authenticated or not)
|
||||
*/
|
||||
o.verifyRequest = function(req, callback) {
|
||||
var user = this.userByReq(req);
|
||||
var that = this;
|
||||
ApikeyAuth.prototype.verifyRequest = function (req, requiredApi, callback) {
|
||||
|
||||
Step(
|
||||
// check api key
|
||||
function(){
|
||||
that.authorizedByAPIKey(req, this);
|
||||
},
|
||||
// get user id or fail
|
||||
function (err, apikey_valid) {
|
||||
if ( err ) throw err;
|
||||
if (apikey_valid) {
|
||||
that.cdbRedis.getUserId(user, this);
|
||||
} else {
|
||||
// no auth
|
||||
callback(null, null);
|
||||
}
|
||||
},
|
||||
function (err, user_id){
|
||||
callback(err, user_id);
|
||||
var valid = false;
|
||||
|
||||
if ( requiredApi ) {
|
||||
if ( requiredApi == req.query.map_key ) {
|
||||
valid = true;
|
||||
} else if ( requiredApi == req.query.api_key ) {
|
||||
valid = true;
|
||||
// check also in request body
|
||||
} else if ( req.body && req.body.map_key && requiredApi == req.body.map_key ) {
|
||||
valid = true;
|
||||
} else if ( req.body && req.body.api_key && requiredApi == req.body.api_key ) {
|
||||
valid = true;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
callback(null, valid);
|
||||
};
|
||||
|
@ -3,33 +3,26 @@
|
||||
* of request headers
|
||||
*/
|
||||
|
||||
function CartodbRequest(cartodb_redis) {
|
||||
this.cartodb_redis = cartodb_redis;
|
||||
function CartodbRequest() {
|
||||
}
|
||||
|
||||
module.exports = CartodbRequest;
|
||||
|
||||
var o = CartodbRequest.prototype;
|
||||
|
||||
o.re_userFromHost = new RegExp(
|
||||
global.settings.user_from_host ||
|
||||
'^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com"
|
||||
);
|
||||
|
||||
o.userByReq = function(req) {
|
||||
CartodbRequest.prototype.userByReq = function(req) {
|
||||
var host = req.headers.host;
|
||||
var mat = host.match(this.re_userFromHost);
|
||||
var mat = host.match(re_userFromHost);
|
||||
if ( ! mat ) {
|
||||
console.error("ERROR: user pattern '" + this.re_userFromHost
|
||||
+ "' does not match hostname '" + host + "'");
|
||||
console.error("ERROR: user pattern '" + re_userFromHost + "' does not match hostname '" + host + "'");
|
||||
return;
|
||||
}
|
||||
// console.log("Matches: "); console.dir(mat);
|
||||
if ( ! mat.length === 2 ) {
|
||||
console.error("ERROR: pattern '" + this.re_userFromHost
|
||||
+ "' gave unexpected matches against '" + host + "': " + mat);
|
||||
console.error("ERROR: pattern '" + re_userFromHost + "' gave unexpected matches against '" + host + "': " + mat);
|
||||
return;
|
||||
}
|
||||
return mat[1];
|
||||
};
|
||||
|
||||
var re_userFromHost = new RegExp(
|
||||
global.settings.user_from_host || '^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com"
|
||||
);
|
||||
|
@ -118,7 +118,6 @@ var oAuth = function(){
|
||||
signature = passed_tokens.oauth_signature;
|
||||
delete passed_tokens['oauth_signature'];
|
||||
|
||||
var base64;
|
||||
var joined = {};
|
||||
|
||||
// remove oauth_signature from body
|
||||
@ -135,7 +134,7 @@ var oAuth = function(){
|
||||
if (err) throw err;
|
||||
|
||||
//console.log(data + " should equal the provided signature: " + signature);
|
||||
callback(err, (signature === data && !_.isUndefined(data)) ? ohash.user_id : null);
|
||||
callback(err, (signature === data && !_.isUndefined(data)) ? true : null);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
4
npm-shrinkwrap.json
generated
4
npm-shrinkwrap.json
generated
@ -48,8 +48,8 @@
|
||||
}
|
||||
},
|
||||
"cartodb-redis": {
|
||||
"version": "0.5.0",
|
||||
"from": "git://github.com/CartoDB/node-cartodb-redis.git#0.5.0",
|
||||
"version": "0.6.0",
|
||||
"from": "git://github.com/CartoDB/node-cartodb-redis.git#0.6.0",
|
||||
"dependencies": {
|
||||
"strftime": {
|
||||
"version": "0.6.2"
|
||||
|
@ -20,7 +20,7 @@
|
||||
"underscore.string": "~1.1.6",
|
||||
"pg": "git://github.com/CartoDB/node-postgres.git#2.6.2-cdb1",
|
||||
"express": "~2.5.11",
|
||||
"cartodb-redis": "~0.5.0",
|
||||
"cartodb-redis": "~0.6.0",
|
||||
"step": "0.0.x",
|
||||
"topojson": "0.0.8",
|
||||
"oauth-client": "0.2.0",
|
||||
|
Loading…
Reference in New Issue
Block a user