diff options
author | Grzegorz Bizon <grzegorz@gitlab.com> | 2017-12-05 08:20:31 +0000 |
---|---|---|
committer | Grzegorz Bizon <grzegorz@gitlab.com> | 2017-12-05 08:20:31 +0000 |
commit | 61392168a0265e6c54cbccc6b7529822b123ff5b (patch) | |
tree | 4e3beda0bdd89b5882be359bbcaa0fb61f88121e | |
parent | f3a3bd50eafdcfcaeea21d6cfa0b8bbae7720fec (diff) | |
parent | 387f16267ca2dae75f46d0871a34a50792d16089 (diff) | |
download | gitlab-ce-61392168a0265e6c54cbccc6b7529822b123ff5b.tar.gz |
Merge branch '40739-access-404' into 'master'
Prevent job link form rendering when user does not have permissions
Closes #40739
See merge request gitlab-org/gitlab-ce!15723
3 files changed, 66 insertions, 38 deletions
diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue index 5dea4555515..08199b4234a 100644 --- a/app/assets/javascripts/pipelines/components/graph/job_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/job_component.vue @@ -78,11 +78,13 @@ <div class="ci-job-component"> <a v-tooltip - v-if="job.status.details_path" + v-if="job.status.has_details" :href="job.status.details_path" :title="tooltipText" :class="cssClassJobName" - data-container="body"> + data-container="body" + class="js-pipeline-graph-job-link" + > <job-name-component :name="job.name" @@ -95,7 +97,8 @@ v-tooltip :title="tooltipText" :class="cssClassJobName" - data-container="body"> + data-container="body" + > <job-name-component :name="job.name" diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index b8fa1a54c24..888e290292b 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -185,6 +185,36 @@ describe 'Pipeline', :js do end end + context 'when user does not have access to read jobs' do + before do + project.update(public_builds: false) + end + + describe 'GET /:project/pipelines/:id' do + include_context 'pipeline builds' + + let(:project) { create(:project, :repository) } + let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id, user: user) } + + before do + visit project_pipeline_path(project, pipeline) + end + + it 'shows the pipeline graph' do + expect(page).to have_selector('.pipeline-visualization') + expect(page).to have_content('Build') + expect(page).to have_content('Test') + expect(page).to have_content('Deploy') + expect(page).to have_content('Retry') + expect(page).to have_content('Cancel running') + end + + it 'should not link to job' do + expect(page).not_to have_selector('.js-pipeline-graph-job-link') + end + end + end + describe 'GET /:project/pipelines/:id/builds' do include_context 'pipeline builds' diff --git a/spec/javascripts/pipelines/graph/job_component_spec.js b/spec/javascripts/pipelines/graph/job_component_spec.js index 342ee6c1242..23c87610d83 100644 --- a/spec/javascripts/pipelines/graph/job_component_spec.js +++ b/spec/javascripts/pipelines/graph/job_component_spec.js @@ -1,8 +1,10 @@ import Vue from 'vue'; import jobComponent from '~/pipelines/components/graph/job_component.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('pipeline graph job component', () => { let JobComponent; + let component; const mockJob = { id: 4256, @@ -13,6 +15,7 @@ describe('pipeline graph job component', () => { label: 'passed', group: 'success', details_path: '/root/ci-mock/builds/4256', + has_details: true, action: { icon: 'retry', title: 'Retry', @@ -26,13 +29,13 @@ describe('pipeline graph job component', () => { JobComponent = Vue.extend(jobComponent); }); + afterEach(() => { + component.$destroy(); + }); + describe('name with link', () => { it('should render the job name and status with a link', (done) => { - const component = new JobComponent({ - propsData: { - job: mockJob, - }, - }).$mount(); + component = mountComponent(JobComponent, { job: mockJob }); Vue.nextTick(() => { const link = component.$el.querySelector('a'); @@ -56,23 +59,23 @@ describe('pipeline graph job component', () => { describe('name without link', () => { it('it should render status and name', () => { - const component = new JobComponent({ - propsData: { - job: { - id: 4256, - name: 'test', - status: { - icon: 'icon_status_success', - text: 'passed', - label: 'passed', - group: 'success', - details_path: '/root/ci-mock/builds/4256', - }, + component = mountComponent(JobComponent, { + job: { + id: 4256, + name: 'test', + status: { + icon: 'icon_status_success', + text: 'passed', + label: 'passed', + group: 'success', + details_path: '/root/ci-mock/builds/4256', + has_details: false, }, }, - }).$mount(); + }); expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined(); + expect(component.$el.querySelector('a')).toBeNull(); expect( component.$el.querySelector('.ci-status-text').textContent.trim(), @@ -82,11 +85,7 @@ describe('pipeline graph job component', () => { describe('action icon', () => { it('it should render the action icon', () => { - const component = new JobComponent({ - propsData: { - job: mockJob, - }, - }).$mount(); + component = mountComponent(JobComponent, { job: mockJob }); expect(component.$el.querySelector('a.ci-action-icon-container')).toBeDefined(); expect(component.$el.querySelector('i.ci-action-icon-wrapper')).toBeDefined(); @@ -95,24 +94,20 @@ describe('pipeline graph job component', () => { describe('dropdown', () => { it('should render the dropdown action icon', () => { - const component = new JobComponent({ - propsData: { - job: mockJob, - isDropdown: true, - }, - }).$mount(); + component = mountComponent(JobComponent, { + job: mockJob, + isDropdown: true, + }); expect(component.$el.querySelector('a.ci-action-icon-wrapper')).toBeDefined(); }); }); it('should render provided class name', () => { - const component = new JobComponent({ - propsData: { - job: mockJob, - cssClassJobName: 'css-class-job-name', - }, - }).$mount(); + component = mountComponent(JobComponent, { + job: mockJob, + cssClassJobName: 'css-class-job-name', + }); expect( component.$el.querySelector('a').classList.contains('css-class-job-name'), |