# frozen_string_literal: true require 'bson' require 'date' require 'opentracing/instrumentation/mongo/direct_sanitazer' module OpenTracing module Instrumentation module Mongo # QuerySanitazer clean private data from requests. class QuerySanitazer < DirectSanitazer DEFAULT_SAFE_CLASSES = [ TrueClass, FalseClass, Numeric, Date, Time, ].freeze DEFAULT_EXCLUDE_KEYS = %w[lsid].freeze def initialize( safety_argument_checker: SampleSafetyArgumentChecker.new, safe_classes: DEFAULT_SAFE_CLASSES, exclude_keys: DEFAULT_EXCLUDE_KEYS ) super() @safety_argument_checker = safety_argument_checker @safe_classes = safe_classes @exclude_keys = exclude_keys end def sanitaze(command, command_name) command_without_command_name = super(command, command_name) exclude_keys.each do |key| command_without_command_name.delete(key) end sanitaze_value(command_without_command_name) end private attr_reader :safe_classes, :exclude_keys, :safety_argument_checker OBJECT_ID_PLACEHOLDER = '$oid' STRING_PLACEHOLDER = '$string' PLACEHOLDER = '?' def sanitaze_value(value) case value when Hash sanitaze_hash(value) when Enumerable sanitaze_array(value) else sanitaze_simple(value) end end def sanitaze_simple(value) case value when BSON::ObjectId OBJECT_ID_PLACEHOLDER when String STRING_PLACEHOLDER when *safe_classes value else PLACEHOLDER end end def sanitaze_hash(hash) hash.map do |(key, value)| # TODO: pass command name. # TODO: recursive build path to key safe_value = if safety_argument_checker.argument_safe?(nil, key, value) value else sanitaze_value(value) end [key, safe_value] end.to_h end def sanitaze_array(array) array.map do |value| sanitaze_value(value) end end end end end end