From 32653be26075e51c2495e2ad9ff8d8b5f77fac40 Mon Sep 17 00:00:00 2001 From: Blake Erickson Date: Fri, 6 Mar 2020 11:57:46 -0700 Subject: [PATCH] FEATURE: Trigger webhook when assigning and unassigning topics (#61) * FEATURE: Trigger webhook when assigning and unassigning topics This PR creates a custom webhook event that you can now select when creating a webhook to trigger only when a topic has been assigned or unassigned. * removed unused file * Removed functionality that was added to core This PR into discourse core: https://github.com/discourse/discourse/pull/9110 adds what was removed in this commit. It is better to have this logic in core so that it is discoverable and future webhooks won't end up accidentally using the same ID. --- config/locales/client.en.yml | 5 ++++ lib/topic_assigner.rb | 31 ++++++++++++++++++++++ plugin.rb | 11 ++++++++ spec/fabricators/assign_hook_fabricator.rb | 9 +++++++ spec/integration/assign_spec.rb | 18 +++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 spec/fabricators/assign_hook_fabricator.rb diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 86139c1..a31b00a 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -45,3 +45,8 @@ en: messages: assigned_title: "Assigned (%{count})" assigned: "Assigned" + admin: + web_hooks: + assign_event: + name: "Assign Event" + details: "When a user assigns or unassigns a topic." diff --git a/lib/topic_assigner.rb b/lib/topic_assigner.rb index 5d2587c..59d97a5 100644 --- a/lib/topic_assigner.rb +++ b/lib/topic_assigner.rb @@ -248,7 +248,23 @@ class ::TopicAssigner ) end + # Create a webhook event + if WebHook.active_web_hooks(:assign).exists? + type = :assigned + payload = { + type: type, + topic_id: @topic.id, + topic_title: @topic.title, + assigned_to_id: assign_to.id, + assigned_to_username: assign_to.username, + assigned_by_id: @assigned_by.id, + assigned_by_username: @assigned_by.username + }.to_json + WebHook.enqueue_assign_hooks(type, payload) + end + { success: true } + end def unassign(silent: false) @@ -328,6 +344,21 @@ class ::TopicAssigner action_code: "unassigned" ) end + + # Create a webhook event + if WebHook.active_web_hooks(:assign).exists? + type = :unassigned + payload = { + type: type, + topic_id: @topic.id, + topic_title: @topic.title, + unassigned_to_id: assigned_user.id, + unassigned_to_username: assigned_user.username, + unassigned_by_id: @assigned_by.id, + unassigned_by_username: @assigned_by.username + }.to_json + WebHook.enqueue_assign_hooks(type, payload) + end end end diff --git a/plugin.rb b/plugin.rb index c90df16..1fbfa47 100644 --- a/plugin.rb +++ b/plugin.rb @@ -334,4 +334,15 @@ after_initialize do assigner.unassign(silent: true) end end + + class ::WebHook + def self.enqueue_assign_hooks(event, payload) + if active_web_hooks('assign').exists? + WebHook.enqueue_hooks(:assign, event, + payload: payload + ) + end + end + end + end diff --git a/spec/fabricators/assign_hook_fabricator.rb b/spec/fabricators/assign_hook_fabricator.rb new file mode 100644 index 0000000..6c145d2 --- /dev/null +++ b/spec/fabricators/assign_hook_fabricator.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +Fabricator(:assign_web_hook, from: :web_hook) do + transient assign_hook: WebHookEventType.find_by(name: 'assign') + + after_build do |web_hook, transients| + web_hook.web_hook_event_types = [transients[:assign_hook]] + end +end diff --git a/spec/integration/assign_spec.rb b/spec/integration/assign_spec.rb index e31591d..0b03e61 100644 --- a/spec/integration/assign_spec.rb +++ b/spec/integration/assign_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' require_relative '../support/assign_allowed_group' +require_relative '../fabricators/assign_hook_fabricator.rb' describe 'integration tests' do before do @@ -92,5 +93,22 @@ describe 'integration tests' do DiscourseEvent.trigger(:assign_topic, topic, user2, admin, true) expect(topic.reload.custom_fields[TopicAssigner::ASSIGNED_TO_ID].to_i).to eq(user2.id) end + + it "triggers a webhook for assigned and unassigned" do + Fabricate(:assign_web_hook) + DiscourseEvent.trigger(:assign_topic, topic, user2, admin, true) + job_args = Jobs::EmitWebHookEvent.jobs[0]["args"].first + expect(job_args["event_name"]).to eq("assigned") + payload = JSON.parse(job_args["payload"]) + expect(payload["topic_id"]).to eq(topic.id) + expect(payload["assigned_to_id"]).to eq(user2.id) + + DiscourseEvent.trigger(:unassign_topic, topic, admin) + job_args = Jobs::EmitWebHookEvent.jobs[1]["args"].first + expect(job_args["event_name"]).to eq("unassigned") + payload = JSON.parse(job_args["payload"]) + expect(payload["topic_id"]).to eq(topic.id) + expect(payload["unassigned_to_id"]).to eq(user2.id) + end end end