command_utils.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. 'use strict';
  2. const Msg = require('./core/connection/msg').Msg;
  3. const KillCursor = require('./core/connection/commands').KillCursor;
  4. const GetMore = require('./core/connection/commands').GetMore;
  5. const deepCopy = require('./utils').deepCopy;
  6. /** Commands that we want to redact because of the sensitive nature of their contents */
  7. const SENSITIVE_COMMANDS = new Set([
  8. 'authenticate',
  9. 'saslStart',
  10. 'saslContinue',
  11. 'getnonce',
  12. 'createUser',
  13. 'updateUser',
  14. 'copydbgetnonce',
  15. 'copydbsaslstart',
  16. 'copydb'
  17. ]);
  18. const HELLO_COMMANDS = new Set(['hello', 'ismaster', 'isMaster']);
  19. const LEGACY_FIND_QUERY_MAP = {
  20. $query: 'filter',
  21. $orderby: 'sort',
  22. $hint: 'hint',
  23. $comment: 'comment',
  24. $maxScan: 'maxScan',
  25. $max: 'max',
  26. $min: 'min',
  27. $returnKey: 'returnKey',
  28. $showDiskLoc: 'showRecordId',
  29. $maxTimeMS: 'maxTimeMS',
  30. $snapshot: 'snapshot'
  31. };
  32. const LEGACY_FIND_OPTIONS_MAP = {
  33. numberToSkip: 'skip',
  34. numberToReturn: 'batchSize',
  35. returnFieldsSelector: 'projection'
  36. };
  37. const OP_QUERY_KEYS = [
  38. 'tailable',
  39. 'oplogReplay',
  40. 'noCursorTimeout',
  41. 'awaitData',
  42. 'partial',
  43. 'exhaust'
  44. ];
  45. const collectionName = command => command.ns.split('.')[1];
  46. const shouldRedactCommand = (commandName, cmd) =>
  47. SENSITIVE_COMMANDS.has(commandName) ||
  48. (HELLO_COMMANDS.has(commandName) && !!cmd.speculativeAuthenticate);
  49. /**
  50. * Extract the actual command from the query, possibly upconverting if it's a legacy
  51. * format
  52. *
  53. * @param {Object} command the command
  54. */
  55. const extractCommand = command => {
  56. let extractedCommand;
  57. if (command instanceof GetMore) {
  58. extractedCommand = {
  59. getMore: deepCopy(command.cursorId),
  60. collection: collectionName(command),
  61. batchSize: command.numberToReturn
  62. };
  63. } else if (command instanceof KillCursor) {
  64. extractedCommand = {
  65. killCursors: collectionName(command),
  66. cursors: deepCopy(command.cursorIds)
  67. };
  68. } else if (command instanceof Msg) {
  69. extractedCommand = deepCopy(command.command);
  70. } else if (command.query && command.query.$query) {
  71. let result;
  72. if (command.ns === 'admin.$cmd') {
  73. // upconvert legacy command
  74. result = Object.assign({}, command.query.$query);
  75. } else {
  76. // upconvert legacy find command
  77. result = { find: collectionName(command) };
  78. Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
  79. if (typeof command.query[key] !== 'undefined')
  80. result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
  81. });
  82. }
  83. Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
  84. if (typeof command[key] !== 'undefined')
  85. result[LEGACY_FIND_OPTIONS_MAP[key]] = deepCopy(command[key]);
  86. });
  87. OP_QUERY_KEYS.forEach(key => {
  88. if (command[key]) result[key] = command[key];
  89. });
  90. if (typeof command.pre32Limit !== 'undefined') {
  91. result.limit = command.pre32Limit;
  92. }
  93. if (command.query.$explain) {
  94. extractedCommand = { explain: result };
  95. } else {
  96. extractedCommand = result;
  97. }
  98. } else {
  99. extractedCommand = deepCopy(command.query || command);
  100. }
  101. const commandName = Object.keys(extractedCommand)[0];
  102. return {
  103. cmd: extractedCommand,
  104. name: commandName,
  105. shouldRedact: shouldRedactCommand(commandName, extractedCommand)
  106. };
  107. };
  108. module.exports = {
  109. extractCommand
  110. };