FEATURE: Add support for user badge revocation webhook events (#21204)
Currently, only user badge grants emit webhook events. This change extends the `user_badge` webhook to emit user badge revocation events. A new `user_badge_revoked` event has been introduced instead of relying on the existing `user_badge_removed` event. `user_badge_removed` emitted just the `badge_id` and `user_id` which aren't helpful for generating a meaningful webhook payload for revoked(deleted) user badges. The new event emits the user badge object.
This commit is contained in:
parent
c03f83bbea
commit
cdf1589a85
|
@ -48,7 +48,10 @@ class UserBadge < ActiveRecord::Base
|
||||||
Badge.decrement_counter "grant_count", self.badge_id
|
Badge.decrement_counter "grant_count", self.badge_id
|
||||||
UserStat.update_distinct_badge_count self.user_id
|
UserStat.update_distinct_badge_count self.user_id
|
||||||
UserBadge.update_featured_ranks! self.user_id
|
UserBadge.update_featured_ranks! self.user_id
|
||||||
|
|
||||||
|
# TODO: Follow up with a deprecation notice for `user_badge_removed`
|
||||||
DiscourseEvent.trigger(:user_badge_removed, self.badge_id, self.user_id)
|
DiscourseEvent.trigger(:user_badge_removed, self.badge_id, self.user_id)
|
||||||
|
DiscourseEvent.trigger(:user_badge_revoked, user_badge: self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.ensure_consistency!
|
def self.ensure_consistency!
|
||||||
|
|
|
@ -55,12 +55,18 @@ end
|
||||||
DiscourseEvent.on(event) { |tag| WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer) }
|
DiscourseEvent.on(event) { |tag| WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer) }
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[user_badge_granted].each do |event|
|
DiscourseEvent.on(:user_badge_granted) do |badge_id, user_id|
|
||||||
# user_badge_revoked
|
ub = UserBadge.find_by(badge_id: badge_id, user_id: user_id)
|
||||||
DiscourseEvent.on(event) do |badge, user_id|
|
WebHook.enqueue_object_hooks(:user_badge, ub, :user_badge_granted, UserBadgeSerializer)
|
||||||
ub = UserBadge.find_by(badge: badge, user_id: user_id)
|
end
|
||||||
WebHook.enqueue_object_hooks(:user_badge, ub, event, UserBadgeSerializer)
|
|
||||||
end
|
DiscourseEvent.on(:user_badge_revoked) do |args|
|
||||||
|
WebHook.enqueue_object_hooks(
|
||||||
|
:user_badge,
|
||||||
|
args[:user_badge],
|
||||||
|
:user_badge_revoked,
|
||||||
|
UserBadgeSerializer,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[reviewable_created reviewable_score_updated].each do |event|
|
%i[reviewable_created reviewable_score_updated].each do |event|
|
||||||
|
|
|
@ -4867,8 +4867,8 @@ en:
|
||||||
name: "User Promoted Event"
|
name: "User Promoted Event"
|
||||||
details: "When a user is promoted from one trust level to another."
|
details: "When a user is promoted from one trust level to another."
|
||||||
user_badge_event:
|
user_badge_event:
|
||||||
name: "Badge Grant Event"
|
name: "Badge Event"
|
||||||
details: "When a user receives a badge."
|
details: "When a badge is granted or revoked."
|
||||||
group_user_event:
|
group_user_event:
|
||||||
name: "Group User Event"
|
name: "Group User Event"
|
||||||
details: "When a user is added or removed in a group."
|
details: "When a user is added or removed in a group."
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe "Webhook event handlers" do
|
||||||
|
fab!(:user_badge) { Fabricate(:user_badge) }
|
||||||
|
fab!(:web_hook) { Fabricate(:user_badge_web_hook) }
|
||||||
|
fab!(:user) { Fabricate(:user) }
|
||||||
|
fab!(:badge) { Fabricate(:badge) }
|
||||||
|
fab!(:post) { Fabricate(:post) }
|
||||||
|
|
||||||
|
describe "user_badge events" do
|
||||||
|
it "enqueues user_badge_granted webhook event" do
|
||||||
|
expect do
|
||||||
|
BadgeGranter.grant(badge, user, granted_by: Discourse.system_user, post_id: post.id)
|
||||||
|
end.to change { Jobs::EmitWebHookEvent.jobs.size }.by(1)
|
||||||
|
|
||||||
|
job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first
|
||||||
|
expect(job_args["id"]).to eq(user.user_badges.last.id)
|
||||||
|
expect(job_args["event_name"]).to eq("user_badge_granted")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "enqueues user_badge_revoked webhook event" do
|
||||||
|
expect { BadgeGranter.revoke(user_badge) }.to change { Jobs::EmitWebHookEvent.jobs.size }.by(
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first
|
||||||
|
expect(job_args["id"]).to eq(user_badge.id)
|
||||||
|
expect(job_args["event_name"]).to eq("user_badge_revoked")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -31,6 +31,22 @@ RSpec.describe UserBadge do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#destroy" do
|
||||||
|
it "triggers the 'user_badge_revoked' DiscourseEvent" do
|
||||||
|
user_badge =
|
||||||
|
UserBadge.create(
|
||||||
|
badge: badge,
|
||||||
|
user: user,
|
||||||
|
granted_at: Time.zone.now,
|
||||||
|
granted_by: Discourse.system_user,
|
||||||
|
)
|
||||||
|
|
||||||
|
event = DiscourseEvent.track(:user_badge_revoked) { user_badge.destroy! }
|
||||||
|
|
||||||
|
expect(event).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "featured rank" do
|
describe "featured rank" do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user) { Fabricate(:user) }
|
||||||
fab!(:user_badge_tl1) do
|
fab!(:user_badge_tl1) do
|
||||||
|
|
Loading…
Reference in New Issue