Commit 7fff7fba authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Heinrich Lee Yu

Disable loading vulnerability feedback when user is unauthorized

This change prevents the application from loading vulnerability feedback
on single Merge Request page when user is unauthorized to read that
information.
parent 3a8fdfbe
...@@ -340,6 +340,7 @@ export default { ...@@ -340,6 +340,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"
......
...@@ -16,6 +16,7 @@ export default class MergeRequestStore extends CEMergeRequestStore { ...@@ -16,6 +16,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,
......
...@@ -71,6 +71,10 @@ module EE ...@@ -71,6 +71,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');
......
...@@ -248,6 +248,32 @@ RSpec.describe MergeRequestWidgetEntity do ...@@ -248,6 +248,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