summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/security_reports/store
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/security_reports/store')
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js24
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js10
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js31
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js16
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js24
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js10
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js30
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js16
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/utils.js75
11 files changed, 244 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
new file mode 100644
index 00000000000..22a45341c51
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
@@ -0,0 +1,24 @@
+import * as types from './mutation_types';
+import { fetchDiffData } from '../../utils';
+
+export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
+
+export const requestDiff = ({ commit }) => commit(types.REQUEST_DIFF);
+
+export const receiveDiffSuccess = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_SUCCESS, response);
+
+export const receiveDiffError = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_ERROR, response);
+
+export const fetchDiff = ({ state, rootState, dispatch }) => {
+ dispatch('requestDiff');
+
+ return fetchDiffData(rootState, state.paths.diffEndpoint, 'sast')
+ .then(data => {
+ dispatch('receiveDiffSuccess', data);
+ })
+ .catch(() => {
+ dispatch('receiveDiffError');
+ });
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
new file mode 100644
index 00000000000..68c81bb4509
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
@@ -0,0 +1,10 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js
new file mode 100644
index 00000000000..aacec0fb679
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutation_types.js
@@ -0,0 +1,4 @@
+export const RECEIVE_DIFF_SUCCESS = 'RECEIVE_DIFF_SUCCESS';
+export const RECEIVE_DIFF_ERROR = 'RECEIVE_DIFF_ERROR';
+export const REQUEST_DIFF = 'REQUEST_DIFF';
+export const SET_DIFF_ENDPOINT = 'SET_DIFF_ENDPOINT';
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
new file mode 100644
index 00000000000..5f6153ca3b1
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import * as types from './mutation_types';
+import { parseDiff } from '../../utils';
+
+export default {
+ [types.SET_DIFF_ENDPOINT](state, path) {
+ Vue.set(state.paths, 'diffEndpoint', path);
+ },
+
+ [types.REQUEST_DIFF](state) {
+ state.isLoading = true;
+ },
+
+ [types.RECEIVE_DIFF_SUCCESS](state, { diff, enrichData }) {
+ const { added, fixed, existing } = parseDiff(diff, enrichData);
+ const baseReportOutofDate = diff.base_report_out_of_date || false;
+ const hasBaseReport = Boolean(diff.base_report_created_at);
+
+ state.isLoading = false;
+ state.newIssues = added;
+ state.resolvedIssues = fixed;
+ state.allIssues = existing;
+ state.baseReportOutofDate = baseReportOutofDate;
+ state.hasBaseReport = hasBaseReport;
+ },
+
+ [types.RECEIVE_DIFF_ERROR](state) {
+ state.isLoading = false;
+ state.hasError = true;
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js
new file mode 100644
index 00000000000..e860e3af924
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/state.js
@@ -0,0 +1,16 @@
+export default () => ({
+ paths: {
+ head: null,
+ base: null,
+ diffEndpoint: null,
+ },
+
+ isLoading: false,
+ hasError: false,
+
+ newIssues: [],
+ resolvedIssues: [],
+ allIssues: [],
+ baseReportOutofDate: false,
+ hasBaseReport: false,
+});
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
new file mode 100644
index 00000000000..c9da824613d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
@@ -0,0 +1,24 @@
+import { fetchDiffData } from '../../utils';
+import * as types from './mutation_types';
+
+export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
+
+export const requestDiff = ({ commit }) => commit(types.REQUEST_DIFF);
+
+export const receiveDiffSuccess = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_SUCCESS, response);
+
+export const receiveDiffError = ({ commit }, response) =>
+ commit(types.RECEIVE_DIFF_ERROR, response);
+
+export const fetchDiff = ({ state, rootState, dispatch }) => {
+ dispatch('requestDiff');
+
+ return fetchDiffData(rootState, state.paths.diffEndpoint, 'secret_detection')
+ .then(data => {
+ dispatch('receiveDiffSuccess', data);
+ })
+ .catch(() => {
+ dispatch('receiveDiffError');
+ });
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
new file mode 100644
index 00000000000..68c81bb4509
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
@@ -0,0 +1,10 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js
new file mode 100644
index 00000000000..aacec0fb679
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutation_types.js
@@ -0,0 +1,4 @@
+export const RECEIVE_DIFF_SUCCESS = 'RECEIVE_DIFF_SUCCESS';
+export const RECEIVE_DIFF_ERROR = 'RECEIVE_DIFF_ERROR';
+export const REQUEST_DIFF = 'REQUEST_DIFF';
+export const SET_DIFF_ENDPOINT = 'SET_DIFF_ENDPOINT';
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js
new file mode 100644
index 00000000000..ee943b0621c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/mutations.js
@@ -0,0 +1,30 @@
+import { parseDiff } from '~/vue_shared/security_reports/store/utils';
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_DIFF_ENDPOINT](state, path) {
+ state.paths.diffEndpoint = path;
+ },
+
+ [types.REQUEST_DIFF](state) {
+ state.isLoading = true;
+ },
+
+ [types.RECEIVE_DIFF_SUCCESS](state, { diff, enrichData }) {
+ const { added, fixed, existing } = parseDiff(diff, enrichData);
+ const baseReportOutofDate = diff.base_report_out_of_date || false;
+ const hasBaseReport = Boolean(diff.base_report_created_at);
+
+ state.isLoading = false;
+ state.newIssues = added;
+ state.resolvedIssues = fixed;
+ state.allIssues = existing;
+ state.baseReportOutofDate = baseReportOutofDate;
+ state.hasBaseReport = hasBaseReport;
+ },
+
+ [types.RECEIVE_DIFF_ERROR](state) {
+ state.isLoading = false;
+ state.hasError = true;
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js
new file mode 100644
index 00000000000..e860e3af924
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/state.js
@@ -0,0 +1,16 @@
+export default () => ({
+ paths: {
+ head: null,
+ base: null,
+ diffEndpoint: null,
+ },
+
+ isLoading: false,
+ hasError: false,
+
+ newIssues: [],
+ resolvedIssues: [],
+ allIssues: [],
+ baseReportOutofDate: false,
+ hasBaseReport: false,
+});
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/utils.js b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
new file mode 100644
index 00000000000..6e50efae741
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
@@ -0,0 +1,75 @@
+import pollUntilComplete from '~/lib/utils/poll_until_complete';
+import axios from '~/lib/utils/axios_utils';
+import {
+ FEEDBACK_TYPE_DISMISSAL,
+ FEEDBACK_TYPE_ISSUE,
+ FEEDBACK_TYPE_MERGE_REQUEST,
+} from '../constants';
+
+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 ?? [],
+ }));
+};
+
+/**
+ * Returns given vulnerability enriched with the corresponding
+ * feedback (`dismissal` or `issue` type)
+ * @param {Object} vulnerability
+ * @param {Array} feedback
+ */
+export const enrichVulnerabilityWithFeedback = (vulnerability, feedback = []) =>
+ feedback
+ .filter(fb => fb.project_fingerprint === vulnerability.project_fingerprint)
+ .reduce((vuln, fb) => {
+ if (fb.feedback_type === FEEDBACK_TYPE_DISMISSAL) {
+ return {
+ ...vuln,
+ isDismissed: true,
+ dismissalFeedback: fb,
+ };
+ }
+ if (fb.feedback_type === FEEDBACK_TYPE_ISSUE && fb.issue_iid) {
+ return {
+ ...vuln,
+ hasIssue: true,
+ issue_feedback: fb,
+ };
+ }
+ if (fb.feedback_type === FEEDBACK_TYPE_MERGE_REQUEST && fb.merge_request_iid) {
+ return {
+ ...vuln,
+ hasMergeRequest: true,
+ merge_request_feedback: fb,
+ };
+ }
+ return vuln;
+ }, vulnerability);
+
+/**
+ * Generates the added, fixed, and existing vulnerabilities from the API report.
+ *
+ * @param {Object} diff The original reports.
+ * @param {Object} enrichData Feedback data to add to the reports.
+ * @returns {Object}
+ */
+export const parseDiff = (diff, enrichData) => {
+ const enrichVulnerability = vulnerability => ({
+ ...enrichVulnerabilityWithFeedback(vulnerability, enrichData),
+ category: vulnerability.report_type,
+ title: vulnerability.message || vulnerability.name,
+ });
+
+ return {
+ added: diff.added ? diff.added.map(enrichVulnerability) : [],
+ fixed: diff.fixed ? diff.fixed.map(enrichVulnerability) : [],
+ existing: diff.existing ? diff.existing.map(enrichVulnerability) : [],
+ };
+};