Commit 3ac5fd95 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch '215570-disable-vuln-feedback-loading-on-unauthorized' into 'master'

Disable loading vulnerability feedback in MR when user is unauthorized

See merge request gitlab-org/gitlab!36172
parents 572efb63 7fff7fba
...@@ -421,6 +421,7 @@ export default { ...@@ -421,6 +421,7 @@ export default {
:container-scanning-help-path="mr.containerScanningHelp" :container-scanning-help-path="mr.containerScanningHelp"
:dependency-scanning-help-path="mr.dependencyScanningHelp" :dependency-scanning-help-path="mr.dependencyScanningHelp"
:secret-scanning-help-path="mr.secretScanningHelp" :secret-scanning-help-path="mr.secretScanningHelp"
:can-read-vulnerability-feedback="mr.canReadVulnerabilityFeedback"
:vulnerability-feedback-path="mr.vulnerabilityFeedbackPath" :vulnerability-feedback-path="mr.vulnerabilityFeedbackPath"
:vulnerability-feedback-help-path="mr.vulnerabilityFeedbackHelpPath" :vulnerability-feedback-help-path="mr.vulnerabilityFeedbackHelpPath"
:create-vulnerability-feedback-issue-path="mr.createVulnerabilityFeedbackIssuePath" :create-vulnerability-feedback-issue-path="mr.createVulnerabilityFeedbackIssuePath"
......
...@@ -17,6 +17,7 @@ export default class MergeRequestStore extends CEMergeRequestStore { ...@@ -17,6 +17,7 @@ export default class MergeRequestStore extends CEMergeRequestStore {
this.secretScanningHelp = data.secret_scanning_help_path; this.secretScanningHelp = data.secret_scanning_help_path;
this.dependencyScanningHelp = data.dependency_scanning_help_path; this.dependencyScanningHelp = data.dependency_scanning_help_path;
this.vulnerabilityFeedbackPath = data.vulnerability_feedback_path; this.vulnerabilityFeedbackPath = data.vulnerability_feedback_path;
this.canReadVulnerabilityFeedback = data.can_read_vulnerability_feedback;
this.vulnerabilityFeedbackHelpPath = data.vulnerability_feedback_help_path; this.vulnerabilityFeedbackHelpPath = data.vulnerability_feedback_help_path;
this.approvalsHelpPath = data.approvals_help_path; this.approvalsHelpPath = data.approvals_help_path;
this.codequalityHelpPath = data.codequality_help_path; this.codequalityHelpPath = data.codequality_help_path;
......
...@@ -77,6 +77,11 @@ export default { ...@@ -77,6 +77,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
canReadVulnerabilityFeedback: {
type: Boolean,
required: false,
default: false,
},
vulnerabilityFeedbackPath: { vulnerabilityFeedbackPath: {
type: String, type: String,
required: false, required: false,
...@@ -204,6 +209,7 @@ export default { ...@@ -204,6 +209,7 @@ export default {
this.setBaseBlobPath(this.baseBlobPath); this.setBaseBlobPath(this.baseBlobPath);
this.setSourceBranch(this.sourceBranch); this.setSourceBranch(this.sourceBranch);
this.setCanReadVulnerabilityFeedback(this.canReadVulnerabilityFeedback);
this.setVulnerabilityFeedbackPath(this.vulnerabilityFeedbackPath); this.setVulnerabilityFeedbackPath(this.vulnerabilityFeedbackPath);
this.setVulnerabilityFeedbackHelpPath(this.vulnerabilityFeedbackHelpPath); this.setVulnerabilityFeedbackHelpPath(this.vulnerabilityFeedbackHelpPath);
this.setCreateVulnerabilityFeedbackIssuePath(this.createVulnerabilityFeedbackIssuePath); this.setCreateVulnerabilityFeedbackIssuePath(this.createVulnerabilityFeedbackIssuePath);
...@@ -253,6 +259,7 @@ export default { ...@@ -253,6 +259,7 @@ export default {
'setHeadBlobPath', 'setHeadBlobPath',
'setBaseBlobPath', 'setBaseBlobPath',
'setSourceBranch', 'setSourceBranch',
'setCanReadVulnerabilityFeedback',
'setVulnerabilityFeedbackPath', 'setVulnerabilityFeedbackPath',
'setVulnerabilityFeedbackHelpPath', 'setVulnerabilityFeedbackHelpPath',
'setCreateVulnerabilityFeedbackIssuePath', 'setCreateVulnerabilityFeedbackIssuePath',
......
...@@ -24,6 +24,9 @@ export const setBaseBlobPath = ({ commit }, blobPath) => commit(types.SET_BASE_B ...@@ -24,6 +24,9 @@ export const setBaseBlobPath = ({ commit }, blobPath) => commit(types.SET_BASE_B
export const setSourceBranch = ({ commit }, branch) => commit(types.SET_SOURCE_BRANCH, branch); export const setSourceBranch = ({ commit }, branch) => commit(types.SET_SOURCE_BRANCH, branch);
export const setCanReadVulnerabilityFeedback = ({ commit }, value) =>
commit(types.SET_CAN_READ_VULNERABILITY_FEEDBACK, value);
export const setVulnerabilityFeedbackPath = ({ commit }, path) => export const setVulnerabilityFeedbackPath = ({ commit }, path) =>
commit(types.SET_VULNERABILITY_FEEDBACK_PATH, path); commit(types.SET_VULNERABILITY_FEEDBACK_PATH, path);
...@@ -41,6 +44,19 @@ export const setCreateVulnerabilityFeedbackDismissalPath = ({ commit }, path) => ...@@ -41,6 +44,19 @@ export const setCreateVulnerabilityFeedbackDismissalPath = ({ commit }, path) =>
export const setPipelineId = ({ commit }, id) => commit(types.SET_PIPELINE_ID, id); export const setPipelineId = ({ commit }, id) => commit(types.SET_PIPELINE_ID, id);
export const fetchDiffData = (state, endpoint, category) => {
const requests = [pollUntilComplete(endpoint)];
if (state.canReadVulnerabilityFeedback) {
requests.push(axios.get(state.vulnerabilityFeedbackPath, { params: { category } }));
}
return Promise.all(requests).then(([diffResponse, enrichResponse]) => ({
diff: diffResponse.data,
enrichData: enrichResponse?.data ?? [],
}));
};
/** /**
* CONTAINER SCANNING * CONTAINER SCANNING
*/ */
...@@ -60,19 +76,9 @@ export const receiveContainerScanningDiffError = ({ commit }) => ...@@ -60,19 +76,9 @@ export const receiveContainerScanningDiffError = ({ commit }) =>
export const fetchContainerScanningDiff = ({ state, dispatch }) => { export const fetchContainerScanningDiff = ({ state, dispatch }) => {
dispatch('requestContainerScanningDiff'); dispatch('requestContainerScanningDiff');
return Promise.all([ return fetchDiffData(state, state.containerScanning.paths.diffEndpoint, 'container_scanning')
pollUntilComplete(state.containerScanning.paths.diffEndpoint), .then(data => {
axios.get(state.vulnerabilityFeedbackPath, { dispatch('receiveContainerScanningDiffSuccess', data);
params: {
category: 'container_scanning',
},
}),
])
.then(values => {
dispatch('receiveContainerScanningDiffSuccess', {
diff: values[0].data,
enrichData: values[1].data,
});
}) })
.catch(() => { .catch(() => {
dispatch('receiveContainerScanningDiffError'); dispatch('receiveContainerScanningDiffError');
...@@ -99,19 +105,9 @@ export const receiveDastDiffError = ({ commit }) => commit(types.RECEIVE_DAST_DI ...@@ -99,19 +105,9 @@ export const receiveDastDiffError = ({ commit }) => commit(types.RECEIVE_DAST_DI
export const fetchDastDiff = ({ state, dispatch }) => { export const fetchDastDiff = ({ state, dispatch }) => {
dispatch('requestDastDiff'); dispatch('requestDastDiff');
return Promise.all([ return fetchDiffData(state, state.dast.paths.diffEndpoint, 'dast')
pollUntilComplete(state.dast.paths.diffEndpoint), .then(data => {
axios.get(state.vulnerabilityFeedbackPath, { dispatch('receiveDastDiffSuccess', data);
params: {
category: 'dast',
},
}),
])
.then(values => {
dispatch('receiveDastDiffSuccess', {
diff: values[0].data,
enrichData: values[1].data,
});
}) })
.catch(() => { .catch(() => {
dispatch('receiveDastDiffError'); dispatch('receiveDastDiffError');
...@@ -137,19 +133,9 @@ export const receiveDependencyScanningDiffError = ({ commit }) => ...@@ -137,19 +133,9 @@ export const receiveDependencyScanningDiffError = ({ commit }) =>
export const fetchDependencyScanningDiff = ({ state, dispatch }) => { export const fetchDependencyScanningDiff = ({ state, dispatch }) => {
dispatch('requestDependencyScanningDiff'); dispatch('requestDependencyScanningDiff');
return Promise.all([ return fetchDiffData(state, state.dependencyScanning.paths.diffEndpoint, 'dependency_scanning')
pollUntilComplete(state.dependencyScanning.paths.diffEndpoint), .then(data => {
axios.get(state.vulnerabilityFeedbackPath, { dispatch('receiveDependencyScanningDiffSuccess', data);
params: {
category: 'dependency_scanning',
},
}),
])
.then(values => {
dispatch('receiveDependencyScanningDiffSuccess', {
diff: values[0].data,
enrichData: values[1].data,
});
}) })
.catch(() => { .catch(() => {
dispatch('receiveDependencyScanningDiffError'); dispatch('receiveDependencyScanningDiffError');
...@@ -177,19 +163,9 @@ export const receiveSecretScanningDiffError = ({ commit }) => ...@@ -177,19 +163,9 @@ export const receiveSecretScanningDiffError = ({ commit }) =>
export const fetchSecretScanningDiff = ({ state, dispatch }) => { export const fetchSecretScanningDiff = ({ state, dispatch }) => {
dispatch('requestSecretScanningDiff'); dispatch('requestSecretScanningDiff');
return Promise.all([ return fetchDiffData(state, state.secretScanning.paths.diffEndpoint, 'secret_scanning')
pollUntilComplete(state.secretScanning.paths.diffEndpoint), .then(data => {
axios.get(state.vulnerabilityFeedbackPath, { dispatch('receiveSecretScanningDiffSuccess', data);
params: {
category: 'secret_scanning',
},
}),
])
.then(values => {
dispatch('receiveSecretScanningDiffSuccess', {
diff: values[0].data,
enrichData: values[1].data,
});
}) })
.catch(() => { .catch(() => {
dispatch('receiveSecretScanningDiffError'); dispatch('receiveSecretScanningDiffError');
......
import axios from '~/lib/utils/axios_utils';
import pollUntilComplete from '~/lib/utils/poll_until_complete';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { fetchDiffData } from '../../actions';
export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path); export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
...@@ -18,19 +17,9 @@ export const receiveDiffError = ({ commit }, response) => ...@@ -18,19 +17,9 @@ export const receiveDiffError = ({ commit }, response) =>
export const fetchDiff = ({ state, rootState, dispatch }) => { export const fetchDiff = ({ state, rootState, dispatch }) => {
dispatch('requestDiff'); dispatch('requestDiff');
return Promise.all([ return fetchDiffData(rootState, state.paths.diffEndpoint, 'sast')
pollUntilComplete(state.paths.diffEndpoint), .then(data => {
axios.get(rootState.vulnerabilityFeedbackPath, { dispatch('receiveDiffSuccess', data);
params: {
category: 'sast',
},
}),
])
.then(values => {
dispatch('receiveDiffSuccess', {
diff: values[0].data,
enrichData: values[1].data,
});
}) })
.catch(() => { .catch(() => {
dispatch('receiveDiffError'); dispatch('receiveDiffError');
......
export const SET_HEAD_BLOB_PATH = 'SET_HEAD_BLOB_PATH'; export const SET_HEAD_BLOB_PATH = 'SET_HEAD_BLOB_PATH';
export const SET_BASE_BLOB_PATH = 'SET_BASE_BLOB_PATH'; export const SET_BASE_BLOB_PATH = 'SET_BASE_BLOB_PATH';
export const SET_SOURCE_BRANCH = 'SET_SOURCE_BRANCH'; export const SET_SOURCE_BRANCH = 'SET_SOURCE_BRANCH';
export const SET_CAN_READ_VULNERABILITY_FEEDBACK = 'SET_CAN_READ_VULNERABILITY_FEEDBACK';
export const SET_VULNERABILITY_FEEDBACK_PATH = 'SET_VULNERABILITY_FEEDBACK_PATH'; export const SET_VULNERABILITY_FEEDBACK_PATH = 'SET_VULNERABILITY_FEEDBACK_PATH';
export const SET_VULNERABILITY_FEEDBACK_HELP_PATH = 'SET_VULNERABILITY_FEEDBACK_HELP_PATH'; export const SET_VULNERABILITY_FEEDBACK_HELP_PATH = 'SET_VULNERABILITY_FEEDBACK_HELP_PATH';
export const SET_CREATE_VULNERABILITY_FEEDBACK_ISSUE_PATH = export const SET_CREATE_VULNERABILITY_FEEDBACK_ISSUE_PATH =
......
...@@ -16,6 +16,10 @@ export default { ...@@ -16,6 +16,10 @@ export default {
state.sourceBranch = branch; state.sourceBranch = branch;
}, },
[types.SET_CAN_READ_VULNERABILITY_FEEDBACK](state, value) {
state.canReadVulnerabilityFeedback = value;
},
[types.SET_VULNERABILITY_FEEDBACK_PATH](state, path) { [types.SET_VULNERABILITY_FEEDBACK_PATH](state, path) {
state.vulnerabilityFeedbackPath = path; state.vulnerabilityFeedbackPath = path;
}, },
......
...@@ -5,6 +5,7 @@ export default () => ({ ...@@ -5,6 +5,7 @@ export default () => ({
}, },
sourceBranch: null, sourceBranch: null,
canReadVulnerabilityFeedback: false,
vulnerabilityFeedbackPath: null, vulnerabilityFeedbackPath: null,
vulnerabilityFeedbackHelpPath: null, vulnerabilityFeedbackHelpPath: null,
createVulnerabilityFeedbackIssuePath: null, createVulnerabilityFeedbackIssuePath: null,
......
...@@ -81,6 +81,10 @@ module EE ...@@ -81,6 +81,10 @@ module EE
merge_request.head_pipeline.id merge_request.head_pipeline.id
end end
expose :can_read_vulnerability_feedback do |merge_request|
can?(current_user, :read_vulnerability_feedback, merge_request.project)
end
expose :vulnerability_feedback_path do |merge_request| expose :vulnerability_feedback_path do |merge_request|
project_vulnerability_feedback_index_path(merge_request.project) project_vulnerability_feedback_index_path(merge_request.project)
end end
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
} }
}, },
"pipeline_id": { "type": "integer" }, "pipeline_id": { "type": "integer" },
"can_read_vulnerability_feedback": { "type": "boolean" },
"vulnerability_feedback_path": { "type": "string" }, "vulnerability_feedback_path": { "type": "string" },
"create_vulnerability_feedback_issue_path": { "type": "string" }, "create_vulnerability_feedback_issue_path": { "type": "string" },
"create_vulnerability_feedback_merge_request_path": { "type": "string" }, "create_vulnerability_feedback_merge_request_path": { "type": "string" },
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
"api_approve_path": { "type": ["string", "null"] }, "api_approve_path": { "type": ["string", "null"] },
"api_unapprove_path": { "type": ["string", "null"] }, "api_unapprove_path": { "type": ["string", "null"] },
"vulnerability_feedback_path": { "type": "string" }, "vulnerability_feedback_path": { "type": "string" },
"can_read_vulnerability_feedback": { "type": "boolean" },
"create_vulnerability_feedback_issue_path": { "type": ["string", "null"] }, "create_vulnerability_feedback_issue_path": { "type": ["string", "null"] },
"create_vulnerability_feedback_merge_request_path": { "type": ["string", "null"] }, "create_vulnerability_feedback_merge_request_path": { "type": ["string", "null"] },
"create_vulnerability_feedback_dismissal_path": { "type": ["string", "null"] } "create_vulnerability_feedback_dismissal_path": { "type": ["string", "null"] }
......
...@@ -45,6 +45,7 @@ describe('Grouped security reports app', () => { ...@@ -45,6 +45,7 @@ describe('Grouped security reports app', () => {
dastHelpPath: 'path', dastHelpPath: 'path',
dependencyScanningHelpPath: 'path', dependencyScanningHelpPath: 'path',
secretScanningHelpPath: 'path', secretScanningHelpPath: 'path',
canReadVulnerabilityFeedbackPath: true,
vulnerabilityFeedbackPath: 'vulnerability_feedback_path.json', vulnerabilityFeedbackPath: 'vulnerability_feedback_path.json',
vulnerabilityFeedbackHelpPath: 'path', vulnerabilityFeedbackHelpPath: 'path',
pipelineId: 123, pipelineId: 123,
......
...@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import { import {
setHeadBlobPath, setHeadBlobPath,
setBaseBlobPath, setBaseBlobPath,
setCanReadVulnerabilityFeedback,
setVulnerabilityFeedbackPath, setVulnerabilityFeedbackPath,
setVulnerabilityFeedbackHelpPath, setVulnerabilityFeedbackHelpPath,
setPipelineId, setPipelineId,
...@@ -148,6 +149,24 @@ describe('security reports actions', () => { ...@@ -148,6 +149,24 @@ describe('security reports actions', () => {
}); });
}); });
describe('setCanReadVulnerabilityFeedback', () => {
it('should commit set vulnerabulity feedback path', done => {
testAction(
setCanReadVulnerabilityFeedback,
true,
mockedState,
[
{
type: types.SET_CAN_READ_VULNERABILITY_FEEDBACK,
payload: true,
},
],
[],
done,
);
});
});
describe('setVulnerabilityFeedbackPath', () => { describe('setVulnerabilityFeedbackPath', () => {
it('should commit set vulnerabulity feedback path', done => { it('should commit set vulnerabulity feedback path', done => {
testAction( testAction(
...@@ -414,6 +433,7 @@ describe('security reports actions', () => { ...@@ -414,6 +433,7 @@ describe('security reports actions', () => {
it('with error should dispatch `receiveDismissVulnerabilityError`', done => { it('with error should dispatch `receiveDismissVulnerabilityError`', done => {
mock.onPost('dismiss_vulnerability_path').reply(500, {}); mock.onPost('dismiss_vulnerability_path').reply(500, {});
mockedState.vulnerabilityFeedbackPath = 'dismiss_vulnerability_path'; mockedState.vulnerabilityFeedbackPath = 'dismiss_vulnerability_path';
mockedState.canReadVulnerabilityFeedback = true;
testAction( testAction(
dismissVulnerability, dismissVulnerability,
...@@ -852,6 +872,7 @@ describe('security reports actions', () => { ...@@ -852,6 +872,7 @@ describe('security reports actions', () => {
it('with error should dispatch `receiveCreateIssueError`', done => { it('with error should dispatch `receiveCreateIssueError`', done => {
mock.onPost('create_issue_path').reply(500, {}); mock.onPost('create_issue_path').reply(500, {});
mockedState.vulnerabilityFeedbackPath = 'create_issue_path'; mockedState.vulnerabilityFeedbackPath = 'create_issue_path';
mockedState.canReadVulnerabilityFeedback = true;
testAction( testAction(
createNewIssue, createNewIssue,
...@@ -980,6 +1001,7 @@ describe('security reports actions', () => { ...@@ -980,6 +1001,7 @@ describe('security reports actions', () => {
it('with error should dispatch `receiveCreateMergeRequestError`', done => { it('with error should dispatch `receiveCreateMergeRequestError`', done => {
mock.onPost('create_merge_request_path').reply(500, {}); mock.onPost('create_merge_request_path').reply(500, {});
mockedState.vulnerabilityFeedbackPath = 'create_merge_request_path'; mockedState.vulnerabilityFeedbackPath = 'create_merge_request_path';
mockedState.canReadVulnerabilityFeedback = true;
testAction( testAction(
createMergeRequest, createMergeRequest,
...@@ -1143,6 +1165,7 @@ describe('security reports actions', () => { ...@@ -1143,6 +1165,7 @@ describe('security reports actions', () => {
beforeEach(() => { beforeEach(() => {
mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback'; mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback';
mockedState.canReadVulnerabilityFeedback = true;
mockedState.containerScanning.paths.diffEndpoint = endpoint; mockedState.containerScanning.paths.diffEndpoint = endpoint;
}); });
...@@ -1179,6 +1202,35 @@ describe('security reports actions', () => { ...@@ -1179,6 +1202,35 @@ describe('security reports actions', () => {
}); });
}); });
describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
beforeEach(() => {
mockedState.canReadVulnerabilityFeedback = false;
mock.onGet(endpoint).reply(200, diff);
});
it('should dispatch `receiveContainerScanningDiffSuccess`', done => {
testAction(
fetchContainerScanningDiff,
null,
mockedState,
[],
[
{
type: 'requestContainerScanningDiff',
},
{
type: 'receiveContainerScanningDiffSuccess',
payload: {
diff,
enrichData: [],
},
},
],
done,
);
});
});
describe('when vulnerabilities path errors', () => { describe('when vulnerabilities path errors', () => {
it('should dispatch `receiveContainerScanningError`', done => { it('should dispatch `receiveContainerScanningError`', done => {
mock.onGet(endpoint).reply(500); mock.onGet(endpoint).reply(500);
...@@ -1300,6 +1352,7 @@ describe('security reports actions', () => { ...@@ -1300,6 +1352,7 @@ describe('security reports actions', () => {
beforeEach(() => { beforeEach(() => {
mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback'; mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback';
mockedState.canReadVulnerabilityFeedback = true;
mockedState.dependencyScanning.paths.diffEndpoint = 'dependency_scanning_diff.json'; mockedState.dependencyScanning.paths.diffEndpoint = 'dependency_scanning_diff.json';
}); });
...@@ -1336,6 +1389,35 @@ describe('security reports actions', () => { ...@@ -1336,6 +1389,35 @@ describe('security reports actions', () => {
}); });
}); });
describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
beforeEach(() => {
mockedState.canReadVulnerabilityFeedback = false;
mock.onGet('dependency_scanning_diff.json').reply(200, diff);
});
it('should dispatch `receiveDependencyScanningDiffSuccess`', done => {
testAction(
fetchDependencyScanningDiff,
null,
mockedState,
[],
[
{
type: 'requestDependencyScanningDiff',
},
{
type: 'receiveDependencyScanningDiffSuccess',
payload: {
diff,
enrichData: [],
},
},
],
done,
);
});
});
describe('when vulnerabilities path errors', () => { describe('when vulnerabilities path errors', () => {
it('should dispatch `receiveDependencyScanningError`', done => { it('should dispatch `receiveDependencyScanningError`', done => {
mock.onGet('dependency_scanning_diff.json').reply(500); mock.onGet('dependency_scanning_diff.json').reply(500);
...@@ -1457,6 +1539,7 @@ describe('security reports actions', () => { ...@@ -1457,6 +1539,7 @@ describe('security reports actions', () => {
beforeEach(() => { beforeEach(() => {
mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback'; mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback';
mockedState.canReadVulnerabilityFeedback = true;
mockedState.dast.paths.diffEndpoint = 'dast_diff.json'; mockedState.dast.paths.diffEndpoint = 'dast_diff.json';
}); });
...@@ -1493,6 +1576,35 @@ describe('security reports actions', () => { ...@@ -1493,6 +1576,35 @@ describe('security reports actions', () => {
}); });
}); });
describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
beforeEach(() => {
mockedState.canReadVulnerabilityFeedback = false;
mock.onGet('dast_diff.json').reply(200, diff);
});
it('should dispatch `receiveDastDiffSuccess`', done => {
testAction(
fetchDastDiff,
null,
mockedState,
[],
[
{
type: 'requestDastDiff',
},
{
type: 'receiveDastDiffSuccess',
payload: {
diff,
enrichData: [],
},
},
],
done,
);
});
});
describe('when vulnerabilities path errors', () => { describe('when vulnerabilities path errors', () => {
it('should dispatch `receiveDastError`', done => { it('should dispatch `receiveDastError`', done => {
mock.onGet('dast_diff.json').reply(500); mock.onGet('dast_diff.json').reply(500);
...@@ -1615,6 +1727,7 @@ describe('security reports actions', () => { ...@@ -1615,6 +1727,7 @@ describe('security reports actions', () => {
beforeEach(() => { beforeEach(() => {
mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback'; mockedState.vulnerabilityFeedbackPath = 'vulnerabilities_feedback';
mockedState.canReadVulnerabilityFeedback = true;
mockedState.secretScanning.paths.diffEndpoint = endpoint; mockedState.secretScanning.paths.diffEndpoint = endpoint;
}); });
...@@ -1651,6 +1764,35 @@ describe('security reports actions', () => { ...@@ -1651,6 +1764,35 @@ describe('security reports actions', () => {
}); });
}); });
describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
beforeEach(() => {
mockedState.canReadVulnerabilityFeedback = false;
mock.onGet(endpoint).reply(200, diff);
});
it('should dispatch `secret_scanning`', done => {
testAction(
fetchSecretScanningDiff,
null,
mockedState,
[],
[
{
type: 'requestSecretScanningDiff',
},
{
type: 'receiveSecretScanningDiffSuccess',
payload: {
diff,
enrichData: [],
},
},
],
done,
);
});
});
describe('when vulnerabilities path errors', () => { describe('when vulnerabilities path errors', () => {
it('should dispatch `receiveSecretScanningError`', done => { it('should dispatch `receiveSecretScanningError`', done => {
mock.onGet(endpoint).reply(500); mock.onGet(endpoint).reply(500);
......
...@@ -92,6 +92,7 @@ describe('sast report actions', () => { ...@@ -92,6 +92,7 @@ describe('sast report actions', () => {
beforeEach(() => { beforeEach(() => {
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
state.paths.diffEndpoint = diffEndpoint; state.paths.diffEndpoint = diffEndpoint;
rootState.canReadVulnerabilityFeedback = true;
}); });
afterEach(() => { afterEach(() => {
...@@ -129,6 +130,35 @@ describe('sast report actions', () => { ...@@ -129,6 +130,35 @@ describe('sast report actions', () => {
}); });
}); });
describe('when diff endpoint responds successfully and fetching vulnerability feedback is not authorized', () => {
beforeEach(() => {
rootState.canReadVulnerabilityFeedback = false;
mock.onGet(diffEndpoint).replyOnce(200, reports.diff);
});
it('should dispatch the `receiveDiffSuccess` action with empty enrich data', done => {
const { diff } = reports;
const enrichData = [];
testAction(
actions.fetchDiff,
{},
{ ...rootState, ...state },
[],
[
{ type: 'requestDiff' },
{
type: 'receiveDiffSuccess',
payload: {
diff,
enrichData,
},
},
],
done,
);
});
});
describe('when the vulnerability feedback endpoint fails', () => { describe('when the vulnerability feedback endpoint fails', () => {
beforeEach(() => { beforeEach(() => {
mock mock
......
...@@ -31,6 +31,14 @@ describe('security reports mutations', () => { ...@@ -31,6 +31,14 @@ describe('security reports mutations', () => {
}); });
}); });
describe('SET_CAN_READ_VULNERABILITY_FEEDBACK', () => {
it('should set the vulnerabilities endpoint', () => {
mutations[types.SET_CAN_READ_VULNERABILITY_FEEDBACK](stateCopy, false);
expect(stateCopy.canReadVulnerabilityFeedback).toEqual(false);
});
});
describe('SET_VULNERABILITY_FEEDBACK_PATH', () => { describe('SET_VULNERABILITY_FEEDBACK_PATH', () => {
it('should set the vulnerabilities endpoint', () => { it('should set the vulnerabilities endpoint', () => {
mutations[types.SET_VULNERABILITY_FEEDBACK_PATH](stateCopy, 'vulnerability_path'); mutations[types.SET_VULNERABILITY_FEEDBACK_PATH](stateCopy, 'vulnerability_path');
......
...@@ -252,6 +252,32 @@ RSpec.describe MergeRequestWidgetEntity do ...@@ -252,6 +252,32 @@ RSpec.describe MergeRequestWidgetEntity do
expect(subject.as_json).to include(:create_vulnerability_feedback_dismissal_path) expect(subject.as_json).to include(:create_vulnerability_feedback_dismissal_path)
end end
describe '#can_read_vulnerability_feedback' do
context 'when user has permissions to read vulnerability feedback' do
before do
project.add_developer(user)
end
it 'is set to true' do
expect(subject.as_json[:can_read_vulnerability_feedback]).to eq(true)
end
end
context 'when user has no permissions to read vulnerability feedback' do
before do
project.add_guest(user)
end
it 'is set to false' do
expect(subject.as_json[:can_read_vulnerability_feedback]).to eq(false)
end
end
end
it 'has can_read_vulnerability_feedback property' do
expect(subject.as_json).to include(:can_read_vulnerability_feedback)
end
it 'has pipeline id' do it 'has pipeline id' do
allow(merge_request).to receive(:head_pipeline).and_return(pipeline) allow(merge_request).to receive(:head_pipeline).and_return(pipeline)
......
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