FEATURE: Webhooks and Event for user being granted a badge

Adding a webhook for badge revocation is left for future work as it's relatively rare.
This commit is contained in:
Kane York 2020-04-08 11:34:35 -07:00 committed by Kane York
parent 14467757df
commit 138d4aebde
7 changed files with 57 additions and 1 deletions

View File

@ -13,6 +13,7 @@ class WebHookEventType < ActiveRecord::Base
NOTIFICATION = 10 NOTIFICATION = 10
SOLVED = 11 SOLVED = 11
ASSIGN = 12 ASSIGN = 12
USER_BADGE = 13
has_and_belongs_to_many :web_hooks has_and_belongs_to_many :web_hooks

View File

@ -410,7 +410,7 @@ class BadgeGranter
end end
def self.send_notification(user_id, username, locale, badge) def self.send_notification(user_id, username, locale, badge)
I18n.with_locale(notification_locale(locale)) do notification = I18n.with_locale(notification_locale(locale)) do
Notification.create!( Notification.create!(
user_id: user_id, user_id: user_id,
notification_type: Notification.types[:granted_badge], notification_type: Notification.types[:granted_badge],
@ -423,6 +423,10 @@ class BadgeGranter
}.to_json }.to_json
) )
end end
DiscourseEvent.trigger(:user_badge_granted, badge, user_id)
notification
end end
end end

View File

@ -74,6 +74,16 @@ end
end end
end end
%i(
user_badge_granted
).each do |event|
# user_badge_revoked
DiscourseEvent.on(event) do |badge, user_id|
ub = UserBadge.find_by(badge: badge, user_id: user_id)
WebHook.enqueue_object_hooks(:user_badge, ub, event, UserBadgeSerializer)
end
end
DiscourseEvent.on(:reviewable_created) do |reviewable| DiscourseEvent.on(:reviewable_created) do |reviewable|
WebHook.enqueue_object_hooks(:reviewable, reviewable, :reviewable_created, reviewable.serializer) WebHook.enqueue_object_hooks(:reviewable, reviewable, :reviewable_created, reviewable.serializer)
end end

View File

@ -3562,6 +3562,9 @@ en:
notification_event: notification_event:
name: "Notification Event" name: "Notification Event"
details: "When a user receives a notification in their feed." details: "When a user receives a notification in their feed."
user_badge_event:
name: "Badge Grant Event"
details: "When a user receives a badge."
delivery_status: delivery_status:
title: "Delivery Status" title: "Delivery Status"
inactive: "Inactive" inactive: "Inactive"

View File

@ -59,3 +59,8 @@ WebHookEventType.seed do |b|
b.id = WebHookEventType::ASSIGN b.id = WebHookEventType::ASSIGN
b.name = "assign" b.name = "assign"
end end
WebHookEventType.seed do |b|
b.id = WebHookEventType::USER_BADGE
b.name = "user_badge"
end

View File

@ -102,3 +102,11 @@ Fabricator(:notification_web_hook, from: :web_hook) do
web_hook.web_hook_event_types = [transients[:notification_hook]] web_hook.web_hook_event_types = [transients[:notification_hook]]
end end
end end
Fabricator(:user_badge_web_hook, from: :web_hook) do
transient user_badge_hook: WebHookEventType.find_by(name: 'user_badge')
after_build do |web_hook, transients|
web_hook.web_hook_event_types = [transients[:user_badge_hook]]
end
end

View File

@ -486,5 +486,30 @@ describe WebHook do
payload = JSON.parse(job_args["payload"]) payload = JSON.parse(job_args["payload"])
expect(payload["id"]).to eq(reviewable.id) expect(payload["id"]).to eq(reviewable.id)
end end
it 'should enqueue the right hooks for badge grants' do
Fabricate(:user_badge_web_hook)
badge = Fabricate(:badge)
badge.multiple_grant = true
badge.show_posts = true
badge.save
now = Time.now
freeze_time now
BadgeGranter.grant(badge, user, granted_by: admin, post_id: post.id)
job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first
expect(job_args["event_name"]).to eq("user_badge_granted")
payload = JSON.parse(job_args["payload"])
expect(payload["badge_id"]).to eq(badge.id)
expect(payload["user_id"]).to eq(user.id)
expect(payload["granted_by_id"]).to eq(admin.id)
# be_within required because rounding occurs
expect(Time.zone.parse(payload["granted_at"]).to_f).to be_within(0.001).of(now.to_f)
expect(payload["post_id"]).to eq(post.id)
# Future work: revoke badge hook
end
end end
end end