From 26d7eedf4c00a6209e1fe55540353ca7522d0c2d Mon Sep 17 00:00:00 2001 From: Vinoth Kannan Date: Thu, 8 Apr 2021 21:16:34 +0530 Subject: [PATCH] FEATURE: trigger webhook when a user added/removed in a group. (#12653) Whenever a group is added or removed from a group a webhook event will get triggered if it's active. --- app/models/group.rb | 12 +++++-- app/models/web_hook_event_type.rb | 1 + .../web_hook_group_user_serializer.rb | 6 ++++ config/initializers/012-web_hook_events.rb | 5 +++ config/locales/client.en.yml | 3 ++ db/fixtures/007_web_hook_event_types.rb | 5 +++ spec/fabricators/web_hook_fabricator.rb | 8 +++++ spec/models/web_hook_spec.rb | 35 +++++++++++++++++++ 8 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 app/serializers/web_hook_group_user_serializer.rb diff --git a/app/models/group.rb b/app/models/group.rb index 0b6204fad44..16c47fd1967 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -643,10 +643,18 @@ class Group < ActiveRecord::Base end def remove(user) - result = self.group_users.where(user: user).each(&:destroy) - return false if result.blank? + group_user = self.group_users.find_by(user: user) + return false if group_user.blank? + + has_webhooks = WebHook.active_web_hooks(:group_user) + payload = WebHook.generate_payload(:group_user, group_user, WebHookGroupUserSerializer) if has_webhooks + group_user.destroy user.update_columns(primary_group_id: nil) if user.primary_group_id == self.id DiscourseEvent.trigger(:user_removed_from_group, user, self) + WebHook.enqueue_hooks(:group_user, :user_removed_from_group, + id: group_user.id, + payload: payload + ) if has_webhooks true end diff --git a/app/models/web_hook_event_type.rb b/app/models/web_hook_event_type.rb index 442f14cb8ce..ff5db8e5837 100644 --- a/app/models/web_hook_event_type.rb +++ b/app/models/web_hook_event_type.rb @@ -12,6 +12,7 @@ class WebHookEventType < ActiveRecord::Base SOLVED = 11 ASSIGN = 12 USER_BADGE = 13 + GROUP_USER = 14 has_and_belongs_to_many :web_hooks diff --git a/app/serializers/web_hook_group_user_serializer.rb b/app/serializers/web_hook_group_user_serializer.rb new file mode 100644 index 00000000000..342b5a5412b --- /dev/null +++ b/app/serializers/web_hook_group_user_serializer.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class WebHookGroupUserSerializer < BasicGroupUserSerializer + attributes :id, + :created_at +end diff --git a/config/initializers/012-web_hook_events.rb b/config/initializers/012-web_hook_events.rb index 043ede89b59..29e543982de 100644 --- a/config/initializers/012-web_hook_events.rb +++ b/config/initializers/012-web_hook_events.rb @@ -95,3 +95,8 @@ end DiscourseEvent.on(:notification_created) do |notification| WebHook.enqueue_object_hooks(:notification, notification, :notification_created, NotificationSerializer) end + +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 diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 9a30d8ced3e..51f9e64b250 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -4018,6 +4018,9 @@ en: user_badge_event: name: "Badge Grant Event" details: "When a user receives a badge." + group_user_event: + name: "Group User Event" + details: "When a user is added or removed in a group." 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 ec666ec5ad2..f82e548f064 100644 --- a/db/fixtures/007_web_hook_event_types.rb +++ b/db/fixtures/007_web_hook_event_types.rb @@ -54,3 +54,8 @@ WebHookEventType.seed do |b| b.id = WebHookEventType::USER_BADGE b.name = "user_badge" end + +WebHookEventType.seed do |b| + b.id = WebHookEventType::GROUP_USER + b.name = "group_user" +end diff --git a/spec/fabricators/web_hook_fabricator.rb b/spec/fabricators/web_hook_fabricator.rb index 9edc591791f..f05c5c6f8c2 100644 --- a/spec/fabricators/web_hook_fabricator.rb +++ b/spec/fabricators/web_hook_fabricator.rb @@ -94,3 +94,11 @@ Fabricator(:user_badge_web_hook, from: :web_hook) do web_hook.web_hook_event_types = [transients[:user_badge_hook]] end end + +Fabricator(:group_user_web_hook, from: :web_hook) do + transient group_user_hook: WebHookEventType.find_by(name: 'group_user') + + after_build do |web_hook, transients| + web_hook.web_hook_event_types = [transients[:group_user_hook]] + end +end diff --git a/spec/models/web_hook_spec.rb b/spec/models/web_hook_spec.rb index f9ac6e13b4e..6f67fce731c 100644 --- a/spec/models/web_hook_spec.rb +++ b/spec/models/web_hook_spec.rb @@ -519,5 +519,40 @@ describe WebHook do # Future work: revoke badge hook end + + it 'should enqueue the right hooks for group user addition' do + Fabricate(:group_user_web_hook) + group = Fabricate(:group) + + now = Time.now + freeze_time now + + group.add(user) + + job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first + expect(job_args["event_name"]).to eq("user_added_to_group") + payload = JSON.parse(job_args["payload"]) + expect(payload["group_id"]).to eq(group.id) + expect(payload["user_id"]).to eq(user.id) + expect(payload["notification_level"]).to eq(group.default_notification_level) + expect(Time.zone.parse(payload["created_at"]).to_f).to be_within(0.001).of(now.to_f) + end + + it 'should enqueue the right hooks for group user deletion' do + Fabricate(:group_user_web_hook) + group = Fabricate(:group) + group_user = Fabricate(:group_user, group: group, user: user) + + now = Time.now + freeze_time now + + group.remove(user) + + job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first + expect(job_args["event_name"]).to eq("user_removed_from_group") + payload = JSON.parse(job_args["payload"]) + expect(payload["group_id"]).to eq(group.id) + expect(payload["user_id"]).to eq(user.id) + end end end