FEATURE: granular webhooks (#23070)

Before this change, webhooks could be only configured for specific groups like for example, all topic events.

We would like to have more granular control like for example topic_created or topic_destroyed.

Test are failing because plugins changed has to be merged as well:
discourse/discourse-assign#498
discourse/discourse-solved#248
discourse/discourse-topic-voting#159
This commit is contained in:
Krzysztof Kotlarek
2023-10-09 14:35:31 +11:00
committed by GitHub
parent 1d3b2d6bd4
commit c468110929
23 changed files with 705 additions and 198 deletions

View File

@ -43,51 +43,53 @@ RSpec.describe WebHook do
end
it "excludes disabled plugin web_hooks" do
web_hook_event_types = WebHookEventType.active.find_by(name: "solved")
expect(web_hook_event_types).to eq(nil)
web_hook_event_types = WebHookEventType.active.where(name: "solved_accept_unaccept")
expect(web_hook_event_types).to be_empty
end
it "includes non-plugin web_hooks" do
web_hook_event_types = WebHookEventType.active.where(name: "topic")
expect(web_hook_event_types.count).to eq(1)
web_hook_event_types = WebHookEventType.active.where(group: "topic")
expect(web_hook_event_types.count).to eq(5)
end
it "includes enabled plugin web_hooks" do
SiteSetting.stubs(:solved_enabled).returns(true)
solved_event_types = WebHookEventType.active.where(name: "solved")
expect(solved_event_types.count).to eq(1)
SiteSetting.stubs(:assign_enabled).returns(true)
assign_event_types = WebHookEventType.active.where(name: "assign")
expect(assign_event_types.count).to eq(1)
assign_event_types = WebHookEventType.active.where(group: "assign").pluck(:name)
expect(assign_event_types).to eq(%w[assigned unassigned])
SiteSetting.stubs(:voting_enabled).returns(true)
voting_event_types = WebHookEventType.active.where(name: "topic_voting")
expect(voting_event_types.count).to eq(1)
voting_event_types = WebHookEventType.active.where(group: "voting").pluck(:name)
expect(voting_event_types).to eq(%w[topic_upvote topic_unvote])
#
SiteSetting.stubs(:solved_enabled).returns(true)
solved_event_types = WebHookEventType.active.where(group: "solved").pluck(:name)
expect(solved_event_types).to eq(%w[accepted_solution unaccepted_solution])
#
SiteSetting.stubs(:chat_enabled).returns(true)
chat_enabled_types = WebHookEventType.active.where("name LIKE 'chat_%'")
expect(chat_enabled_types.count).to eq(1)
chat_event_types = WebHookEventType.active.where(group: "chat").pluck(:name)
expect(chat_event_types).to eq(
%w[chat_message_created chat_message_edited chat_message_trashed chat_message_restored],
)
end
describe "#active_web_hooks" do
it "returns unique hooks" do
post_hook.web_hook_event_types << WebHookEventType.find_by(name: "topic")
post_hook.web_hook_event_types << WebHookEventType.find_by(group: "topic")
post_hook.update!(wildcard_web_hook: true)
expect(WebHook.active_web_hooks(:post)).to eq([post_hook])
expect(WebHook.active_web_hooks(:post_created)).to eq([post_hook])
end
it "find relevant hooks" do
expect(WebHook.active_web_hooks(:post)).to eq([post_hook])
expect(WebHook.active_web_hooks(:topic)).to eq([topic_hook])
expect(WebHook.active_web_hooks(:post_created)).to eq([post_hook])
expect(WebHook.active_web_hooks(:topic_created)).to eq([topic_hook])
end
it "excludes inactive hooks" do
post_hook.update!(active: false)
expect(WebHook.active_web_hooks(:post)).to eq([])
expect(WebHook.active_web_hooks(:topic)).to eq([topic_hook])
expect(WebHook.active_web_hooks(:post_created)).to eq([])
expect(WebHook.active_web_hooks(:topic_created)).to eq([topic_hook])
end
describe "wildcard web hooks" do
@ -96,9 +98,15 @@ RSpec.describe WebHook do
it "should include wildcard hooks" do
expect(WebHook.active_web_hooks(:wildcard)).to eq([wildcard_hook])
expect(WebHook.active_web_hooks(:post)).to contain_exactly(post_hook, wildcard_hook)
expect(WebHook.active_web_hooks(:post_created)).to contain_exactly(
post_hook,
wildcard_hook,
)
expect(WebHook.active_web_hooks(:topic)).to contain_exactly(topic_hook, wildcard_hook)
expect(WebHook.active_web_hooks(:topic_created)).to contain_exactly(
topic_hook,
wildcard_hook,
)
end
end
end
@ -231,6 +239,24 @@ RSpec.describe WebHook do
expect(payload["tags"]).to contain_exactly(tag.name)
end
it "should enqueue granular hooks for topic" do
topic_web_hook.web_hook_event_types.delete(
WebHookEventType.where(name: "topic_destroyed").last,
)
post = PostCreator.create(user, raw: "post", title: "topic", skip_validations: true)
topic_id = post.topic.id
job_args = Jobs::EmitWebHookEvent.jobs.last["args"].first
expect(job_args["event_name"]).to eq("topic_created")
payload = JSON.parse(job_args["payload"])
expect(payload["id"]).to eq(topic_id)
expect { PostDestroyer.new(user, post).destroy }.not_to change {
Jobs::EmitWebHookEvent.jobs.count
}
end
it "should not log a personal message view when processing new topic" do
SiteSetting.log_personal_messages_views = true
Fabricate(:topic_web_hook)