You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.2 KiB
125 lines
3.2 KiB
2 months ago
|
'use strict';
|
||
|
const Msg = require('./core/connection/msg').Msg;
|
||
|
const KillCursor = require('./core/connection/commands').KillCursor;
|
||
|
const GetMore = require('./core/connection/commands').GetMore;
|
||
|
const deepCopy = require('./utils').deepCopy;
|
||
|
|
||
|
/** Commands that we want to redact because of the sensitive nature of their contents */
|
||
|
const SENSITIVE_COMMANDS = new Set([
|
||
|
'authenticate',
|
||
|
'saslStart',
|
||
|
'saslContinue',
|
||
|
'getnonce',
|
||
|
'createUser',
|
||
|
'updateUser',
|
||
|
'copydbgetnonce',
|
||
|
'copydbsaslstart',
|
||
|
'copydb'
|
||
|
]);
|
||
|
|
||
|
const HELLO_COMMANDS = new Set(['hello', 'ismaster', 'isMaster']);
|
||
|
|
||
|
const LEGACY_FIND_QUERY_MAP = {
|
||
|
$query: 'filter',
|
||
|
$orderby: 'sort',
|
||
|
$hint: 'hint',
|
||
|
$comment: 'comment',
|
||
|
$maxScan: 'maxScan',
|
||
|
$max: 'max',
|
||
|
$min: 'min',
|
||
|
$returnKey: 'returnKey',
|
||
|
$showDiskLoc: 'showRecordId',
|
||
|
$maxTimeMS: 'maxTimeMS',
|
||
|
$snapshot: 'snapshot'
|
||
|
};
|
||
|
|
||
|
const LEGACY_FIND_OPTIONS_MAP = {
|
||
|
numberToSkip: 'skip',
|
||
|
numberToReturn: 'batchSize',
|
||
|
returnFieldsSelector: 'projection'
|
||
|
};
|
||
|
|
||
|
const OP_QUERY_KEYS = [
|
||
|
'tailable',
|
||
|
'oplogReplay',
|
||
|
'noCursorTimeout',
|
||
|
'awaitData',
|
||
|
'partial',
|
||
|
'exhaust'
|
||
|
];
|
||
|
|
||
|
const collectionName = command => command.ns.split('.')[1];
|
||
|
|
||
|
const shouldRedactCommand = (commandName, cmd) =>
|
||
|
SENSITIVE_COMMANDS.has(commandName) ||
|
||
|
(HELLO_COMMANDS.has(commandName) && !!cmd.speculativeAuthenticate);
|
||
|
|
||
|
/**
|
||
|
* Extract the actual command from the query, possibly upconverting if it's a legacy
|
||
|
* format
|
||
|
*
|
||
|
* @param {Object} command the command
|
||
|
*/
|
||
|
const extractCommand = command => {
|
||
|
let extractedCommand;
|
||
|
if (command instanceof GetMore) {
|
||
|
extractedCommand = {
|
||
|
getMore: deepCopy(command.cursorId),
|
||
|
collection: collectionName(command),
|
||
|
batchSize: command.numberToReturn
|
||
|
};
|
||
|
} else if (command instanceof KillCursor) {
|
||
|
extractedCommand = {
|
||
|
killCursors: collectionName(command),
|
||
|
cursors: deepCopy(command.cursorIds)
|
||
|
};
|
||
|
} else if (command instanceof Msg) {
|
||
|
extractedCommand = deepCopy(command.command);
|
||
|
} else if (command.query && command.query.$query) {
|
||
|
let result;
|
||
|
if (command.ns === 'admin.$cmd') {
|
||
|
// upconvert legacy command
|
||
|
result = Object.assign({}, command.query.$query);
|
||
|
} else {
|
||
|
// upconvert legacy find command
|
||
|
result = { find: collectionName(command) };
|
||
|
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
|
||
|
if (typeof command.query[key] !== 'undefined')
|
||
|
result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
|
||
|
if (typeof command[key] !== 'undefined')
|
||
|
result[LEGACY_FIND_OPTIONS_MAP[key]] = deepCopy(command[key]);
|
||
|
});
|
||
|
|
||
|
OP_QUERY_KEYS.forEach(key => {
|
||
|
if (command[key]) result[key] = command[key];
|
||
|
});
|
||
|
|
||
|
if (typeof command.pre32Limit !== 'undefined') {
|
||
|
result.limit = command.pre32Limit;
|
||
|
}
|
||
|
|
||
|
if (command.query.$explain) {
|
||
|
extractedCommand = { explain: result };
|
||
|
} else {
|
||
|
extractedCommand = result;
|
||
|
}
|
||
|
} else {
|
||
|
extractedCommand = deepCopy(command.query || command);
|
||
|
}
|
||
|
|
||
|
const commandName = Object.keys(extractedCommand)[0];
|
||
|
return {
|
||
|
cmd: extractedCommand,
|
||
|
name: commandName,
|
||
|
shouldRedact: shouldRedactCommand(commandName, extractedCommand)
|
||
|
};
|
||
|
};
|
||
|
|
||
|
module.exports = {
|
||
|
extractCommand
|
||
|
};
|