Commit 93bc2d52 authored by Boyan Tabakov's avatar Boyan Tabakov

Added support for firing system hooks on group create/destroy and adding/removing users to group.

Added tests and updated docs. Also adding 'user_id' field in the hooks for adding/removing user from team.
parent a4dad708
...@@ -59,6 +59,7 @@ v 7.8.0 ...@@ -59,6 +59,7 @@ v 7.8.0
- -
- -
- -
- Added support for firing system hooks on group create/destroy and adding/removing users to group (Boyan Tabakov)
v 7.7.1 v 7.7.1
- Improve mention autocomplete performance - Improve mention autocomplete performance
......
...@@ -25,6 +25,9 @@ class Group < Namespace ...@@ -25,6 +25,9 @@ class Group < Namespace
mount_uploader :avatar, AttachmentUploader mount_uploader :avatar, AttachmentUploader
after_create :post_create_hook
after_destroy :post_destroy_hook
def human_name def human_name
name name
end end
...@@ -74,6 +77,18 @@ class Group < Namespace ...@@ -74,6 +77,18 @@ class Group < Namespace
projects.public_only.any? projects.public_only.any?
end end
def post_create_hook
system_hook_service.execute_hooks_for(self, :create)
end
def post_destroy_hook
system_hook_service.execute_hooks_for(self, :destroy)
end
def system_hook_service
SystemHooksService.new
end
class << self class << self
def search(query) def search(query)
where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%") where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%")
......
...@@ -27,8 +27,9 @@ class GroupMember < Member ...@@ -27,8 +27,9 @@ class GroupMember < Member
scope :with_group, ->(group) { where(source_id: group.id) } scope :with_group, ->(group) { where(source_id: group.id) }
scope :with_user, ->(user) { where(user_id: user.id) } scope :with_user, ->(user) { where(user_id: user.id) }
after_create :notify_create after_create :post_create_hook
after_update :notify_update after_update :notify_update
after_destroy :post_destroy_hook
def self.access_level_roles def self.access_level_roles
Gitlab::Access.options_with_owner Gitlab::Access.options_with_owner
...@@ -42,8 +43,9 @@ class GroupMember < Member ...@@ -42,8 +43,9 @@ class GroupMember < Member
access_level access_level
end end
def notify_create def post_create_hook
notification_service.new_group_member(self) notification_service.new_group_member(self)
system_hook_service.execute_hooks_for(self, :create)
end end
def notify_update def notify_update
...@@ -52,6 +54,14 @@ class GroupMember < Member ...@@ -52,6 +54,14 @@ class GroupMember < Member
end end
end end
def post_destroy_hook
system_hook_service.execute_hooks_for(self, :destroy)
end
def system_hook_service
SystemHooksService.new
end
def notification_service def notification_service
NotificationService.new NotificationService.new
end end
......
...@@ -60,6 +60,26 @@ class SystemHooksService ...@@ -60,6 +60,26 @@ class SystemHooksService
access_level: model.human_access, access_level: model.human_access,
project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
}) })
when Group
owner = model.owner
data.merge!(
name: model.name,
path: model.path,
group_id: model.id,
owner_name: owner.respond_to?(:name) ? owner.name : nil,
owner_email: owner.respond_to?(:email) ? owner.email : nil,
)
when GroupMember
data.merge!(
group_name: model.group.name,
group_path: model.group.path,
group_id: model.group.id,
user_name: model.user.name,
user_email: model.user.email,
user_id: model.user.id,
group_access: model.human_access,
)
end end
end end
...@@ -68,6 +88,9 @@ class SystemHooksService ...@@ -68,6 +88,9 @@ class SystemHooksService
when ProjectMember when ProjectMember
return "user_add_to_team" if event == :create return "user_add_to_team" if event == :create
return "user_remove_from_team" if event == :destroy return "user_remove_from_team" if event == :destroy
when GroupMember
return 'user_add_to_group' if event == :create
return 'user_remove_from_group' if event == :destroy
else else
"#{model.class.name.downcase}_#{event.to_s}" "#{model.class.name.downcase}_#{event.to_s}"
end end
......
# System hooks # System hooks
Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create` and `key_destroy`. Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
System hooks can be used, e.g. for logging or changing information in a LDAP server. System hooks can be used, e.g. for logging or changing information in a LDAP server.
...@@ -50,6 +50,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser ...@@ -50,6 +50,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
"project_path": "storecloud", "project_path": "storecloud",
"user_email": "johnsmith@gmail.com", "user_email": "johnsmith@gmail.com",
"user_name": "John Smith", "user_name": "John Smith",
"user_id": 41,
"project_visibility": "private", "project_visibility": "private",
} }
``` ```
...@@ -66,6 +67,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser ...@@ -66,6 +67,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
"project_path": "storecloud", "project_path": "storecloud",
"user_email": "johnsmith@gmail.com", "user_email": "johnsmith@gmail.com",
"user_name": "John Smith", "user_name": "John Smith",
"user_id": 41,
"project_visibility": "private", "project_visibility": "private",
} }
``` ```
...@@ -117,3 +119,62 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser ...@@ -117,3 +119,62 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
"id": 4 "id": 4
} }
``` ```
**Group created:**
```json
{
"created_at": "2012-07-21T07:30:54Z",
"event_name": "group_create",
"name": "StormCloud",
"owner_email": "johnsmith@gmail.com",
"owner_name": "John Smith",
"path": "stormcloud",
"group_id": 78
}
```
**Group removed:**
```json
{
"created_at": "2012-07-21T07:30:54Z",
"event_name": "group_destroy",
"name": "StoreCloud",
"owner_email": "johnsmith@gmail.com",
"owner_name": "John Smith",
"path": "storecloud",
"group_id": 78
}
```
**New Group Member:**
```json
{
"created_at": "2012-07-21T07:30:56Z",
"event_name": "user_add_to_group",
"group_access": "Master",
"group_id": 78,
"group_name": "StoreCloud",
"group_path": "storecloud",
"user_email": "johnsmith@gmail.com",
"user_name": "John Smith",
"user_id": 41
}
```
**Group Member Removed:**
```json
{
"created_at": "2012-07-21T07:30:56Z",
"event_name": "user_remove_from_group",
"group_access": "Master",
"group_id": 78,
"group_name": "StoreCloud",
"group_path": "storecloud",
"user_email": "johnsmith@gmail.com",
"user_name": "John Smith",
"user_id": 41
}
```
...@@ -61,5 +61,40 @@ describe SystemHook do ...@@ -61,5 +61,40 @@ describe SystemHook do
project.project_members.destroy_all project.project_members.destroy_all
WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once
end end
it 'group create hook' do
create(:group)
WebMock.should have_requested(:post, @system_hook.url).with(
body: /group_create/
).once
end
it 'group destroy hook' do
group = create(:group)
group.destroy
WebMock.should have_requested(:post, @system_hook.url).with(
body: /group_destroy/
).once
end
it 'group member create hook' do
group = create(:group)
user = create(:user)
group.add_user(user, Gitlab::Access::MASTER)
WebMock.should have_requested(:post, @system_hook.url).with(
body: /user_add_to_group/
).once
end
it 'group member destroy hook' do
group = create(:group)
user = create(:user)
group.add_user(user, Gitlab::Access::MASTER)
group.group_members.destroy_all
WebMock.should have_requested(:post, @system_hook.url).with(
body: /user_remove_from_group/
).once
end
end end
end end
...@@ -5,6 +5,8 @@ describe SystemHooksService do ...@@ -5,6 +5,8 @@ describe SystemHooksService do
let (:project) { create :project } let (:project) { create :project }
let (:project_member) { create :project_member } let (:project_member) { create :project_member }
let (:key) { create(:key, user: user) } let (:key) { create(:key, user: user) }
let (:group) { create(:group) }
let (:group_member) { create(:group_member) }
context 'event data' do context 'event data' do
it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) } it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) }
...@@ -15,6 +17,31 @@ describe SystemHooksService do ...@@ -15,6 +17,31 @@ describe SystemHooksService do
it { event_data(project_member, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) } it { event_data(project_member, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
it { event_data(key, :create).should include(:username, :key, :id) } it { event_data(key, :create).should include(:username, :key, :id) }
it { event_data(key, :destroy).should include(:username, :key, :id) } it { event_data(key, :destroy).should include(:username, :key, :id) }
it do
event_data(group, :create).should include(
:event_name, :name, :created_at, :path, :group_id, :owner_name,
:owner_email
)
end
it do
event_data(group, :destroy).should include(
:event_name, :name, :created_at, :path, :group_id, :owner_name,
:owner_email
)
end
it do
event_data(group_member, :create).should include(
:event_name, :created_at, :group_name, :group_path, :group_id, :user_id,
:user_name, :user_email, :group_access
)
end
it do
event_data(group_member, :destroy).should include(
:event_name, :created_at, :group_name, :group_path, :group_id, :user_id,
:user_name, :user_email, :group_access
)
end
end end
context 'event names' do context 'event names' do
...@@ -26,6 +53,10 @@ describe SystemHooksService do ...@@ -26,6 +53,10 @@ describe SystemHooksService do
it { event_name(project_member, :destroy).should eq "user_remove_from_team" } it { event_name(project_member, :destroy).should eq "user_remove_from_team" }
it { event_name(key, :create).should eq 'key_create' } it { event_name(key, :create).should eq 'key_create' }
it { event_name(key, :destroy).should eq 'key_destroy' } it { event_name(key, :destroy).should eq 'key_destroy' }
it { event_name(group, :create).should eq 'group_create' }
it { event_name(group, :destroy).should eq 'group_destroy' }
it { event_name(group_member, :create).should eq 'user_add_to_group' }
it { event_name(group_member, :destroy).should eq 'user_remove_from_group' }
end end
def event_data(*args) def event_data(*args)
......
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