Use authenticated middleware in query controller

This commit is contained in:
Daniel García Aubert 2018-02-19 13:24:44 +01:00
parent 114070ef96
commit 75c2d85dbb
4 changed files with 32 additions and 31 deletions

View File

@ -15,13 +15,14 @@ module.exports = JobController;
JobController.prototype.route = function (app) {
const { base_url } = global.settings;
const forceToBeAuthenticated = true;
app.post(
`${base_url}/sql/job`,
checkBodyPayloadSize(),
userMiddleware(),
credentialsMiddleware(),
authenticatedMiddleware(this.userDatabaseService),
authenticatedMiddleware(this.userDatabaseService, forceToBeAuthenticated),
createJob(this.jobService),
setServedByDBHostHeader(),
profile(),
@ -46,7 +47,7 @@ JobController.prototype.route = function (app) {
`${base_url}/sql/job/:job_id`,
userMiddleware(),
credentialsMiddleware(),
authenticatedMiddleware(this.userDatabaseService),
authenticatedMiddleware(this.userDatabaseService, forceToBeAuthenticated),
getJob(this.jobService),
setServedByDBHostHeader(),
profile(),
@ -60,7 +61,7 @@ JobController.prototype.route = function (app) {
`${base_url}/sql/job/:job_id`,
userMiddleware(),
credentialsMiddleware(),
authenticatedMiddleware(this.userDatabaseService),
authenticatedMiddleware(this.userDatabaseService, forceToBeAuthenticated),
cancelJob(this.jobService),
setServedByDBHostHeader(),
profile(),

View File

@ -5,7 +5,6 @@ var step = require('step');
var assert = require('assert');
var PSQL = require('cartodb-psql');
var CachedQueryTables = require('../services/cached-query-tables');
var AuthApi = require('../auth/auth_api');
var queryMayWrite = require('../utils/query_may_write');
var formats = require('../models/formats');
@ -15,6 +14,7 @@ var getContentDisposition = require('../utils/content_disposition');
const credentialsMiddleware = require('../middlewares/credentials');
const userMiddleware = require('../middlewares/user');
const errorMiddleware = require('../middlewares/error');
const authenticatedMiddleware = require('../middlewares/authenticated-request');
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) {
const { base_url } = global.settings;
app.all(
global.settings.base_url + '/sql',
`${base_url}/sql`,
userMiddleware(),
credentialsMiddleware(),
authenticatedMiddleware(this.userDatabaseService),
this.handleQuery.bind(this),
errorMiddleware()
);
app.all(
global.settings.base_url + '/sql.:f',
`${base_url}/sql.:f`,
userMiddleware(),
credentialsMiddleware(),
authenticatedMiddleware(this.userDatabaseService),
this.handleQuery.bind(this),
errorMiddleware()
);
@ -47,7 +51,7 @@ QueryController.prototype.handleQuery = function (req, res, next) {
// extract input
var body = (req.body) ? req.body : {};
// 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 limit = parseInt(params.rows_per_page);
var offset = parseInt(params.page);
@ -58,11 +62,12 @@ QueryController.prototype.handleQuery = function (req, res, next) {
var requestedFilename = params.filename;
var filename = requestedFilename;
var requestedSkipfields = params.skipfields;
var cdbUsername = res.locals.user;
const { user: username, userDbParams: dbopts, authDbParams, userLimits } = res.locals;
var skipfields;
var dp = params.dp; // decimal point digits (defaults to 6)
var gn = "the_geom"; // TODO: read from configuration FILE
var userLimits;
if ( req.profiler ) {
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");
}
// Database options
var dbopts = {};
var formatter;
if ( req.profiler ) {
req.profiler.done('init');
}
// 1. Get user database and related parameters
// 3. Get the list of tables affected by the query
// 4. Setup headers
// 5. Send formatted results back
// 1. Get the list of tables affected by the query
// 2. Setup headers
// 3. Send formatted results back
// 4. Handle error
step(
function getUserDBInfo() {
self.userDatabaseService.getConnectionParams(new AuthApi(req, res, params), cdbUsername, this);
},
function queryExplain(err, dbParams, authDbParams, userTimeoutLimits) {
assert.ifError(err);
function queryExplain() {
var next = this;
dbopts = dbParams;
userLimits = userTimeoutLimits;
if ( req.profiler ) {
req.profiler.done('setDBAuth');
}
@ -150,6 +145,7 @@ QueryController.prototype.handleQuery = function (req, res, next) {
checkAborted('queryExplain');
var pg = new PSQL(authDbParams);
var skipCache = !!dbopts.authenticated;
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();
var opts = {
username: cdbUsername,
username: username,
dbopts: dbopts,
sink: res,
gn: gn,

View File

@ -3,28 +3,31 @@
var _ = require('underscore');
var AuthApi = require('../auth/auth_api');
function authenticatedMiddleware(userDatabaseService) {
function authenticatedMiddleware(userDatabaseService, forceToBeAuthenticated = false) {
return function middleware(req, res, next) {
req.profiler.start('sqlapi.job');
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
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);
userDatabaseService.getConnectionParams(authApi, res.locals.user, function connectionParams(err, userDbParams) {
userDatabaseService.getConnectionParams(authApi, user, function (err, dbParams, authDbParams, userLimits) {
req.profiler.done('setDBAuth');
if (err) {
return next(err);
}
if (!userDbParams.authenticated) {
if (forceToBeAuthenticated && !dbParams.authenticated) {
return next(new Error('permission denied'));
}
res.locals.userDbParams = userDbParams;
res.locals.userDbParams = dbParams;
res.locals.authDbParams = authDbParams;
res.locals.userLimits = userLimits;
next();
});

View File

@ -29,6 +29,7 @@ describe('app-configuration', function() {
it('GET /api/v1/sql', function(done){
assert.response(server, {
url: '/api/v1/sql',
headers: {host: 'vizzuality.cartodb.com'},
method: 'GET'
},{
status: 400