diff --git a/app/services/ci/runners/assign_runner_service.rb b/app/services/ci/runners/assign_runner_service.rb index 290f945cc7216c1e5e5aadbe0bf71a9657a0df45..4e7b08bdd7a1e9f06415223f2a3b544707c7d2db 100644 --- a/app/services/ci/runners/assign_runner_service.rb +++ b/app/services/ci/runners/assign_runner_service.rb @@ -17,6 +17,10 @@ def execute return ServiceResponse.error(message: 'user not allowed to assign runner', http_status: :forbidden) end + unless @user.can?(:register_project_runners, @project) + return ServiceResponse.error(message: 'user not allowed to add runners to project', http_status: :forbidden) + end + if @runner.assign_to(@project, @user) ServiceResponse.success else diff --git a/spec/services/ci/runners/assign_runner_service_spec.rb b/spec/services/ci/runners/assign_runner_service_spec.rb index 92f6db2bdfb389e65f27ee54c4ce37bbe3b6dec5..00fbb5e2d26a14c97f182286d18da1a962c0f865 100644 --- a/spec/services/ci/runners/assign_runner_service_spec.rb +++ b/spec/services/ci/runners/assign_runner_service_spec.rb @@ -3,10 +3,12 @@ require 'spec_helper' RSpec.describe ::Ci::Runners::AssignRunnerService, '#execute', feature_category: :runner_fleet do - subject(:execute) { described_class.new(runner, project, user).execute } + subject(:execute) { described_class.new(runner, new_project, user).execute } - let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) } - let_it_be(:project) { create(:project) } + let_it_be(:owner_group) { create(:group) } + let_it_be(:owner_project) { create(:project, group: owner_group) } + let_it_be(:new_project) { create(:project) } + let_it_be(:runner) { create(:ci_runner, :project, projects: [owner_project]) } context 'without user' do let(:user) { nil } @@ -30,11 +32,54 @@ end end + context 'with authorized user' do + let(:user) { create(:user) } + + context 'with user owning runner and being maintainer of new project' do + before do + owner_project.group.add_owner(user) + new_project.add_maintainer(user) + end + + it 'calls assign_to on runner and returns success response' do + expect(runner).to receive(:assign_to).with(new_project, user).once.and_call_original + + is_expected.to be_success + end + end + + context 'with user owning runner' do + before do + owner_project.add_maintainer(user) + end + + it 'does not call assign_to on runner and returns error message', :aggregate_failures do + expect(runner).not_to receive(:assign_to) + + is_expected.to be_error + expect(execute.message).to eq('user not allowed to add runners to project') + end + end + + context 'with user being maintainer of new project', :aggregate_failures do + before do + new_project.add_maintainer(user) + end + + it 'does not call assign_to on runner and returns error message' do + expect(runner).not_to receive(:assign_to) + + is_expected.to be_error + expect(execute.message).to eq('user not allowed to assign runner') + end + end + end + context 'with admin user', :enable_admin_mode do - let(:user) { create_default(:user, :admin) } + let(:user) { create(:user, :admin) } it 'calls assign_to on runner and returns success response' do - expect(runner).to receive(:assign_to).with(project, user).once.and_call_original + expect(runner).to receive(:assign_to).with(new_project, user).once.and_call_original is_expected.to be_success end