Class: SchwabRb::Redactor

Inherits:
Object
  • Object
show all
Defined in:
lib/schwab_rb/utils/redactor.rb

Constant Summary collapse

ACCOUNT_NUMBER_PATTERN =
/\b\d{8,12}\b/.freeze
ACCOUNT_HASH_PATTERN =
/\b[A-Z0-9]{32}\b/.freeze
SENSITIVE_KEYS =

JSON keys that commonly contain sensitive account information

%w[
  accountNumber
  accountId
  accountHash
  hashValue
  encryptedId
].freeze

Class Method Summary collapse

Class Method Details

.redact_data(data) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/schwab_rb/utils/redactor.rb', line 28

def self.redact_data(data)
  return data unless data

  case data
  when Hash
    redact_hash(data)
  when String
    begin
      parsed = JSON.parse(data)
      redact_data(parsed).to_json
    rescue JSON::ParserError
      redact_string(data)
    end
  else
    data
  end
end

.redact_hash(hash) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/schwab_rb/utils/redactor.rb', line 72

def self.redact_hash(hash)
  hash.each_with_object({}) do |(key, value), redacted|
    redacted[key] = if SENSITIVE_KEYS.include?(key.to_s)
                      "[REDACTED]"
    else
      case value
      when Hash
        redact_hash(value)
      when Array
        value.map { |item| redact_data(item) }
      when String
        redact_string(value)
      else
        value
      end
                    end
  end
end

.redact_response_body(response) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/schwab_rb/utils/redactor.rb', line 46

def self.redact_response_body(response)
  return unless response.respond_to?(:body)

  body = response.body
  return unless body

  begin
    if body.is_a?(String)
      parsed = JSON.parse(body)
      redact_data(parsed)
    elsif body.respond_to?(:read)
      content = body.read
      body.rewind if body.respond_to?(:rewind)
      parsed = JSON.parse(content)
      redact_data(parsed)
    else
      redact_data(body)
    end
  rescue JSON::ParserError
    # If it's not JSON, just redact as a string
    body_str = body.respond_to?(:read) ? body.read : body.to_s
    body.rewind if body.respond_to?(:rewind)
    redact_string(body_str)
  end
end

.redact_string(str) ⇒ Object



91
92
93
94
95
96
97
98
# File 'lib/schwab_rb/utils/redactor.rb', line 91

def self.redact_string(str)
  return str unless str.is_a?(String)

  redacted = str.dup
  redacted.gsub!(, "[REDACTED_ACCOUNT_NUMBER]")
  redacted.gsub!(, "[REDACTED_ACCOUNT_HASH]")
  redacted
end

.redact_url(url_string) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/schwab_rb/utils/redactor.rb', line 19

def self.redact_url(url_string)
  return url_string unless url_string

  redacted = url_string.to_s.dup
  redacted.gsub!(, "[REDACTED_ACCOUNT_NUMBER]")
  redacted.gsub!(, "[REDACTED_ACCOUNT_HASH]")
  redacted
end