FEATURE: add support for like webhooks (#12917)

* FEATURE: add support for like webhooks

Add support for like webhooks. Webhook events only send on user membership
in the defined webhook group filters.

This also fixes group webhook events, as before this was never used, and
the logic was not correct.
This commit is contained in:
Jeff Wong 2021-04-30 14:08:38 -10:00 committed by GitHub
parent 656b0ae39e
commit 75e159f0ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 91 additions and 6 deletions

View File

@ -115,8 +115,8 @@ module Jobs
end
def group_webhook_invalid?
@web_hook.group_ids.present? && (@arguments[:group_id].present? ||
!@web_hook.group_ids.include?(@arguments[:group_id]))
@web_hook.group_ids.present? && (@arguments[:group_ids].blank? ||
(@web_hook.group_ids & @arguments[:group_ids]).blank?)
end
def category_webhook_invalid?

View File

@ -57,13 +57,14 @@ class WebHook < ActiveRecord::Base
end
end
def self.enqueue_object_hooks(type, object, event, serializer = nil)
def self.enqueue_object_hooks(type, object, event, serializer = nil, opts = {})
if active_web_hooks(type).exists?
payload = WebHook.generate_payload(type, object, serializer)
WebHook.enqueue_hooks(type, event,
id: object.id,
payload: payload
WebHook.enqueue_hooks(type, event, opts.merge(
id: object.id,
payload: payload
)
)
end
end

View File

@ -13,6 +13,7 @@ class WebHookEventType < ActiveRecord::Base
ASSIGN = 12
USER_BADGE = 13
GROUP_USER = 14
LIKE = 15
has_and_belongs_to_many :web_hooks

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
class WebHookLikeSerializer < ApplicationSerializer
has_one :post, serializer: WebHookPostSerializer, embed: :objects
has_one :user, serializer: BasicUserSerializer, embed: :objects
end

View File

@ -106,3 +106,9 @@ DiscourseEvent.on(:user_added_to_group) do |user, group, options|
group_user = GroupUser.find_by(user: user, group: group)
WebHook.enqueue_object_hooks(:group_user, group_user, :user_added_to_group, WebHookGroupUserSerializer)
end
DiscourseEvent.on(:like_created) do |post_action|
user = post_action.user
group_ids = user.groups.map(&:id)
WebHook.enqueue_object_hooks(:like, post_action, :post_liked, WebHookLikeSerializer, group_ids: group_ids)
end

View File

@ -4040,6 +4040,9 @@ en:
group_user_event:
name: "Group User Event"
details: "When a user is added or removed in a group."
like_event:
name: "Like Event"
details: "When a user likes a post."
delivery_status:
title: "Delivery Status"
inactive: "Inactive"

View File

@ -59,3 +59,8 @@ WebHookEventType.seed do |b|
b.id = WebHookEventType::GROUP_USER
b.name = "group_user"
end
WebHookEventType.seed do |b|
b.id = WebHookEventType::LIKE
b.name = "like"
end

View File

@ -102,3 +102,11 @@ Fabricator(:group_user_web_hook, from: :web_hook) do
web_hook.web_hook_event_types = [transients[:group_user_hook]]
end
end
Fabricator(:like_web_hook, from: :web_hook) do
transient like_hook: WebHookEventType.find_by(name: 'like')
after_build do |web_hook, transients|
web_hook.web_hook_event_types = [transients[:like_hook]]
end
end

View File

@ -234,6 +234,42 @@ describe Jobs::EmitWebHookEvent do
end
end
context 'with group filters' do
fab!(:group) { Fabricate(:group) }
fab!(:user) { Fabricate(:user, groups: [group]) }
fab!(:like_hook) { Fabricate(:like_web_hook, groups: [group]) }
it "doesn't emit when event is not included any groups" do
subject.execute(
web_hook_id: like_hook.id,
event_type: 'like',
payload: { test: "some payload" }.to_json
)
end
it "doesn't emit when event is not related with defined groups" do
subject.execute(
web_hook_id: like_hook.id,
event_type: 'like',
group_ids: [Fabricate(:group).id],
payload: { test: "some payload" }.to_json
)
end
it 'emit when event is related with defined groups' do
stub_request(:post, like_hook.payload_url)
.with(body: "{\"like\":{\"test\":\"some payload\"}}")
.to_return(body: 'OK', status: 200)
subject.execute(
web_hook_id: like_hook.id,
event_type: 'like',
group_ids: user.groups.pluck(:id),
payload: { test: "some payload" }.to_json
)
end
end
describe '#send_webhook!' do
it 'creates delivery event record' do
stub_request(:post, post_hook.payload_url)

View File

@ -572,5 +572,25 @@ describe WebHook do
expect(payload["group_id"]).to eq(group.id)
expect(payload["user_id"]).to eq(user.id)
end
it 'should enqueue hooks for user likes in a group' do
group = Fabricate(:group)
Fabricate(:like_web_hook, groups: [group])
group_user = Fabricate(:group_user, group: group, user: user)
poster = Fabricate(:user)
post = Fabricate(:post, user: poster)
like = Fabricate(:post_action, post: post, user: user, post_action_type_id: PostActionType.types[:like])
now = Time.now
freeze_time now
DiscourseEvent.trigger(:like_created, like)
job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first
expect(job_args["event_name"]).to eq("post_liked")
expect(job_args["group_ids"]).to eq([group.id])
payload = JSON.parse(job_args["payload"])
expect(payload["post"]["id"]).to eq(post.id)
expect(payload["user"]["id"]).to eq(user.id)
end
end
end