Commit 6dbcb880 authored by Zeger-Jan van de Weg's avatar Zeger-Jan van de Weg

Allow a project member to leave the projected through the API

parent 734df1bb
......@@ -37,6 +37,7 @@ v 8.7.0 (unreleased)
- ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591
- Update number of Todos in the sidebar when it's marked as "Done". !3600
- API: Expose 'updated_at' for issue, snippet, and merge request notes (Robert Schilling)
- API: User can leave a project through the API when not master or owner. !3613
v 8.6.5
- Fix importing from GitHub Enterprise. !3529
......
......@@ -780,8 +780,10 @@ Parameters:
- `id` (required) - The ID or NAMESPACE/PROJECT_NAME of a project
- `user_id` (required) - The ID of a team member
This method is idempotent and can be called multiple times with the same parameters.
Revoking team membership for a user who is not currently a team member is considered success.
This method removes the project member if the user has the proper access rights to do so.
It returns a status code 403 if the member does not have the proper rights to perform this action.
In all other cases this method is idempotent and revoking team membership for a user who is not
currently a team member is considered success.
Please note that the returned JSON currently differs slightly. Thus you should not
rely on the returned JSON structure.
......
......@@ -93,12 +93,17 @@ module API
# Example Request:
# DELETE /projects/:id/members/:user_id
delete ":id/members/:user_id" do
authorize! :admin_project, user_project
project_member = user_project.project_members.find_by(user_id: params[:user_id])
unless project_member.nil?
project_member.destroy
else
unless current_user.can?(:admin_project, user_project) ||
current_user.can?(:destroy_project_member, project_member)
forbidden!
end
if project_member.nil?
{ message: "Access revoked", id: params[:user_id].to_i }
else
project_member.destroy
end
end
end
......
......@@ -118,8 +118,10 @@ describe API::API, api: true do
end
describe "DELETE /projects/:id/members/:user_id" do
before { project_member }
before { project_member2 }
before do
project_member
project_member2
end
it "should remove user from project team" do
expect do
......@@ -132,6 +134,7 @@ describe API::API, api: true do
expect do
delete api("/projects/#{project.id}/members/#{user3.id}", user)
end.to_not change { ProjectMember.count }
expect(response.status).to eq(200)
end
it "should return 200 if team member already removed" do
......@@ -145,8 +148,19 @@ describe API::API, api: true do
delete api("/projects/#{project.id}/members/1000000", user)
end.to change { ProjectMember.count }.by(0)
expect(response.status).to eq(200)
expect(json_response['message']).to eq("Access revoked")
expect(json_response['id']).to eq(1000000)
expect(json_response['message']).to eq('Access revoked')
end
context 'when the user is not an admin or owner' do
it 'can leave the project' do
expect do
delete api("/projects/#{project.id}/members/#{user3.id}", user3)
end.to change { ProjectMember.count }.by(-1)
expect(response.status).to eq(200)
expect(json_response['id']).to eq(project_member2.id)
end
end
end
end
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