summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-04-29 08:23:43 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-04-29 08:23:57 +0000
commit5a9cce5925119370b328c9470f23c9ce017db33d (patch)
treeda726ff97a2aaeecbb538584f7cf93bf4fc7b5d7
parent90f15e050d48dfada581e7c24ff99b2b2b4bc806 (diff)
downloadgitlab-ce-5a9cce5925119370b328c9470f23c9ce017db33d.tar.gz
Add latest changes from gitlab-org/security/gitlab@14-9-stable-ee
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb7
-rw-r--r--app/policies/ci/pipeline_schedule_policy.rb5
-rw-r--r--doc/ci/pipelines/schedules.md14
-rw-r--r--lib/api/ci/pipeline_schedules.rb2
-rw-r--r--lib/gitlab/import_export/project/import_export.yml1
-rw-r--r--lib/gitlab/import_export/project/relation_factory.rb6
-rw-r--r--spec/controllers/projects/pipeline_schedules_controller_spec.rb104
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb127
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/project.json1
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/tree/project.json3
-rw-r--r--spec/lib/gitlab/import_export/project/relation_factory_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb4
-rw-r--r--spec/policies/ci/pipeline_schedule_policy_spec.rb7
-rw-r--r--spec/requests/api/ci/pipeline_schedules_spec.rb55
14 files changed, 246 insertions, 108 deletions
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 271c31b6429..a1f0572a36a 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -7,7 +7,8 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :authorize_play_pipeline_schedule!, only: [:play]
before_action :authorize_read_pipeline_schedule!
before_action :authorize_create_pipeline_schedule!, only: [:new, :create]
- before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play]
+ before_action :authorize_update_pipeline_schedule!, only: [:edit, :update]
+ before_action :authorize_take_ownership_pipeline_schedule!, only: [:take_ownership]
before_action :authorize_admin_pipeline_schedule!, only: [:destroy]
before_action do
@@ -112,6 +113,10 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
return access_denied! unless can?(current_user, :update_pipeline_schedule, schedule)
end
+ def authorize_take_ownership_pipeline_schedule!
+ return access_denied! unless can?(current_user, :take_ownership_pipeline_schedule, schedule)
+ end
+
def authorize_admin_pipeline_schedule!
return access_denied! unless can?(current_user, :admin_pipeline_schedule, schedule)
end
diff --git a/app/policies/ci/pipeline_schedule_policy.rb b/app/policies/ci/pipeline_schedule_policy.rb
index 2ef5ffd6a5a..3a674bfef92 100644
--- a/app/policies/ci/pipeline_schedule_policy.rb
+++ b/app/policies/ci/pipeline_schedule_policy.rb
@@ -15,11 +15,14 @@ module Ci
rule { can?(:create_pipeline) }.enable :play_pipeline_schedule
rule { can?(:admin_pipeline) | (can?(:update_build) & owner_of_schedule) }.policy do
- enable :update_pipeline_schedule
enable :admin_pipeline_schedule
enable :read_pipeline_schedule_variables
end
+ rule { admin | (owner_of_schedule & can?(:update_build)) }.policy do
+ enable :update_pipeline_schedule
+ end
+
rule { can?(:admin_pipeline_schedule) & ~owner_of_schedule }.policy do
enable :take_ownership_pipeline_schedule
end
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index 8813f3e1d59..8ab80e3798a 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -39,6 +39,20 @@ To add a pipeline schedule:
These variables are available only when the scheduled pipeline runs,
and not in any other pipeline run.
+## Edit a pipeline schedule
+
+> Introduced in GitLab 14.8, only a pipeline schedule owner can edit the schedule.
+
+The owner of a pipeline schedule can edit it:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. In the left sidebar, select **CI/CD > Schedules**.
+1. Next to the schedule, select **Edit** (**{pencil}**) and fill in the form.
+
+The user must have the Developer role or above for the project. If the user is
+not the owner of the schedule, they must first [take ownership](#take-ownership)
+of the schedule.
+
## Run manually
To trigger a pipeline schedule manually, so that it runs immediately instead of
diff --git a/lib/api/ci/pipeline_schedules.rb b/lib/api/ci/pipeline_schedules.rb
index 8a9ba2cbe0f..6030fe86f00 100644
--- a/lib/api/ci/pipeline_schedules.rb
+++ b/lib/api/ci/pipeline_schedules.rb
@@ -93,7 +93,7 @@ module API
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
end
post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do
- authorize! :update_pipeline_schedule, pipeline_schedule
+ authorize! :take_ownership_pipeline_schedule, pipeline_schedule
if pipeline_schedule.own!(current_user)
present pipeline_schedule, with: Entities::Ci::PipelineScheduleDetails
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index fc05cc1a79c..7dcf26ca89a 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -639,7 +639,6 @@ included_attributes:
- :build_allow_git_fetch
- :build_coverage_regex
- :build_timeout
- - :ci_config_path
- :delete_error
- :description
- :disable_overriding_approvers_per_merge_request
diff --git a/lib/gitlab/import_export/project/relation_factory.rb b/lib/gitlab/import_export/project/relation_factory.rb
index c391f86b47b..8110720fb46 100644
--- a/lib/gitlab/import_export/project/relation_factory.rb
+++ b/lib/gitlab/import_export/project/relation_factory.rb
@@ -87,6 +87,8 @@ module Gitlab
when *BUILD_MODELS then setup_build
when :issues then setup_issue
when :'Ci::PipelineSchedule' then setup_pipeline_schedule
+ when :'ProtectedBranch::MergeAccessLevel' then setup_protected_branch_access_level
+ when :'ProtectedBranch::PushAccessLevel' then setup_protected_branch_access_level
end
update_project_references
@@ -152,6 +154,10 @@ module Gitlab
@relation_hash['active'] = false
end
+ def setup_protected_branch_access_level
+ @relation_hash['access_level'] = Gitlab::Access::MAINTAINER
+ end
+
def compute_relative_position
return unless max_relative_position
diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
index d86f38c1f0b..77acd5fe13c 100644
--- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb
+++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
@@ -13,10 +13,43 @@ RSpec.describe Projects::PipelineSchedulesController do
project.add_developer(user)
end
+ shared_examples 'access update schedule' do
+ describe 'security' do
+ it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
+ expect { go }.to be_allowed_for(:admin)
+ end
+
+ it 'is denied for admin when admin mode disabled' do
+ expect { go }.to be_denied_for(:admin)
+ end
+
+ it { expect { go }.to be_denied_for(:owner).of(project) }
+ it { expect { go }.to be_denied_for(:maintainer).of(project) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_denied_for(:reporter).of(project) }
+ it { expect { go }.to be_denied_for(:guest).of(project) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ it { expect { go }.to be_denied_for(:visitor) }
+
+ context 'when user is schedule owner' do
+ it { expect { go }.to be_allowed_for(:owner).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_allowed_for(:developer).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:reporter).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:guest).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:user).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:external).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:visitor).own(pipeline_schedule) }
+ end
+ end
+ end
+
describe 'GET #index' do
render_views
let(:scope) { nil }
+
let!(:inactive_pipeline_schedule) do
create(:ci_pipeline_schedule, :inactive, project: project)
end
@@ -130,12 +163,15 @@ RSpec.describe Projects::PipelineSchedulesController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is denied for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_allowed_for(:developer).of(project) }
+
it { expect { go }.to be_denied_for(:reporter).of(project) }
it { expect { go }.to be_denied_for(:guest).of(project) }
it { expect { go }.to be_denied_for(:user) }
@@ -284,20 +320,7 @@ RSpec.describe Projects::PipelineSchedulesController do
describe 'security' do
let(:schedule) { { description: 'updated_desc' } }
- it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
- expect { go }.to be_allowed_for(:admin)
- end
- it 'is denied for admin when admin mode disabled' do
- expect { go }.to be_denied_for(:admin)
- end
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:maintainer).of(project) }
- it { expect { go }.to be_allowed_for(:developer).of(project).own(pipeline_schedule) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- it { expect { go }.to be_denied_for(:visitor) }
+ it_behaves_like 'access update schedule'
context 'when a developer created a pipeline schedule' do
let(:developer_1) { create(:user) }
@@ -308,8 +331,10 @@ RSpec.describe Projects::PipelineSchedulesController do
end
it { expect { go }.to be_allowed_for(developer_1) }
+
+ it { expect { go }.to be_denied_for(:owner).of(project) }
+ it { expect { go }.to be_denied_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
- it { expect { go }.to be_allowed_for(:maintainer).of(project) }
end
context 'when a maintainer created a pipeline schedule' do
@@ -321,17 +346,21 @@ RSpec.describe Projects::PipelineSchedulesController do
end
it { expect { go }.to be_allowed_for(maintainer_1) }
- it { expect { go }.to be_allowed_for(:maintainer).of(project) }
+
+ it { expect { go }.to be_denied_for(:owner).of(project) }
+ it { expect { go }.to be_denied_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
end
end
def go
- put :update, params: { namespace_id: project.namespace.to_param,
- project_id: project,
- id: pipeline_schedule,
- schedule: schedule },
- as: :html
+ put :update, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: pipeline_schedule,
+ schedule: schedule
+ },
+ as: :html
end
end
@@ -341,6 +370,7 @@ RSpec.describe Projects::PipelineSchedulesController do
before do
project.add_maintainer(user)
+ pipeline_schedule.update!(owner: user)
sign_in(user)
end
@@ -352,22 +382,7 @@ RSpec.describe Projects::PipelineSchedulesController do
end
end
- describe 'security' do
- it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
- expect { go }.to be_allowed_for(:admin)
- end
- it 'is denied for admin when admin mode disabled' do
- expect { go }.to be_denied_for(:admin)
- end
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:maintainer).of(project) }
- it { expect { go }.to be_allowed_for(:developer).of(project).own(pipeline_schedule) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- it { expect { go }.to be_denied_for(:visitor) }
- end
+ it_behaves_like 'access update schedule'
def go
get :edit, params: { namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id }
@@ -379,17 +394,30 @@ RSpec.describe Projects::PipelineSchedulesController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is denied for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
- it { expect { go }.to be_allowed_for(:developer).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
it { expect { go }.to be_denied_for(:reporter).of(project) }
it { expect { go }.to be_denied_for(:guest).of(project) }
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
it { expect { go }.to be_denied_for(:visitor) }
+
+ context 'when user is schedule owner' do
+ it { expect { go }.to be_denied_for(:owner).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:maintainer).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:developer).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:reporter).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:guest).of(project).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:user).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:external).own(pipeline_schedule) }
+ it { expect { go }.to be_denied_for(:visitor).own(pipeline_schedule) }
+ end
end
def go
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 63867a7e900..7cb14feabd2 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -9,7 +9,77 @@ RSpec.describe 'Pipeline Schedules', :js do
let(:scope) { nil }
let!(:user) { create(:user) }
- context 'logged in as maintainer' do
+ context 'logged in as the pipeline scheduler owner' do
+ before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
+ project.add_developer(user)
+ pipeline_schedule.update!(owner: user)
+ gitlab_sign_in(user)
+ end
+
+ describe 'GET /projects/pipeline_schedules' do
+ before do
+ visit_pipelines_schedules
+ end
+
+ it 'edits the pipeline' do
+ page.within('.pipeline-schedule-table-row') do
+ click_link 'Edit'
+ end
+
+ expect(page).to have_content('Edit Pipeline Schedule')
+ end
+ end
+
+ describe 'PATCH /projects/pipelines_schedules/:id/edit' do
+ before do
+ edit_pipeline_schedule
+ end
+
+ it 'displays existing properties' do
+ description = find_field('schedule_description').value
+ expect(description).to eq('pipeline schedule')
+ expect(page).to have_button('master')
+ expect(page).to have_button('UTC')
+ end
+
+ it 'edits the scheduled pipeline' do
+ fill_in 'schedule_description', with: 'my brand new description'
+
+ save_pipeline_schedule
+
+ expect(page).to have_content('my brand new description')
+ end
+
+ context 'when ref is nil' do
+ before do
+ pipeline_schedule.update_attribute(:ref, nil)
+ edit_pipeline_schedule
+ end
+
+ it 'shows the pipeline schedule with default ref' do
+ page.within('[data-testid="schedule-target-ref"]') do
+ expect(first('.gl-new-dropdown-button-text').text).to eq('master')
+ end
+ end
+ end
+
+ context 'when ref is empty' do
+ before do
+ pipeline_schedule.update_attribute(:ref, '')
+ edit_pipeline_schedule
+ end
+
+ it 'shows the pipeline schedule with default ref' do
+ page.within('[data-testid="schedule-target-ref"]') do
+ expect(first('.gl-new-dropdown-button-text').text).to eq('master')
+ end
+ end
+ end
+ end
+ end
+
+ context 'logged in as a project maintainer' do
before do
stub_feature_flags(bootstrap_confirmation_modals: false)
project.add_maintainer(user)
@@ -46,14 +116,6 @@ RSpec.describe 'Pipeline Schedules', :js do
end
end
- it 'edits the pipeline' do
- page.within('.pipeline-schedule-table-row') do
- click_link 'Edit'
- end
-
- expect(page).to have_content('Edit Pipeline Schedule')
- end
-
it 'deletes the pipeline' do
accept_confirm { click_link 'Delete' }
@@ -108,53 +170,6 @@ RSpec.describe 'Pipeline Schedules', :js do
end
end
- describe 'PATCH /projects/pipelines_schedules/:id/edit' do
- before do
- edit_pipeline_schedule
- end
-
- it 'displays existing properties' do
- description = find_field('schedule_description').value
- expect(description).to eq('pipeline schedule')
- expect(page).to have_button('master')
- expect(page).to have_button('UTC')
- end
-
- it 'edits the scheduled pipeline' do
- fill_in 'schedule_description', with: 'my brand new description'
-
- save_pipeline_schedule
-
- expect(page).to have_content('my brand new description')
- end
-
- context 'when ref is nil' do
- before do
- pipeline_schedule.update_attribute(:ref, nil)
- edit_pipeline_schedule
- end
-
- it 'shows the pipeline schedule with default ref' do
- page.within('[data-testid="schedule-target-ref"]') do
- expect(first('.gl-new-dropdown-button-text').text).to eq('master')
- end
- end
- end
-
- context 'when ref is empty' do
- before do
- pipeline_schedule.update_attribute(:ref, '')
- edit_pipeline_schedule
- end
-
- it 'shows the pipeline schedule with default ref' do
- page.within('[data-testid="schedule-target-ref"]') do
- expect(first('.gl-new-dropdown-button-text').text).to eq('master')
- end
- end
- end
- end
-
context 'when user creates a new pipeline schedule with variables' do
before do
visit_pipelines_schedules
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json
index 95f2ce45b46..ce0df4250d6 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json
@@ -4,6 +4,7 @@
"creator_id": 123,
"visibility_level": 10,
"archived": false,
+ "ci_config_path": "config/path",
"labels": [
{
"id": 2,
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/tree/project.json b/spec/fixtures/lib/gitlab/import_export/complex/tree/project.json
index 2c5045ce806..9e03e3e51a2 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/tree/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/tree/project.json
@@ -6,5 +6,6 @@
"archived": false,
"deploy_keys": [],
"hooks": [],
- "shared_runners_enabled": true
+ "shared_runners_enabled": true,
+ "ci_config_path": "config/path"
}
diff --git a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
index 240d86077c4..52b33e22089 100644
--- a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
@@ -417,4 +417,22 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
expect(created_object.project).to equal(project)
end
end
+
+ context 'merge request access level object' do
+ let(:relation_sym) { :'ProtectedBranch::MergeAccessLevel' }
+ let(:relation_hash) { { 'access_level' => 30, 'created_at' => '2022-03-29T09:53:13.457Z', 'updated_at' => '2022-03-29T09:54:13.457Z' } }
+
+ it 'sets access level to maintainer' do
+ expect(created_object.access_level).to equal(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ context 'push access level object' do
+ let(:relation_sym) { :'ProtectedBranch::PushAccessLevel' }
+ let(:relation_hash) { { 'access_level' => 30, 'created_at' => '2022-03-29T09:53:13.457Z', 'updated_at' => '2022-03-29T09:54:13.457Z' } }
+
+ it 'sets access level to maintainer' do
+ expect(created_object.access_level).to equal(Gitlab::Access::MAINTAINER)
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index fdf8260c058..a3e891db658 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -111,6 +111,10 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
end
end
+ it 'does not import ci config path' do
+ expect(@project.ci_config_path).to be_nil
+ end
+
it 'creates a valid pipeline note' do
expect(Ci::Pipeline.find_by_sha('sha-notes').notes).not_to be_empty
end
diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb
index 1e36f455f6f..f2c99e0de95 100644
--- a/spec/policies/ci/pipeline_schedule_policy_spec.rb
+++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb
@@ -84,11 +84,14 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models do
project.add_maintainer(user)
end
- it 'includes abilities to do all operations on pipeline schedule' do
+ it 'allows for playing and destroying a pipeline schedule' do
expect(policy).to be_allowed :play_pipeline_schedule
- expect(policy).to be_allowed :update_pipeline_schedule
expect(policy).to be_allowed :admin_pipeline_schedule
end
+
+ it 'does not allow for updating of an existing schedule' do
+ expect(policy).not_to be_allowed :update_pipeline_schedule
+ end
end
describe 'rules for non-owner of schedule' do
diff --git a/spec/requests/api/ci/pipeline_schedules_spec.rb b/spec/requests/api/ci/pipeline_schedules_spec.rb
index 4c8a356469d..5fb94976c5f 100644
--- a/spec/requests/api/ci/pipeline_schedules_spec.rb
+++ b/spec/requests/api/ci/pipeline_schedules_spec.rb
@@ -291,10 +291,36 @@ RSpec.describe API::Ci::PipelineSchedules do
end
context 'authenticated user with invalid permissions' do
- it 'does not update pipeline_schedule' do
- put api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", user)
+ context 'as a project maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
- expect(response).to have_gitlab_http_status(:not_found)
+ it 'does not update pipeline_schedule' do
+ put api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'as a project owner' do
+ before do
+ project.add_owner(user)
+ end
+
+ it 'does not update pipeline_schedule' do
+ put api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'with no special role' do
+ it 'does not update pipeline_schedule' do
+ put api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
@@ -312,16 +338,21 @@ RSpec.describe API::Ci::PipelineSchedules do
create(:ci_pipeline_schedule, project: project, owner: developer)
end
- context 'authenticated user with valid permissions' do
+ let(:project_maintainer) do
+ create(:user).tap { |u| project.add_maintainer(u) }
+ end
+
+ context 'as an authenticated user with valid permissions' do
it 'updates owner' do
- post api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/take_ownership", developer)
+ expect { post api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/take_ownership", project_maintainer) }
+ .to change { pipeline_schedule.reload.owner }.from(developer).to(project_maintainer)
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('pipeline_schedule')
end
end
- context 'authenticated user with invalid permissions' do
+ context 'as an authenticated user with invalid permissions' do
it 'does not update owner' do
post api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/take_ownership", user)
@@ -329,13 +360,23 @@ RSpec.describe API::Ci::PipelineSchedules do
end
end
- context 'unauthenticated user' do
+ context 'as an unauthenticated user' do
it 'does not update owner' do
post api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/take_ownership")
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
+
+ context 'as the existing owner of the schedule' do
+ it 'rejects the request and leaves the schedule unchanged' do
+ expect do
+ post api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/take_ownership", developer)
+ end.not_to change { pipeline_schedule.reload.owner }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
end
describe 'DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id' do