appsignal/appsignal

View on GitHub
lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module Appsignal
  class EventFormatter
    # @api private
    module MongoRubyDriver
      class QueryFormatter
        ALLOWED = {
          "find" => {
            "find"   => :allow,
            "filter" => :sanitize_document
          },
          "count" => {
            "count" => :allow,
            "query" => :sanitize_document
          },
          "distinct" => {
            "distinct" => :allow,
            "key"      => :allow,
            "query"    => :sanitize_document
          },
          "insert" => {
            "insert"    => :allow,
            "documents" => :deny_array,
            "ordered"   => :allow
          },
          "update" => {
            "update"  => :allow,
            "updates" => :sanitize_bulk,
            "ordered" => :allow
          },
          "findandmodify" => {
            "findandmodify" => :allow,
            "query"         => :sanitize_document,
            "update"        => :deny_array,
            "new"           => :allow
          },
          "delete" => {
            "delete" => :allow,
            "deletes" => :sanitize_bulk,
            "ordered" => :allow
          },
          "bulk" => {
            "q"      => :sanitize_document,
            "u"      => :deny_array,
            "limit"  => :allow,
            "multi"  => :allow,
            "upsert" => :allow
          }
        }.freeze

        # Format command based on given strategy
        def self.format(strategy, command)
          # Stop processing if command is not a hash
          return {} unless command.is_a?(Hash)

          # Get the strategy and stop if it's not present
          strategies = ALLOWED[strategy.to_s]
          return {} unless strategies

          {}.tap do |hsh|
            command.each do |key, val|
              hsh[key] = apply_strategy(strategies[key], val)
            end
          end
        end

        # Applies strategy on hash values based on keys
        def self.apply_strategy(strategy, val)
          case strategy
          when :allow      then val
          when :deny       then "?"
          when :deny_array then "[?]"
          when :sanitize_document
            Appsignal::Utils::QueryParamsSanitizer.sanitize(val, true, :mongodb)
          when :sanitize_bulk
            if val.length > 1
              [
                format(:bulk, val.first),
                "[...]"
              ]
            else
              val.map { |v| format(:bulk, v) }
            end
          else "?"
          end
        end
      end
    end
  end
end