require 'spec_helper' require 'tempfile' require 'rollbar/scrubbers/params' require 'rspec/expectations' describe Rollbar::Scrubbers::Params do describe '.call' do it 'calls #call in a new instance' do arguments = [:foo, :bar] expect_any_instance_of(described_class).to receive(:call).with(*arguments) described_class.call(*arguments) end end describe '#call' do let(:options) do options = { :params => params, :config => scrub_config } if defined? whitelist options[:whitelist] = whitelist end options end context 'with scrub fields configured' do let(:scrub_config) do [:secret, :password] end context 'with Array object' do let(:params) do [ { :foo => 'bar', :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' } ] end let(:result) do [ { :foo => 'bar', :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/ } ] end it 'scrubs the required parameters' do expect(subject.call(options).first).to be_eql_hash_with_regexes(result.first) end end context 'with simple Hash' do let(:params) do { :foo => 'bar', :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' } end let(:result) do { :foo => 'bar', :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/ } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with nested Hash' do let(:scrub_config) do super().push(:other) end let(:params) do { :foo => 'bar', :extra => { :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' }, :other => { :param => 'filtered' } } end let(:result) do { :foo => 'bar', :extra => { :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/ }, :other => /\*+/ } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with nested Array' do let(:scrub_config) do super().push(:other) end let(:params) do { :foo => 'bar', :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' }], :other => [{ :param => 'filtered' }] } end let(:result) do { :foo => 'bar', :extra => [{ :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/ }], :other => /\*+/ } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with skipped instance' do let(:tempfile) { Tempfile.new('foo') } let(:params) do { :foo => 'bar', :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password', :skipped => tempfile }] } end let(:result) do { :foo => 'bar', :extra => [{ :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/, :skipped => "Skipped value of class 'Tempfile'" }] } end after { tempfile.close } it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with attachment instance' do let(:tempfile) { double(:size => 100) } let(:attachment) do double(:class => double(:name => 'ActionDispatch::Http::UploadedFile'), :tempfile => tempfile, :content_type => 'content-type', 'original_filename' => 'filename') end let(:params) do { :foo => 'bar', :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password', :attachment => attachment }] } end let(:result) do { :foo => 'bar', :extra => [{ :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/, :attachment => { :content_type => 'content-type', :original_filename => 'filename', :size => 100 } }] } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end context 'if getting the attachment values fails' do let(:tempfile) { Object.new } let(:attachment) do double(:class => double(:name => 'ActionDispatch::Http::UploadedFile'), :tempfile => tempfile, :content_type => 'content-type', 'original_filename' => 'filename') end let(:params) do { :foo => 'bar', :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password', :attachment => attachment }] } end let(:result) do { :foo => 'bar', :extra => [{ :secret => /\*+/, :password => /\*+/, :password_confirmation => /\*+/, :attachment => 'Uploaded file' }] } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end end context 'without params' do let(:params) do nil end let(:result) do {} end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end end context 'with :scrub_all option' do let(:scrub_config) { :scrub_all } let(:params) do { :foo => 'bar', :password => 'the-password', :bar => 'foo', :extra => { :foo => 'more-foo', :bar => 'more-bar' } } end let(:result) do { :foo => /\*+/, :password => /\*+/, :bar => /\*+/, :extra => { :foo => /\*+/, :bar => /\*+/ } } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with :whitelist option' do let(:scrub_config) do [:secret, :password] end let(:whitelist) { true } context 'with Array object' do let(:params) do [ { :foo => 'bar', :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' } ] end let(:result) do [ { :foo => /\*+/, :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' } ] end it 'scrubs the required parameters' do expect(subject.call(options).first).to be_eql_hash_with_regexes(result.first) end end context 'with simple Hash' do let(:params) do { :foo => 'bar', :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' } end let(:result) do { :foo => /\*+/, :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with nested Hash' do let(:scrub_config) do super().push(:param) end let(:params) do { :foo => 'bar', :extra => { :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' }, :other => { :param => 'filtered', :to_scrub => 'to_scrub' } } end let(:result) do { :foo => /\*+/, :extra => { :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' }, :other => { :param => 'filtered', :to_scrub => /\*+/ } } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with nested Array' do let(:scrub_config) do super().push(:param) end let(:params) do { :foo => 'bar', :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' }], :other => [{ :param => 'filtered', :to_scrub => 'to_scrub' }] } end let(:result) do { :foo => /\*+/, :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password' }], :other => [{ :param => 'filtered', :to_scrub => /\*+/ }] } end it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end context 'with skipped instance' do let(:tempfile) { Tempfile.new('foo') } let(:params) do { :foo => 'bar', :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password', :skipped => tempfile }] } end let(:result) do { :foo => /\*+/, :extra => [{ :secret => 'the-secret', :password => 'the-password', :password_confirmation => 'the-password', :skipped => "Skipped value of class 'Tempfile'" }] } end after { tempfile.close } it 'scrubs the required parameters' do expect(subject.call(options)).to be_eql_hash_with_regexes(result) end end end end end describe Rollbar::Scrubbers::Params::ATTACHMENT_CLASSES do it 'has the correct values' do expect(described_class).to be_eql(%w(ActionDispatch::Http::UploadedFile Rack::Multipart::UploadedFile).freeze) end end describe Rollbar::Scrubbers::Params::SKIPPED_CLASSES do it 'has the correct values' do expect(described_class).to be_eql([Tempfile]) end end