Commit 90d49705 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge pull request #4515 from amacarthur/fork-admin

Additon of apis for fork administration.
parents d2d566b1 ea5a006f
......@@ -453,3 +453,28 @@ Parameters:
+ `id` (required) - The ID of the project.
+ `branch` (required) - The name of the branch.
## Admin fork relation
Allows modification of the forked relationship between existing projects. . Available only for admins.
### Create a forked from/to relation between existing projects.
```
POST /projects/:id/fork/:forked_from_id
```
Parameters:
+ `id` (required) - The ID of the project
+ `forked_from_id:` (required) - The ID of the project that was forked from
### Delete an existing forked from relationship
```
DELETE /projects/:id/fork
```
Parameter:
+ `id` (required) - The ID of the project
\ No newline at end of file
......@@ -25,6 +25,12 @@ module API
expose :id, :url, :created_at
end
class ForkedFromProject < Grape::Entity
expose :id
expose :name, :name_with_namespace
expose :path, :path_with_namespace
end
class Project < Grape::Entity
expose :id, :description, :default_branch, :public, :ssh_url_to_repo, :http_url_to_repo, :web_url
expose :owner, using: Entities::UserBasic
......@@ -32,6 +38,7 @@ module API
expose :path, :path_with_namespace
expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at, :last_activity_at
expose :namespace
expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? }
end
class ProjectMember < UserBasic
......
......@@ -5,12 +5,12 @@ module API
end
def user_project
@project ||= find_project
@project ||= find_project(params[:id])
@project || not_found!
end
def find_project
project = Project.find_by_id(params[:id]) || Project.find_with_namespace(params[:id])
def find_project(id)
project = Project.find_by_id(id) || Project.find_with_namespace(id)
if project && can?(current_user, :read_project, project)
project
......
......@@ -121,6 +121,42 @@ module API
end
# Mark this project as forked from another
#
# Parameters:
# id: (required) - The ID of the project being marked as a fork
# forked_from_id: (required) - The ID of the project it was forked from
# Example Request:
# POST /projects/:id/fork/:forked_from_id
post ":id/fork/:forked_from_id" do
authenticated_as_admin!
forked_from_project = find_project(params[:forked_from_id])
unless forked_from_project.nil?
if user_project.forked_from_project.nil?
user_project.create_forked_project_link(forked_to_project_id: user_project.id, forked_from_project_id: forked_from_project.id)
else
render_api_error!("Project already forked", 409)
end
else
not_found!
end
end
# Remove a forked_from relationship
#
# Parameters:
# id: (required) - The ID of the project being marked as a fork
# Example Request:
# DELETE /projects/:id/fork
delete ":id/fork" do
authenticated_as_admin!
unless user_project.forked_project_link.nil?
user_project.forked_project_link.destroy
end
end
# Get a project team members
#
# Parameters:
......
......@@ -595,4 +595,71 @@ describe API::API do
end
end
end
describe :fork_admin do
let(:project_fork_target) { create(:project) }
let(:project_fork_source) { create(:project, public: true) }
describe "POST /projects/:id/fork/:forked_from_id" do
let(:new_project_fork_source) { create(:project, public: true) }
it "shouldn't available for non admin users" do
post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user)
response.status.should == 403
end
it "should allow project to be forked from an existing project" do
project_fork_target.forked?.should_not be_true
post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
response.status.should == 201
project_fork_target.reload
project_fork_target.forked_from_project.id.should == project_fork_source.id
project_fork_target.forked_project_link.should_not be_nil
project_fork_target.forked?.should be_true
end
it "should fail if forked_from project which does not exist" do
post api("/projects/#{project_fork_target.id}/fork/9999", admin)
response.status.should == 404
end
it "should fail with 409 if already forked" do
post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
project_fork_target.reload
project_fork_target.forked_from_project.id.should == project_fork_source.id
post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin)
response.status.should == 409
project_fork_target.reload
project_fork_target.forked_from_project.id.should == project_fork_source.id
project_fork_target.forked?.should be_true
end
end
describe "DELETE /projects/:id/fork" do
it "shouldn't available for non admin users" do
delete api("/projects/#{project_fork_target.id}/fork", user)
response.status.should == 403
end
it "should make forked project unforked" do
post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
project_fork_target.reload
project_fork_target.forked_from_project.should_not be_nil
project_fork_target.forked?.should be_true
delete api("/projects/#{project_fork_target.id}/fork", admin)
response.status.should == 200
project_fork_target.reload
project_fork_target.forked_from_project.should be_nil
project_fork_target.forked?.should_not be_true
end
it "should be idempotent if not forked" do
project_fork_target.forked_from_project.should be_nil
delete api("/projects/#{project_fork_target.id}/fork", admin)
response.status.should == 200
project_fork_target.reload.forked_from_project.should be_nil
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