From 501d206c2b25afb9e59cba2b7a6502f3c861d6a4 Mon Sep 17 00:00:00 2001 From: Javier Julio Date: Wed, 1 May 2024 17:25:58 -0400 Subject: [PATCH 1/7] Include warden scope in user info --- lib/bugsnag/middleware/warden_user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bugsnag/middleware/warden_user.rb b/lib/bugsnag/middleware/warden_user.rb index 59c6af0de..6650aa52e 100644 --- a/lib/bugsnag/middleware/warden_user.rb +++ b/lib/bugsnag/middleware/warden_user.rb @@ -21,7 +21,7 @@ def call(report) best_scope = warden_scopes.include?("user") ? "user" : warden_scopes.first # Extract useful user information - user = {} + user = { :warden_scope => best_scope } user_object = env["warden"].user({:scope => best_scope, :run_callbacks => false}) rescue nil if user_object # Build the user info for this scope From c2a6093b216e120e2a3ae6f2480a4a5be5fcbc93 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Fri, 17 May 2024 08:56:28 +0100 Subject: [PATCH 2/7] Update tests to include the warden scope in user --- spec/integrations/warden_user_spec.rb | 58 ++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/spec/integrations/warden_user_spec.rb b/spec/integrations/warden_user_spec.rb index 03b0b5fdf..cfa3eeb9e 100644 --- a/spec/integrations/warden_user_spec.rb +++ b/spec/integrations/warden_user_spec.rb @@ -6,31 +6,71 @@ user = double allow(user).to receive_messages( - :email => "TEST_EMAIL", - :name => "TEST_NAME", - :created_at => "TEST_NOW" + email: "TEST_EMAIL", + name: "TEST_NAME", + created_at: "TEST_NOW", ) warden = double allow(warden).to receive(:user).with({ - :scope => "user", - :run_callbacks => false + scope: "user", + run_callbacks: false, }).and_return(user) report = double("Bugsnag::Report") + expect(report).to receive(:request_data).exactly(3).times.and_return({ + rack_env: { + "warden" => warden, + "rack.session" => { + "warden.user.user.key" => "TEST_USER", + } + } + }) + + expect(report).to receive(:user=).with({ + email: "TEST_EMAIL", + name: "TEST_NAME", + created_at: "TEST_NOW", + warden_scope: "user", + }) + + expect(callback).to receive(:call).with(report) + + middleware = Bugsnag::Middleware::WardenUser.new(callback) + middleware.call(report) + end + + it "sets the scope to the 'best scope'" do + callback = double + + user = double + allow(user).to receive_messages( + email: "TEST_EMAIL", + name: "TEST_NAME", + created_at: "TEST_NOW", + ) + + warden = double + allow(warden).to receive(:user).with({ + scope: "admin", + run_callbacks: false, + }).and_return(user) + + report = double("Bugsnag::Report") expect(report).to receive(:request_data).exactly(3).times.and_return({ :rack_env => { "warden" => warden, "rack.session" => { - "warden.user.user.key" => "TEST_USER" + "warden.user.admin.key" => "TEST_USER" } } }) expect(report).to receive(:user=).with({ - :email => "TEST_EMAIL", - :name => "TEST_NAME", - :created_at => "TEST_NOW" + email: "TEST_EMAIL", + name: "TEST_NAME", + created_at: "TEST_NOW", + warden_scope: "admin", }) expect(callback).to receive(:call).with(report) From 912acacaa0ecedcc384f9190d6bf129f527aa038 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Fri, 17 May 2024 08:57:24 +0100 Subject: [PATCH 3/7] Only set the warden scope if there's a user object This prevents having a user object that only contains the scope with no other information --- lib/bugsnag/middleware/warden_user.rb | 5 ++++- spec/integrations/warden_user_spec.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/bugsnag/middleware/warden_user.rb b/lib/bugsnag/middleware/warden_user.rb index 6650aa52e..bb9b84327 100644 --- a/lib/bugsnag/middleware/warden_user.rb +++ b/lib/bugsnag/middleware/warden_user.rb @@ -21,9 +21,12 @@ def call(report) best_scope = warden_scopes.include?("user") ? "user" : warden_scopes.first # Extract useful user information - user = { :warden_scope => best_scope } + user = {} user_object = env["warden"].user({:scope => best_scope, :run_callbacks => false}) rescue nil + if user_object + user[:warden_scope] = best_scope + # Build the user info for this scope COMMON_USER_FIELDS.each do |field| user[field] = user_object.send(field) if user_object.respond_to?(field) diff --git a/spec/integrations/warden_user_spec.rb b/spec/integrations/warden_user_spec.rb index cfa3eeb9e..1a228d9a4 100644 --- a/spec/integrations/warden_user_spec.rb +++ b/spec/integrations/warden_user_spec.rb @@ -78,4 +78,31 @@ middleware = Bugsnag::Middleware::WardenUser.new(callback) middleware.call(report) end + + it "doesn't set the user if the user object is empty" do + callback = double + + warden = double + allow(warden).to receive(:user).with({ + scope: "user", + run_callbacks: false, + }).and_return(nil) + + report = double("Bugsnag::Report") + expect(report).to receive(:request_data).exactly(3).times.and_return({ + :rack_env => { + "warden" => warden, + "rack.session" => { + "warden.user.user.key" => "TEST_USER" + } + } + }) + + expect(report).not_to receive(:user=) + + expect(callback).to receive(:call).with(report) + + middleware = Bugsnag::Middleware::WardenUser.new(callback) + middleware.call(report) + end end From e66f7e9f39e76e6778eda68463cbe66bc414f2d7 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Fri, 17 May 2024 08:58:10 +0100 Subject: [PATCH 4/7] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 111dc7998..d17bd5f65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ Changelog ========= +## TBD + +### Enhancements + +* Include the Warden scope in user metadata + | [#821](https://github.com/bugsnag/bugsnag-ruby/pull/821) + | [javierjulio](https://github.com/javierjulio) + ## v6.26.4 (25 March 2024) ### Fixes From 0bd883c4e36e6d94e675037b3110ee50bbd2d295 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Wed, 22 May 2024 09:35:42 +0100 Subject: [PATCH 5/7] Pin Rails 6 integrations tests to Ruby 3.3.0 3.3.1 has a bug causing the fixture to fail to start: https://github.com/ruby/ruby/pull/10619 --- .github/workflows/maze-runner.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maze-runner.yml b/.github/workflows/maze-runner.yml index e2e27582a..0c31db330 100644 --- a/.github/workflows/maze-runner.yml +++ b/.github/workflows/maze-runner.yml @@ -127,7 +127,7 @@ jobs: strategy: fail-fast: false matrix: - ruby-version: ['2.7', '3.3'] + ruby-version: ['2.7', '3.3.0'] # TODO: change back to '3.3' after https://github.com/ruby/ruby/pull/10619 is released rails-version: ['6', '7', '_integrations'] include: - ruby-version: '2.5' @@ -135,7 +135,7 @@ jobs: exclude: - ruby-version: '2.7' rails-version: '6' - - ruby-version: '3.3' + - ruby-version: '3.3.0' # TODO: change back to '3.3' after https://github.com/ruby/ruby/pull/10619 is released rails-version: '_integrations' uses: ./.github/workflows/run-maze-runner.yml From 4d594506e3d5944a5bcbfc8fc2b551e686e52189 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Wed, 22 May 2024 09:16:07 +0100 Subject: [PATCH 6/7] Add block variant of `add_on_error` Usage: Bugsnag.on_error do |event| event.add_metadata(:info, { a: 1 }) end --- CHANGELOG.md | 2 ++ lib/bugsnag.rb | 14 +++++++++++++ lib/bugsnag/configuration.rb | 14 +++++++++++++ spec/on_error_spec.rb | 39 ++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d17bd5f65..dca836b42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Changelog * Include the Warden scope in user metadata | [#821](https://github.com/bugsnag/bugsnag-ruby/pull/821) | [javierjulio](https://github.com/javierjulio) +* Add a block variant of `add_on_error` + | [#824](https://github.com/bugsnag/bugsnag-ruby/pull/824) ## v6.26.4 (25 March 2024) diff --git a/lib/bugsnag.rb b/lib/bugsnag.rb index 5d002a907..950f17267 100644 --- a/lib/bugsnag.rb +++ b/lib/bugsnag.rb @@ -309,6 +309,20 @@ def leave_breadcrumb(name, meta_data={}, type=Bugsnag::Breadcrumbs::MANUAL_BREAD configuration.breadcrumbs << breadcrumb unless breadcrumb.ignore? end + ## + # Add the given block to the list of on_error callbacks + # + # The on_error callbacks will be called when an error is captured or reported + # and are passed a {Bugsnag::Report} object + # + # Returning false from an on_error callback will cause the error to be ignored + # and will prevent any remaining callbacks from being called + # + # @return [void] + def on_error(&block) + configuration.on_error(&block) + end + ## # Add the given callback to the list of on_error callbacks # diff --git a/lib/bugsnag/configuration.rb b/lib/bugsnag/configuration.rb index 36dda53d8..bcf64c813 100644 --- a/lib/bugsnag/configuration.rb +++ b/lib/bugsnag/configuration.rb @@ -569,6 +569,20 @@ def disable_sessions @enable_sessions = false end + ## + # Add the given block to the list of on_error callbacks + # + # The on_error callbacks will be called when an error is captured or reported + # and are passed a {Bugsnag::Report} object + # + # Returning false from an on_error callback will cause the error to be ignored + # and will prevent any remaining callbacks from being called + # + # @return [void] + def on_error(&block) + middleware.use(block) + end + ## # Add the given callback to the list of on_error callbacks # diff --git a/spec/on_error_spec.rb b/spec/on_error_spec.rb index 15bcdb5aa..798befd1d 100644 --- a/spec/on_error_spec.rb +++ b/spec/on_error_spec.rb @@ -18,6 +18,20 @@ end) end + it "accepts a block" do + Bugsnag.on_error {|report| report.add_tab(:important, { hello: "world" }) } + Bugsnag.on_error {|report| report.add_tab(:significant, { hey: "earth" }) } + + Bugsnag.notify(RuntimeError.new("Oh no!")) + + expect(Bugsnag).to(have_sent_notification do |payload, _headers| + event = get_event_from_payload(payload) + + expect(event["metaData"]["important"]).to eq({ "hello" => "world" }) + expect(event["metaData"]["significant"]).to eq({ "hey" => "earth" }) + end) + end + it "can add callbacks in a configure block" do callback1 = proc {|report| report.add_tab(:important, { hello: "world" }) } callback2 = proc {|report| report.add_tab(:significant, { hey: "earth" }) } @@ -25,6 +39,9 @@ Bugsnag.configure do |config| config.add_on_error(callback1) config.add_on_error(callback2) + config.on_error do |report| + report.add_tab(:critical, { hi: "planet" }) + end end Bugsnag.notify(RuntimeError.new("Oh no!")) @@ -34,6 +51,7 @@ expect(event["metaData"]["important"]).to eq({ "hello" => "world" }) expect(event["metaData"]["significant"]).to eq({ "hey" => "earth" }) + expect(event["metaData"]["critical"]).to eq({ "hi" => "planet" }) end) end @@ -56,6 +74,27 @@ end) end + it "can remove an already registered block" do + callback1 = proc {|report| report.add_tab(:important, { hello: "world" }) } + callback2 = proc {|report| report.add_tab(:significant, { hey: "earth" }) } + + Bugsnag.add_on_error(callback1) + + # pass callback2 as a block so that it can be removed + Bugsnag.on_error(&callback2) + + Bugsnag.remove_on_error(callback2) + + Bugsnag.notify(RuntimeError.new("Oh no!")) + + expect(Bugsnag).to(have_sent_notification do |payload, _headers| + event = get_event_from_payload(payload) + + expect(event["metaData"]["important"]).to eq({ "hello" => "world" }) + expect(event["metaData"]["significant"]).to be_nil + end) + end + it "can remove all registered callbacks" do callback1 = proc {|report| report.add_tab(:important, { hello: "world" }) } callback2 = proc {|report| report.add_tab(:significant, { hey: "earth" }) } From 39401d3e0c43a51bfbe95df1624e67177a70f3f3 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Thu, 23 May 2024 09:43:24 +0100 Subject: [PATCH 7/7] Bump version to v6.27.0 --- CHANGELOG.md | 2 +- VERSION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dca836b42..f8b5bec13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Changelog ========= -## TBD +## v6.27.0 (23 May 2024) ### Enhancements diff --git a/VERSION b/VERSION index 30bfaeb1e..9cd1a39f6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.26.4 +6.27.0