BigW Consortium Gitlab

Commit 081f67f1 by Sean McGivern Committed by Mayra Cabrera

Merge branch '42682-merge-request-internal-access' into 'security-10-6'

Do not allow non-members to create MRs via forked projects when MRs are private See merge request gitlab/gitlabhq!2368
parent 670de249
...@@ -29,6 +29,19 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap ...@@ -29,6 +29,19 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
define_new_vars define_new_vars
render action: "new" render action: "new"
end end
rescue Gitlab::Access::AccessDeniedError
flash[:alert] = 'You do not have permission to create a Merge Request on the target project'
params = merge_request_params
params.delete(:force_remove_source_branch)
@merge_request = ::MergeRequests::BuildService.new(project, current_user, params).execute
@source_project = @merge_request.source_project
@target_project = @merge_request.target_project
define_new_vars
render action: 'new'
end end
def pipelines def pipelines
......
...@@ -127,6 +127,8 @@ class ProjectPolicy < BasePolicy ...@@ -127,6 +127,8 @@ class ProjectPolicy < BasePolicy
rule { guest & can?(:download_code) }.enable :build_download_code rule { guest & can?(:download_code) }.enable :build_download_code
rule { guest & can?(:read_container_image) }.enable :build_read_container_image rule { guest & can?(:read_container_image) }.enable :build_read_container_image
rule { ~anonymous & ~merge_requests_disabled }.enable :create_forked_merge_request
rule { can?(:reporter_access) }.policy do rule { can?(:reporter_access) }.policy do
enable :download_code enable :download_code
enable :download_wiki_code enable :download_wiki_code
......
...@@ -58,6 +58,10 @@ module MergeRequests ...@@ -58,6 +58,10 @@ module MergeRequests
pipelines.order(id: :desc).first pipelines.order(id: :desc).first
end end
def forked?
@project != @source_project
end
def set_projects! def set_projects!
# @project is used to determine whether the user can set the merge request's # @project is used to determine whether the user can set the merge request's
# assignee, milestone and labels. Whether they can depends on their # assignee, milestone and labels. Whether they can depends on their
...@@ -71,8 +75,11 @@ module MergeRequests ...@@ -71,8 +75,11 @@ module MergeRequests
params.delete(:source_project_id) params.delete(:source_project_id)
params.delete(:target_project_id) params.delete(:target_project_id)
create_ability = forked? ? :create_forked_merge_request : :create_merge_request
unless can?(current_user, :read_project, @source_project) && unless can?(current_user, :read_project, @source_project) &&
can?(current_user, :read_project, @project) can?(current_user, :read_project, @project) &&
can?(current_user, create_ability, @project)
raise Gitlab::Access::AccessDeniedError raise Gitlab::Access::AccessDeniedError
end end
......
---
title: Do not allow non-members to create MRs via forked projects when MRs are private
merge_request:
author:
type: security
...@@ -21,7 +21,7 @@ Gitlab::Seeder.quiet do ...@@ -21,7 +21,7 @@ Gitlab::Seeder.quiet do
assignee: project.team.users.sample assignee: project.team.users.sample
} }
MergeRequests::CreateService.new(project, project.team.users.sample, params).execute MergeRequests::CreateService.new(project, project.team.developers.sample, params).execute
print '.' print '.'
end end
end end
......
...@@ -194,12 +194,18 @@ module API ...@@ -194,12 +194,18 @@ module API
mr_params = declared_params(include_missing: false) mr_params = declared_params(include_missing: false)
mr_params[:force_remove_source_branch] = mr_params.delete(:remove_source_branch) mr_params[:force_remove_source_branch] = mr_params.delete(:remove_source_branch)
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute begin
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute
if merge_request.valid? if merge_request.valid?
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
else else
handle_merge_request_errors! merge_request.errors handle_merge_request_errors! merge_request.errors
end
rescue Gitlab::Access::AccessDeniedError => ex
raise ex if Project.find(mr_params[:target_project_id]).merge_requests_enabled?
error!('Target project has disabled merge requests', 422)
end end
end end
......
...@@ -98,12 +98,18 @@ module API ...@@ -98,12 +98,18 @@ module API
mr_params = declared_params(include_missing: false) mr_params = declared_params(include_missing: false)
mr_params[:force_remove_source_branch] = mr_params.delete(:remove_source_branch) if mr_params[:remove_source_branch].present? mr_params[:force_remove_source_branch] = mr_params.delete(:remove_source_branch) if mr_params[:remove_source_branch].present?
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute begin
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute
if merge_request.valid? if merge_request.valid?
present merge_request, with: ::API::V3::Entities::MergeRequest, current_user: current_user, project: user_project present merge_request, with: ::API::V3::Entities::MergeRequest, current_user: current_user, project: user_project
else else
handle_merge_request_errors! merge_request.errors handle_merge_request_errors! merge_request.errors
end
rescue Gitlab::Access::AccessDeniedError => ex
raise ex if Project.find(mr_params[:target_project_id]).merge_requests_enabled?
error!('Target project has disabled merge requests', 422)
end end
end end
......
...@@ -31,6 +31,30 @@ describe Projects::MergeRequests::CreationsController do ...@@ -31,6 +31,30 @@ describe Projects::MergeRequests::CreationsController do
end end
end end
describe 'POST create' do
context 'merge request to a project the user has no access to' do
let(:project) { create(:project, :internal, :merge_requests_private) }
let(:user) { create(:user) }
let(:opts) do
{
target_project_id: project.id,
source_project_id: fork_project.id,
source_branch: 'remove-submodule',
target_branch: 'master'
}
end
it 'shows a proper error message' do
expect do
post :create, get_diff_params.merge(merge_request: opts)
end.not_to change { MergeRequest.count }
expect(response).to be_success
expect(flash[:alert]).to eq('You do not have permission to create a Merge Request on the target project')
end
end
end
describe 'GET diffs' do describe 'GET diffs' do
context 'when merge request cannot be created' do context 'when merge request cannot be created' do
it 'does not assign diffs var' do it 'does not assign diffs var' do
......
...@@ -334,6 +334,28 @@ describe MergeRequests::CreateService do ...@@ -334,6 +334,28 @@ describe MergeRequests::CreateService do
.to raise_error Gitlab::Access::AccessDeniedError .to raise_error Gitlab::Access::AccessDeniedError
end end
end end
context 'when the user is not a member of target project and MR feature is restricted' do
let(:target_project) { create(:project, :internal, :merge_requests_private) }
let(:service) { described_class.new(project, user, opts) }
before do
project.add_master(user)
target_project.add_developer(assignee)
allow(service).to receive(:execute_hooks)
end
it 'raises an error' do
expect { service.execute }
.to raise_error(Gitlab::Access::AccessDeniedError)
end
it 'does not create the MR' do
expect do
service.execute rescue nil
end.not_to change { MergeRequest.count }
end
end
end end
context 'when user sets source project id' do context 'when user sets source project id' do
......
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