summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--doc/api/groups.md14
-rw-r--r--lib/api/group_members.rb24
-rw-r--r--lib/api/helpers.rb5
-rw-r--r--lib/api/project_members.rb12
-rw-r--r--spec/requests/api/group_members_spec.rb63
6 files changed, 109 insertions, 11 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 286091afacf..52a41c7df3d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -50,7 +50,7 @@ v 7.8.0 (unreleased)
-
- Password reset token validity increased from 2 hours to 2 days since it is also send on account creation.
-
- -
+ - Edit group members via API
- Enable raw image paste from clipboard, currently Chrome only (Marco Cyriacks)
-
-
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 9f01b550641..3c1858e697d 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -152,6 +152,20 @@ Parameters:
- `user_id` (required) - The ID of a user to add
- `access_level` (required) - Project access level
+### Edit group team member
+
+Updates a group team member to a specified access level.
+
+```
+PUT /groups/:id/members/:user_id
+```
+
+Parameters:
+
+- `id` (required) - The ID of a group
+- `user_id` (required) - The ID of a group member
+- `access_level` (required) - Project access level
+
### Remove user team member
Removes user from user team.
diff --git a/lib/api/group_members.rb b/lib/api/group_members.rb
index 4373070083a..c9c9ccbcb2e 100644
--- a/lib/api/group_members.rb
+++ b/lib/api/group_members.rb
@@ -40,6 +40,30 @@ module API
present member.user, with: Entities::GroupMember, group: group
end
+ # Update group member
+ #
+ # Parameters:
+ # id (required) - The ID of a group
+ # user_id (required) - The ID of a group member
+ # access_level (required) - Project access level
+ # Example Request:
+ # PUT /groups/:id/members/:user_id
+ put ':id/members/:user_id' do
+ group = find_group(params[:id])
+ authorize! :manage_group, group
+ required_attributes! [:access_level]
+
+ team_member = group.group_members.find_by(user_id: params[:user_id])
+ not_found!('User can not be found') if team_member.nil?
+
+ if team_member.update_attributes(access_level: params[:access_level])
+ @member = team_member.user
+ present @member, with: Entities::GroupMember, group: group
+ else
+ handle_member_errors team_member.errors
+ end
+ end
+
# Remove member.
#
# Parameters:
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 8fa30460ba6..a50ee4659a3 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -238,5 +238,10 @@ module API
def secret_token
File.read(Rails.root.join('.gitlab_shell_secret'))
end
+
+ def handle_member_errors(errors)
+ error!(errors[:access_level], 422) if errors[:access_level].any?
+ not_found!(errors)
+ end
end
end
diff --git a/lib/api/project_members.rb b/lib/api/project_members.rb
index 1e890f9e199..73cf062155b 100644
--- a/lib/api/project_members.rb
+++ b/lib/api/project_members.rb
@@ -4,14 +4,6 @@ module API
before { authenticate! }
resource :projects do
- helpers do
- def handle_project_member_errors(errors)
- if errors[:access_level].any?
- error!(errors[:access_level], 422)
- end
- not_found!(errors)
- end
- end
# Get a project team members
#
@@ -66,7 +58,7 @@ module API
@member = team_member.user
present @member, with: Entities::ProjectMember, project: user_project
else
- handle_project_member_errors team_member.errors
+ handle_member_errors team_member.errors
end
end
@@ -89,7 +81,7 @@ module API
@member = team_member.user
present @member, with: Entities::ProjectMember, project: user_project
else
- handle_project_member_errors team_member.errors
+ handle_member_errors team_member.errors
end
end
diff --git a/spec/requests/api/group_members_spec.rb b/spec/requests/api/group_members_spec.rb
index 4957186f605..43d26d67efe 100644
--- a/spec/requests/api/group_members_spec.rb
+++ b/spec/requests/api/group_members_spec.rb
@@ -104,6 +104,69 @@ describe API::API, api: true do
end
end
+ describe 'PUT /groups/:id/members/:user_id' do
+ context 'when not a member of the group' do
+ it 'should return a 409 error if the user is not a group member' do
+ put(
+ api("/groups/#{group_no_members.id}/members/#{developer.id}",
+ owner), access_level: GroupMember::MASTER
+ )
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context 'when a member of the group' do
+ it 'should return ok and update member access level' do
+ put(
+ api("/groups/#{group_with_members.id}/members/#{reporter.id}",
+ owner),
+ access_level: GroupMember::MASTER
+ )
+
+ expect(response.status).to eq(200)
+
+ get api("/groups/#{group_with_members.id}/members", owner)
+ json_reporter = json_response.find do |e|
+ e['id'] == reporter.id
+ end
+
+ expect(json_reporter['access_level']).to eq(GroupMember::MASTER)
+ end
+
+ it 'should not allow guest to modify group members' do
+ put(
+ api("/groups/#{group_with_members.id}/members/#{developer.id}",
+ guest),
+ access_level: GroupMember::MASTER
+ )
+
+ expect(response.status).to eq(403)
+
+ get api("/groups/#{group_with_members.id}/members", owner)
+ json_developer = json_response.find do |e|
+ e['id'] == developer.id
+ end
+
+ expect(json_developer['access_level']).to eq(GroupMember::DEVELOPER)
+ end
+
+ it 'should return a 400 error when access level is not given' do
+ put(
+ api("/groups/#{group_with_members.id}/members/#{master.id}", owner)
+ )
+ expect(response.status).to eq(400)
+ end
+
+ it 'should return a 422 error when access level is not known' do
+ put(
+ api("/groups/#{group_with_members.id}/members/#{master.id}", owner),
+ access_level: 1234
+ )
+ expect(response.status).to eq(422)
+ end
+ end
+ end
+
describe "DELETE /groups/:id/members/:user_id" do
context "when not a member of the group" do
it "should not delete guest's membership of group_with_members" do