Commit 6781c46d authored by Filipa Lacerda's avatar Filipa Lacerda

Does not render modalbox footer when user has no persmissions

parent a8fe17de
...@@ -2,11 +2,7 @@ ...@@ -2,11 +2,7 @@
import $ from 'jquery'; import $ from 'jquery';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { inserted } from '~/feature_highlight/feature_highlight_helper'; import { inserted } from '~/feature_highlight/feature_highlight_helper';
import { import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover';
mouseenter,
debouncedMouseleave,
togglePopover,
} from '~/shared/popover';
export default { export default {
name: 'SecurityReportsHelpPopover', name: 'SecurityReportsHelpPopover',
...@@ -22,7 +18,8 @@ export default { ...@@ -22,7 +18,8 @@ export default {
mounted() { mounted() {
const $el = $(this.$el); const $el = $(this.$el);
$el.popover({ $el
.popover({
html: true, html: true,
trigger: 'focus', trigger: 'focus',
container: 'body', container: 'body',
......
<script> <script>
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import Modal from '~/vue_shared/components/gl_modal.vue'; import Modal from '~/vue_shared/components/gl_modal.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue'; import LoadingButton from '~/vue_shared/components/loading_button.vue';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import ExpandButton from '~/vue_shared/components/expand_button.vue'; import ExpandButton from '~/vue_shared/components/expand_button.vue';
export default { export default {
components: { components: {
Modal, Modal,
LoadingButton, LoadingButton,
...@@ -32,6 +32,12 @@ ...@@ -32,6 +32,12 @@
this.modal.vulnerability.dismissalFeedback.author this.modal.vulnerability.dismissalFeedback.author
); );
}, },
shouldHideModalFooter() {
return (
this.modal.isResolved ||
(!this.canCreateFeedbackPermission && !this.canCreateIssuePermission)
);
},
}, },
methods: { methods: {
...mapActions(['dismissIssue', 'revertDismissIssue', 'createNewIssue']), ...mapActions(['dismissIssue', 'revertDismissIssue', 'createNewIssue']),
...@@ -58,13 +64,13 @@ ...@@ -58,13 +64,13 @@
return key === 'links' && this.hasValue(field); return key === 'links' && this.hasValue(field);
}, },
}, },
}; };
</script> </script>
<template> <template>
<modal <modal
id="modal-mrwidget-security-issue" id="modal-mrwidget-security-issue"
:header-title-text="modal.title" :header-title-text="modal.title"
:class="{'modal-hide-footer': modal.isResolved}" :class="{ 'modal-hide-footer': shouldHideModalFooter }"
class="modal-security-report-dast" class="modal-security-report-dast"
> >
<slot> <slot>
...@@ -203,7 +209,7 @@ ...@@ -203,7 +209,7 @@
</div> </div>
</slot> </slot>
<div slot="footer"> <div slot="footer">
<template v-if="!modal.isResolved"> <template v-if="!modal.isResolved && (canCreateFeedbackPermission || canCreateIssuePermission)">
<button <button
type="button" type="button"
class="btn btn-default" class="btn btn-default"
...@@ -229,12 +235,13 @@ ...@@ -229,12 +235,13 @@
> >
{{ __('View issue' ) }} {{ __('View issue' ) }}
</a> </a>
<loading-button <loading-button
v-else-if="!modal.vulnerability.hasIssue && canCreateIssuePermission" v-else-if="!modal.vulnerability.hasIssue && canCreateIssuePermission"
:loading="modal.isCreatingNewIssue" :loading="modal.isCreatingNewIssue"
:disabled="modal.isCreatingNewIssue" :disabled="modal.isCreatingNewIssue"
:label="__('Create issue')" :label="__('Create issue')"
container-class="btn btn-success btn-inverted" container-class="js-create-issue-btn btn btn-success btn-inverted"
@click="createNewIssue" @click="createNewIssue"
/> />
</template> </template>
......
...@@ -20,7 +20,7 @@ describe('Security Reports modal', () => { ...@@ -20,7 +20,7 @@ describe('Security Reports modal', () => {
store.dispatch('setPipelineId', 123); store.dispatch('setPipelineId', 123);
}); });
describe('wit permissions', () => { describe('with permissions', () => {
beforeEach(() => { beforeEach(() => {
store.dispatch('setCanCreateIssuePermission', true); store.dispatch('setCanCreateIssuePermission', true);
store.dispatch('setCanCreateFeedbackPermission', true); store.dispatch('setCanCreateFeedbackPermission', true);
...@@ -126,6 +126,7 @@ describe('Security Reports modal', () => { ...@@ -126,6 +126,7 @@ describe('Security Reports modal', () => {
describe('with instances', () => { describe('with instances', () => {
beforeEach(() => { beforeEach(() => {
store.dispatch('setModalData', { store.dispatch('setModalData', {
issue: {
title: 'Absence of Anti-CSRF Tokens', title: 'Absence of Anti-CSRF Tokens',
riskcode: '1', riskcode: '1',
riskdesc: 'Low (Medium)', riskdesc: 'Low (Medium)',
...@@ -147,6 +148,8 @@ describe('Security Reports modal', () => { ...@@ -147,6 +148,8 @@ describe('Security Reports modal', () => {
], ],
description: ' No Anti-CSRF tokens were found in a HTML submission form. ', description: ' No Anti-CSRF tokens were found in a HTML submission form. ',
solution: '', solution: '',
},
status: 'failed',
}); });
vm = mountComponentWithStore(Component, { vm = mountComponentWithStore(Component, {
...@@ -169,6 +172,7 @@ describe('Security Reports modal', () => { ...@@ -169,6 +172,7 @@ describe('Security Reports modal', () => {
describe('data & create issue button', () => { describe('data & create issue button', () => {
beforeEach(() => { beforeEach(() => {
store.dispatch('setModalData', { store.dispatch('setModalData', {
issue: {
tool: 'bundler_audit', tool: 'bundler_audit',
message: 'Arbitrary file existence disclosure in Action Pack', message: 'Arbitrary file existence disclosure in Action Pack',
cve: 'CVE-2014-9999', cve: 'CVE-2014-9999',
...@@ -182,6 +186,8 @@ describe('Security Reports modal', () => { ...@@ -182,6 +186,8 @@ describe('Security Reports modal', () => {
links: [{ links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk', url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}], }],
},
status: 'failed',
}); });
vm = mountComponentWithStore(Component, { vm = mountComponentWithStore(Component, {
...@@ -248,6 +254,114 @@ describe('Security Reports modal', () => { ...@@ -248,6 +254,114 @@ describe('Security Reports modal', () => {
expect(vm.$el.querySelector('.js-dismiss-btn')).toBe(null); expect(vm.$el.querySelector('.js-dismiss-btn')).toBe(null);
expect(vm.$el.querySelector('.js-create-issue-btn')).toBe(null); expect(vm.$el.querySelector('.js-create-issue-btn')).toBe(null);
}); });
it('does not display the footer', () => {
expect(vm.$el.classList.contains('modal-hide-footer')).toEqual(true);
});
});
describe('with permission to create issue', () => {
beforeEach(() => {
store.dispatch('setCanCreateIssuePermission', true);
store.dispatch('setModalData', {
issue: {
tool: 'bundler_audit',
message: 'Arbitrary file existence disclosure in Action Pack',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
cve: 'CVE-2014-9999',
file: 'Gemfile.lock',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
isDismissed: true,
dismissalFeedback: {
id: 1,
category: 'sast',
feedback_type: 'dismissal',
issue_id: null,
author: {
name: 'John Smith',
username: 'jsmith',
web_url: 'https;//gitlab.com/user1',
},
pipeline: {
id: 123,
path: '/jsmith/awesome-project/pipelines/123',
},
},
},
status: 'failed',
});
vm = mountComponentWithStore(Component, {
store,
});
});
it('does not render dismiss button', () => {
expect(vm.$el.querySelector('.js-dismiss-btn')).toBe(null);
});
it('renders create issue button', () => {
expect(vm.$el.querySelector('.js-create-issue-btn')).not.toBe(null);
});
it('renders the footer', () => {
expect(vm.$el.classList.contains('modal-hide-footer')).toEqual(false);
});
});
describe('with permission to dismiss issue', () => {
beforeEach(() => {
store.dispatch('setCanCreateFeedbackPermission', true);
store.dispatch('setModalData', {
issue: {
tool: 'bundler_audit',
message: 'Arbitrary file existence disclosure in Action Pack',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
cve: 'CVE-2014-9999',
file: 'Gemfile.lock',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
isDismissed: true,
dismissalFeedback: {
id: 1,
category: 'sast',
feedback_type: 'dismissal',
issue_id: null,
author: {
name: 'John Smith',
username: 'jsmith',
web_url: 'https;//gitlab.com/user1',
},
pipeline: {
id: 123,
path: '/jsmith/awesome-project/pipelines/123',
},
},
},
status: 'failed',
});
vm = mountComponentWithStore(Component, {
store,
});
});
it('does not render create issue button', () => {
expect(vm.$el.querySelector('.js-create-issue-btn')).toBe(null);
});
it('renders create issue button and footer', () => {
expect(vm.$el.querySelector('.js-dismiss-btn')).not.toBe(null);
});
it('renders the footer', () => {
expect(vm.$el.classList.contains('modal-hide-footer')).toEqual(false);
});
}); });
describe('with a resolved issue', () => { describe('with a resolved issue', () => {
......
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