summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormhasbini <mohammad.hasbini@gmail.com>2017-04-27 01:04:07 +0300
committermhasbini <mohammad.hasbini@gmail.com>2017-04-27 01:04:07 +0300
commitccac05dd90cb5cfa9abbeb11a50f953541eb83bb (patch)
treeff721d7fddfa595a75b3e2594ab7b5af7590d47f
parent43fb9279ce39d51b1deceb5108560bf37b8d340d (diff)
downloadgitlab-ce-ccac05dd90cb5cfa9abbeb11a50f953541eb83bb.tar.gz
Fix 404 when upstream has disabled merge requests
-rw-r--r--app/helpers/merge_requests_helper.rb6
-rw-r--r--app/models/merge_request.rb7
-rw-r--r--app/models/project.rb8
-rw-r--r--app/services/merge_requests/build_service.rb2
-rw-r--r--app/views/projects/merge_requests/_new_compare.html.haml2
-rw-r--r--changelogs/unreleased/26488-target-disabled-mr.yml4
-rw-r--r--lib/api/merge_requests.rb2
-rw-r--r--lib/api/v3/merge_requests.rb2
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb46
-rw-r--r--spec/requests/api/merge_requests_spec.rb13
-rw-r--r--spec/requests/api/v3/merge_requests_spec.rb13
-rw-r--r--spec/services/merge_requests/build_service_spec.rb10
12 files changed, 111 insertions, 4 deletions
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index e347f61fb8d..2614cdfe90e 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -1,6 +1,6 @@
module MergeRequestsHelper
def new_mr_path_from_push_event(event)
- target_project = event.project.forked_from_project || event.project
+ target_project = event.project.default_merge_request_target
new_namespace_project_merge_request_path(
event.project.namespace,
event.project,
@@ -127,6 +127,10 @@ module MergeRequestsHelper
end
end
+ def target_projects(project)
+ [project, project.default_merge_request_target].uniq
+ end
+
def merge_request_button_visibility(merge_request, closed)
return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_without_fork?
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 9d2288c311e..365fa4f1e70 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -100,6 +100,7 @@ class MergeRequest < ActiveRecord::Base
validates :merge_user, presence: true, if: :merge_when_pipeline_succeeds?, unless: :importing?
validate :validate_branches, unless: [:allow_broken, :importing?, :closed_without_fork?]
validate :validate_fork, unless: :closed_without_fork?
+ validate :validate_target_project, on: :create
scope :by_source_or_target_branch, ->(branch_name) do
where("source_branch = :branch OR target_branch = :branch", branch: branch_name)
@@ -330,6 +331,12 @@ class MergeRequest < ActiveRecord::Base
end
end
+ def validate_target_project
+ return true if target_project.merge_requests_enabled?
+
+ errors.add :base, 'Target project has disabled merge requests'
+ end
+
def validate_fork
return true unless target_project && source_project
return true if target_project == source_project
diff --git a/app/models/project.rb b/app/models/project.rb
index c7dc562c238..9d64e5d406d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1314,6 +1314,14 @@ class Project < ActiveRecord::Base
namespace_id_changed?
end
+ def default_merge_request_target
+ if forked_from_project&.merge_requests_enabled?
+ forked_from_project
+ else
+ self
+ end
+ end
+
alias_method :name_with_namespace, :full_name
alias_method :human_name, :full_name
alias_method :path_with_namespace, :full_path
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index d45da5180e1..bc0e7ad4e39 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -28,7 +28,7 @@ module MergeRequests
def find_target_project
return target_project if target_project.present? && can?(current_user, :read_project, target_project)
- project.forked_from_project || project
+ project.default_merge_request_target
end
def find_target_branch
diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml
index 8d134aaac67..9cf24e10842 100644
--- a/app/views/projects/merge_requests/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/_new_compare.html.haml
@@ -38,7 +38,7 @@
.panel-heading
Target branch
.panel-body.clearfix
- - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project]
+ - projects = target_projects(@project)
.merge-request-select.dropdown
= f.hidden_field :target_project_id
= dropdown_toggle f.object.target_project.path_with_namespace, { toggle: "dropdown", field_name: "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted? }, { toggle_class: "js-compare-dropdown js-target-project" }
diff --git a/changelogs/unreleased/26488-target-disabled-mr.yml b/changelogs/unreleased/26488-target-disabled-mr.yml
new file mode 100644
index 00000000000..02058481ccf
--- /dev/null
+++ b/changelogs/unreleased/26488-target-disabled-mr.yml
@@ -0,0 +1,4 @@
+---
+title: Disallow merge requests from fork when source project have disabled merge requests
+merge_request:
+author: mhasbini
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index e5793fbc5cb..710deba5ae3 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -20,6 +20,8 @@ module API
error!(errors[:validate_fork], 422)
elsif errors[:validate_branches].any?
conflict!(errors[:validate_branches])
+ elsif errors[:base].any?
+ error!(errors[:base], 422)
end
render_api_error!(errors, 400)
diff --git a/lib/api/v3/merge_requests.rb b/lib/api/v3/merge_requests.rb
index 3077240e650..1616142a619 100644
--- a/lib/api/v3/merge_requests.rb
+++ b/lib/api/v3/merge_requests.rb
@@ -23,6 +23,8 @@ module API
error!(errors[:validate_fork], 422)
elsif errors[:validate_branches].any?
conflict!(errors[:validate_branches])
+ elsif errors[:base].any?
+ error!(errors[:base], 422)
end
render_api_error!(errors, 400)
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index e9037749ef2..10681af5f7e 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -64,7 +64,7 @@ describe MergeRequestsHelper do
it do
@project = project
-
+
is_expected.to eq("#1, #2, and #{other_project.namespace.path}/#{other_project.path}#3")
end
end
@@ -149,6 +149,50 @@ describe MergeRequestsHelper do
end
end
+ describe '#target_projects' do
+ let(:project) { create(:empty_project) }
+ let(:fork_project) { create(:empty_project, forked_from_project: project) }
+
+ context 'when target project has enabled merge requests' do
+ it 'returns the forked_from project' do
+ expect(target_projects(fork_project)).to contain_exactly(project, fork_project)
+ end
+ end
+
+ context 'when target project has disabled merge requests' do
+ it 'returns the forked project' do
+ project.project_feature.update(merge_requests_access_level: 0)
+
+ expect(target_projects(fork_project)).to contain_exactly(fork_project)
+ end
+ end
+ end
+
+ describe '#new_mr_path_from_push_event' do
+ subject(:url_params) { URI.decode_www_form(new_mr_path_from_push_event(event)).to_h }
+ let(:user) { create(:user) }
+ let(:project) { create(:empty_project, creator: user) }
+ let(:fork_project) { create(:project, forked_from_project: project, creator: user) }
+ let(:event) do
+ push_data = Gitlab::DataBuilder::Push.build_sample(fork_project, user)
+ create(:event, :pushed, project: fork_project, target: fork_project, author: user, data: push_data)
+ end
+
+ context 'when target project has enabled merge requests' do
+ it 'returns link to create merge request on source project' do
+ expect(url_params['merge_request[target_project_id]'].to_i).to eq(project.id)
+ end
+ end
+
+ context 'when target project has disabled merge requests' do
+ it 'returns link to create merge request on forked project' do
+ project.project_feature.update(merge_requests_access_level: 0)
+
+ expect(url_params['merge_request[target_project_id]'].to_i).to eq(fork_project.id)
+ end
+ end
+ end
+
describe '#mr_issues_mentioned_but_not_closing' do
let(:user_1) { create(:user) }
let(:user_2) { create(:user) }
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index c4bff1647b5..16e5efb2f5b 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -434,6 +434,19 @@ describe API::MergeRequests do
expect(json_response['title']).to eq('Test merge_request')
end
+ it 'returns 422 when target project has disabled merge requests' do
+ project.project_feature.update(merge_requests_access_level: 0)
+
+ post api("/projects/#{fork_project.id}/merge_requests", user2),
+ title: 'Test',
+ target_branch: 'master',
+ source_branch: 'markdown',
+ author: user2,
+ target_project_id: project.id
+
+ expect(response).to have_http_status(422)
+ end
+
it "returns 400 when source_branch is missing" do
post api("/projects/#{fork_project.id}/merge_requests", user2),
title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
diff --git a/spec/requests/api/v3/merge_requests_spec.rb b/spec/requests/api/v3/merge_requests_spec.rb
index 6c2950a6e6f..f6ff96be566 100644
--- a/spec/requests/api/v3/merge_requests_spec.rb
+++ b/spec/requests/api/v3/merge_requests_spec.rb
@@ -338,6 +338,19 @@ describe API::MergeRequests do
expect(json_response['title']).to eq('Test merge_request')
end
+ it "returns 422 when target project has disabled merge requests" do
+ project.project_feature.update(merge_requests_access_level: 0)
+
+ post v3_api("/projects/#{fork_project.id}/merge_requests", user2),
+ title: 'Test',
+ target_branch: "master",
+ source_branch: 'markdown',
+ author: user2,
+ target_project_id: project.id
+
+ expect(response).to have_http_status(422)
+ end
+
it "returns 400 when source_branch is missing" do
post v3_api("/projects/#{fork_project.id}/merge_requests", user2),
title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index be9f9ea2dec..6f9d1208b1d 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -261,6 +261,16 @@ describe MergeRequests::BuildService, services: true do
end
end
+ context 'upstream project has disabled merge requests' do
+ let(:upstream_project) { create(:empty_project, :merge_requests_disabled) }
+ let(:project) { create(:empty_project, forked_from_project: upstream_project) }
+ let(:commits) { Commit.decorate([commit_1], project) }
+
+ it 'sets target project correctly' do
+ expect(merge_request.target_project).to eq(project)
+ end
+ end
+
context 'target_project is set and accessible by current_user' do
let(:target_project) { create(:project, :public, :repository)}
let(:commits) { Commit.decorate([commit_1], project) }