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
						
					
					
				| '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
 | |
| };
 |