2019-07-26 17:34:15 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const sanitizeFilename = require('../utils/filename_sanitizer');
|
|
|
|
const formats = require('../models/formats');
|
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
module.exports = function parameters ({ strategy = 'query' } = {}) {
|
|
|
|
const getParameters = getParametersFromStrategy(strategy);
|
2019-07-26 22:41:16 +08:00
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
return function parametersMiddleware (req, res, next) {
|
2019-07-26 22:51:11 +08:00
|
|
|
const input = Object.assign({}, req.query, req.body || {});
|
2019-07-26 22:41:16 +08:00
|
|
|
|
|
|
|
try {
|
2019-07-26 23:18:18 +08:00
|
|
|
res.locals.params = getParameters(input);
|
2019-07-26 22:41:16 +08:00
|
|
|
next();
|
|
|
|
} catch (err) {
|
|
|
|
next(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
function getParametersFromStrategy (strategy) {
|
2019-07-26 22:41:16 +08:00
|
|
|
let fn;
|
2019-07-26 22:06:53 +08:00
|
|
|
|
|
|
|
switch (strategy) {
|
|
|
|
case('query'):
|
2019-07-26 23:18:18 +08:00
|
|
|
fn = queryParametersStrategy;
|
2019-07-26 22:06:53 +08:00
|
|
|
break;
|
|
|
|
case('job'):
|
2019-07-26 23:18:18 +08:00
|
|
|
fn = jobParametersStrategy;
|
2019-07-26 22:06:53 +08:00
|
|
|
break;
|
|
|
|
case('copyfrom'):
|
2019-07-26 23:18:18 +08:00
|
|
|
fn = copyFromParametersStrategy;
|
2019-07-26 22:06:53 +08:00
|
|
|
break;
|
|
|
|
case('copyto'):
|
2019-07-26 23:18:18 +08:00
|
|
|
fn = copyToParametersStrategy;
|
2019-07-26 22:06:53 +08:00
|
|
|
break;
|
|
|
|
default:
|
2019-07-26 22:41:16 +08:00
|
|
|
throw new Error('Missig parameter strategy');
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 22:41:16 +08:00
|
|
|
return fn;
|
|
|
|
}
|
2019-07-26 22:06:53 +08:00
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
function queryParametersStrategy (input) {
|
2019-07-26 22:06:53 +08:00
|
|
|
const params = {};
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.sql = input.q;
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:06:53 +08:00
|
|
|
if (typeof params.sql !== 'string') {
|
2019-07-26 22:41:16 +08:00
|
|
|
throw new Error('You must indicate a sql query');
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.format = parseFormat(input.format);
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:06:53 +08:00
|
|
|
if (!formats.hasOwnProperty(params.format) ) {
|
2019-07-26 22:41:16 +08:00
|
|
|
throw new Error(`Invalid format: ${params.format}`);
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.orderBy = input.order_by;
|
|
|
|
params.sortOrder = input.sort_order;
|
|
|
|
params.skipfields = parseSkipFiles(input.skipfields);
|
|
|
|
params.decimalPrecision = input.dp ? input.dp : '6';
|
|
|
|
params.filename = parseQueryFilename(input.filename);
|
|
|
|
params.limit = parseLimit(input.rows_per_page);
|
|
|
|
params.offset = parseOffset(input.page, params.limit);
|
|
|
|
params.callback = input.callback;
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:41:16 +08:00
|
|
|
return params;
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
function jobParametersStrategy (input) {
|
2019-07-26 22:06:53 +08:00
|
|
|
const params = {};
|
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.sql = input.query;
|
2019-07-26 22:06:53 +08:00
|
|
|
|
2019-07-26 22:41:16 +08:00
|
|
|
return params;
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
function copyFromParametersStrategy (input) {
|
2019-07-26 22:06:53 +08:00
|
|
|
const params = {};
|
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.sql = input.q;
|
2019-07-26 22:06:53 +08:00
|
|
|
|
|
|
|
if (typeof params.sql !== 'string') {
|
2019-07-26 22:41:16 +08:00
|
|
|
throw new Error('SQL is missing');
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 22:41:16 +08:00
|
|
|
if (!params.sql.toUpperCase().startsWith('COPY ')) {
|
|
|
|
throw new Error('SQL must start with COPY');
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 22:41:16 +08:00
|
|
|
return params;
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 23:18:18 +08:00
|
|
|
function copyToParametersStrategy (input) {
|
2019-07-26 22:06:53 +08:00
|
|
|
const params = {};
|
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.sql = input.q;
|
2019-07-26 22:06:53 +08:00
|
|
|
|
|
|
|
if (typeof params.sql !== 'string') {
|
2019-07-26 22:41:16 +08:00
|
|
|
throw new Error('SQL is missing');
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!params.sql .toUpperCase().startsWith('COPY ')) {
|
2019-07-26 22:41:16 +08:00
|
|
|
throw new Error('SQL must start with COPY');
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
|
|
|
|
2019-07-26 22:51:11 +08:00
|
|
|
params.filename = input.filename ? input.filename : 'carto-sql-copyto.dmp';
|
2019-07-26 22:06:53 +08:00
|
|
|
|
2019-07-26 22:41:16 +08:00
|
|
|
return params;
|
2019-07-26 22:06:53 +08:00
|
|
|
}
|
2019-07-26 17:34:15 +08:00
|
|
|
|
2019-07-26 22:06:53 +08:00
|
|
|
function parseQueryFilename (inputFilename) {
|
2019-07-26 17:34:15 +08:00
|
|
|
return (inputFilename === '' || inputFilename === undefined) ? 'cartodb-query' : sanitizeFilename(inputFilename);
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseOffset (inputPage, inputLimit) {
|
|
|
|
let offset;
|
|
|
|
|
|
|
|
offset = parseInt(inputPage, 10);
|
|
|
|
|
|
|
|
if (Number.isFinite(offset)) {
|
|
|
|
offset = offset * inputLimit;
|
|
|
|
} else {
|
|
|
|
offset = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseLimit (inputLimit) {
|
|
|
|
let limit;
|
|
|
|
|
|
|
|
limit = parseInt(inputLimit, 10);
|
|
|
|
|
|
|
|
if (!Number.isFinite(limit)) {
|
|
|
|
limit = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseFormat (inputFormat) {
|
|
|
|
let format;
|
|
|
|
|
|
|
|
if (Array.isArray(inputFormat)) {
|
|
|
|
format = inputFormat[inputFormat.length - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inputFormat === '' || inputFormat === undefined) {
|
|
|
|
format = 'json';
|
|
|
|
} else if (typeof inputFormat === 'string'){
|
|
|
|
format = inputFormat.toLowerCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Accept both comma-separated string or array of comma-separated strings
|
|
|
|
function parseSkipFiles (inputSkippedFiles) {
|
|
|
|
let skipfields;
|
|
|
|
|
|
|
|
if (!inputSkippedFiles) {
|
|
|
|
skipfields = [];
|
|
|
|
return skipfields;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof inputSkippedFiles === 'string' ) {
|
|
|
|
skipfields = inputSkippedFiles.split(',');
|
|
|
|
return skipfields;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Array.isArray(inputSkippedFiles) ) {
|
|
|
|
skipfields = [];
|
|
|
|
|
|
|
|
inputSkippedFiles.forEach(e => {
|
|
|
|
skipfields = skipfields.concat(e.split(','));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return skipfields;
|
|
|
|
}
|