Commit c7e8da7c authored by Sam Beckham's avatar Sam Beckham Committed by Phil Hughes

Adds in a URL field for DAST reports modal data

- Adds it to the dashboard
- Adds it to the MR widget
parent 64d6c3ab
import Vue from 'vue';
import { s__, __ } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import getFileLocation from 'ee/vue_shared/security_reports/store/utils/get_file_location';
import * as types from './mutation_types';
import { DAYS } from './constants';
import { isSameVulnerability } from './utils';
......@@ -99,6 +100,7 @@ export default {
operating_system: namespace,
class: className,
} = location;
const fileLocation = getFileLocation(location);
let lineSuffix = '';
......@@ -113,6 +115,8 @@ export default {
Vue.set(state.modal.data.file, 'value', file ? `${file}${lineSuffix}` : null);
Vue.set(state.modal.data.image, 'value', image);
Vue.set(state.modal.data.namespace, 'value', namespace);
Vue.set(state.modal.data.url, 'value', fileLocation);
Vue.set(state.modal.data.url, 'url', fileLocation);
}
Vue.set(state.modal.data.severity, 'value', vulnerability.severity);
......
import { s__ } from '~/locale';
import { __, s__ } from '~/locale';
export default () => ({
isLoadingVulnerabilities: true,
......@@ -25,6 +25,7 @@ export default () => ({
text: s__('Vulnerability|Project'),
isLink: true,
},
url: { text: __('URL'), isLink: true },
file: { text: s__('Vulnerability|File') },
identifiers: { text: s__('Vulnerability|Identifiers') },
severity: { text: s__('Vulnerability|Severity') },
......
......@@ -8,6 +8,7 @@ import {
parseDiff,
} from './utils';
import filterByKey from './utils/filter_by_key';
import getFileLocation from './utils/get_file_location';
import { parseSastContainer } from './utils/container_scanning';
import { visitUrl } from '~/lib/utils/url_utility';
......@@ -269,6 +270,7 @@ export default {
[types.SET_ISSUE_MODAL_DATA](state, payload) {
const { issue, status } = payload;
const fileLocation = getFileLocation(issue.location);
Vue.set(state.modal, 'title', issue.title);
Vue.set(state.modal.data.description, 'value', issue.description);
......@@ -278,6 +280,8 @@ export default {
Vue.set(state.modal.data.methodName, 'value', issue.location && issue.location.method);
Vue.set(state.modal.data.image, 'value', issue.location && issue.location.image);
Vue.set(state.modal.data.namespace, 'value', issue.location && issue.location.operating_system);
Vue.set(state.modal.data.url, 'value', fileLocation);
Vue.set(state.modal.data.url, 'url', fileLocation);
if (issue.identifiers && issue.identifiers.length > 0) {
Vue.set(state.modal.data.identifiers, 'value', issue.identifiers);
......
import { s__ } from '~/locale';
import { __, s__ } from '~/locale';
export default () => ({
blobPath: {
......@@ -68,6 +68,12 @@ export default () => ({
text: s__('ciReport|Description'),
isLink: false,
},
url: {
value: null,
url: null,
text: __('URL'),
isLink: true,
},
file: {
value: null,
url: null,
......
/**
* Parses the location object on a vulnerability to get a url
* @param {Object} location
* @returns {(String|null)} The parsed url or null if unparsable
*/
const getFileLocation = (location = {}) => {
const { hostname, path } = location;
if (typeof hostname !== 'string' || typeof path !== 'string') {
return null;
}
return `${hostname}${path}`;
};
export default getFileLocation;
---
title: Adds in a URL field for DAST reports modal data
merge_request: 20162
author:
type: changed
......@@ -369,6 +369,9 @@ describe('security reports mutations', () => {
expect(stateCopy.modal.isCreatingNewIssue).toEqual(false);
expect(stateCopy.modal.isDismissingVulnerability).toEqual(false);
expect(stateCopy.modal.data.url.value).toEqual(null);
expect(stateCopy.modal.data.url.url).toEqual(null);
expect(stateCopy.modal.title).toEqual(null);
expect(stateCopy.modal.learnMoreUrl).toEqual(null);
expect(stateCopy.modal.error).toEqual(null);
......@@ -391,6 +394,8 @@ describe('security reports mutations', () => {
method: 'do_something',
image: 'https://example.org/docker/example:v1.2.3',
operating_system: 'debian:8',
hostname: 'https://gitlab.com',
path: '/user6',
},
links: [
{
......@@ -431,6 +436,12 @@ describe('security reports mutations', () => {
expect(stateCopy.modal.data.confidence.value).toEqual(issue.confidence);
expect(stateCopy.modal.data.links.value).toEqual(issue.links);
expect(stateCopy.modal.data.instances.value).toEqual(issue.instances);
expect(stateCopy.modal.data.url.value).toEqual(
`${issue.location.hostname}${issue.location.path}`,
);
expect(stateCopy.modal.data.url.url).toEqual(
`${issue.location.hostname}${issue.location.path}`,
);
expect(stateCopy.modal.vulnerability).toEqual(issue);
expect(stateCopy.modal.isResolved).toEqual(true);
});
......
......@@ -13,6 +13,7 @@ import {
groupedReportText,
} from 'ee/vue_shared/security_reports/store/utils';
import filterByKey from 'ee/vue_shared/security_reports/store/utils/filter_by_key';
import getFileLocation from 'ee/vue_shared/security_reports/store/utils/get_file_location';
import {
formatContainerScanningDescription,
formatContainerScanningMessage,
......@@ -382,6 +383,35 @@ describe('security reports utils', () => {
});
});
describe('getFileLocation', () => {
const hostname = 'https://hostna.me';
const path = '/deeply/nested/route';
it('should return the correct location when passed both a hostname and a path', () => {
const result = getFileLocation({ hostname, path });
expect(result).toEqual(`${hostname}${path}`);
});
it('should return null if the hostname is not present', () => {
const result = getFileLocation({ path });
expect(result).toBeNull();
});
it('should return null if the path is not present', () => {
const result = getFileLocation({ hostname });
expect(result).toBeNull();
});
it('should return null if the argument is undefined', () => {
const result = getFileLocation(undefined);
expect(result).toBeNull();
});
});
describe('getUnapprovedVulnerabilities', () => {
it('return unapproved vulnerabilities', () => {
const unapproved = getUnapprovedVulnerabilities(
......
......@@ -41,7 +41,9 @@
"start_line": 29,
"end_line": 29,
"class": "com.gitlab.security_products.tests.App",
"method": "insecureCypher"
"method": "insecureCypher",
"hostname": "https://gitlab.com",
"path": "/user6"
},
"links": [
{
......
......@@ -275,6 +275,15 @@ describe('vulnerabilities module mutations', () => {
it('should set the modal vulnerability', () => {
expect(state.modal.vulnerability).toEqual(vulnerability);
});
it('should set the modal URL', () => {
const { url } = state.modal.data;
const { hostname, path } = vulnerability.location;
const expected = `${hostname}${path}`;
expect(url.value).toEqual(expected);
expect(url.url).toEqual(expected);
});
});
describe('with irregular data', () => {
......
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