From b0dacc8eb06615cf5d0afb1fc8d799dd64325846 Mon Sep 17 00:00:00 2001 From: Vinnie Okada Date: Tue, 20 Jan 2015 20:34:09 -0700 Subject: [PATCH] Edit group members via API Add an API endpoint to update the access level of an existing group member. --- CHANGELOG | 2 +- doc/api/groups.md | 14 ++++++ lib/api/group_members.rb | 24 ++++++++++ lib/api/helpers.rb | 5 ++ lib/api/project_members.rb | 12 +---- spec/requests/api/group_members_spec.rb | 63 +++++++++++++++++++++++++ 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