Skip to content

Commit be3eaaf

Browse files
committed
RUBY-1021 Test and documentation for Redacted Options
1 parent ec242d4 commit be3eaaf

File tree

3 files changed

+170
-6
lines changed

3 files changed

+170
-6
lines changed

lib/mongo/client.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,14 @@ def list_databases
292292
private
293293

294294
def create_from_addresses(addresses, opts = {})
295-
@options = Options::Redacted.new.merge(Database::DEFAULT_OPTIONS.merge(opts)).freeze
295+
@options = Options::Redacted.new(Database::DEFAULT_OPTIONS.merge(opts)).freeze
296296
@cluster = Cluster.new(addresses, @monitoring, options)
297297
@database = Database.new(self, options[:database], options)
298298
end
299299

300300
def create_from_uri(connection_string, opts = {})
301301
uri = URI.new(connection_string, opts)
302-
@options = Options::Redacted.new.merge(Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts))).freeze
302+
@options = Options::Redacted.new(Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts))).freeze
303303
@cluster = Cluster.new(uri.servers, @monitoring, options)
304304
@database = Database.new(self, options[:database], options)
305305
end

lib/mongo/options/redacted.rb

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,63 @@
1515
module Mongo
1616
module Options
1717

18-
REDACTED_OPTIONS = [:password, :pwd]
19-
REDACTED_STRING = '<REDACTED>'
20-
18+
# Class for wrapping options that could be sensitive.
19+
# When printed, the sensitive values will be redacted.
20+
#
21+
# @since 2.1.0
2122
class Redacted < BSON::Document
2223

24+
# The options whose values will be redacted.
25+
#
26+
# @since 2.1.0
27+
SENSITIVE_OPTIONS = [ :password,
28+
:pwd ]
29+
30+
# The replacement string used in place of the value for sensitive keys.
31+
#
32+
# @since 2.1.0
33+
STRING_REPLACEMENT = '<REDACTED>'
34+
35+
# Get a string representation of the options.
36+
#
37+
# @return [ String ] The string representation of the options.
38+
#
39+
# @since 2.1.0
2340
def inspect
2441
'{' + reduce([]) do |list, (k, v)|
2542
list << "#{k.inspect}=>#{redact(k, v, __method__)}"
2643
end.join(', ') + '}'
2744
end
2845

46+
# Get a string representation of the options.
47+
#
48+
# @return [ String ] The string representation of the options.
49+
#
50+
# @since 2.1.0
2951
def to_s
3052
'{' + reduce([]) do |list, (k, v)|
3153
list << "#{k.to_s}=>#{redact(k, v, __method__)}"
3254
end.join(', ') + '}'
3355
end
3456

57+
# Whether these options contain a given key.
58+
#
59+
# @example Determine if the options contain a given key.
60+
# options.has_key?(:name)
61+
#
62+
# @param [ String, Symbol ] key The key to check for existence.
63+
#
64+
# @return [ true, false ] If the options contain the given key.
65+
#
66+
# @since 2.1.0
3567
def has_key?(key)
3668
super(convert_key(key))
3769
end
3870

3971
private
4072

4173
def redact(k, v, method)
42-
return REDACTED_STRING if REDACTED_OPTIONS.include?(k.to_sym)
74+
return STRING_REPLACEMENT if SENSITIVE_OPTIONS.include?(k.to_sym)
4375
v.send(method)
4476
end
4577
end

spec/mongo/options/redacted_spec.rb

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
require 'spec_helper'
2+
3+
describe Mongo::Options::Redacted do
4+
5+
let(:options) do
6+
described_class.new(original_opts)
7+
end
8+
9+
describe '#to_s' do
10+
11+
context 'when the hash contains a sensitive key' do
12+
13+
let(:original_opts) do
14+
{ password: '123' }
15+
end
16+
17+
it 'replaces the value with the redacted string' do
18+
expect(options.to_s).not_to match(/123/)
19+
end
20+
21+
it 'replaces the value with the redacted string' do
22+
expect(options.to_s).to match(Mongo::Options::Redacted::STRING_REPLACEMENT)
23+
end
24+
end
25+
26+
context 'when the hash does not contain a sensitive key' do
27+
28+
it 'prints all the values' do
29+
30+
end
31+
end
32+
end
33+
34+
describe '#inspect' do
35+
36+
context 'when the hash contains a sensitive key' do
37+
38+
let(:original_opts) do
39+
{ password: '123' }
40+
end
41+
42+
it 'replaces the value with the redacted string' do
43+
expect(options.inspect).not_to match(/123/)
44+
end
45+
46+
it 'replaces the value with the redacted string' do
47+
expect(options.inspect).to match(Mongo::Options::Redacted::STRING_REPLACEMENT)
48+
end
49+
end
50+
51+
context 'when the hash does not contain a sensitive key' do
52+
53+
let(:original_opts) do
54+
{ name: '123' }
55+
end
56+
57+
it 'does not replace the value with the redacted string' do
58+
expect(options.inspect).to match(/123/)
59+
end
60+
61+
it 'does not replace the value with the redacted string' do
62+
expect(options.inspect).not_to match(Mongo::Options::Redacted::STRING_REPLACEMENT)
63+
end
64+
end
65+
end
66+
67+
describe '#has_key?' do
68+
69+
context 'when the original key is a String' do
70+
71+
let(:original_opts) do
72+
{ 'name' => 'Emily' }
73+
end
74+
75+
context 'when the method argument is a String' do
76+
77+
it 'returns true when ' do
78+
expect(options.has_key?('name')).to be(true)
79+
end
80+
end
81+
82+
context 'when method argument is a Symbol' do
83+
84+
it 'returns true' do
85+
expect(options.has_key?(:name)).to be(true)
86+
end
87+
end
88+
end
89+
90+
context 'when the original key is a Symbol' do
91+
92+
let(:original_opts) do
93+
{ name: 'Emily' }
94+
end
95+
96+
context 'when the method argument is a String' do
97+
98+
it 'returns true when ' do
99+
expect(options.has_key?('name')).to be(true)
100+
end
101+
end
102+
103+
context 'when method argument is a Symbol' do
104+
105+
it 'returns true' do
106+
expect(options.has_key?(:name)).to be(true)
107+
end
108+
end
109+
end
110+
111+
context 'when the hash does not contain the key' do
112+
113+
let(:original_opts) do
114+
{ other: 'Emily' }
115+
end
116+
117+
context 'when the method argument is a String' do
118+
119+
it 'returns true when ' do
120+
expect(options.has_key?('name')).to be(false)
121+
end
122+
end
123+
124+
context 'when method argument is a Symbol' do
125+
126+
it 'returns true' do
127+
expect(options.has_key?(:name)).to be(false)
128+
end
129+
end
130+
end
131+
end
132+
end

0 commit comments

Comments
 (0)