Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /app/assets/javascripts/vue_shared/security_reports
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/vue_shared/security_reports')
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/constants.js3
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue26
-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
13 files changed, 268 insertions, 5 deletions
diff --git a/app/assets/javascripts/vue_shared/security_reports/constants.js b/app/assets/javascripts/vue_shared/security_reports/constants.js
new file mode 100644
index 00000000000..2f87c4e7878
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/constants.js
@@ -0,0 +1,3 @@
+export const FEEDBACK_TYPE_DISMISSAL = 'dismissal';
+export const FEEDBACK_TYPE_ISSUE = 'issue';
+export const FEEDBACK_TYPE_MERGE_REQUEST = 'merge_request';
diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
index d5696e3c8cf..89253cc7116 100644
--- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
@@ -3,6 +3,7 @@ import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import ReportSection from '~/reports/components/report_section.vue';
import { status } from '~/reports/constants';
import { s__ } from '~/locale';
+import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
import Flash from '~/flash';
import Api from '~/api';
@@ -52,12 +53,27 @@ export default {
});
},
methods: {
- checkHasSecurityReports(reportTypes) {
- return Api.pipelineJobs(this.projectId, this.pipelineId).then(({ data: jobs }) =>
- jobs.some(({ artifacts = [] }) =>
+ async checkHasSecurityReports(reportTypes) {
+ let page = 1;
+ while (page) {
+ // eslint-disable-next-line no-await-in-loop
+ const { data: jobs, headers } = await Api.pipelineJobs(this.projectId, this.pipelineId, {
+ per_page: 100,
+ page,
+ });
+
+ const hasSecurityReports = jobs.some(({ artifacts = [] }) =>
artifacts.some(({ file_type }) => reportTypes.includes(file_type)),
- ),
- );
+ );
+
+ if (hasSecurityReports) {
+ return true;
+ }
+
+ page = parseIntPagination(normalizeHeaders(headers)).nextPage;
+ }
+
+ return false;
},
activatePipelinesTab() {
if (window.mrTabs) {
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) : [],
+ };
+};