diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb index 5ed9d1aa517..7efea564ba6 100644 --- a/app/services/ci/create_pipeline_service.rb +++ b/app/services/ci/create_pipeline_service.rb @@ -27,7 +27,7 @@ module Ci return error('Reference not found') end - unless Ci::Pipeline.allowed_to_create?(current_user, project, ref) + unless triggering_user_allowed_for_ref?(trigger_request, ref) return error("Insufficient permissions for protected #{ref}") end @@ -56,6 +56,14 @@ module Ci private + def triggering_user_allowed_for_ref?(trigger_request, ref) + triggering_user = current_user || trigger_request.trigger.owner + + (triggering_user && + Ci::Pipeline.allowed_to_create?(triggering_user, project, ref)) || + !project.protected_for?(ref) + end + def process! Ci::Pipeline.transaction do update_merge_requests_head_pipeline if pipeline.save diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index 13a1c6a504d..2616dcc6f04 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -10,13 +10,19 @@ describe Ci::CreatePipelineService, services: true do end describe '#execute' do - def execute_service(source: :push, after: project.commit.id, message: 'Message', ref: ref_name) + def execute_service( + source: :push, + after: project.commit.id, + message: 'Message', + ref: ref_name, + trigger_request: nil) params = { ref: ref, before: '00000000', after: after, commits: [{ message: message }] } - described_class.new(project, user, params).execute(source) + described_class.new(project, user, params).execute( + source, trigger_request: trigger_request) end context 'valid params' do @@ -337,6 +343,53 @@ describe Ci::CreatePipelineService, services: true do expect(Ci::Pipeline.count).to eq(1) end end + + context 'when trigger belongs to no one' do + let(:user) {} + let(:trigger_request) { create(:ci_trigger_request) } + + it 'does not create a pipeline' do + expect(execute_service(trigger_request: trigger_request)) + .not_to be_persisted + expect(Ci::Pipeline.count).to eq(0) + end + end + + context 'when trigger belongs to a developer' do + let(:user) {} + + let(:trigger_request) do + create(:ci_trigger_request).tap do |request| + user = create(:user) + project.add_developer(user) + request.trigger.update(owner: user) + end + end + + it 'does not create a pipeline' do + expect(execute_service(trigger_request: trigger_request)) + .not_to be_persisted + expect(Ci::Pipeline.count).to eq(0) + end + end + + context 'when trigger belongs to a master' do + let(:user) {} + + let(:trigger_request) do + create(:ci_trigger_request).tap do |request| + user = create(:user) + project.add_master(user) + request.trigger.update(owner: user) + end + end + + it 'does not create a pipeline' do + expect(execute_service(trigger_request: trigger_request)) + .to be_persisted + expect(Ci::Pipeline.count).to eq(1) + end + end end context 'when ref is a protected branch' do