Commit b7ffc097 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Allow collaboration with forks through the API

These APIs are used by the web IDE.

They need to be on par with git & web access, allowing edits from
maintainers to forks with merge requests that allow access.
parent 3a77664d
...@@ -6,6 +6,18 @@ module API ...@@ -6,6 +6,18 @@ module API
before { authorize! :download_code, user_project } before { authorize! :download_code, user_project }
helpers do
def user_access
@user_access ||= Gitlab::UserAccess.new(current_user, project: user_project)
end
def authorize_push_to_branch!(branch)
unless user_access.can_push_to_branch?(branch)
forbidden!("You are not allowed to push into this branch")
end
end
end
params do params do
requires :id, type: String, desc: 'The ID of a project' requires :id, type: String, desc: 'The ID of a project'
end end
...@@ -67,7 +79,7 @@ module API ...@@ -67,7 +79,7 @@ module API
optional :author_name, type: String, desc: 'Author name for commit' optional :author_name, type: String, desc: 'Author name for commit'
end end
post ':id/repository/commits' do post ':id/repository/commits' do
authorize! :push_code, user_project authorize_push_to_branch!(params[:branch])
attrs = declared_params attrs = declared_params
attrs[:branch_name] = attrs.delete(:branch) attrs[:branch_name] = attrs.delete(:branch)
...@@ -142,7 +154,7 @@ module API ...@@ -142,7 +154,7 @@ module API
requires :branch, type: String, desc: 'The name of the branch' requires :branch, type: String, desc: 'The name of the branch'
end end
post ':id/repository/commits/:sha/cherry_pick', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do post ':id/repository/commits/:sha/cherry_pick', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
authorize! :push_code, user_project authorize_push_to_branch!(params[:branch])
commit = user_project.commit(params[:sha]) commit = user_project.commit(params[:sha])
not_found!('Commit') unless commit not_found!('Commit') unless commit
......
...@@ -514,6 +514,38 @@ describe API::Commits do ...@@ -514,6 +514,38 @@ describe API::Commits do
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
end end
context 'when committing into a fork as a maintainer' do
include_context 'merge request allowing collaboration'
let(:project_id) { forked_project.id }
def push_params(branch_name)
{
branch: branch_name,
commit_message: 'Hello world',
actions: [
{
action: 'create',
file_path: 'foo/bar/baz.txt',
content: 'puts 8'
}
]
}
end
it 'allows pushing to the source branch of the merge request' do
post api(url, user), push_params('feature')
expect(response).to have_gitlab_http_status(:created)
end
it 'denies pushing to another branch' do
post api(url, user), push_params('other-branch')
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end end
describe 'GET /projects/:id/repository/commits/:sha/refs' do describe 'GET /projects/:id/repository/commits/:sha/refs' do
...@@ -1065,9 +1097,27 @@ describe API::Commits do ...@@ -1065,9 +1097,27 @@ describe API::Commits do
it 'returns 400 if you are not allowed to push to the target branch' do it 'returns 400 if you are not allowed to push to the target branch' do
post api(route, current_user), branch: 'feature' post api(route, current_user), branch: 'feature'
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(:forbidden)
expect(json_response['message']).to eq('You are not allowed to push into this branch') expect(json_response['message']).to match(/You are not allowed to push into this branch/)
end
end
end end
context 'when cherry picking to a fork as a maintainer' do
include_context 'merge request allowing collaboration'
let(:project_id) { forked_project.id }
it 'allows access from a maintainer that to the source branch' do
post api(route, user), branch: 'feature'
expect(response).to have_gitlab_http_status(:created)
end
it 'denies cherry picking to another branch' do
post api(route, user), branch: 'master'
expect(response).to have_gitlab_http_status(:forbidden)
end end
end end
end end
......
shared_context 'merge request allowing collaboration' do
include ProjectForksHelper
let(:canonical) { create(:project, :public, :repository) }
let(:forked_project) { fork_project(canonical, nil, repository: true) }
before do
canonical.add_maintainer(user)
create(:merge_request,
target_project: canonical,
source_project: forked_project,
source_branch: 'feature',
allow_collaboration: true)
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