diff options
author | Olaf Tomalka <olaf.tomalka@gmail.com> | 2016-09-06 02:31:06 +0200 |
---|---|---|
committer | Olaf Tomalka <olaf.tomalka@gmail.com> | 2016-09-06 04:16:14 +0200 |
commit | bad3fb895cad46c52575aa91b02f7e7786634a47 (patch) | |
tree | bbcf1a2652b566db7c6c3e12d6173cda5c61fc9f | |
parent | 7d2bd6b91bdfa0afd6b0032ddf23c24a28c61056 (diff) | |
download | gitlab-ce-bad3fb895cad46c52575aa91b02f7e7786634a47.tar.gz |
Added fork API paremeter for a specific namespace
Browser interface allows forking to an owned grup.
This commit brings API up to speed by providing optional namespace
parameter to fork API. This allows forking to users and groups under
forker's control using their id or unique name.
Fixes #21591
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | doc/api/projects.md | 3 | ||||
-rw-r--r-- | lib/api/projects.rb | 16 | ||||
-rw-r--r-- | spec/requests/api/fork_spec.rb | 54 |
4 files changed, 70 insertions, 4 deletions
diff --git a/CHANGELOG b/CHANGELOG index 3f52fab74d7..49c0c906e62 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.12.0 (unreleased) + - Add abillity to fork to a specific namespace using API. @ritave <olaf@tomalka.me> - Prepend blank line to `Closes` message on merge request linked to issue (lukehowell) - Filter tags by name !6121 - Make push events have equal vertical spacing. diff --git a/doc/api/projects.md b/doc/api/projects.md index a62aaee14d7..fe3c8709d13 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -514,7 +514,7 @@ invalid, 400 is returned. ### Fork project -Forks a project into the user namespace of the authenticated user. +Forks a project into the user namespace of the authenticated user or the one provided. ``` POST /projects/fork/:id @@ -523,6 +523,7 @@ POST /projects/fork/:id Parameters: - `id` (required) - The ID or NAMESPACE/PROJECT_NAME of the project to be forked +- `namespace` (optional) - The ID or path of the namespace that the project will be forked to ### Star a project diff --git a/lib/api/projects.rb b/lib/api/projects.rb index a1fd598414a..d35ec73c8c1 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -189,16 +189,28 @@ module API end end - # Fork new project for the current user. + # Fork new project for the current user or provided namespace. # # Parameters: # id (required) - The ID of a project + # namespace (optional) - The ID or name of the namespace that the project will be forked into. # Example Request # POST /projects/fork/:id post 'fork/:id' do + attrs = {} + namespace_id = params[:namespace] + if namespace_id.present? + namespace = Namespace.find_by(id: namespace_id) || Namespace.find_by_path_or_name(namespace_id) + if namespace.nil? + not_found!('Target Namespace') + end + authorize! :create_projects, namespace + attrs[:namespace] = namespace + end @forked_project = ::Projects::ForkService.new(user_project, - current_user).execute + current_user, + attrs).execute if @forked_project.errors.any? conflict!(@forked_project.errors.messages) else diff --git a/spec/requests/api/fork_spec.rb b/spec/requests/api/fork_spec.rb index f802fcd2d2e..97f17efc053 100644 --- a/spec/requests/api/fork_spec.rb +++ b/spec/requests/api/fork_spec.rb @@ -3,9 +3,15 @@ require 'spec_helper' describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } - let(:user2) { create(:user) } + let(:user2) { create(:user, username: 'user2_name') } let(:user3) { create(:user) } let(:admin) { create(:admin) } + let(:group) { create(:group, name: 'group_name') } + let(:group2) do + group = create(:group, name: 'group2_name') + group.add_owner(user2) + group + end let(:project) do create(:project, creator_id: user.id, namespace: user.namespace) @@ -58,6 +64,52 @@ describe API::API, api: true do expect(response).to have_http_status(404) expect(json_response['message']).to eq('404 Project Not Found') end + + it 'forks with explicit own user namespace id' do + post api("/projects/fork/#{project.id}?namespace=#{user2.namespace.id}", user2) + expect(response).to have_http_status(201) + expect(json_response['owner']['id']).to eq(user2.id) + end + + it 'forks with explicit own user name as namespace' do + post api("/projects/fork/#{project.id}?namespace=#{user2.username}", user2) + expect(response).to have_http_status(201) + expect(json_response['owner']['id']).to eq(user2.id) + end + + it 'forks to another user when admin' do + post api("/projects/fork/#{project.id}?namespace=#{user2.username}", admin) + expect(response).to have_http_status(201) + expect(json_response['owner']['id']).to eq(user2.id) + end + + it 'fails if trying to fork to another user when not admin' do + post api("/projects/fork/#{project.id}?namespace=#{admin.namespace.id}", user2) + expect(response).to have_http_status(403) + end + + it 'fails if trying to fork to non-existent namespace' do + post api("/projects/fork/#{project.id}?namespace=42424242", user2) + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 Target Namespace Not Found') + end + + it 'forks to owned group' do + post api("/projects/fork/#{project.id}?namespace=#{group2.name}", user2) + expect(response).to have_http_status(201) + expect(json_response['namespace']['name']).to eq(group2.name) + end + + it 'fails to fork to not owned group' do + post api("/projects/fork/#{project.id}?namespace=#{group.name}", user2) + expect(response).to have_http_status(403) + end + + it 'forks to not owned group when admin' do + post api("/projects/fork/#{project.id}?namespace=#{group.name}", admin) + expect(response).to have_http_status(201) + expect(json_response['namespace']['name']).to eq(group.name) + end end context 'when unauthenticated' do |