Commit c023bbbb authored by Shinya Maeda's avatar Shinya Maeda

Fix policy by new guild line

parent 7d5351e1
...@@ -2,22 +2,24 @@ module Ci ...@@ -2,22 +2,24 @@ module Ci
class PipelineSchedulePolicy < PipelinePolicy class PipelineSchedulePolicy < PipelinePolicy
alias_method :pipeline_schedule, :subject alias_method :pipeline_schedule, :subject
def rules condition(:protected_action) do
super owned_by_developer? && owned_by_another?
if owned_by_developer? && owned_by_another?
cannot! :update_pipeline_schedule
end
end end
rule { protected_action }.prevent :update_pipeline_schedule
private private
def owned_by_developer? def owned_by_developer?
pipeline_schedule.project.team.developer?(user) return false unless @user
pipeline_schedule.project.team.developer?(@user)
end end
def owned_by_another? def owned_by_another?
!pipeline_schedule.owned_by?(user) return false unless @user
!pipeline_schedule.owned_by?(@user)
end end
end end
end end
...@@ -19,6 +19,14 @@ describe Projects::PipelineSchedulesController do ...@@ -19,6 +19,14 @@ describe Projects::PipelineSchedulesController do
expect(response).to render_template(:index) expect(response).to render_template(:index)
end end
it 'avoids N + 1 queries' do
control_count = ActiveRecord::QueryRecorder.new { visit_pipelines_schedules }.count
create_list(:ci_pipeline_schedule, 2, project: project)
expect { visit_pipelines_schedules }.not_to exceed_query_limit(control_count)
end
context 'when the scope is set to active' do context 'when the scope is set to active' do
let(:scope) { 'active' } let(:scope) { 'active' }
...@@ -158,13 +166,11 @@ describe Projects::PipelineSchedulesController do ...@@ -158,13 +166,11 @@ describe Projects::PipelineSchedulesController do
# expect(assigns(:schedule).errors['variables.key']).not_to be_empty # expect(assigns(:schedule).errors['variables.key']).not_to be_empty
# end # end
# end # end
def go
post :create, namespace_id: project.namespace.to_param, project_id: project, schedule: schedule
end
end end
describe 'security' do describe 'security' do
let(:schedule) { { description: 'aaaaaaaa', cron: '0 4 * * *', cron_timezone: 'UTC', ref: 'master', active: '1' } }
it { expect { go }.to be_allowed_for(:admin) } it { expect { go }.to be_allowed_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) } it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:master).of(project) } it { expect { go }.to be_allowed_for(:master).of(project) }
...@@ -174,14 +180,10 @@ describe Projects::PipelineSchedulesController do ...@@ -174,14 +180,10 @@ describe Projects::PipelineSchedulesController do
it { expect { go }.to be_denied_for(:user) } it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) } it { expect { go }.to be_denied_for(:external) }
it { expect { go }.to be_denied_for(:visitor) } it { expect { go }.to be_denied_for(:visitor) }
end
def go def go
post :create, namespace_id: project.namespace.to_param, post :create, namespace_id: project.namespace.to_param, project_id: project, schedule: schedule
project_id: project,
schedule: { description: 'aaaaaaaa', cron: '0 4 * * *',
cron_timezone: 'UTC', ref: 'master',
active: '1' }
end
end end
end end
...@@ -280,8 +282,8 @@ describe Projects::PipelineSchedulesController do ...@@ -280,8 +282,8 @@ describe Projects::PipelineSchedulesController do
end end
let!(:pipeline_schedule_variable) do let!(:pipeline_schedule_variable) do
create(:ci_pipeline_schedule_variable, key: 'CCC', create(:ci_pipeline_schedule_variable,
pipeline_schedule: pipeline_schedule) key: 'CCC', pipeline_schedule: pipeline_schedule)
end end
context 'when params do not include variables' do context 'when params do not include variables' do
...@@ -307,7 +309,7 @@ describe Projects::PipelineSchedulesController do ...@@ -307,7 +309,7 @@ describe Projects::PipelineSchedulesController do
context 'when adds a new variable' do context 'when adds a new variable' do
let(:schedule) do let(:schedule) do
basic_param.merge({ basic_param.merge({
variables_attributes: [ { key: 'AAA', value: 'AAA123' }] variables_attributes: [{ key: 'AAA', value: 'AAA123' }]
}) })
end end
...@@ -321,7 +323,7 @@ describe Projects::PipelineSchedulesController do ...@@ -321,7 +323,7 @@ describe Projects::PipelineSchedulesController do
context 'when updates a variable' do context 'when updates a variable' do
let(:schedule) do let(:schedule) do
basic_param.merge({ basic_param.merge({
variables_attributes: [ { id: pipeline_schedule_variable.id, value: 'new_value' } ] variables_attributes: [{ id: pipeline_schedule_variable.id, value: 'new_value' }]
}) })
end end
...@@ -337,7 +339,7 @@ describe Projects::PipelineSchedulesController do ...@@ -337,7 +339,7 @@ describe Projects::PipelineSchedulesController do
context 'when deletes a variable' do context 'when deletes a variable' do
let(:schedule) do let(:schedule) do
basic_param.merge({ basic_param.merge({
variables_attributes: [ { id: pipeline_schedule_variable.id, _destroy: true } ] variables_attributes: [{ id: pipeline_schedule_variable.id, _destroy: true }]
}) })
end end
...@@ -347,15 +349,21 @@ describe Projects::PipelineSchedulesController do ...@@ -347,15 +349,21 @@ describe Projects::PipelineSchedulesController do
end end
end end
end end
def go
put :update, namespace_id: project.namespace.to_param,
project_id: project, id: pipeline_schedule,
schedule: schedule
end
end end
describe 'security' do describe 'security' do
let(:schedule) { { description: 'updated_desc' } }
it { expect { go }.to be_allowed_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:master).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) }
it { expect { go }.to be_denied_for(:external) }
it { expect { go }.to be_denied_for(:visitor) }
context 'when a developer created a pipeline schedule' do context 'when a developer created a pipeline schedule' do
let(:developer_1) { create(:user) } let(:developer_1) { create(:user) }
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: developer_1) } let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: developer_1) }
...@@ -364,18 +372,10 @@ describe Projects::PipelineSchedulesController do ...@@ -364,18 +372,10 @@ describe Projects::PipelineSchedulesController do
project.add_developer(developer_1) project.add_developer(developer_1)
end end
context 'when the developer updates' do
it { expect { go }.to be_allowed_for(developer_1) } it { expect { go }.to be_allowed_for(developer_1) }
end
context 'when another developer updates' do
it { expect { go }.to be_denied_for(:developer).of(project) } it { expect { go }.to be_denied_for(:developer).of(project) }
end
context 'when a master updates' do
it { expect { go }.to be_allowed_for(:master).of(project) } it { expect { go }.to be_allowed_for(:master).of(project) }
end end
end
context 'when a master created a pipeline schedule' do context 'when a master created a pipeline schedule' do
let(:master_1) { create(:user) } let(:master_1) { create(:user) }
...@@ -385,28 +385,21 @@ describe Projects::PipelineSchedulesController do ...@@ -385,28 +385,21 @@ describe Projects::PipelineSchedulesController do
project.add_master(master_1) project.add_master(master_1)
end end
context 'when the master updates' do
it { expect { go }.to be_allowed_for(master_1) } it { expect { go }.to be_allowed_for(master_1) }
end
context 'when other masters updates' do
it { expect { go }.to be_allowed_for(:master).of(project) } it { expect { go }.to be_allowed_for(:master).of(project) }
end
context 'when a developer updates' do
it { expect { go }.to be_denied_for(:developer).of(project) } it { expect { go }.to be_denied_for(:developer).of(project) }
end end
end end
end
def go def go
put :update, namespace_id: project.namespace.to_param, put :update, namespace_id: project.namespace.to_param,
project_id: project, id: pipeline_schedule, project_id: project, id: pipeline_schedule,
schedule: { description: 'updated_desc' } schedule: schedule
end end
end end
describe 'GET edit' do describe 'GET #edit' do
describe 'functionality' do
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
...@@ -423,87 +416,69 @@ describe Projects::PipelineSchedulesController do ...@@ -423,87 +416,69 @@ describe Projects::PipelineSchedulesController do
end end
end end
describe 'DELETE #destroy' do
set(:user) { create(:user) }
context 'when a developer makes the request' do
before do
project.add_developer(user)
sign_in(user)
delete :destroy, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
end
it 'does not delete the pipeline schedule' do
expect(response).not_to have_http_status(:ok)
end
end
context 'when a master makes the request' do
before do
project.add_master(user)
sign_in(user)
end
it 'destroys the pipeline schedule' do
expect do
delete :destroy, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
end.to change { project.pipeline_schedules.count }.by(-1)
expect(response).to have_http_status(302)
end
end
end
describe 'security' do describe 'security' do
include AccessMatchersForController
describe 'GET edit' do
it { expect { go }.to be_allowed_for(:admin) } it { expect { go }.to be_allowed_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) } it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:master).of(project) } it { expect { go }.to be_allowed_for(:master).of(project) }
it { expect { go }.to be_allowed_for(:developer).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(:reporter).of(project) }
it { expect { go }.to be_denied_for(:guest).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(:user) }
it { expect { go }.to be_denied_for(:external) } it { expect { go }.to be_denied_for(:external) }
it { expect { go }.to be_denied_for(:visitor) } it { expect { go }.to be_denied_for(:visitor) }
end
def go def go
get :edit, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id get :edit, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
end end
end end
describe 'GET take_ownership' do describe 'GET #take_ownership' do
describe 'security' do
it { expect { go }.to be_allowed_for(:admin) } it { expect { go }.to be_allowed_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) } it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:master).of(project) } it { expect { go }.to be_allowed_for(:master).of(project) }
it { expect { go }.to be_allowed_for(:developer).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(:reporter).of(project) }
it { expect { go }.to be_denied_for(:guest).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(:user) }
it { expect { go }.to be_denied_for(:external) } it { expect { go }.to be_denied_for(:external) }
it { expect { go }.to be_denied_for(:visitor) } it { expect { go }.to be_denied_for(:visitor) }
end
def go def go
post :take_ownership, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id post :take_ownership, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
end end
end end
describe 'PUT update' do describe 'DELETE #destroy' do
it { expect { go }.to be_allowed_for(:admin) } set(:user) { create(:user) }
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:master).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) }
it { expect { go }.to be_denied_for(:external) }
it { expect { go }.to be_denied_for(:visitor) }
def go context 'when a developer makes the request' do
put :update, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id, before do
schedule: { description: 'a' } project.add_developer(user)
sign_in(user)
delete :destroy, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
end
it 'does not delete the pipeline schedule' do
expect(response).not_to have_http_status(:ok)
end
end
context 'when a master makes the request' do
before do
project.add_master(user)
sign_in(user)
end
it 'destroys the pipeline schedule' do
expect do
delete :destroy, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
end.to change { project.pipeline_schedules.count }.by(-1)
expect(response).to have_http_status(302)
end end
end end
end end
......
...@@ -19,19 +19,12 @@ feature 'Pipeline Schedules', :feature, js: true do ...@@ -19,19 +19,12 @@ feature 'Pipeline Schedules', :feature, js: true do
visit_pipelines_schedules visit_pipelines_schedules
end end
it 'avoids N + 1 queries' do
control_count = ActiveRecord::QueryRecorder.new { visit_pipelines_schedules }.count
create_list(:ci_pipeline_schedule, 2, project: project)
expect { visit_pipelines_schedules }.not_to exceed_query_limit(control_count)
end
describe 'The view' do describe 'The view' do
it 'displays the required information description' do it 'displays the required information description' do
page.within('.pipeline-schedule-table-row') do page.within('.pipeline-schedule-table-row') do
expect(page).to have_content('pipeline schedule') expect(page).to have_content('pipeline schedule')
expect(page).to have_content(pipeline_schedule.real_next_run.strftime('%b %d, %Y')) expect(find(".next-run-cell time")['data-original-title'])
.to include(pipeline_schedule.real_next_run.strftime('%b %d, %Y'))
expect(page).to have_link('master') expect(page).to have_link('master')
expect(page).to have_link("##{pipeline.id}") expect(page).to have_link("##{pipeline.id}")
end end
...@@ -62,7 +55,7 @@ feature 'Pipeline Schedules', :feature, js: true do ...@@ -62,7 +55,7 @@ feature 'Pipeline Schedules', :feature, js: true do
it 'deletes the pipeline' do it 'deletes the pipeline' do
click_link 'Delete' click_link 'Delete'
expect(page).not_to have_content('pipeline schedule') expect(page).not_to have_css(".pipeline-schedule-table-row")
end end
end end
...@@ -150,16 +143,18 @@ feature 'Pipeline Schedules', :feature, js: true do ...@@ -150,16 +143,18 @@ feature 'Pipeline Schedules', :feature, js: true do
scenario 'user sees the new variable in edit window' do scenario 'user sees the new variable in edit window' do
find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('AAA') page.within('.pipeline-variable-list') do
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('AAA123') expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('AAA')
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(2) .pipeline-variable-key-input").value).to eq('BBB') expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('AAA123')
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(2) .pipeline-variable-value-input").value).to eq('BBB123') expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-key-input").value).to eq('BBB')
expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-value-input").value).to eq('BBB123')
end
end end
end end
context 'when user edits a variable of a pipeline schedule' do context 'when user edits a variable of a pipeline schedule' do
background do background do
create(:ci_pipeline_schedule, owner: user).tap do |pipeline_schedule| create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule) create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule)
end end
visit_pipelines_schedules visit_pipelines_schedules
...@@ -171,26 +166,30 @@ feature 'Pipeline Schedules', :feature, js: true do ...@@ -171,26 +166,30 @@ feature 'Pipeline Schedules', :feature, js: true do
scenario 'user sees the updated variable in edit window' do scenario 'user sees the updated variable in edit window' do
find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('foo') page.within('.pipeline-variable-list') do
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('bar') expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('foo')
expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('bar')
end
end end
end end
context 'when user removes a variable of a pipeline schedule' do context 'when user removes a variable of a pipeline schedule' do
background do background do
create(:ci_pipeline_schedule, owner: user).tap do |pipeline_schedule| create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule) create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule)
end end
visit_pipelines_schedules visit_pipelines_schedules
find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
first('.pipeline-variable-list .pipeline-variable-row-remove-button').click find('.pipeline-variable-list .pipeline-variable-row-remove-button').click
click_button 'Save pipeline schedule' click_button 'Save pipeline schedule'
end end
scenario 'user does not see the removed variable in edit window' do scenario 'user does not see the removed variable in edit window' do
find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('') page.within('.pipeline-variable-list') do
expect(find(".pipeline-variable-list .pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('') expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('')
expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('')
end
end end
end end
......
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