airbrake-ruby 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +5 -36
- data/lib/airbrake-ruby/backtrace.rb +1 -1
- data/lib/airbrake-ruby/filters/keys_blacklist.rb +1 -1
- data/lib/airbrake-ruby/filters/keys_filter.rb +35 -1
- data/lib/airbrake-ruby/filters/keys_whitelist.rb +2 -2
- data/lib/airbrake-ruby/notice.rb +13 -20
- data/lib/airbrake-ruby/notifier.rb +11 -29
- data/lib/airbrake-ruby/sync_sender.rb +4 -6
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +0 -8
- data/spec/notifier_spec.rb +0 -262
- data/spec/notifier_spec/blacklist_keys_spec.rb +192 -0
- data/spec/notifier_spec/options_spec.rb +0 -195
- data/spec/notifier_spec/whitelist_keys_spec.rb +246 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab4ce2485ab1b938a76f15f2b71d92db0fe6e0e2
|
4
|
+
data.tar.gz: a48ae79d2523577c1400d2ed6b914e5340e9f5ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05d26b46d931156979aa32411b8d722c46023056eee2d0545be53df86a26e5ee565640a59999ddd37d1b947db44f113ac6dc636df5e9b6cb800682d66ef87c55
|
7
|
+
data.tar.gz: ec26b798eb2c9139ffbd44a0bd42385886663fade0ddcab147ea0b6d68b94c4635813398fe9c2b0b4e87398d26099751d016900e3b026cfac79acd0dc29d9998
|
data/lib/airbrake-ruby.rb
CHANGED
@@ -69,6 +69,11 @@ module Airbrake
|
|
69
69
|
# for special cases where we need to work around older implementations
|
70
70
|
RUBY_19 = RUBY_VERSION.start_with?('1.9')
|
71
71
|
|
72
|
+
##
|
73
|
+
# @return [Boolean] true if current Ruby is Ruby 2.0.*. The result is used
|
74
|
+
# for special cases where we need to work around older implementations
|
75
|
+
RUBY_20 = RUBY_VERSION.start_with?('2.0')
|
76
|
+
|
72
77
|
##
|
73
78
|
# A Hash that holds all notifiers. The keys of the Hash are notifier
|
74
79
|
# names, the values are Airbrake::Notifier instances.
|
@@ -188,42 +193,6 @@ module Airbrake
|
|
188
193
|
call_notifier(notifier, __method__, filter, &block)
|
189
194
|
end
|
190
195
|
|
191
|
-
##
|
192
|
-
# Specifies which keys should *not* be filtered. All other keys will be
|
193
|
-
# substituted with the +[Filtered]+ label.
|
194
|
-
#
|
195
|
-
# @macro proxy_method
|
196
|
-
# @example
|
197
|
-
# Airbrake.whitelist([:email, /user/i, 'account_id'])
|
198
|
-
#
|
199
|
-
# @param [Array<String, Symbol, Regexp>] keys The keys, which shouldn't be
|
200
|
-
# filtered
|
201
|
-
# @return [void]
|
202
|
-
# @since v5.0.0
|
203
|
-
# @see .blacklist_keys
|
204
|
-
# @deprecated Please use {Airbrake::Config#whitelist_keys} instead
|
205
|
-
def whitelist_keys(keys, notifier = :default)
|
206
|
-
call_notifier(notifier, __method__, keys)
|
207
|
-
end
|
208
|
-
|
209
|
-
##
|
210
|
-
# Specifies which keys *should* be filtered. Such keys will be replaced with
|
211
|
-
# the +[Filtered]+ label.
|
212
|
-
#
|
213
|
-
# @macro proxy_method
|
214
|
-
# @example
|
215
|
-
# Airbrake.blacklist_keys([:email, /credit/i, 'password'])
|
216
|
-
#
|
217
|
-
# @param [Array<String, Symbol, Regexp>] keys The keys, which should be
|
218
|
-
# filtered
|
219
|
-
# @return [void]
|
220
|
-
# @since v5.0.0
|
221
|
-
# @see .whitelist_keys
|
222
|
-
# @deprecated Please use {Airbrake::Config#blacklist_keys} instead
|
223
|
-
def blacklist_keys(keys, notifier = :default)
|
224
|
-
call_notifier(notifier, __method__, keys)
|
225
|
-
end
|
226
|
-
|
227
196
|
##
|
228
197
|
# Builds an Airbrake notice. This is useful, if you want to add or modify a
|
229
198
|
# value only for a specific notice. When you're done modifying the notice,
|
@@ -151,7 +151,7 @@ module Airbrake
|
|
151
151
|
return false unless defined?(ExecJS::RuntimeError)
|
152
152
|
return true if exception.is_a?(ExecJS::RuntimeError)
|
153
153
|
|
154
|
-
if Airbrake::RUBY_19
|
154
|
+
if Airbrake::RUBY_19 || Airbrake::RUBY_20
|
155
155
|
# Ruby 1.9 doesn't support Exception#cause. We work around this by
|
156
156
|
# parsing backtraces. It's slow, so we check only a few first frames.
|
157
157
|
exception.backtrace[0..2].each do |frame|
|
@@ -2,7 +2,7 @@ module Airbrake
|
|
2
2
|
module Filters
|
3
3
|
##
|
4
4
|
# A default Airbrake notice filter. Filters only specific keys listed in the
|
5
|
-
# list of parameters in the
|
5
|
+
# list of parameters in the payload of a notice.
|
6
6
|
#
|
7
7
|
# @example
|
8
8
|
# filter = Airbrake::Filters::KeysBlacklist.new(:email, /credit/i, 'password')
|
@@ -13,13 +13,20 @@ module Airbrake
|
|
13
13
|
# @return [String] The label to replace real values of filtered payload
|
14
14
|
FILTERED = '[Filtered]'.freeze
|
15
15
|
|
16
|
+
##
|
17
|
+
# @return [Array<String,Symbol,Regexp>] the array of classes instances of
|
18
|
+
# which can compared with payload keys
|
19
|
+
VALID_PATTERN_CLASSES = [String, Symbol, Regexp].freeze
|
20
|
+
|
16
21
|
##
|
17
22
|
# Creates a new KeysBlacklist or KeysWhitelist filter that uses the given
|
18
23
|
# +patterns+ for filtering a notice's payload.
|
19
24
|
#
|
20
25
|
# @param [Array<String,Regexp,Symbol>] patterns
|
21
|
-
def initialize(*patterns)
|
26
|
+
def initialize(logger, *patterns)
|
27
|
+
@logger = logger
|
22
28
|
@patterns = patterns
|
29
|
+
@valid_patterns = false
|
23
30
|
end
|
24
31
|
|
25
32
|
##
|
@@ -30,6 +37,11 @@ module Airbrake
|
|
30
37
|
# @return [void]
|
31
38
|
# @see FilterChain
|
32
39
|
def call(notice)
|
40
|
+
unless @valid_patterns
|
41
|
+
eval_proc_patterns!
|
42
|
+
validate_patterns
|
43
|
+
end
|
44
|
+
|
33
45
|
FILTERABLE_KEYS.each { |key| filter_hash(notice[key]) }
|
34
46
|
|
35
47
|
if notice[:context][:user]
|
@@ -86,6 +98,28 @@ module Airbrake
|
|
86
98
|
return unless url.query
|
87
99
|
notice[:context][:url] = filter_url_params(url)
|
88
100
|
end
|
101
|
+
|
102
|
+
def eval_proc_patterns!
|
103
|
+
return unless @patterns.any? { |pattern| pattern.is_a?(Proc) }
|
104
|
+
|
105
|
+
@patterns = @patterns.flat_map do |pattern|
|
106
|
+
next(pattern) unless pattern.respond_to?(:call)
|
107
|
+
pattern.call
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def validate_patterns
|
112
|
+
@valid_patterns = @patterns.all? do |pattern|
|
113
|
+
VALID_PATTERN_CLASSES.any? { |c| pattern.is_a?(c) }
|
114
|
+
end
|
115
|
+
|
116
|
+
return if @valid_patterns
|
117
|
+
|
118
|
+
@logger.error(
|
119
|
+
"#{LOG_LABEL} one of the patterns in #{self.class} is invalid. " \
|
120
|
+
"Known patterns: #{@patterns}"
|
121
|
+
)
|
122
|
+
end
|
89
123
|
end
|
90
124
|
end
|
91
125
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Airbrake
|
2
2
|
module Filters
|
3
3
|
##
|
4
|
-
# A default Airbrake notice filter. Filters everything in the
|
5
|
-
#
|
4
|
+
# A default Airbrake notice filter. Filters everything in the payload of a
|
5
|
+
# notice, but specified keys.
|
6
6
|
#
|
7
7
|
# @example
|
8
8
|
# filter = Airbrake::Filters::KeysWhitelist.new(:email, /user/i, 'account_id')
|
data/lib/airbrake-ruby/notice.rb
CHANGED
@@ -57,17 +57,14 @@ module Airbrake
|
|
57
57
|
def initialize(config, exception, params = {})
|
58
58
|
@config = config
|
59
59
|
|
60
|
-
@
|
61
|
-
notifier: NOTIFIER
|
62
|
-
}.freeze
|
63
|
-
|
64
|
-
@modifiable_payload = {
|
60
|
+
@payload = {
|
65
61
|
errors: NestedException.new(exception, @config.logger).as_json,
|
66
62
|
context: context(params),
|
67
63
|
environment: {},
|
68
64
|
session: {},
|
69
65
|
params: params
|
70
66
|
}
|
67
|
+
|
71
68
|
extract_custom_attributes(exception)
|
72
69
|
|
73
70
|
@truncator = PayloadTruncator.new(PAYLOAD_MAX_SIZE, @config.logger)
|
@@ -82,7 +79,7 @@ module Airbrake
|
|
82
79
|
def to_json
|
83
80
|
loop do
|
84
81
|
begin
|
85
|
-
json = payload.to_json
|
82
|
+
json = @payload.to_json
|
86
83
|
rescue *JSON_EXCEPTIONS => ex
|
87
84
|
@config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")
|
88
85
|
else
|
@@ -100,7 +97,7 @@ module Airbrake
|
|
100
97
|
# @see #ignored?
|
101
98
|
# @note Ignored noticed can't be unignored
|
102
99
|
def ignore!
|
103
|
-
@
|
100
|
+
@payload = nil
|
104
101
|
end
|
105
102
|
|
106
103
|
##
|
@@ -109,21 +106,21 @@ module Airbrake
|
|
109
106
|
# @return [Boolean]
|
110
107
|
# @see #ignore!
|
111
108
|
def ignored?
|
112
|
-
@
|
109
|
+
@payload.nil?
|
113
110
|
end
|
114
111
|
|
115
112
|
##
|
116
|
-
# Reads a value from notice's
|
113
|
+
# Reads a value from notice's payload.
|
117
114
|
# @return [Object]
|
118
115
|
#
|
119
116
|
# @raise [Airbrake::Error] if the notice is ignored
|
120
117
|
def [](key)
|
121
118
|
raise_if_ignored
|
122
|
-
@
|
119
|
+
@payload[key]
|
123
120
|
end
|
124
121
|
|
125
122
|
##
|
126
|
-
# Writes a value to the
|
123
|
+
# Writes a value to the payload hash. Restricts unrecognized
|
127
124
|
# writes.
|
128
125
|
# @example
|
129
126
|
# notice[:params][:my_param] = 'foobar'
|
@@ -137,7 +134,7 @@ module Airbrake
|
|
137
134
|
raise_if_unrecognized_key(key)
|
138
135
|
raise_if_non_hash_value(value)
|
139
136
|
|
140
|
-
@
|
137
|
+
@payload[key] = value.to_hash
|
141
138
|
end
|
142
139
|
|
143
140
|
private
|
@@ -178,17 +175,13 @@ module Airbrake
|
|
178
175
|
raise Airbrake::Error, "Got #{value.class} value, wanted a Hash"
|
179
176
|
end
|
180
177
|
|
181
|
-
def payload
|
182
|
-
@modifiable_payload.merge(@private_payload)
|
183
|
-
end
|
184
|
-
|
185
178
|
def truncate_payload
|
186
|
-
@
|
179
|
+
@payload[:errors].each do |error|
|
187
180
|
@truncator.truncate_error(error)
|
188
181
|
end
|
189
182
|
|
190
183
|
Filters::FILTERABLE_KEYS.each do |key|
|
191
|
-
@truncator.truncate_object(@
|
184
|
+
@truncator.truncate_object(@payload[key])
|
192
185
|
end
|
193
186
|
|
194
187
|
new_max_size = @truncator.reduce_max_size
|
@@ -196,7 +189,7 @@ module Airbrake
|
|
196
189
|
@config.logger.error(
|
197
190
|
"#{LOG_LABEL} truncation failed. File an issue at " \
|
198
191
|
"https://github.com/airbrake/airbrake-ruby " \
|
199
|
-
"and attach the following payload: #{payload}"
|
192
|
+
"and attach the following payload: #{@payload}"
|
200
193
|
)
|
201
194
|
end
|
202
195
|
|
@@ -218,7 +211,7 @@ module Airbrake
|
|
218
211
|
return unless attributes
|
219
212
|
|
220
213
|
begin
|
221
|
-
@
|
214
|
+
@payload.merge!(attributes)
|
222
215
|
rescue TypeError
|
223
216
|
@config.logger.error(
|
224
217
|
"#{LOG_LABEL} #{exception.class}#to_airbrake failed:" \
|
@@ -36,13 +36,7 @@ module Airbrake
|
|
36
36
|
|
37
37
|
@filter_chain = FilterChain.new(@config)
|
38
38
|
|
39
|
-
|
40
|
-
add_filter(Filters::KeysBlacklist.new(*@config.blacklist_keys))
|
41
|
-
end
|
42
|
-
|
43
|
-
if @config.whitelist_keys.any?
|
44
|
-
add_filter(Filters::KeysWhitelist.new(*@config.whitelist_keys))
|
45
|
-
end
|
39
|
+
add_filters_for_config_keys
|
46
40
|
|
47
41
|
@async_sender = AsyncSender.new(@config)
|
48
42
|
@sync_sender = SyncSender.new(@config)
|
@@ -71,28 +65,6 @@ module Airbrake
|
|
71
65
|
@filter_chain.add_filter(block_given? ? block : filter)
|
72
66
|
end
|
73
67
|
|
74
|
-
##
|
75
|
-
# @macro see_public_api_method
|
76
|
-
# @deprecated Please use {Airbrake::Config#whitelist_keys} instead
|
77
|
-
def whitelist_keys(keys)
|
78
|
-
@config.logger.warn(
|
79
|
-
"#{LOG_LABEL} Airbrake.whitelist_keys is deprecated. Please use the " \
|
80
|
-
"whitelist_keys option instead (https://goo.gl/sQwpYN)"
|
81
|
-
)
|
82
|
-
add_filter(Filters::KeysWhitelist.new(*keys))
|
83
|
-
end
|
84
|
-
|
85
|
-
##
|
86
|
-
# @macro see_public_api_method
|
87
|
-
# @deprecated Please use {Airbrake::Config#blacklist_keys} instead
|
88
|
-
def blacklist_keys(keys)
|
89
|
-
@config.logger.warn(
|
90
|
-
"#{LOG_LABEL} Airbrake.blacklist_keys is deprecated. Please use the " \
|
91
|
-
"blacklist_keys option instead (https://goo.gl/jucrFt)"
|
92
|
-
)
|
93
|
-
add_filter(Filters::KeysBlacklist.new(*keys))
|
94
|
-
end
|
95
|
-
|
96
68
|
##
|
97
69
|
# @macro see_public_api_method
|
98
70
|
def build_notice(exception, params = {})
|
@@ -171,5 +143,15 @@ module Airbrake
|
|
171
143
|
return caller_copy if clean_bt.empty?
|
172
144
|
clean_bt
|
173
145
|
end
|
146
|
+
|
147
|
+
def add_filters_for_config_keys
|
148
|
+
if @config.blacklist_keys.any?
|
149
|
+
add_filter(Filters::KeysBlacklist.new(@config.logger, *@config.blacklist_keys))
|
150
|
+
end
|
151
|
+
|
152
|
+
return if @config.whitelist_keys.none?
|
153
|
+
|
154
|
+
add_filter(Filters::KeysWhitelist.new(@config.logger, *@config.whitelist_keys))
|
155
|
+
end
|
174
156
|
end
|
175
157
|
end
|
@@ -67,12 +67,10 @@ module Airbrake
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def proxy_params
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
@config.proxy[:password]]
|
75
|
-
end
|
70
|
+
return unless @config.proxy.key?(:host)
|
71
|
+
|
72
|
+
[@config.proxy[:host], @config.proxy[:port], @config.proxy[:user],
|
73
|
+
@config.proxy[:password]]
|
76
74
|
end
|
77
75
|
end
|
78
76
|
end
|
data/spec/airbrake_spec.rb
CHANGED
@@ -176,14 +176,6 @@ RSpec.describe Airbrake do
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
-
describe ".whitelist_keys" do
|
180
|
-
include_examples 'non-configured notifier handling', :whitelist_keys
|
181
|
-
end
|
182
|
-
|
183
|
-
describe ".blacklist_keys" do
|
184
|
-
include_examples 'non-configured notifier handling', :blacklist_keys
|
185
|
-
end
|
186
|
-
|
187
179
|
describe ".build_notice" do
|
188
180
|
include_examples 'non-configured notifier handling', :build_notice
|
189
181
|
end
|
data/spec/notifier_spec.rb
CHANGED
@@ -472,268 +472,6 @@ RSpec.describe Airbrake::Notifier do
|
|
472
472
|
end
|
473
473
|
end
|
474
474
|
|
475
|
-
describe "#blacklist_keys" do
|
476
|
-
describe "the list of arguments" do
|
477
|
-
it "accepts regexps" do
|
478
|
-
@airbrake.blacklist_keys(/\Abin/)
|
479
|
-
|
480
|
-
@airbrake.notify_sync(ex, bingo: 'bango')
|
481
|
-
|
482
|
-
expect(
|
483
|
-
a_request(:post, endpoint).
|
484
|
-
with(body: /"params":{"bingo":"\[Filtered\]"}/)
|
485
|
-
).to have_been_made.once
|
486
|
-
end
|
487
|
-
|
488
|
-
it "accepts symbols" do
|
489
|
-
@airbrake.blacklist_keys(:bingo)
|
490
|
-
|
491
|
-
@airbrake.notify_sync(ex, bingo: 'bango')
|
492
|
-
|
493
|
-
expect(
|
494
|
-
a_request(:post, endpoint).
|
495
|
-
with(body: /"params":{"bingo":"\[Filtered\]"}/)
|
496
|
-
).to have_been_made.once
|
497
|
-
end
|
498
|
-
|
499
|
-
it "accepts strings" do
|
500
|
-
@airbrake.blacklist_keys('bingo')
|
501
|
-
|
502
|
-
@airbrake.notify_sync(ex, bingo: 'bango', bbingoo: 'bbangoo')
|
503
|
-
|
504
|
-
expect(
|
505
|
-
a_request(:post, endpoint).
|
506
|
-
with(body: /"params":{"bingo":"\[Filtered\]","bbingoo":"bbangoo"}/)
|
507
|
-
).to have_been_made.once
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
|
-
describe "hash values" do
|
512
|
-
context "non-recursive" do
|
513
|
-
it "filters nested hashes" do
|
514
|
-
@airbrake.blacklist_keys('bish')
|
515
|
-
|
516
|
-
@airbrake.notify_sync(ex, bongo: { bish: 'bash' })
|
517
|
-
|
518
|
-
expect(
|
519
|
-
a_request(:post, endpoint).
|
520
|
-
with(body: /"params":{"bongo":{"bish":"\[Filtered\]"}}/)
|
521
|
-
).to have_been_made.once
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
|
-
context "recursive" do
|
526
|
-
it "filters recursive hashes" do
|
527
|
-
@airbrake.blacklist_keys('bango')
|
528
|
-
|
529
|
-
bongo = { bingo: {} }
|
530
|
-
bongo[:bingo][:bango] = bongo
|
531
|
-
|
532
|
-
@airbrake.notify_sync(ex, bongo)
|
533
|
-
|
534
|
-
expect(
|
535
|
-
a_request(:post, endpoint).
|
536
|
-
with(body: /"params":{"bingo":{"bango":"\[Filtered\]"}}/)
|
537
|
-
).to have_been_made.once
|
538
|
-
end
|
539
|
-
end
|
540
|
-
end
|
541
|
-
|
542
|
-
it "filters query parameters correctly" do
|
543
|
-
@airbrake.blacklist_keys(%w(bish))
|
544
|
-
|
545
|
-
notice = @airbrake.build_notice(ex)
|
546
|
-
notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash&color=%23FFAAFF'
|
547
|
-
|
548
|
-
@airbrake.notify_sync(notice)
|
549
|
-
|
550
|
-
# rubocop:disable Metrics/LineLength
|
551
|
-
expected_body =
|
552
|
-
%r("context":{.*"url":"http://localhost:3000/crash\?foo=bar&baz=bongo&bish=\[Filtered\]&color=%23FFAAFF".*})
|
553
|
-
# rubocop:enable Metrics/LineLength
|
554
|
-
|
555
|
-
expect(
|
556
|
-
a_request(:post, endpoint).
|
557
|
-
with(body: expected_body)
|
558
|
-
).to have_been_made.once
|
559
|
-
end
|
560
|
-
|
561
|
-
it "filters out user" do
|
562
|
-
@airbrake.blacklist_keys('user')
|
563
|
-
|
564
|
-
notice = @airbrake.build_notice(ex)
|
565
|
-
notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
|
566
|
-
|
567
|
-
@airbrake.notify_sync(notice)
|
568
|
-
|
569
|
-
expect_a_request_with_body(/"user":"\[Filtered\]"/)
|
570
|
-
end
|
571
|
-
|
572
|
-
it "filters out individual user fields" do
|
573
|
-
@airbrake.blacklist_keys('name')
|
574
|
-
|
575
|
-
notice = @airbrake.build_notice(ex)
|
576
|
-
notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
|
577
|
-
|
578
|
-
@airbrake.notify_sync(notice)
|
579
|
-
|
580
|
-
expect_a_request_with_body(/"user":{"id":1337,"name":"\[Filtered\]"}/)
|
581
|
-
end
|
582
|
-
end
|
583
|
-
|
584
|
-
describe "#whitelist_keys" do
|
585
|
-
describe "the list of arguments" do
|
586
|
-
it "accepts regexes" do
|
587
|
-
@airbrake.whitelist_keys(/\Abin/)
|
588
|
-
|
589
|
-
@airbrake.notify_sync(ex, bingo: 'bango', bongo: 'bish', bash: 'bosh')
|
590
|
-
|
591
|
-
body = /"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
|
592
|
-
|
593
|
-
expect(
|
594
|
-
a_request(:post, endpoint).
|
595
|
-
with(body: body)
|
596
|
-
).to have_been_made.once
|
597
|
-
end
|
598
|
-
|
599
|
-
it "accepts symbols" do
|
600
|
-
@airbrake.whitelist_keys(:bongo)
|
601
|
-
|
602
|
-
@airbrake.notify_sync(ex, bingo: 'bango', bongo: 'bish', bash: 'bosh')
|
603
|
-
|
604
|
-
body = /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]"}/
|
605
|
-
|
606
|
-
expect(
|
607
|
-
a_request(:post, endpoint).
|
608
|
-
with(body: body)
|
609
|
-
).to have_been_made.once
|
610
|
-
end
|
611
|
-
|
612
|
-
it "accepts strings" do
|
613
|
-
@airbrake.whitelist_keys('bash')
|
614
|
-
|
615
|
-
@airbrake.notify_sync(
|
616
|
-
ex,
|
617
|
-
bingo: 'bango',
|
618
|
-
bongo: 'bish',
|
619
|
-
bash: 'bosh',
|
620
|
-
bbashh: 'bboshh'
|
621
|
-
)
|
622
|
-
|
623
|
-
expect(
|
624
|
-
a_request(:post, endpoint).
|
625
|
-
with(
|
626
|
-
body: /"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]",
|
627
|
-
"bash":"bosh","bbashh":"\[Filtered\]"}/x
|
628
|
-
)
|
629
|
-
).to have_been_made.once
|
630
|
-
end
|
631
|
-
end
|
632
|
-
|
633
|
-
describe "hash values" do
|
634
|
-
context "non-recursive" do
|
635
|
-
it "filters out everything but the provided keys" do
|
636
|
-
@airbrake.whitelist_keys(%w(bongo bish))
|
637
|
-
|
638
|
-
@airbrake.notify_sync(ex, bingo: 'bango', bongo: { bish: 'bash' })
|
639
|
-
|
640
|
-
expect(
|
641
|
-
a_request(:post, endpoint).
|
642
|
-
with(body: /"params":{"bingo":"\[Filtered\]","bongo":{"bish":"bash"}}/)
|
643
|
-
).to have_been_made.once
|
644
|
-
end
|
645
|
-
end
|
646
|
-
|
647
|
-
context "recursive" do
|
648
|
-
it "errors when nested hashes are not filtered" do
|
649
|
-
@airbrake.whitelist_keys(%w(bingo bango))
|
650
|
-
|
651
|
-
bongo = { bingo: {} }
|
652
|
-
bongo[:bingo][:bango] = bongo
|
653
|
-
|
654
|
-
if RUBY_ENGINE == 'jruby'
|
655
|
-
# JRuby might raise two different exceptions, which represent the
|
656
|
-
# same thing. One is a Java exception, the other is a Ruby
|
657
|
-
# exception. It's probably a JRuby bug:
|
658
|
-
# https://github.com/jruby/jruby/issues/1903
|
659
|
-
begin
|
660
|
-
expect do
|
661
|
-
@airbrake.notify_sync(ex, bongo)
|
662
|
-
end.to raise_error(SystemStackError)
|
663
|
-
rescue RSpec::Expectations::ExpectationNotMetError
|
664
|
-
expect do
|
665
|
-
@airbrake.notify_sync(ex, bongo)
|
666
|
-
end.to raise_error(java.lang.StackOverflowError)
|
667
|
-
end
|
668
|
-
else
|
669
|
-
expect do
|
670
|
-
@airbrake.notify_sync(ex, bongo)
|
671
|
-
end.to raise_error(SystemStackError)
|
672
|
-
end
|
673
|
-
end
|
674
|
-
end
|
675
|
-
end
|
676
|
-
|
677
|
-
describe "context/url" do
|
678
|
-
it "filters query parameters correctly" do
|
679
|
-
@airbrake.whitelist_keys(%w(bish))
|
680
|
-
|
681
|
-
notice = @airbrake.build_notice(ex)
|
682
|
-
notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash'
|
683
|
-
|
684
|
-
@airbrake.notify_sync(notice)
|
685
|
-
|
686
|
-
# rubocop:disable Metrics/LineLength
|
687
|
-
expected_body =
|
688
|
-
%r("context":{.*"url":"http://localhost:3000/crash\?foo=\[Filtered\]&baz=\[Filtered\]&bish=bash".*})
|
689
|
-
# rubocop:enable Metrics/LineLength
|
690
|
-
|
691
|
-
expect(
|
692
|
-
a_request(:post, endpoint).
|
693
|
-
with(body: expected_body)
|
694
|
-
).to have_been_made.once
|
695
|
-
end
|
696
|
-
|
697
|
-
context "given a non-standard URL" do
|
698
|
-
it "leaves the URL unfiltered" do
|
699
|
-
@airbrake.whitelist_keys(%w(bish))
|
700
|
-
|
701
|
-
notice = @airbrake.build_notice(ex)
|
702
|
-
notice[:context][:url] =
|
703
|
-
'http://localhost:3000/cra]]]sh?foo=bar&baz=bongo&bish=bash'
|
704
|
-
|
705
|
-
@airbrake.notify_sync(notice)
|
706
|
-
|
707
|
-
# rubocop:disable Metrics/LineLength
|
708
|
-
expected_body =
|
709
|
-
%r("context":{.*"url":"http://localhost:3000/cra\]\]\]sh\?foo=bar&baz=bongo&bish=bash".*})
|
710
|
-
# rubocop:enable Metrics/LineLength
|
711
|
-
|
712
|
-
expect(
|
713
|
-
a_request(:post, endpoint).
|
714
|
-
with(body: expected_body)
|
715
|
-
).to have_been_made.once
|
716
|
-
end
|
717
|
-
end
|
718
|
-
|
719
|
-
context "given a URL without a query" do
|
720
|
-
it "skips params filtering and leaves the URL untouched" do
|
721
|
-
@airbrake.whitelist_keys(%w(bish))
|
722
|
-
|
723
|
-
notice = @airbrake.build_notice(ex)
|
724
|
-
notice[:context][:url] = 'http://localhost:3000/crash'
|
725
|
-
|
726
|
-
@airbrake.notify_sync(notice)
|
727
|
-
|
728
|
-
expect(
|
729
|
-
a_request(:post, endpoint).
|
730
|
-
with(body: %r("context":{.*"url":"http://localhost:3000/crash".*}))
|
731
|
-
).to have_been_made.once
|
732
|
-
end
|
733
|
-
end
|
734
|
-
end
|
735
|
-
end
|
736
|
-
|
737
475
|
describe "#build_notice" do
|
738
476
|
it "builds a notice from exception" do
|
739
477
|
expect(@airbrake.build_notice(ex)).to be_an Airbrake::Notice
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Airbrake::Notifier blacklist_keys" do
|
4
|
+
def expect_a_request_with_body(body)
|
5
|
+
expect(a_request(:post, endpoint).with(body: body)).to have_been_made.once
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:project_id) { 105138 }
|
9
|
+
let(:project_key) { 'fd04e13d806a90f96614ad8e529b2822' }
|
10
|
+
let(:localhost) { 'http://localhost:8080' }
|
11
|
+
|
12
|
+
let(:endpoint) do
|
13
|
+
"https://airbrake.io/api/v3/projects/#{project_id}/notices?key=#{project_key}"
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:airbrake_params) do
|
17
|
+
{ project_id: project_id,
|
18
|
+
project_key: project_key,
|
19
|
+
logger: Logger.new(StringIO.new) }
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:ex) { AirbrakeTestError.new }
|
23
|
+
|
24
|
+
shared_examples 'blacklisting' do |keys, params|
|
25
|
+
it "filters out the value" do
|
26
|
+
blacklist = { blacklist_keys: keys }
|
27
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
28
|
+
|
29
|
+
notifier.notify_sync(ex, params)
|
30
|
+
|
31
|
+
expect_a_request_with_body(expected_body)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples 'logging' do |keys, params|
|
36
|
+
it "logs the error" do
|
37
|
+
out = StringIO.new
|
38
|
+
blacklist = { blacklist_keys: keys, logger: Logger.new(out) }
|
39
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
40
|
+
|
41
|
+
notifier.notify_sync(ex, params)
|
42
|
+
|
43
|
+
expect(out.string).to match(expected_output)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
before do
|
48
|
+
stub_request(:post, endpoint).to_return(status: 201, body: '{}')
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when blacklisting with a Regexp" do
|
52
|
+
let(:expected_body) { /"params":{"bingo":"\[Filtered\]"}/ }
|
53
|
+
include_examples('blacklisting', [/\Abin/], bingo: 'bango')
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when blacklisting with a Symbol" do
|
57
|
+
let(:expected_body) { /"params":{"bingo":"\[Filtered\]"}/ }
|
58
|
+
include_examples('blacklisting', [:bingo], bingo: 'bango')
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when blacklisting with a String" do
|
62
|
+
let(:expected_body) { /"params":{"bingo":"\[Filtered\]"}/ }
|
63
|
+
include_examples('blacklisting', ['bingo'], bingo: 'bango')
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when payload has a hash" do
|
67
|
+
context "and it is a non-recursive hash" do
|
68
|
+
let(:expected_body) { /"params":{"bongo":{"bish":"\[Filtered\]"}}/ }
|
69
|
+
include_examples('blacklisting', ['bish'], bongo: { bish: 'bash' })
|
70
|
+
end
|
71
|
+
|
72
|
+
context "and it is a recursive hash" do
|
73
|
+
let(:expected_body) { /"params":{"bingo":{"bango":"\[Filtered\]"}}/ }
|
74
|
+
|
75
|
+
bongo = { bingo: {} }
|
76
|
+
bongo[:bingo][:bango] = bongo
|
77
|
+
|
78
|
+
include_examples('blacklisting', ['bango'], bongo)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when there was invalid pattern provided" do
|
83
|
+
let(:expected_output) do
|
84
|
+
/ERROR.+KeysBlacklist is invalid.+patterns: \[#<Object:.+>\]/
|
85
|
+
end
|
86
|
+
|
87
|
+
include_examples('logging', [Object.new], bingo: 'bango')
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when there was a proc provided, which returns an array of keys" do
|
91
|
+
let(:expected_body) { /"params":{"bingo":"\[Filtered\]","bongo":"bish"}/ }
|
92
|
+
include_examples('blacklisting', [proc { 'bingo' }], bingo: 'bango', bongo: 'bish')
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when there was a proc provided along with normal keys" do
|
96
|
+
let(:expected_body) do
|
97
|
+
/"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
|
98
|
+
end
|
99
|
+
|
100
|
+
include_examples(
|
101
|
+
'blacklisting',
|
102
|
+
[proc { 'bongo' }, :bash],
|
103
|
+
bingo: 'bango', bongo: 'bish', bash: 'bosh'
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when there was a proc provided, which doesn't return an array of keys" do
|
108
|
+
let(:expected_output) do
|
109
|
+
/ERROR.+KeysBlacklist is invalid.+patterns: \[#<Object:.+>\]/
|
110
|
+
end
|
111
|
+
|
112
|
+
include_examples('logging', [proc { Object.new }], bingo: 'bango')
|
113
|
+
|
114
|
+
it "doesn't blacklist keys" do
|
115
|
+
blacklist = { blacklist_keys: [proc { Object.new }] }
|
116
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
117
|
+
|
118
|
+
notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
|
119
|
+
|
120
|
+
expect_a_request_with_body(/"params":{"bingo":"bango","bongo":"bish"}/)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when there was a proc provided, which returns another proc" do
|
125
|
+
context "when called once" do
|
126
|
+
let(:expected_output) do
|
127
|
+
/ERROR.+KeysBlacklist is invalid.+patterns: \[#<Proc:.+>\]/
|
128
|
+
end
|
129
|
+
|
130
|
+
include_examples('logging', [proc { proc { ['bingo'] } }], bingo: 'bango')
|
131
|
+
end
|
132
|
+
|
133
|
+
context "when called twice" do
|
134
|
+
it "unwinds procs and filters keys" do
|
135
|
+
blacklist = { blacklist_keys: [proc { proc { ['bingo'] } }] }
|
136
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
137
|
+
|
138
|
+
notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
|
139
|
+
notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
|
140
|
+
|
141
|
+
expect_a_request_with_body(
|
142
|
+
/"params":{"bingo":"\[Filtered\]","bongo":"bish"}/
|
143
|
+
)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it "filters query parameters correctly" do
|
149
|
+
blacklist = { blacklist_keys: ['bish'] }
|
150
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
151
|
+
|
152
|
+
notice = notifier.build_notice(ex)
|
153
|
+
notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash&color=%23FFAAFF'
|
154
|
+
|
155
|
+
notifier.notify_sync(notice)
|
156
|
+
|
157
|
+
# rubocop:disable Metrics/LineLength
|
158
|
+
expected_body =
|
159
|
+
%r("context":{.*"url":"http://localhost:3000/crash\?foo=bar&baz=bongo&bish=\[Filtered\]&color=%23FFAAFF".*})
|
160
|
+
# rubocop:enable Metrics/LineLength
|
161
|
+
|
162
|
+
expect_a_request_with_body(expected_body)
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when the user payload is present" do
|
166
|
+
context "and when the user key is ignored" do
|
167
|
+
it "filters out user entirely" do
|
168
|
+
blacklist = { blacklist_keys: ['user'] }
|
169
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
170
|
+
|
171
|
+
notice = notifier.build_notice(ex)
|
172
|
+
notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
|
173
|
+
|
174
|
+
notifier.notify_sync(notice)
|
175
|
+
|
176
|
+
expect_a_request_with_body(/"user":"\[Filtered\]"/)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
it "filters out individual user fields" do
|
181
|
+
blacklist = { blacklist_keys: ['name'] }
|
182
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(blacklist))
|
183
|
+
|
184
|
+
notice = notifier.build_notice(ex)
|
185
|
+
notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
|
186
|
+
|
187
|
+
notifier.notify_sync(notice)
|
188
|
+
|
189
|
+
expect_a_request_with_body(/"user":{"id":1337,"name":"\[Filtered\]"}/)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -225,200 +225,5 @@ RSpec.describe Airbrake::Notifier do
|
|
225
225
|
include_examples 'sent notice', environment: :development
|
226
226
|
end
|
227
227
|
end
|
228
|
-
|
229
|
-
describe ":blacklist_keys" do
|
230
|
-
describe "the list of values" do
|
231
|
-
it "accepts regexps" do
|
232
|
-
params = { blacklist_keys: [/\Abin/] }
|
233
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
234
|
-
|
235
|
-
airbrake.notify_sync(ex, bingo: 'bango')
|
236
|
-
|
237
|
-
expect_a_request_with_body(/"params":{"bingo":"\[Filtered\]"}/)
|
238
|
-
end
|
239
|
-
|
240
|
-
it "accepts symbols" do
|
241
|
-
params = { blacklist_keys: [:bingo] }
|
242
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
243
|
-
|
244
|
-
airbrake.notify_sync(ex, bingo: 'bango')
|
245
|
-
|
246
|
-
expect_a_request_with_body(/"params":{"bingo":"\[Filtered\]"}/)
|
247
|
-
end
|
248
|
-
|
249
|
-
it "accepts strings" do
|
250
|
-
params = { blacklist_keys: ['bingo'] }
|
251
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
252
|
-
|
253
|
-
airbrake.notify_sync(ex, bingo: 'bango')
|
254
|
-
|
255
|
-
expect_a_request_with_body(/"params":{"bingo":"\[Filtered\]"}/)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
describe "hash values" do
|
260
|
-
context "non-recursive" do
|
261
|
-
it "filters nested hashes" do
|
262
|
-
params = { blacklist_keys: ['bish'] }
|
263
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
264
|
-
|
265
|
-
airbrake.notify_sync(ex, bongo: { bish: 'bash' })
|
266
|
-
|
267
|
-
expect_a_request_with_body(/"params":{"bongo":{"bish":"\[Filtered\]"}}/)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
context "recursive" do
|
272
|
-
it "filters recursive hashes" do
|
273
|
-
params = { blacklist_keys: ['bango'] }
|
274
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
275
|
-
|
276
|
-
bongo = { bingo: {} }
|
277
|
-
bongo[:bingo][:bango] = bongo
|
278
|
-
|
279
|
-
airbrake.notify_sync(ex, bongo)
|
280
|
-
|
281
|
-
expect_a_request_with_body(/"params":{"bingo":{"bango":"\[Filtered\]"}}/)
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
it "filters query parameters correctly" do
|
287
|
-
params = { blacklist_keys: ['bish'] }
|
288
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
289
|
-
|
290
|
-
notice = airbrake.build_notice(ex)
|
291
|
-
notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash&color=%23FFAAFF'
|
292
|
-
|
293
|
-
airbrake.notify_sync(notice)
|
294
|
-
|
295
|
-
# rubocop:disable Metrics/LineLength
|
296
|
-
expected_body =
|
297
|
-
%r("context":{.*"url":"http://localhost:3000/crash\?foo=bar&baz=bongo&bish=\[Filtered\]&color=%23FFAAFF".*})
|
298
|
-
# rubocop:enable Metrics/LineLength
|
299
|
-
|
300
|
-
expect_a_request_with_body(expected_body)
|
301
|
-
end
|
302
|
-
|
303
|
-
it "filters out user" do
|
304
|
-
params = { blacklist_keys: ['user'] }
|
305
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
306
|
-
|
307
|
-
notice = airbrake.build_notice(ex)
|
308
|
-
notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
|
309
|
-
|
310
|
-
airbrake.notify_sync(notice)
|
311
|
-
|
312
|
-
expect_a_request_with_body(/"user":"\[Filtered\]"/)
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
describe ":whitelist_keys" do
|
317
|
-
describe "the list of values" do
|
318
|
-
it "accepts regexes" do
|
319
|
-
params = { whitelist_keys: [/\Abin/] }
|
320
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
321
|
-
|
322
|
-
airbrake.notify_sync(ex, bingo: 'bango', bongo: 'bish', bash: 'bosh')
|
323
|
-
|
324
|
-
expect_a_request_with_body(
|
325
|
-
/"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
|
326
|
-
)
|
327
|
-
end
|
328
|
-
|
329
|
-
it "accepts symbols" do
|
330
|
-
params = { whitelist_keys: [:bongo] }
|
331
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
332
|
-
|
333
|
-
airbrake.notify_sync(ex, bingo: 'bango', bongo: 'bish', bash: 'bosh')
|
334
|
-
|
335
|
-
expect_a_request_with_body(
|
336
|
-
/"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]"}/
|
337
|
-
)
|
338
|
-
end
|
339
|
-
|
340
|
-
it "accepts strings" do
|
341
|
-
params = { whitelist_keys: ['bash'] }
|
342
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
343
|
-
|
344
|
-
airbrake.notify_sync(
|
345
|
-
ex,
|
346
|
-
bingo: 'bango',
|
347
|
-
bongo: 'bish',
|
348
|
-
bash: 'bosh',
|
349
|
-
bbashh: 'bboshh'
|
350
|
-
)
|
351
|
-
|
352
|
-
expect_a_request_with_body(
|
353
|
-
/"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]",
|
354
|
-
"bash":"bosh","bbashh":"\[Filtered\]"}/x
|
355
|
-
)
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
describe "hash values" do
|
360
|
-
context "non-recursive" do
|
361
|
-
it "filters out everything but the provided keys" do
|
362
|
-
params = { whitelist_keys: %w(bongo bish) }
|
363
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
364
|
-
|
365
|
-
airbrake.notify_sync(ex, bingo: 'bango', bongo: { bish: 'bash' })
|
366
|
-
|
367
|
-
expect_a_request_with_body(
|
368
|
-
/"params":{"bingo":"\[Filtered\]","bongo":{"bish":"bash"}}/
|
369
|
-
)
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
context "recursive" do
|
374
|
-
it "errors when nested hashes are not filtered" do
|
375
|
-
params = { whitelist_keys: %w(bingo bango) }
|
376
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
377
|
-
|
378
|
-
bongo = { bingo: {} }
|
379
|
-
bongo[:bingo][:bango] = bongo
|
380
|
-
|
381
|
-
if RUBY_ENGINE == 'jruby'
|
382
|
-
# JRuby might raise two different exceptions, which represent the
|
383
|
-
# same thing. One is a Java exception, the other is a Ruby
|
384
|
-
# exception. It's probably a JRuby bug:
|
385
|
-
# https://github.com/jruby/jruby/issues/1903
|
386
|
-
begin
|
387
|
-
expect do
|
388
|
-
airbrake.notify_sync(ex, bongo)
|
389
|
-
end.to raise_error(SystemStackError)
|
390
|
-
rescue RSpec::Expectations::ExpectationNotMetError
|
391
|
-
expect do
|
392
|
-
airbrake.notify_sync(ex, bongo)
|
393
|
-
end.to raise_error(java.lang.StackOverflowError)
|
394
|
-
end
|
395
|
-
else
|
396
|
-
expect do
|
397
|
-
airbrake.notify_sync(ex, bongo)
|
398
|
-
end.to raise_error(SystemStackError)
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
describe "context/url" do
|
405
|
-
it "filters query parameters correctly" do
|
406
|
-
params = { whitelist_keys: %w(bish) }
|
407
|
-
airbrake = described_class.new(airbrake_params.merge(params))
|
408
|
-
|
409
|
-
notice = airbrake.build_notice(ex)
|
410
|
-
notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash'
|
411
|
-
|
412
|
-
airbrake.notify_sync(notice)
|
413
|
-
|
414
|
-
# rubocop:disable Metrics/LineLength
|
415
|
-
expected_body =
|
416
|
-
%r("context":{.*"url":"http://localhost:3000/crash\?foo=\[Filtered\]&baz=\[Filtered\]&bish=bash".*})
|
417
|
-
# rubocop:enable Metrics/LineLength
|
418
|
-
|
419
|
-
expect_a_request_with_body(expected_body)
|
420
|
-
end
|
421
|
-
end
|
422
|
-
end
|
423
228
|
end
|
424
229
|
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Airbrake::Notifier whitelist_keys" do
|
4
|
+
def expect_a_request_with_body(body)
|
5
|
+
expect(a_request(:post, endpoint).with(body: body)).to have_been_made.once
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:project_id) { 105138 }
|
9
|
+
let(:project_key) { 'fd04e13d806a90f96614ad8e529b2822' }
|
10
|
+
let(:localhost) { 'http://localhost:8080' }
|
11
|
+
|
12
|
+
let(:endpoint) do
|
13
|
+
"https://airbrake.io/api/v3/projects/#{project_id}/notices?key=#{project_key}"
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:airbrake_params) do
|
17
|
+
{ project_id: project_id,
|
18
|
+
project_key: project_key,
|
19
|
+
logger: Logger.new(StringIO.new) }
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:ex) { AirbrakeTestError.new }
|
23
|
+
|
24
|
+
shared_examples 'whitelisting' do |keys, params|
|
25
|
+
it "filters everything but the value of the specified key" do
|
26
|
+
whitelist = { whitelist_keys: keys }
|
27
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(whitelist))
|
28
|
+
|
29
|
+
notifier.notify_sync(ex, params)
|
30
|
+
|
31
|
+
expect_a_request_with_body(expected_body)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples 'logging' do |keys, params|
|
36
|
+
it "logs the error" do
|
37
|
+
out = StringIO.new
|
38
|
+
whitelist = { whitelist_keys: keys, logger: Logger.new(out) }
|
39
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(whitelist))
|
40
|
+
|
41
|
+
notifier.notify_sync(ex, params)
|
42
|
+
|
43
|
+
expect(out.string).to match(expected_output)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
before do
|
48
|
+
stub_request(:post, endpoint).to_return(status: 201, body: '{}')
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when whitelisting with a Regexp" do
|
52
|
+
let(:expected_body) do
|
53
|
+
/"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
|
54
|
+
end
|
55
|
+
|
56
|
+
include_examples(
|
57
|
+
'whitelisting',
|
58
|
+
[/\Abin/],
|
59
|
+
bingo: 'bango', bongo: 'bish', bash: 'bosh'
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when whitelisting with a Symbol" do
|
64
|
+
let(:expected_body) do
|
65
|
+
/"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]"}/
|
66
|
+
end
|
67
|
+
|
68
|
+
include_examples(
|
69
|
+
'whitelisting',
|
70
|
+
[:bongo],
|
71
|
+
bingo: 'bango', bongo: 'bish', bash: 'bosh'
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when whitelisting with a String" do
|
76
|
+
let(:expected_body) do
|
77
|
+
/"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]",
|
78
|
+
"bash":"bosh","bbashh":"\[Filtered\]"}/x
|
79
|
+
end
|
80
|
+
|
81
|
+
include_examples(
|
82
|
+
'whitelisting',
|
83
|
+
['bash'],
|
84
|
+
bingo: 'bango', bongo: 'bish', bash: 'bosh', bbashh: 'bboshh'
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when payload has a hash" do
|
89
|
+
context "and it is a non-recursive hash" do
|
90
|
+
let(:expected_body) { /"params":{"bingo":"\[Filtered\]","bongo":{"bish":"bash"}}/ }
|
91
|
+
|
92
|
+
include_examples(
|
93
|
+
'whitelisting',
|
94
|
+
%w(bongo bish),
|
95
|
+
bingo: 'bango', bongo: { bish: 'bash' }
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
context "and it is a recursive hash" do
|
100
|
+
it "errors when nested hashes are not filtered" do
|
101
|
+
whitelist = airbrake_params.merge(whitelist_keys: %w(bingo bango))
|
102
|
+
notifier = Airbrake::Notifier.new(whitelist)
|
103
|
+
|
104
|
+
bongo = { bingo: {} }
|
105
|
+
bongo[:bingo][:bango] = bongo
|
106
|
+
|
107
|
+
if RUBY_ENGINE == 'jruby'
|
108
|
+
# JRuby might raise two different exceptions, which represent the
|
109
|
+
# same thing. One is a Java exception, the other is a Ruby
|
110
|
+
# exception. It's probably a JRuby bug:
|
111
|
+
# https://github.com/jruby/jruby/issues/1903
|
112
|
+
begin
|
113
|
+
expect do
|
114
|
+
notifier.notify_sync(ex, bongo)
|
115
|
+
end.to raise_error(SystemStackError)
|
116
|
+
rescue RSpec::Expectations::ExpectationNotMetError
|
117
|
+
expect do
|
118
|
+
notifier.notify_sync(ex, bongo)
|
119
|
+
end.to raise_error(java.lang.StackOverflowError)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
expect do
|
123
|
+
notifier.notify_sync(ex, bongo)
|
124
|
+
end.to raise_error(SystemStackError)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when there was a proc provided, which returns an array of keys" do
|
131
|
+
let(:expected_body) do
|
132
|
+
/"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]"}/
|
133
|
+
end
|
134
|
+
|
135
|
+
include_examples(
|
136
|
+
'whitelisting',
|
137
|
+
[proc { 'bongo' }],
|
138
|
+
bingo: 'bango', bongo: 'bish', bash: 'bosh'
|
139
|
+
)
|
140
|
+
end
|
141
|
+
|
142
|
+
context "when there was a proc provided along with normal keys" do
|
143
|
+
let(:expected_body) do
|
144
|
+
/"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"bosh"}/
|
145
|
+
end
|
146
|
+
|
147
|
+
include_examples(
|
148
|
+
'whitelisting',
|
149
|
+
[proc { 'bongo' }, :bash],
|
150
|
+
bingo: 'bango', bongo: 'bish', bash: 'bosh'
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when there was a proc provided, which returns another proc" do
|
155
|
+
context "when called once" do
|
156
|
+
let(:expected_output) do
|
157
|
+
/ERROR.+KeysWhitelist is invalid.+patterns: \[#<Proc:.+>\]/
|
158
|
+
end
|
159
|
+
|
160
|
+
include_examples('logging', [proc { proc { ['bingo'] } }], bingo: 'bango')
|
161
|
+
end
|
162
|
+
|
163
|
+
context "when called twice" do
|
164
|
+
it "unwinds procs and filters keys" do
|
165
|
+
whitelist = { whitelist_keys: [proc { proc { ['bingo'] } }] }
|
166
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(whitelist))
|
167
|
+
|
168
|
+
notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
|
169
|
+
notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
|
170
|
+
|
171
|
+
expect_a_request_with_body(
|
172
|
+
/"params":{"bingo":"bango","bongo":"\[Filtered\]"}/
|
173
|
+
)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context "when there was a proc provided, which doesn't return an array of keys" do
|
179
|
+
let(:expected_output) do
|
180
|
+
/ERROR.+KeysWhitelist is invalid.+patterns: \[#<Object:.+>\]/
|
181
|
+
end
|
182
|
+
|
183
|
+
include_examples('logging', [proc { Object.new }], bingo: 'bango')
|
184
|
+
|
185
|
+
it "doesn't whitelist keys" do
|
186
|
+
whitelist = { whitelist_keys: [proc { Object.new }] }
|
187
|
+
notifier = Airbrake::Notifier.new(airbrake_params.merge(whitelist))
|
188
|
+
|
189
|
+
notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
|
190
|
+
|
191
|
+
expect_a_request_with_body(
|
192
|
+
/"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]"}/
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "context/url" do
|
198
|
+
let(:notifier) do
|
199
|
+
Airbrake::Notifier.new(airbrake_params.merge(whitelist_keys: %w(bish)))
|
200
|
+
end
|
201
|
+
|
202
|
+
context "given a standard URL" do
|
203
|
+
it "filters query parameters correctly" do
|
204
|
+
notice = notifier.build_notice(ex)
|
205
|
+
notice[:context][:url] = 'http://localhost:3000/crash?foo=bar&baz=bongo&bish=bash'
|
206
|
+
|
207
|
+
notifier.notify_sync(notice)
|
208
|
+
|
209
|
+
expect_a_request_with_body(
|
210
|
+
# rubocop:disable Metrics/LineLength
|
211
|
+
%r("context":{.*"url":"http://localhost:3000/crash\?foo=\[Filtered\]&baz=\[Filtered\]&bish=bash".*})
|
212
|
+
# rubocop:enable Metrics/LineLength
|
213
|
+
)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "given a non-standard URL" do
|
218
|
+
it "leaves the URL unfiltered" do
|
219
|
+
notice = notifier.build_notice(ex)
|
220
|
+
notice[:context][:url] =
|
221
|
+
'http://localhost:3000/cra]]]sh?foo=bar&baz=bongo&bish=bash'
|
222
|
+
|
223
|
+
notifier.notify_sync(notice)
|
224
|
+
|
225
|
+
expect_a_request_with_body(
|
226
|
+
# rubocop:disable Metrics/LineLength
|
227
|
+
%r("context":{.*"url":"http://localhost:3000/cra\]\]\]sh\?foo=bar&baz=bongo&bish=bash".*})
|
228
|
+
# rubocop:enable Metrics/LineLength
|
229
|
+
)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context "given a URL without a query" do
|
234
|
+
it "skips params filtering and leaves the URL untouched" do
|
235
|
+
notice = notifier.build_notice(ex)
|
236
|
+
notice[:context][:url] = 'http://localhost:3000/crash'
|
237
|
+
|
238
|
+
notifier.notify_sync(notice)
|
239
|
+
|
240
|
+
expect_a_request_with_body(
|
241
|
+
%r("context":{.*"url":"http://localhost:3000/crash".*})
|
242
|
+
)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: benchmark-ips
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,7 +121,9 @@ files:
|
|
121
121
|
- spec/nested_exception_spec.rb
|
122
122
|
- spec/notice_spec.rb
|
123
123
|
- spec/notifier_spec.rb
|
124
|
+
- spec/notifier_spec/blacklist_keys_spec.rb
|
124
125
|
- spec/notifier_spec/options_spec.rb
|
126
|
+
- spec/notifier_spec/whitelist_keys_spec.rb
|
125
127
|
- spec/payload_truncator_spec.rb
|
126
128
|
- spec/spec_helper.rb
|
127
129
|
- spec/sync_sender_spec.rb
|
@@ -158,7 +160,9 @@ test_files:
|
|
158
160
|
- spec/filter_chain_spec.rb
|
159
161
|
- spec/nested_exception_spec.rb
|
160
162
|
- spec/notice_spec.rb
|
163
|
+
- spec/notifier_spec/blacklist_keys_spec.rb
|
161
164
|
- spec/notifier_spec/options_spec.rb
|
165
|
+
- spec/notifier_spec/whitelist_keys_spec.rb
|
162
166
|
- spec/notifier_spec.rb
|
163
167
|
- spec/payload_truncator_spec.rb
|
164
168
|
- spec/spec_helper.rb
|