summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Tomalka <olaf.tomalka@gmail.com>2016-09-06 02:31:06 +0200
committerOlaf Tomalka <olaf.tomalka@gmail.com>2016-09-06 04:16:14 +0200
commitbad3fb895cad46c52575aa91b02f7e7786634a47 (patch)
treebbcf1a2652b566db7c6c3e12d6173cda5c61fc9f
parent7d2bd6b91bdfa0afd6b0032ddf23c24a28c61056 (diff)
downloadgitlab-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--CHANGELOG1
-rw-r--r--doc/api/projects.md3
-rw-r--r--lib/api/projects.rb16
-rw-r--r--spec/requests/api/fork_spec.rb54
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