FEATURE: trigger webhook when a user added/removed in a group. (#12653)

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.

diff --git a/app/models/group.rb b/app/models/group.rb
index 0b6204f..16c47fd 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 442f14c..ff5db8e 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 0000000..342b5a5
--- /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 043ede8..29e5439 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 9a30d8c..51f9e64 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 ec666ec..f82e548 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 9edc591..f05c5c6 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 f9ac6e1..6f67fce 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

GitHub sha: 26d7eedf

This commit appears in #12653 which was approved by eviltrout. It was merged by vinothkannans.