rollbar 2.16.2 → 2.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +47 -0
  3. data/.travis.yml +182 -94
  4. data/Appraisals +10 -10
  5. data/Gemfile +45 -13
  6. data/README.md +20 -3
  7. data/Rakefile +0 -0
  8. data/data/rollbar.snippet.js +1 -1
  9. data/docs/configuration.md +15 -0
  10. data/gemfiles/rails30.gemfile +21 -14
  11. data/gemfiles/rails31.gemfile +21 -12
  12. data/gemfiles/rails32.gemfile +18 -8
  13. data/gemfiles/rails40.gemfile +18 -6
  14. data/gemfiles/rails41.gemfile +17 -6
  15. data/gemfiles/rails42.gemfile +24 -14
  16. data/gemfiles/rails50.gemfile +20 -11
  17. data/gemfiles/rails51.gemfile +20 -10
  18. data/gemfiles/rails52.gemfile +65 -0
  19. data/gemfiles/rails60.gemfile +67 -0
  20. data/lib/generators/rollbar/rollbar_generator.rb +1 -1
  21. data/lib/rails/rollbar_runner.rb +17 -2
  22. data/lib/rollbar.rb +2 -3
  23. data/lib/rollbar/capistrano.rb +71 -39
  24. data/lib/rollbar/capistrano3.rb +56 -1
  25. data/lib/rollbar/capistrano_tasks.rb +130 -0
  26. data/lib/rollbar/configuration.rb +95 -7
  27. data/lib/rollbar/delay/active_job.rb +17 -0
  28. data/lib/rollbar/delay/girl_friday.rb +2 -2
  29. data/lib/rollbar/delay/resque.rb +4 -6
  30. data/lib/rollbar/delay/shoryuken.rb +15 -9
  31. data/lib/rollbar/delay/sidekiq.rb +6 -8
  32. data/lib/rollbar/delay/sucker_punch.rb +17 -19
  33. data/lib/rollbar/delay/thread.rb +3 -3
  34. data/lib/rollbar/deploy.rb +90 -0
  35. data/lib/rollbar/encoding/encoder.rb +9 -9
  36. data/lib/rollbar/exception_reporter.rb +19 -5
  37. data/lib/rollbar/item.rb +62 -20
  38. data/lib/rollbar/item/backtrace.rb +4 -4
  39. data/lib/rollbar/item/frame.rb +7 -1
  40. data/lib/rollbar/item/locals.rb +56 -0
  41. data/lib/rollbar/json.rb +5 -51
  42. data/lib/rollbar/language_support.rb +4 -20
  43. data/lib/rollbar/lazy_store.rb +5 -5
  44. data/lib/rollbar/logger.rb +1 -0
  45. data/lib/rollbar/logger_proxy.rb +15 -2
  46. data/lib/rollbar/middleware/js.rb +110 -10
  47. data/lib/rollbar/middleware/js/json_value.rb +26 -0
  48. data/lib/rollbar/middleware/rack.rb +4 -1
  49. data/lib/rollbar/middleware/rails/rollbar.rb +10 -1
  50. data/lib/rollbar/notifier.rb +118 -49
  51. data/lib/rollbar/notifier/trace_with_bindings.rb +65 -0
  52. data/lib/rollbar/plugin.rb +54 -6
  53. data/lib/rollbar/plugins.rb +7 -1
  54. data/lib/rollbar/plugins/active_job.rb +5 -1
  55. data/lib/rollbar/plugins/basic_socket.rb +21 -6
  56. data/lib/rollbar/plugins/delayed_job/job_data.rb +3 -3
  57. data/lib/rollbar/plugins/delayed_job/plugin.rb +3 -3
  58. data/lib/rollbar/plugins/goalie.rb +11 -3
  59. data/lib/rollbar/plugins/rails/controller_methods.rb +17 -4
  60. data/lib/rollbar/plugins/rails/railtie_mixin.rb +7 -3
  61. data/lib/rollbar/plugins/rake.rb +2 -2
  62. data/lib/rollbar/plugins/sidekiq/plugin.rb +10 -6
  63. data/lib/rollbar/rake_tasks.rb +3 -86
  64. data/lib/rollbar/request_data_extractor.rb +35 -21
  65. data/lib/rollbar/rollbar_test.rb +147 -0
  66. data/lib/rollbar/scrubbers.rb +7 -3
  67. data/lib/rollbar/scrubbers/params.rb +38 -20
  68. data/lib/rollbar/scrubbers/url.rb +27 -13
  69. data/lib/rollbar/truncation.rb +9 -2
  70. data/lib/rollbar/truncation/min_body_strategy.rb +2 -3
  71. data/lib/rollbar/truncation/remove_any_key_strategy.rb +123 -0
  72. data/lib/rollbar/truncation/remove_extra_strategy.rb +35 -0
  73. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  74. data/lib/rollbar/truncation/strings_strategy.rb +3 -4
  75. data/lib/rollbar/util.rb +75 -45
  76. data/lib/rollbar/util/hash.rb +30 -6
  77. data/lib/rollbar/util/ip_anonymizer.rb +8 -7
  78. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  79. data/lib/rollbar/version.rb +1 -1
  80. data/lib/tasks/benchmark.rake +103 -0
  81. data/rollbar.gemspec +14 -8
  82. metadata +25 -277
  83. data/gemfiles/ruby_1_8_and_1_9_2.gemfile +0 -49
  84. data/lib/rollbar/json/default.rb +0 -11
  85. data/lib/rollbar/json/oj.rb +0 -16
  86. data/lib/rollbar/tasks/rollbar.cap +0 -47
  87. data/spec/cacert.pem +0 -3988
  88. data/spec/controllers/home_controller_spec.rb +0 -480
  89. data/spec/delay/sidekiq_spec.rb +0 -61
  90. data/spec/delay/sucker_punch_spec.rb +0 -25
  91. data/spec/delayed/backend/test.rb +0 -140
  92. data/spec/delayed/serialization/test.rb +0 -0
  93. data/spec/dummyapp/.gitignore +0 -73
  94. data/spec/dummyapp/Rakefile +0 -7
  95. data/spec/dummyapp/app/assets/javascripts/application.js +0 -3
  96. data/spec/dummyapp/app/assets/stylesheets/application.css.scss +0 -37
  97. data/spec/dummyapp/app/controllers/application_controller.rb +0 -3
  98. data/spec/dummyapp/app/controllers/home_controller.rb +0 -60
  99. data/spec/dummyapp/app/controllers/users_controller.rb +0 -17
  100. data/spec/dummyapp/app/helpers/.gitkeep +0 -0
  101. data/spec/dummyapp/app/mailers/.gitkeep +0 -0
  102. data/spec/dummyapp/app/models/.gitkeep +0 -0
  103. data/spec/dummyapp/app/models/book.rb +0 -5
  104. data/spec/dummyapp/app/models/post.rb +0 -9
  105. data/spec/dummyapp/app/models/user.rb +0 -9
  106. data/spec/dummyapp/app/views/devise/registrations/edit.html.erb +0 -27
  107. data/spec/dummyapp/app/views/devise/registrations/new.html.erb +0 -20
  108. data/spec/dummyapp/app/views/devise/shared/_links.html.erb +0 -25
  109. data/spec/dummyapp/app/views/home/cause_exception.html.erb +0 -1
  110. data/spec/dummyapp/app/views/home/index.html.erb +0 -4
  111. data/spec/dummyapp/app/views/home/report_exception.html.erb +0 -1
  112. data/spec/dummyapp/app/views/js/test.html.erb +0 -1
  113. data/spec/dummyapp/app/views/layouts/_messages.html.erb +0 -5
  114. data/spec/dummyapp/app/views/layouts/_navigation.html.erb +0 -21
  115. data/spec/dummyapp/app/views/layouts/application.html.erb +0 -25
  116. data/spec/dummyapp/app/views/layouts/simple.html.erb +0 -18
  117. data/spec/dummyapp/app/views/users/index.html.erb +0 -8
  118. data/spec/dummyapp/app/views/users/show.html.erb +0 -3
  119. data/spec/dummyapp/config.ru +0 -4
  120. data/spec/dummyapp/config/application.rb +0 -59
  121. data/spec/dummyapp/config/boot.rb +0 -10
  122. data/spec/dummyapp/config/database.yml +0 -25
  123. data/spec/dummyapp/config/environment.rb +0 -5
  124. data/spec/dummyapp/config/environments/development.rb +0 -37
  125. data/spec/dummyapp/config/environments/production.rb +0 -67
  126. data/spec/dummyapp/config/environments/test.rb +0 -37
  127. data/spec/dummyapp/config/initializers/backtrace_silencers.rb +0 -7
  128. data/spec/dummyapp/config/initializers/inflections.rb +0 -15
  129. data/spec/dummyapp/config/initializers/mime_types.rb +0 -5
  130. data/spec/dummyapp/config/initializers/rollbar.rb +0 -26
  131. data/spec/dummyapp/config/initializers/secret_token.rb +0 -7
  132. data/spec/dummyapp/config/initializers/session_store.rb +0 -8
  133. data/spec/dummyapp/config/initializers/wrap_parameters.rb +0 -16
  134. data/spec/dummyapp/config/locales/devise.en.yml +0 -58
  135. data/spec/dummyapp/config/locales/en.yml +0 -5
  136. data/spec/dummyapp/config/routes.rb +0 -17
  137. data/spec/dummyapp/config/secrets.yml +0 -2
  138. data/spec/dummyapp/db/migrate/20121121184652_devise_create_users.rb +0 -46
  139. data/spec/dummyapp/db/migrate/20121121184654_add_name_to_users.rb +0 -5
  140. data/spec/dummyapp/db/migrate/20161219184410_create_books.rb +0 -10
  141. data/spec/dummyapp/db/migrate/20161219185529_add_username_to_users.rb +0 -5
  142. data/spec/dummyapp/db/schema.rb +0 -41
  143. data/spec/dummyapp/db/seeds.rb +0 -12
  144. data/spec/dummyapp/lib/assets/.gitkeep +0 -0
  145. data/spec/dummyapp/public/404.html +0 -26
  146. data/spec/dummyapp/public/422.html +0 -26
  147. data/spec/dummyapp/public/500.html +0 -25
  148. data/spec/dummyapp/public/favicon.ico +0 -0
  149. data/spec/dummyapp/script/rails +0 -6
  150. data/spec/fixtures/file1 +0 -1
  151. data/spec/fixtures/file2 +0 -1
  152. data/spec/fixtures/payloads/message.json +0 -25
  153. data/spec/fixtures/payloads/sample.trace.json +0 -275
  154. data/spec/fixtures/payloads/sample.trace_chain.json +0 -530
  155. data/spec/fixtures/plugins/dummy1.rb +0 -5
  156. data/spec/fixtures/plugins/dummy2.rb +0 -5
  157. data/spec/generators/rollbar/rollbar_generator_rails30_spec.rb +0 -31
  158. data/spec/generators/rollbar/rollbar_generator_spec.rb +0 -51
  159. data/spec/requests/home_spec.rb +0 -49
  160. data/spec/rollbar/configuration_spec.rb +0 -46
  161. data/spec/rollbar/delay/delayed_job_spec.rb +0 -22
  162. data/spec/rollbar/delay/girl_friday_spec.rb +0 -41
  163. data/spec/rollbar/delay/resque_spec.rb +0 -37
  164. data/spec/rollbar/delay/thread_spec.rb +0 -27
  165. data/spec/rollbar/encoding/encoder_spec.rb +0 -63
  166. data/spec/rollbar/item/backtrace_spec.rb +0 -26
  167. data/spec/rollbar/item/frame_spec.rb +0 -267
  168. data/spec/rollbar/item_spec.rb +0 -736
  169. data/spec/rollbar/json/oj_spec.rb +0 -18
  170. data/spec/rollbar/json_spec.rb +0 -110
  171. data/spec/rollbar/lazy_store_spec.rb +0 -99
  172. data/spec/rollbar/logger_proxy_spec.rb +0 -50
  173. data/spec/rollbar/logger_spec.rb +0 -124
  174. data/spec/rollbar/middleware/js_spec.rb +0 -421
  175. data/spec/rollbar/middleware/sinatra_spec.rb +0 -197
  176. data/spec/rollbar/notifier_spec.rb +0 -56
  177. data/spec/rollbar/plugin_spec.rb +0 -209
  178. data/spec/rollbar/plugins/active_job_spec.rb +0 -38
  179. data/spec/rollbar/plugins/delayed_job/job_data_spec.rb +0 -48
  180. data/spec/rollbar/plugins/delayed_job_spec.rb +0 -129
  181. data/spec/rollbar/plugins/rack_spec.rb +0 -152
  182. data/spec/rollbar/plugins/rails_js_spec.rb +0 -19
  183. data/spec/rollbar/plugins/rake_spec.rb +0 -34
  184. data/spec/rollbar/plugins/resque/failure_spec.rb +0 -36
  185. data/spec/rollbar/plugins/sidekiq_spec.rb +0 -171
  186. data/spec/rollbar/plugins/validations_spec.rb +0 -56
  187. data/spec/rollbar/plugins_spec.rb +0 -68
  188. data/spec/rollbar/request_data_extractor_spec.rb +0 -270
  189. data/spec/rollbar/scrubbers/params_spec.rb +0 -314
  190. data/spec/rollbar/scrubbers/url_spec.rb +0 -136
  191. data/spec/rollbar/scrubbers_spec.rb +0 -31
  192. data/spec/rollbar/sidekig/clear_scope_spec.rb +0 -19
  193. data/spec/rollbar/truncation/frames_strategy_spec.rb +0 -70
  194. data/spec/rollbar/truncation/min_body_strategy_spec.rb +0 -57
  195. data/spec/rollbar/truncation/strings_strategy_spec.rb +0 -89
  196. data/spec/rollbar/truncation_spec.rb +0 -27
  197. data/spec/rollbar/util/hash_spec.rb +0 -22
  198. data/spec/rollbar/util/ip_anonymizer_spec.rb +0 -30
  199. data/spec/rollbar/util_spec.rb +0 -80
  200. data/spec/rollbar_bc_spec.rb +0 -380
  201. data/spec/rollbar_spec.rb +0 -1667
  202. data/spec/spec_helper.rb +0 -84
  203. data/spec/support/cause_exception.rb +0 -1
  204. data/spec/support/encoding_helpers.rb +0 -8
  205. data/spec/support/encodings/iso_8859_9 +0 -1
  206. data/spec/support/fixture_helpers.rb +0 -10
  207. data/spec/support/get_ip_raising.rb +0 -7
  208. data/spec/support/helpers.rb +0 -5
  209. data/spec/support/matchers.rb +0 -23
  210. data/spec/support/notifier_helpers.rb +0 -57
  211. data/spec/support/rollbar_api.rb +0 -57
  212. data/spec/support/shared_contexts.rb +0 -12
@@ -10,15 +10,19 @@ require 'rollbar/json'
10
10
 
11
11
  module Rollbar
12
12
  module RequestDataExtractor
13
- ALLOWED_HEADERS_REGEX = /^HTTP_|^CONTENT_TYPE$|^CONTENT_LENGTH$/
14
- ALLOWED_BODY_PARSEABLE_METHODS = %w(POST PUT PATCH DELETE).freeze
13
+ ALLOWED_HEADERS_REGEX = /^HTTP_|^CONTENT_TYPE$|^CONTENT_LENGTH$/.freeze
14
+ ALLOWED_BODY_PARSEABLE_METHODS = %w[POST PUT PATCH DELETE].freeze
15
15
 
16
16
  def extract_person_data_from_controller(env)
17
- if env.has_key?('rollbar.person_data')
17
+ if env.key?('rollbar.person_data')
18
18
  person_data = env['rollbar.person_data'] || {}
19
19
  else
20
20
  controller = env['action_controller.instance']
21
- person_data = controller.rollbar_person_data rescue {}
21
+ person_data = begin
22
+ controller.rollbar_person_data
23
+ rescue StandardError
24
+ {}
25
+ end
22
26
  end
23
27
 
24
28
  person_data
@@ -50,9 +54,7 @@ module Rollbar
50
54
  :method => rollbar_request_method(env)
51
55
  }
52
56
 
53
- if env['action_dispatch.request_id']
54
- data[:request_id] = env['action_dispatch.request_id']
55
- end
57
+ data[:request_id] = env['action_dispatch.request_id'] if env['action_dispatch.request_id']
56
58
 
57
59
  data
58
60
  end
@@ -63,7 +65,8 @@ module Rollbar
63
65
  :scrub_fields => Array(Rollbar.configuration.scrub_fields) + sensitive_params,
64
66
  :scrub_user => Rollbar.configuration.scrub_user,
65
67
  :scrub_password => Rollbar.configuration.scrub_password,
66
- :randomize_scrub_length => Rollbar.configuration.randomize_scrub_length
68
+ :randomize_scrub_length => Rollbar.configuration.randomize_scrub_length,
69
+ :whitelist => Rollbar.configuration.scrub_whitelist
67
70
  }
68
71
 
69
72
  Rollbar::Scrubbers::URL.call(options)
@@ -73,7 +76,8 @@ module Rollbar
73
76
  options = {
74
77
  :params => params,
75
78
  :config => Rollbar.configuration.scrub_fields,
76
- :extra_fields => sensitive_params
79
+ :extra_fields => sensitive_params,
80
+ :whitelist => Rollbar.configuration.scrub_whitelist
77
81
  }
78
82
  Rollbar::Scrubbers::Params.call(options)
79
83
  end
@@ -105,6 +109,14 @@ module Rollbar
105
109
  { name => Rollbar::Scrubbers.scrub_value(env[header]) }
106
110
  elsif name == 'X-Forwarded-For' && !Rollbar.configuration.collect_user_ip
107
111
  {}
112
+ elsif name == 'X-Forwarded-For' && Rollbar.configuration.collect_user_ip && Rollbar.configuration.anonymize_user_ip
113
+ ips = env[header].sub(' ', '').split(',')
114
+ ips = ips.map { |ip| Rollbar::Util::IPAnonymizer.anonymize_ip(ip) }
115
+ { name => ips.join(', ') }
116
+ elsif name == 'X-Real-Ip' && !Rollbar.configuration.collect_user_ip
117
+ {}
118
+ elsif name == 'X-Real-Ip' && Rollbar.configuration.collect_user_ip && Rollbar.configuration.anonymize_user_ip
119
+ { name => Rollbar::Util::IPAnonymizer.anonymize_ip(env[header]) }
108
120
  else
109
121
  { name => env[header] }
110
122
  end
@@ -124,8 +136,8 @@ module Rollbar
124
136
  end
125
137
 
126
138
  port = env['HTTP_X_FORWARDED_PORT']
127
- if port && !(!scheme.nil? && scheme.downcase == 'http' && port.to_i == 80) && \
128
- !(!scheme.nil? && scheme.downcase == 'https' && port.to_i == 443) && \
139
+ if port && !(!scheme.nil? && scheme.casecmp('http').zero? && port.to_i == 80) && \
140
+ !(!scheme.nil? && scheme.casecmp('https').zero? && port.to_i == 443) && \
129
141
  !(host.include? ':')
130
142
  host = host + ':' + port
131
143
  end
@@ -135,12 +147,13 @@ module Rollbar
135
147
 
136
148
  def rollbar_user_ip(env)
137
149
  return nil unless Rollbar.configuration.collect_user_ip
150
+
138
151
  user_ip_string = (env['action_dispatch.remote_ip'] || env['HTTP_X_REAL_IP'] || x_forwarded_for_client(env['HTTP_X_FORWARDED_FOR']) || env['REMOTE_ADDR']).to_s
139
152
 
140
153
  user_ip_string = Rollbar::Util::IPAnonymizer.anonymize_ip(user_ip_string)
141
154
 
142
155
  Rollbar::Util::IPObfuscator.obfuscate_ip(user_ip_string)
143
- rescue
156
+ rescue StandardError
144
157
  nil
145
158
  end
146
159
 
@@ -166,13 +179,13 @@ module Rollbar
166
179
 
167
180
  def rollbar_get_params(rack_req)
168
181
  rack_req.GET
169
- rescue
182
+ rescue StandardError
170
183
  {}
171
184
  end
172
185
 
173
186
  def rollbar_post_params(rack_req)
174
187
  rack_req.POST
175
- rescue
188
+ rescue StandardError
176
189
  {}
177
190
  end
178
191
 
@@ -185,18 +198,19 @@ module Rollbar
185
198
  raw_body = rack_req.body.read
186
199
  begin
187
200
  Rollbar::JSON.load(raw_body)
188
- rescue
201
+ rescue StandardError
189
202
  raw_body
190
203
  end
191
- rescue
204
+ rescue StandardError
192
205
  {}
193
206
  ensure
194
207
  rack_req.body.rewind
195
208
  end
196
209
 
197
210
  def json_request?(rack_req)
198
- !!(rack_req.env['CONTENT_TYPE'] =~ %r{application/json} ||
199
- rack_req.env['ACCEPT'] =~ /\bjson\b/)
211
+ json_regex = /\bjson\b/
212
+
213
+ !!(rack_req.env['CONTENT_TYPE'] =~ json_regex)
200
214
  end
201
215
 
202
216
  def rollbar_route_params(env)
@@ -209,7 +223,7 @@ module Rollbar
209
223
  # route params (if any)and format (if defined)
210
224
  ::Rails.application.routes.recognize_path(env['PATH_INFO'],
211
225
  environment)
212
- rescue
226
+ rescue StandardError
213
227
  {}
214
228
  end
215
229
  end
@@ -218,13 +232,13 @@ module Rollbar
218
232
  session = env.fetch('rack.session', {})
219
233
 
220
234
  session.to_hash
221
- rescue
235
+ rescue StandardError
222
236
  {}
223
237
  end
224
238
 
225
239
  def rollbar_request_cookies(rack_req)
226
240
  rack_req.cookies
227
- rescue
241
+ rescue StandardError
228
242
  {}
229
243
  end
230
244
 
@@ -0,0 +1,147 @@
1
+ require 'rollbar'
2
+ begin
3
+ require 'rack/mock'
4
+ rescue LoadError
5
+ puts 'Cannot load rack/mock'
6
+ end
7
+ require 'logger'
8
+
9
+ # Module to inject into the Rails controllers or rack apps
10
+ module RollbarTest # :nodoc:
11
+ def test_rollbar
12
+ puts 'Raising RollbarTestingException to simulate app failure.'
13
+
14
+ raise RollbarTestingException.new, ::RollbarTest.success_message
15
+ end
16
+
17
+ def self.run
18
+ return unless confirmed_token?
19
+
20
+ configure_rails if defined?(Rails)
21
+
22
+ puts 'Testing manual report...'
23
+ Rollbar.error('Test error from rollbar:test')
24
+
25
+ return unless defined?(Rack::MockRequest)
26
+
27
+ protocol, app = setup_app
28
+
29
+ puts 'Processing...'
30
+ env = Rack::MockRequest.env_for("#{protocol}://www.example.com/verify", 'REMOTE_ADDR' => '127.0.0.1')
31
+ status, = app.call(env)
32
+
33
+ puts error_message unless status.to_i == 500
34
+ end
35
+
36
+ def self.configure_rails
37
+ Rails.logger = if defined?(ActiveSupport::TaggedLogging)
38
+ ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
39
+ else
40
+ Logger.new(STDOUT)
41
+ end
42
+
43
+ Rails.logger.level = Logger::DEBUG
44
+ Rollbar.preconfigure do |config|
45
+ config.logger = Rails.logger
46
+ end
47
+ end
48
+
49
+ def self.confirmed_token?
50
+ return true if Rollbar.configuration.access_token
51
+
52
+ puts token_error_message
53
+
54
+ false
55
+ end
56
+
57
+ def self.authlogic_config
58
+ # from http://stackoverflow.com/questions/5270835/authlogic-activation-problems
59
+ return unless defined?(Authlogic)
60
+
61
+ Authlogic::Session::Base.controller = Authlogic::ControllerAdapters::RailsAdapter.new(self)
62
+ end
63
+
64
+ def self.setup_app
65
+ puts 'Setting up the test app.'
66
+
67
+ if defined?(Rails)
68
+ app = rails_app
69
+
70
+ draw_rails_route(app)
71
+
72
+ authlogic_config
73
+
74
+ [rails_protocol(app), app]
75
+ else
76
+ ['http', rack_app]
77
+ end
78
+ end
79
+
80
+ def self.rails_app
81
+ # The setup below is needed for Rails 5.x, but not for Rails 4.x and below.
82
+ # (And fails on Rails 4.x in various ways depending on the exact version.)
83
+ return Rails.application if Rails.version < '5.0.0'
84
+
85
+ # Spring now runs by default in development on all new Rails installs. This causes
86
+ # the new `/verify` route to not get picked up if `config.cache_classes == false`
87
+ # which is also a default in development env.
88
+ #
89
+ # `config.cache_classes` needs to be set, but the only possible time is at app load,
90
+ # so here we clone the default app with an updated config.
91
+ #
92
+ config = Rails.application.config
93
+ config.cache_classes = true
94
+
95
+ # Make a copy of the app, so the config can be updated.
96
+ Rails.application.class.name.constantize.new(:config => config)
97
+ end
98
+
99
+ def self.draw_rails_route(app)
100
+ app.routes_reloader.execute_if_updated
101
+ app.routes.draw do
102
+ get 'verify' => 'rollbar_test#verify', :as => 'verify'
103
+ end
104
+ end
105
+
106
+ def self.rails_protocol(app)
107
+ defined?(app.config.force_ssl && app.config.force_ssl) ? 'https' : 'http'
108
+ end
109
+
110
+ def self.rack_app
111
+ Class.new do
112
+ include RollbarTest
113
+
114
+ def self.call(_env)
115
+ new.test_rollbar
116
+ end
117
+ end
118
+ end
119
+
120
+ def self.token_error_message
121
+ 'Rollbar needs an access token configured. Check the README for instructions.'
122
+ end
123
+
124
+ def self.error_message
125
+ 'Test failed! You may have a configuration issue, or you could be using a gem that\'s blocking the test. Contact support@rollbar.com if you need help troubleshooting.'
126
+ end
127
+
128
+ def self.success_message
129
+ 'Testing rollbar with "rake rollbar:test". If you can see this, it works.'
130
+ end
131
+ end
132
+
133
+ class RollbarTestingException < RuntimeError; end
134
+
135
+ if defined?(Rails)
136
+ class RollbarTestController < ActionController::Base # :nodoc:
137
+ include RollbarTest
138
+
139
+ def verify
140
+ test_rollbar
141
+ end
142
+
143
+ def logger
144
+ nil
145
+ end
146
+ end
147
+ end
@@ -1,17 +1,21 @@
1
1
  module Rollbar
2
2
  module Scrubbers
3
- extend self
3
+ module_function
4
4
 
5
5
  def scrub_value(value)
6
6
  if Rollbar.configuration.randomize_scrub_length
7
7
  random_filtered_value
8
8
  else
9
- '*' * (value.length rescue 8)
9
+ '*' * (begin
10
+ value.length
11
+ rescue StandardError
12
+ 8
13
+ end)
10
14
  end
11
15
  end
12
16
 
13
17
  def random_filtered_value
14
- '*' * (rand(5) + 3)
18
+ '*' * rand(3..7)
15
19
  end
16
20
  end
17
21
  end
@@ -6,10 +6,11 @@ module Rollbar
6
6
  # This class contains the logic to scrub the received parameters. It will
7
7
  # scrub the parameters matching Rollbar.configuration.scrub_fields Array.
8
8
  # Also, if that configuration option is set to :scrub_all, it will scrub all
9
- # received parameters
9
+ # received parameters. It will not scrub anything that is in the scrub_whitelist
10
+ # configuration array even if :scrub_all is true.
10
11
  class Params
11
- SKIPPED_CLASSES = [::Tempfile]
12
- ATTACHMENT_CLASSES = %w(ActionDispatch::Http::UploadedFile Rack::Multipart::UploadedFile).freeze
12
+ SKIPPED_CLASSES = [::Tempfile].freeze
13
+ ATTACHMENT_CLASSES = %w[ActionDispatch::Http::UploadedFile Rack::Multipart::UploadedFile].freeze
13
14
  SCRUB_ALL = :scrub_all
14
15
 
15
16
  def self.call(*args)
@@ -20,20 +21,24 @@ module Rollbar
20
21
  params = options[:params]
21
22
  return {} unless params
22
23
 
24
+ @scrubbed_object_ids = {}
25
+
23
26
  config = options[:config]
24
27
  extra_fields = options[:extra_fields]
28
+ whitelist = options[:whitelist] || []
25
29
 
26
- scrub(params, build_scrub_options(config, extra_fields))
30
+ scrub(params, build_scrub_options(config, extra_fields, whitelist))
27
31
  end
28
32
 
29
33
  private
30
34
 
31
- def build_scrub_options(config, extra_fields)
35
+ def build_scrub_options(config, extra_fields, whitelist)
32
36
  ary_config = Array(config)
33
37
 
34
38
  {
35
39
  :fields_regex => build_fields_regex(ary_config, extra_fields),
36
- :scrub_all => ary_config.include?(SCRUB_ALL)
40
+ :scrub_all => ary_config.include?(SCRUB_ALL),
41
+ :whitelist => build_whitelist_regex(whitelist)
37
42
  }
38
43
  end
39
44
 
@@ -46,26 +51,39 @@ module Rollbar
46
51
  Regexp.new(fields.map { |val| Regexp.escape(val.to_s).to_s }.join('|'), true)
47
52
  end
48
53
 
54
+ def build_whitelist_regex(whitelist)
55
+ fields = whitelist.find_all { |f| f.is_a?(String) || f.is_a?(Symbol) || f.is_a?(Regexp) }
56
+ return unless fields.any?
57
+
58
+ Regexp.new(fields.map { |val| val.is_a?(Regexp) ? val : /\A#{Regexp.escape(val.to_s)}\z/ }.join('|'))
59
+ end
60
+
49
61
  def scrub(params, options)
62
+ return params if @scrubbed_object_ids[params.object_id]
63
+
64
+ @scrubbed_object_ids[params.object_id] = true
65
+
50
66
  fields_regex = options[:fields_regex]
51
67
  scrub_all = options[:scrub_all]
68
+ whitelist_regex = options[:whitelist]
52
69
 
53
70
  return scrub_array(params, options) if params.is_a?(Array)
54
71
 
55
72
  params.to_hash.inject({}) do |result, (key, value)|
56
- if fields_regex === Rollbar::Encoding.encode(key).to_s
57
- result[key] = scrub_value(value)
58
- elsif value.is_a?(Hash)
59
- result[key] = scrub(value, options)
60
- elsif value.is_a?(Array)
61
- result[key] = scrub_array(value, options)
62
- elsif skip_value?(value)
63
- result[key] = "Skipped value of class '#{value.class.name}'"
64
- elsif scrub_all
65
- result[key] = scrub_value(value)
66
- else
67
- result[key] = rollbar_filtered_param_value(value)
68
- end
73
+ encoded_key = Rollbar::Encoding.encode(key).to_s
74
+ result[key] = if (fields_regex === encoded_key) && !(whitelist_regex === encoded_key)
75
+ scrub_value(value)
76
+ elsif value.is_a?(Hash)
77
+ scrub(value, options)
78
+ elsif scrub_all && !(whitelist_regex === encoded_key)
79
+ scrub_value(value)
80
+ elsif value.is_a?(Array)
81
+ scrub_array(value, options)
82
+ elsif skip_value?(value)
83
+ "Skipped value of class '#{value.class.name}'"
84
+ else
85
+ rollbar_filtered_param_value(value)
86
+ end
69
87
 
70
88
  result
71
89
  end
@@ -85,7 +103,7 @@ module Rollbar
85
103
  if ATTACHMENT_CLASSES.include?(value.class.name)
86
104
  begin
87
105
  attachment_value(value)
88
- rescue
106
+ rescue StandardError
89
107
  'Uploaded file'
90
108
  end
91
109
  else
@@ -6,32 +6,42 @@ require 'rollbar/language_support'
6
6
  module Rollbar
7
7
  module Scrubbers
8
8
  class URL
9
+ SCRUB_ALL = :scrub_all
10
+
9
11
  def self.call(*args)
10
12
  new.call(*args)
11
13
  end
12
14
 
13
15
  def call(options = {})
14
16
  url = options[:url]
15
- return url unless Rollbar::LanguageSupport.can_scrub_url?
16
17
 
17
18
  filter(url,
18
19
  build_regex(options[:scrub_fields]),
19
20
  options[:scrub_user],
20
21
  options[:scrub_password],
21
- options.fetch(:randomize_scrub_length, true))
22
- rescue => e
22
+ options.fetch(:randomize_scrub_length, true),
23
+ options[:scrub_fields].include?(SCRUB_ALL),
24
+ build_whitelist_regex(options[:whitelist] || []))
25
+ rescue StandardError => e
23
26
  Rollbar.logger.error("[Rollbar] There was an error scrubbing the url: #{e}, options: #{options.inspect}")
24
27
  url
25
28
  end
26
29
 
27
30
  private
28
31
 
29
- def filter(url, regex, scrub_user, scrub_password, randomize_scrub_length)
32
+ def build_whitelist_regex(whitelist)
33
+ fields = whitelist.find_all { |f| f.is_a?(String) || f.is_a?(Symbol) }
34
+ return unless fields.any?
35
+
36
+ Regexp.new(fields.map { |val| /\A#{Regexp.escape(val.to_s)}\z/ }.join('|'))
37
+ end
38
+
39
+ def filter(url, regex, scrub_user, scrub_password, randomize_scrub_length, scrub_all, whitelist)
30
40
  uri = URI.parse(url)
31
41
 
32
42
  uri.user = filter_user(uri.user, scrub_user, randomize_scrub_length)
33
43
  uri.password = filter_password(uri.password, scrub_password, randomize_scrub_length)
34
- uri.query = filter_query(uri.query, regex, randomize_scrub_length)
44
+ uri.query = filter_query(uri.query, regex, randomize_scrub_length, scrub_all, whitelist)
35
45
 
36
46
  uri.to_s
37
47
  end
@@ -52,12 +62,12 @@ module Rollbar
52
62
  scrub_password && password ? filtered_value(password, randomize_scrub_length) : password
53
63
  end
54
64
 
55
- def filter_query(query, regex, randomize_scrub_length)
65
+ def filter_query(query, regex, randomize_scrub_length, scrub_all, whitelist)
56
66
  return query unless query
57
67
 
58
68
  params = decode_www_form(query)
59
69
 
60
- encoded_query = encode_www_form(filter_query_params(params, regex, randomize_scrub_length))
70
+ encoded_query = encode_www_form(filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist))
61
71
 
62
72
  # We want this to rebuild array params like foo[]=1&foo[]=2
63
73
  URI.escape(CGI.unescape(encoded_query))
@@ -71,26 +81,30 @@ module Rollbar
71
81
  URI.encode_www_form(params)
72
82
  end
73
83
 
74
- def filter_query_params(params, regex, randomize_scrub_length)
84
+ def filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist)
75
85
  params.map do |key, value|
76
- [key, filter_key?(key, regex) ? filtered_value(value, randomize_scrub_length) : value]
86
+ [key, filter_key?(key, regex, scrub_all, whitelist) ? filtered_value(value, randomize_scrub_length) : value]
77
87
  end
78
88
  end
79
89
 
80
- def filter_key?(key, regex)
81
- !!(key =~ regex)
90
+ def filter_key?(key, regex, scrub_all, whitelist)
91
+ !(whitelist === key) && (scrub_all || regex === key)
82
92
  end
83
93
 
84
94
  def filtered_value(value, randomize_scrub_length)
85
95
  if randomize_scrub_length
86
96
  random_filtered_value
87
97
  else
88
- '*' * (value.length rescue 8)
98
+ '*' * (begin
99
+ value.length
100
+ rescue StandardError
101
+ 8
102
+ end)
89
103
  end
90
104
  end
91
105
 
92
106
  def random_filtered_value
93
- '*' * (rand(5) + 3)
107
+ '*' * rand(3..7)
94
108
  end
95
109
  end
96
110
  end