diff --git a/app/jobs/regular/emit_web_hook_event.rb b/app/jobs/regular/emit_web_hook_event.rb index 94371eaa33b..7b22f0398b9 100644 --- a/app/jobs/regular/emit_web_hook_event.rb +++ b/app/jobs/regular/emit_web_hook_event.rb @@ -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? diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb index 9c11c9af54d..ac8dadeb2cd 100644 --- a/app/models/web_hook.rb +++ b/app/models/web_hook.rb @@ -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 diff --git a/app/models/web_hook_event_type.rb b/app/models/web_hook_event_type.rb index ff5db8e5837..70f2144f8a4 100644 --- a/app/models/web_hook_event_type.rb +++ b/app/models/web_hook_event_type.rb @@ -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 diff --git a/app/serializers/web_hook_like_serializer.rb b/app/serializers/web_hook_like_serializer.rb new file mode 100644 index 00000000000..0a3e74fb080 --- /dev/null +++ b/app/serializers/web_hook_like_serializer.rb @@ -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 diff --git a/config/initializers/012-web_hook_events.rb b/config/initializers/012-web_hook_events.rb index 4bf6c2afc18..942260c85ce 100644 --- a/config/initializers/012-web_hook_events.rb +++ b/config/initializers/012-web_hook_events.rb @@ -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 diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 0f97c5f963d..30febe1340e 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -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" diff --git a/db/fixtures/007_web_hook_event_types.rb b/db/fixtures/007_web_hook_event_types.rb index f82e548f064..42ed0e861b5 100644 --- a/db/fixtures/007_web_hook_event_types.rb +++ b/db/fixtures/007_web_hook_event_types.rb @@ -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 diff --git a/spec/fabricators/web_hook_fabricator.rb b/spec/fabricators/web_hook_fabricator.rb index f05c5c6f8c2..554e162fd1c 100644 --- a/spec/fabricators/web_hook_fabricator.rb +++ b/spec/fabricators/web_hook_fabricator.rb @@ -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 diff --git a/spec/jobs/emit_web_hook_event_spec.rb b/spec/jobs/emit_web_hook_event_spec.rb index 0e649c882e2..9db61d2f3cf 100644 --- a/spec/jobs/emit_web_hook_event_spec.rb +++ b/spec/jobs/emit_web_hook_event_spec.rb @@ -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) diff --git a/spec/models/web_hook_spec.rb b/spec/models/web_hook_spec.rb index 03c665acc2f..492cb83a7d8 100644 --- a/spec/models/web_hook_spec.rb +++ b/spec/models/web_hook_spec.rb @@ -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