2016-02-22 18:40:25 +08:00
|
|
|
|
var PSQL = require('cartodb-psql');
|
2015-02-09 21:46:52 +08:00
|
|
|
|
var _ = require('underscore');
|
|
|
|
|
|
|
|
|
|
function PgConnection(metadataBackend) {
|
|
|
|
|
this.metadataBackend = metadataBackend;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = PgConnection;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
//
|
2018-02-08 18:29:17 +08:00
|
|
|
|
PgConnection.prototype.setDBAuth = function(username, params, apikeyType, callback) {
|
|
|
|
|
if (apikeyType === 'master') {
|
2018-02-08 00:14:13 +08:00
|
|
|
|
this.metadataBackend.getMasterApikey(username, (err, apikey) => {
|
|
|
|
|
if (err) {
|
2018-02-20 01:48:02 +08:00
|
|
|
|
if (isNameNotFoundError(err)) {
|
2018-02-20 01:28:58 +08:00
|
|
|
|
err.http_status = 404;
|
|
|
|
|
}
|
2018-02-08 00:14:13 +08:00
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
params.dbuser = apikey.databaseRole;
|
|
|
|
|
params.dbpassword = apikey.databasePassword;
|
|
|
|
|
|
2018-02-15 00:31:05 +08:00
|
|
|
|
//Remove this block when Auth fallback is not used anymore
|
|
|
|
|
// AUTH_FALLBACK
|
|
|
|
|
if (!params.dbuser && apikey.user_id && global.environment.postgres_auth_user) {
|
|
|
|
|
params.dbuser = _.template(global.environment.postgres_auth_user, apikey);
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-08 00:14:13 +08:00
|
|
|
|
return callback();
|
|
|
|
|
});
|
2018-02-16 18:20:04 +08:00
|
|
|
|
} else if (apikeyType === 'regular') { //Actually it can be any type of api key
|
2018-02-15 22:19:09 +08:00
|
|
|
|
this.metadataBackend.getApikey(username, params.api_key, (err, apikey) => {
|
2018-02-08 00:14:13 +08:00
|
|
|
|
if (err) {
|
2018-02-20 01:48:02 +08:00
|
|
|
|
if (isNameNotFoundError(err)) {
|
2018-02-20 01:28:58 +08:00
|
|
|
|
err.http_status = 404;
|
|
|
|
|
}
|
2018-02-08 00:14:13 +08:00
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
params.dbuser = apikey.databaseRole;
|
|
|
|
|
params.dbpassword = apikey.databasePassword;
|
|
|
|
|
|
2018-02-15 00:31:05 +08:00
|
|
|
|
//Remove this block when Auth fallback is not used anymore
|
|
|
|
|
// AUTH_FALLBACK
|
|
|
|
|
if (!params.dbuser && apikey.user_id && apikey.type === 'master' && global.environment.postgres_auth_user) {
|
|
|
|
|
params.dbuser = _.template(global.environment.postgres_auth_user, apikey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Remove this block when Auth fallback is not used anymore
|
|
|
|
|
// AUTH_FALLBACK
|
|
|
|
|
if (!params.dbpassword && global.environment.postgres.password) {
|
|
|
|
|
params.dbpassword = global.environment.postgres.password;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-16 18:20:04 +08:00
|
|
|
|
//Remove this block when Auth fallback is not used anymore
|
|
|
|
|
// AUTH_FALLBACK
|
|
|
|
|
// If api key not found use default
|
|
|
|
|
if (!params.dbuser && !params.dbpassword) {
|
|
|
|
|
return this.setDBAuth(username, params, 'default', callback);
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-20 01:28:58 +08:00
|
|
|
|
return callback();
|
2018-02-08 00:14:13 +08:00
|
|
|
|
});
|
2018-02-08 18:29:17 +08:00
|
|
|
|
} else if (apikeyType === 'default') {
|
|
|
|
|
this.metadataBackend.getApikey(username, 'default_public', (err, apikey) => {
|
|
|
|
|
if (err) {
|
2018-02-20 01:48:02 +08:00
|
|
|
|
if (isNameNotFoundError(err)) {
|
2018-02-20 01:28:58 +08:00
|
|
|
|
err.http_status = 404;
|
|
|
|
|
}
|
2018-02-08 18:29:17 +08:00
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
params.dbuser = apikey.databaseRole;
|
|
|
|
|
params.dbpassword = apikey.databasePassword;
|
|
|
|
|
|
2018-02-15 00:31:05 +08:00
|
|
|
|
//Remove this block when Auth fallback is not used anymore
|
|
|
|
|
// AUTH_FALLBACK
|
|
|
|
|
if (!params.dbpassword && global.environment.postgres.password) {
|
|
|
|
|
params.dbpassword = global.environment.postgres.password;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-08 18:29:17 +08:00
|
|
|
|
return callback();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
return callback(new Error(`Invalid Apikey type: ${apikeyType}, valid ones: master, regular, default`));
|
2018-02-08 00:14:13 +08:00
|
|
|
|
}
|
2015-02-09 21:46:52 +08:00
|
|
|
|
};
|
|
|
|
|
|
2018-02-20 01:48:02 +08:00
|
|
|
|
function isNameNotFoundError (err) {
|
|
|
|
|
return err.message && -1 !== err.message.indexOf('name not found');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-02-09 21:46:52 +08:00
|
|
|
|
// Set db connection parameters to those for the given username
|
|
|
|
|
//
|
|
|
|
|
// @param dbowner cartodb username of database owner,
|
|
|
|
|
// mapped to a database username
|
|
|
|
|
// via CartodbRedis metadata records
|
|
|
|
|
//
|
|
|
|
|
// @param params the parameters to set connection options into
|
|
|
|
|
// added params are: "dbname", "dbhost"
|
|
|
|
|
//
|
|
|
|
|
// @param callback function(err)
|
|
|
|
|
//
|
|
|
|
|
PgConnection.prototype.setDBConn = function(dbowner, params, callback) {
|
|
|
|
|
_.defaults(params, {
|
2018-02-08 19:04:03 +08:00
|
|
|
|
// dbuser: global.environment.postgres.user,
|
|
|
|
|
// dbpassword: global.environment.postgres.password,
|
2015-02-09 21:46:52 +08:00
|
|
|
|
dbhost: global.environment.postgres.host,
|
|
|
|
|
dbport: global.environment.postgres.port
|
|
|
|
|
});
|
2018-02-07 22:49:32 +08:00
|
|
|
|
|
|
|
|
|
this.metadataBackend.getUserDBConnectionParams(dbowner, (err, dbParams) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we don’t want null values or overwrite a non public user
|
|
|
|
|
if (params.dbuser !== 'publicuser' || !dbParams.dbuser) {
|
|
|
|
|
delete dbParams.dbuser;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dbParams) {
|
|
|
|
|
_.extend(params, dbParams);
|
2015-02-09 21:46:52 +08:00
|
|
|
|
}
|
2016-02-22 18:40:25 +08:00
|
|
|
|
|
2018-02-07 22:49:32 +08:00
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
};
|
2016-02-22 18:40:25 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a `cartodb-psql` object for a given username.
|
|
|
|
|
* @param {String} username
|
|
|
|
|
* @param {Function} callback function({Error}, {PSQL})
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
PgConnection.prototype.getConnection = function(username, callback) {
|
2018-02-08 19:04:03 +08:00
|
|
|
|
require('debug')('cachechan')("getConn1");
|
2016-02-22 18:40:25 +08:00
|
|
|
|
|
2018-02-08 19:04:03 +08:00
|
|
|
|
this.getDatabaseParams(username, (err, databaseParams) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
return callback(err, new PSQL({
|
|
|
|
|
user: databaseParams.dbuser,
|
|
|
|
|
pass: databaseParams.dbpass,
|
|
|
|
|
host: databaseParams.dbhost,
|
|
|
|
|
port: databaseParams.dbport,
|
|
|
|
|
dbname: databaseParams.dbname
|
|
|
|
|
}));
|
2016-02-22 18:40:25 +08:00
|
|
|
|
|
2018-02-08 19:04:03 +08:00
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PgConnection.prototype.getDatabaseParams = function(username, callback) {
|
|
|
|
|
const databaseParams = {};
|
|
|
|
|
|
|
|
|
|
this.setDBAuth(username, databaseParams, 'master', err => {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
2016-02-22 18:40:25 +08:00
|
|
|
|
}
|
2018-02-08 19:04:03 +08:00
|
|
|
|
|
|
|
|
|
this.setDBConn(username, databaseParams, err => {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
callback(null, databaseParams);
|
|
|
|
|
});
|
|
|
|
|
});
|
2016-02-22 18:40:25 +08:00
|
|
|
|
};
|