Commit 4b8764fa authored by Serena Fang's avatar Serena Fang Committed by Imre Farkas

Fire webhook when update or destroy group member

Webhook working, specs not working yet
parent 88f935cb
......@@ -113,11 +113,30 @@ module EE
def post_create_hook
super
execute_hooks_for(:create)
end
override :post_update_hook
def post_update_hook
super
if saved_change_to_access_level? || saved_change_to_expires_at?
execute_hooks_for(:update)
end
end
def post_destroy_hook
super
execute_hooks_for(:destroy)
end
def execute_hooks_for(event)
return unless self.source.feature_available?(:group_webhooks)
return unless GroupHook.where(group_id: self.source.self_and_ancestors).exists?
run_after_commit do
data = ::Gitlab::HookData::GroupMemberBuilder.new(self).build(:create)
data = ::Gitlab::HookData::GroupMemberBuilder.new(self).build(event)
self.source.execute_hooks(data, :member_hooks)
end
end
......
......@@ -3,4 +3,4 @@
= form.label :member_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Member events')
%p.text-muted.gl-ml-1
= s_('Webhooks|This URL will be triggered when a member is added to a group')
= s_('Webhooks|This URL will be triggered when a group member is created/updated/removed')
---
title: Add support for member update & destroy events in Group webhooks
merge_request: 50217
author:
type: added
......@@ -241,33 +241,20 @@ RSpec.describe GroupMember do
context 'group member webhooks', :sidekiq_inline do
let_it_be(:group) { create(:group_with_plan, plan: :gold_plan) }
let_it_be(:group_hook) { create(:group_hook, group: group, member_events: true) }
let(:user) { create(:user) }
let_it_be(:user) { create(:user) }
context 'when a member is added to the group' do
let(:group_member) { create(:group_member, group: group) }
context 'fires the webhook when a member is added' do
before do
WebMock.stub_request(:post, group_hook.url)
end
it 'execute webhooks' do
member = group.add_guest(user)
it 'executes user_add_to_group event webhook' do
group.add_guest(group_member.user)
expect(WebMock).to have_requested(:post, group_hook.url).with(
headers: { 'Content-Type' => 'application/json', 'User-Agent' => "GitLab/#{Gitlab::VERSION}", 'X-Gitlab-Event' => 'Member Hook' },
body: {
created_at: member.created_at&.xmlschema,
updated_at: member.updated_at&.xmlschema,
group_name: group.name,
group_path: group.path,
group_id: group.id,
user_username: user.username,
user_name: user.name,
user_email: user.email,
user_id: user.id,
group_access: 'Guest',
expires_at: member.expires_at&.xmlschema,
group_plan: 'gold',
event_name: 'user_add_to_group'
}.to_json
webhook_data(group_member, 'user_add_to_group')
)
end
......@@ -275,7 +262,7 @@ RSpec.describe GroupMember do
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:subgroup_hook) { create(:group_hook, group: subgroup, member_events: true) }
it 'fires webhook twice when parent group has member_events webhook enabled' do
it 'fires two webhooks when parent group has member_events webhook enabled' do
WebMock.stub_request(:post, subgroup_hook.url)
subgroup.add_guest(user)
......@@ -284,7 +271,7 @@ RSpec.describe GroupMember do
expect(WebMock).to have_requested(:post, group_hook.url)
end
it 'fires webhook once when parent group has member_events webhook disabled' do
it 'fires one webhook when parent group has member_events webhook disabled' do
group_hook = create(:group_hook, group: group, member_events: false)
WebMock.stub_request(:post, subgroup_hook.url)
......@@ -297,6 +284,44 @@ RSpec.describe GroupMember do
end
end
context 'when a group member is updated' do
let(:group_member) { create(:group_member, :developer, group: group, expires_at: 1.day.from_now) }
it 'executes user_update_for_group event webhook when user role is updated' do
WebMock.stub_request(:post, group_hook.url)
group_member.update!(access_level: Gitlab::Access::MAINTAINER)
expect(WebMock).to have_requested(:post, group_hook.url).with(
webhook_data(group_member, 'user_update_for_group')
)
end
it 'executes user_update_for_group event webhook when user expiration date is updated' do
WebMock.stub_request(:post, group_hook.url)
group_member.update!(expires_at: 2.days.from_now)
expect(WebMock).to have_requested(:post, group_hook.url).with(
webhook_data(group_member, 'user_update_for_group')
)
end
end
context 'when the group member is deleted' do
let_it_be(:group_member) { create(:group_member, :developer, group: group, expires_at: 1.day.from_now) }
it 'executes user_remove_from_group event webhook when group member is deleted' do
WebMock.stub_request(:post, group_hook.url)
group_member.destroy!
expect(WebMock).to have_requested(:post, group_hook.url).with(
webhook_data(group_member, 'user_remove_from_group')
)
end
end
context 'does not execute webhook' do
before do
WebMock.stub_request(:post, group_hook.url)
......@@ -319,4 +344,25 @@ RSpec.describe GroupMember do
end
end
end
def webhook_data(group_member, event)
{
headers: { 'Content-Type' => 'application/json', 'User-Agent' => "GitLab/#{Gitlab::VERSION}", 'X-Gitlab-Event' => 'Member Hook' },
body: {
created_at: group_member.created_at&.xmlschema,
updated_at: group_member.updated_at&.xmlschema,
group_name: group.name,
group_path: group.path,
group_id: group.id,
user_username: group_member.user.username,
user_name: group_member.user.name,
user_email: group_member.user.email,
user_id: group_member.user.id,
group_access: group_member.human_access,
expires_at: group_member.expires_at&.xmlschema,
group_plan: 'gold',
event_name: event
}.to_json
}
end
end
......@@ -31211,7 +31211,7 @@ msgstr ""
msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
msgstr ""
msgid "Webhooks|This URL will be triggered when a member is added to a group"
msgid "Webhooks|This URL will be triggered when a group member is created/updated/removed"
msgstr ""
msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment