Use authenticated middleware in query controller
This commit is contained in:
parent
114070ef96
commit
75c2d85dbb
@ -15,13 +15,14 @@ module.exports = JobController;
|
|||||||
|
|
||||||
JobController.prototype.route = function (app) {
|
JobController.prototype.route = function (app) {
|
||||||
const { base_url } = global.settings;
|
const { base_url } = global.settings;
|
||||||
|
const forceToBeAuthenticated = true;
|
||||||
|
|
||||||
app.post(
|
app.post(
|
||||||
`${base_url}/sql/job`,
|
`${base_url}/sql/job`,
|
||||||
checkBodyPayloadSize(),
|
checkBodyPayloadSize(),
|
||||||
userMiddleware(),
|
userMiddleware(),
|
||||||
credentialsMiddleware(),
|
credentialsMiddleware(),
|
||||||
authenticatedMiddleware(this.userDatabaseService),
|
authenticatedMiddleware(this.userDatabaseService, forceToBeAuthenticated),
|
||||||
createJob(this.jobService),
|
createJob(this.jobService),
|
||||||
setServedByDBHostHeader(),
|
setServedByDBHostHeader(),
|
||||||
profile(),
|
profile(),
|
||||||
@ -46,7 +47,7 @@ JobController.prototype.route = function (app) {
|
|||||||
`${base_url}/sql/job/:job_id`,
|
`${base_url}/sql/job/:job_id`,
|
||||||
userMiddleware(),
|
userMiddleware(),
|
||||||
credentialsMiddleware(),
|
credentialsMiddleware(),
|
||||||
authenticatedMiddleware(this.userDatabaseService),
|
authenticatedMiddleware(this.userDatabaseService, forceToBeAuthenticated),
|
||||||
getJob(this.jobService),
|
getJob(this.jobService),
|
||||||
setServedByDBHostHeader(),
|
setServedByDBHostHeader(),
|
||||||
profile(),
|
profile(),
|
||||||
@ -60,7 +61,7 @@ JobController.prototype.route = function (app) {
|
|||||||
`${base_url}/sql/job/:job_id`,
|
`${base_url}/sql/job/:job_id`,
|
||||||
userMiddleware(),
|
userMiddleware(),
|
||||||
credentialsMiddleware(),
|
credentialsMiddleware(),
|
||||||
authenticatedMiddleware(this.userDatabaseService),
|
authenticatedMiddleware(this.userDatabaseService, forceToBeAuthenticated),
|
||||||
cancelJob(this.jobService),
|
cancelJob(this.jobService),
|
||||||
setServedByDBHostHeader(),
|
setServedByDBHostHeader(),
|
||||||
profile(),
|
profile(),
|
||||||
|
@ -5,7 +5,6 @@ var step = require('step');
|
|||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var PSQL = require('cartodb-psql');
|
var PSQL = require('cartodb-psql');
|
||||||
var CachedQueryTables = require('../services/cached-query-tables');
|
var CachedQueryTables = require('../services/cached-query-tables');
|
||||||
var AuthApi = require('../auth/auth_api');
|
|
||||||
var queryMayWrite = require('../utils/query_may_write');
|
var queryMayWrite = require('../utils/query_may_write');
|
||||||
|
|
||||||
var formats = require('../models/formats');
|
var formats = require('../models/formats');
|
||||||
@ -15,6 +14,7 @@ var getContentDisposition = require('../utils/content_disposition');
|
|||||||
const credentialsMiddleware = require('../middlewares/credentials');
|
const credentialsMiddleware = require('../middlewares/credentials');
|
||||||
const userMiddleware = require('../middlewares/user');
|
const userMiddleware = require('../middlewares/user');
|
||||||
const errorMiddleware = require('../middlewares/error');
|
const errorMiddleware = require('../middlewares/error');
|
||||||
|
const authenticatedMiddleware = require('../middlewares/authenticated-request');
|
||||||
|
|
||||||
var ONE_YEAR_IN_SECONDS = 31536000; // 1 year time to live by default
|
var ONE_YEAR_IN_SECONDS = 31536000; // 1 year time to live by default
|
||||||
|
|
||||||
@ -25,17 +25,21 @@ function QueryController(userDatabaseService, tableCache, statsd_client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueryController.prototype.route = function (app) {
|
QueryController.prototype.route = function (app) {
|
||||||
|
const { base_url } = global.settings;
|
||||||
|
|
||||||
app.all(
|
app.all(
|
||||||
global.settings.base_url + '/sql',
|
`${base_url}/sql`,
|
||||||
userMiddleware(),
|
userMiddleware(),
|
||||||
credentialsMiddleware(),
|
credentialsMiddleware(),
|
||||||
|
authenticatedMiddleware(this.userDatabaseService),
|
||||||
this.handleQuery.bind(this),
|
this.handleQuery.bind(this),
|
||||||
errorMiddleware()
|
errorMiddleware()
|
||||||
);
|
);
|
||||||
app.all(
|
app.all(
|
||||||
global.settings.base_url + '/sql.:f',
|
`${base_url}/sql.:f`,
|
||||||
userMiddleware(),
|
userMiddleware(),
|
||||||
credentialsMiddleware(),
|
credentialsMiddleware(),
|
||||||
|
authenticatedMiddleware(this.userDatabaseService),
|
||||||
this.handleQuery.bind(this),
|
this.handleQuery.bind(this),
|
||||||
errorMiddleware()
|
errorMiddleware()
|
||||||
);
|
);
|
||||||
@ -47,7 +51,7 @@ QueryController.prototype.handleQuery = function (req, res, next) {
|
|||||||
// extract input
|
// extract input
|
||||||
var body = (req.body) ? req.body : {};
|
var body = (req.body) ? req.body : {};
|
||||||
// clone so don't modify req.params or req.body so oauth is not broken
|
// clone so don't modify req.params or req.body so oauth is not broken
|
||||||
var params = _.extend({}, res.locals, req.query, body);
|
var params = _.extend({}, req.query, body);
|
||||||
var sql = params.q;
|
var sql = params.q;
|
||||||
var limit = parseInt(params.rows_per_page);
|
var limit = parseInt(params.rows_per_page);
|
||||||
var offset = parseInt(params.page);
|
var offset = parseInt(params.page);
|
||||||
@ -58,11 +62,12 @@ QueryController.prototype.handleQuery = function (req, res, next) {
|
|||||||
var requestedFilename = params.filename;
|
var requestedFilename = params.filename;
|
||||||
var filename = requestedFilename;
|
var filename = requestedFilename;
|
||||||
var requestedSkipfields = params.skipfields;
|
var requestedSkipfields = params.skipfields;
|
||||||
var cdbUsername = res.locals.user;
|
|
||||||
|
const { user: username, userDbParams: dbopts, authDbParams, userLimits } = res.locals;
|
||||||
|
|
||||||
var skipfields;
|
var skipfields;
|
||||||
var dp = params.dp; // decimal point digits (defaults to 6)
|
var dp = params.dp; // decimal point digits (defaults to 6)
|
||||||
var gn = "the_geom"; // TODO: read from configuration FILE
|
var gn = "the_geom"; // TODO: read from configuration FILE
|
||||||
var userLimits;
|
|
||||||
|
|
||||||
if ( req.profiler ) {
|
if ( req.profiler ) {
|
||||||
req.profiler.start('sqlapi.query');
|
req.profiler.start('sqlapi.query');
|
||||||
@ -119,30 +124,20 @@ QueryController.prototype.handleQuery = function (req, res, next) {
|
|||||||
throw new Error("You must indicate a sql query");
|
throw new Error("You must indicate a sql query");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database options
|
|
||||||
var dbopts = {};
|
|
||||||
var formatter;
|
var formatter;
|
||||||
|
|
||||||
if ( req.profiler ) {
|
if ( req.profiler ) {
|
||||||
req.profiler.done('init');
|
req.profiler.done('init');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Get user database and related parameters
|
// 1. Get the list of tables affected by the query
|
||||||
// 3. Get the list of tables affected by the query
|
// 2. Setup headers
|
||||||
// 4. Setup headers
|
// 3. Send formatted results back
|
||||||
// 5. Send formatted results back
|
// 4. Handle error
|
||||||
step(
|
step(
|
||||||
function getUserDBInfo() {
|
function queryExplain() {
|
||||||
self.userDatabaseService.getConnectionParams(new AuthApi(req, res, params), cdbUsername, this);
|
|
||||||
},
|
|
||||||
function queryExplain(err, dbParams, authDbParams, userTimeoutLimits) {
|
|
||||||
assert.ifError(err);
|
|
||||||
|
|
||||||
var next = this;
|
var next = this;
|
||||||
|
|
||||||
dbopts = dbParams;
|
|
||||||
userLimits = userTimeoutLimits;
|
|
||||||
|
|
||||||
if ( req.profiler ) {
|
if ( req.profiler ) {
|
||||||
req.profiler.done('setDBAuth');
|
req.profiler.done('setDBAuth');
|
||||||
}
|
}
|
||||||
@ -150,6 +145,7 @@ QueryController.prototype.handleQuery = function (req, res, next) {
|
|||||||
checkAborted('queryExplain');
|
checkAborted('queryExplain');
|
||||||
|
|
||||||
var pg = new PSQL(authDbParams);
|
var pg = new PSQL(authDbParams);
|
||||||
|
|
||||||
var skipCache = !!dbopts.authenticated;
|
var skipCache = !!dbopts.authenticated;
|
||||||
|
|
||||||
self.queryTables.getAffectedTablesFromQuery(pg, sql, skipCache, function(err, result) {
|
self.queryTables.getAffectedTablesFromQuery(pg, sql, skipCache, function(err, result) {
|
||||||
@ -221,7 +217,7 @@ QueryController.prototype.handleQuery = function (req, res, next) {
|
|||||||
sql = new PSQL.QueryWrapper(sql).orderBy(orderBy, sortOrder).window(limit, offset).query();
|
sql = new PSQL.QueryWrapper(sql).orderBy(orderBy, sortOrder).window(limit, offset).query();
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
username: cdbUsername,
|
username: username,
|
||||||
dbopts: dbopts,
|
dbopts: dbopts,
|
||||||
sink: res,
|
sink: res,
|
||||||
gn: gn,
|
gn: gn,
|
||||||
|
@ -3,28 +3,31 @@
|
|||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var AuthApi = require('../auth/auth_api');
|
var AuthApi = require('../auth/auth_api');
|
||||||
|
|
||||||
function authenticatedMiddleware(userDatabaseService) {
|
function authenticatedMiddleware(userDatabaseService, forceToBeAuthenticated = false) {
|
||||||
return function middleware(req, res, next) {
|
return function middleware(req, res, next) {
|
||||||
req.profiler.start('sqlapi.job');
|
req.profiler.start('sqlapi.job');
|
||||||
req.profiler.done('init');
|
req.profiler.done('init');
|
||||||
|
|
||||||
var body = (req.body) ? req.body : {};
|
|
||||||
// clone so don't modify req.params or req.body so oauth is not broken
|
// clone so don't modify req.params or req.body so oauth is not broken
|
||||||
var params = _.extend({}, res.locals, req.query, body);
|
const params = _.extend({}, res.locals, req.query, req.body);
|
||||||
|
|
||||||
|
const { user } = res.locals;
|
||||||
|
|
||||||
var authApi = new AuthApi(req, res, params);
|
var authApi = new AuthApi(req, res, params);
|
||||||
userDatabaseService.getConnectionParams(authApi, res.locals.user, function connectionParams(err, userDbParams) {
|
userDatabaseService.getConnectionParams(authApi, user, function (err, dbParams, authDbParams, userLimits) {
|
||||||
req.profiler.done('setDBAuth');
|
req.profiler.done('setDBAuth');
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!userDbParams.authenticated) {
|
if (forceToBeAuthenticated && !dbParams.authenticated) {
|
||||||
return next(new Error('permission denied'));
|
return next(new Error('permission denied'));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.locals.userDbParams = userDbParams;
|
res.locals.userDbParams = dbParams;
|
||||||
|
res.locals.authDbParams = authDbParams;
|
||||||
|
res.locals.userLimits = userLimits;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
@ -29,6 +29,7 @@ describe('app-configuration', function() {
|
|||||||
it('GET /api/v1/sql', function(done){
|
it('GET /api/v1/sql', function(done){
|
||||||
assert.response(server, {
|
assert.response(server, {
|
||||||
url: '/api/v1/sql',
|
url: '/api/v1/sql',
|
||||||
|
headers: {host: 'vizzuality.cartodb.com'},
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},{
|
},{
|
||||||
status: 400
|
status: 400
|
||||||
|
Loading…
Reference in New Issue
Block a user