diff options
author | Toon Claes <toon@gitlab.com> | 2018-03-30 14:16:24 +0200 |
---|---|---|
committer | Toon Claes <toon@gitlab.com> | 2018-03-30 14:24:21 +0200 |
commit | f940ab2044e7f7cf2b6b4450f1755ae8d8bb2c41 (patch) | |
tree | 31a3d16ba91bd34cfa32379e013566a9f9da9c92 | |
parent | d2b47c76bbc3704f2875c99c857d50e986f2315e (diff) | |
download | gitlab-ce-tc-api-fork-owners.tar.gz |
Allow project owners to set up forking relation through APItc-api-fork-owners
Before this change only GitLab admins where allowed to set up forking
relation through the API. This changes that so project owners can
do this too.
Closes gitlab-org/gitlab-ce#40550.
-rw-r--r-- | changelogs/unreleased/tc-api-fork-owners.yml | 5 | ||||
-rw-r--r-- | doc/api/projects.md | 4 | ||||
-rw-r--r-- | lib/api/projects.rb | 2 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 97 |
4 files changed, 75 insertions, 33 deletions
diff --git a/changelogs/unreleased/tc-api-fork-owners.yml b/changelogs/unreleased/tc-api-fork-owners.yml new file mode 100644 index 00000000000..feaa3c1705e --- /dev/null +++ b/changelogs/unreleased/tc-api-fork-owners.yml @@ -0,0 +1,5 @@ +--- +title: Allow project owners to set up forking relation through API +merge_request: 18104 +author: +type: changed diff --git a/doc/api/projects.md b/doc/api/projects.md index 271ee91dc72..d6fa9547963 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -1272,9 +1272,9 @@ DELETE /projects/:id/hooks/:hook_id Note the JSON response differs if the hook is available or not. If the project hook is available before it is returned in the JSON response or an empty response is returned. -## Admin fork relation +## Fork relationship -Allows modification of the forked relationship between existing projects. Available only for admins. +Allows modification of the forked relationship between existing projects. Available only for project owners and admins. ### Create a forked from/to relation between existing projects diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 467bc78dad8..7ea02fce973 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -378,7 +378,7 @@ module API requires :forked_from_id, type: String, desc: 'The ID of the project it was forked from' end post ":id/fork/:forked_from_id" do - authenticated_as_admin! + authorize! :admin_project, user_project fork_from_project = find_project!(params[:forked_from_id]) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index d73a42f48ad..278295f8d4a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1121,47 +1121,84 @@ describe API::Projects do describe 'fork management' do let(:project_fork_target) { create(:project) } let(:project_fork_source) { create(:project, :public) } + let(:private_project_fork_source) { create(:project, :private) } describe 'POST /projects/:id/fork/:forked_from_id' do - let(:new_project_fork_source) { create(:project, :public) } + context 'user is a developer' do + before do + project_fork_target.add_developer(user) + end - it "is not available for non admin users" do - post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) - expect(response).to have_gitlab_http_status(403) - end + it 'denies project to be forked from an existing project' do + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) - it 'allows project to be forked from an existing project' do - expect(project_fork_target.forked?).not_to be_truthy - post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) - expect(response).to have_gitlab_http_status(201) - project_fork_target.reload - expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) - expect(project_fork_target.forked_project_link).not_to be_nil - expect(project_fork_target.forked?).to be_truthy + expect(response).to have_gitlab_http_status(403) + end end - it 'refreshes the forks count cachce' do - expect(project_fork_source.forks_count).to be_zero + context 'user is master' do + before do + project_fork_target.add_master(user) + end - post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) + it 'allows project to be forked from an existing project' do + expect(project_fork_target.forked?).not_to be_truthy - expect(project_fork_source.forks_count).to eq(1) - end + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) + project_fork_target.reload - it 'fails if forked_from project which does not exist' do - post api("/projects/#{project_fork_target.id}/fork/9999", admin) - expect(response).to have_gitlab_http_status(404) + expect(response).to have_gitlab_http_status(201) + expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) + expect(project_fork_target.forked_project_link).not_to be_nil + expect(project_fork_target.forked?).to be_truthy + end + + it 'denies project to be forked from a private project' do + post api("/projects/#{project_fork_target.id}/fork/#{private_project_fork_source.id}", user) + + expect(response).to have_gitlab_http_status(404) + end end - it 'fails with 409 if already forked' do - post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) - project_fork_target.reload - expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) - post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin) - expect(response).to have_gitlab_http_status(409) - project_fork_target.reload - expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) - expect(project_fork_target.forked?).to be_truthy + context 'user is admin' do + it 'allows project to be forked from an existing project' do + expect(project_fork_target.forked?).not_to be_truthy + + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) + project_fork_target.reload + + expect(response).to have_gitlab_http_status(201) + end + + it 'allows project to be forked from a private project' do + post api("/projects/#{project_fork_target.id}/fork/#{private_project_fork_source.id}", admin) + + expect(response).to have_gitlab_http_status(201) + end + + it 'refreshes the forks count cachce' do + expect do + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) + end.to change(project_fork_source, :forks_count).by(1) + end + + it 'fails if forked_from project which does not exist' do + post api("/projects/#{project_fork_target.id}/fork/9999", admin) + expect(response).to have_gitlab_http_status(404) + end + + it 'fails with 409 if already forked' do + other_project_fork_source = create(:project, :public) + + Projects::ForkService.new(project_fork_source, admin).execute(project_fork_target) + + post api("/projects/#{project_fork_target.id}/fork/#{other_project_fork_source.id}", admin) + project_fork_target.reload + + expect(response).to have_gitlab_http_status(409) + expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) + expect(project_fork_target.forked?).to be_truthy + end end end |