Commit ca1ebef6 authored by Fernando's avatar Fernando

Add empty body message to Vuln sourceed from API Fuzzing

* When body is blank, show default message

Add merge request ID to changelog

* Add ID

Add empty body message to Vuln sourceed from API Fuzzing

* When body is blank, show default message

Add merge request ID to changelog

* Add ID

Code review changes

* Refactor into helper function
* Refactor empty body message into constant

Additonal unit test refactor

* Refactor strings

Replace strings with constants

Fix bad rebase
parent 86a789cd
......@@ -9,3 +9,4 @@ export const SEVERITY_TOOLTIP_TITLE_MAP = {
};
export const VULNERABILITY_MODAL_ID = 'modal-mrwidget-security-issue';
export const EMPTY_BODY_MESSAGE = '<Message body is not provided>';
import { EMPTY_BODY_MESSAGE } from './constants';
export const bodyWithFallBack = (body) => body || EMPTY_BODY_MESSAGE;
......@@ -7,6 +7,7 @@ import SeverityBadge from './severity_badge.vue';
import getFileLocation from '../store/utils/get_file_location';
import VulnerabilityDetail from './vulnerability_detail.vue';
import { s__, sprintf } from '~/locale';
import { bodyWithFallBack } from './helpers';
export default {
name: 'VulnerabilityDetails',
......@@ -137,7 +138,7 @@ export default {
const headerLines = this.getHeadersAsCodeBlockLines(headers);
return statusCode && reasonPhrase && headerLines
? [`${statusCode} ${reasonPhrase}\n`, headerLines, '\n\n', body].join('')
? [`${statusCode} ${reasonPhrase}\n`, headerLines, '\n\n', bodyWithFallBack(body)].join('')
: '';
},
constructRequest(request) {
......@@ -145,7 +146,7 @@ export default {
const headerLines = this.getHeadersAsCodeBlockLines(headers);
return method && url && headerLines
? [`${method} ${url}\n`, headerLines, '\n\n', body].join('')
? [`${method} ${url}\n`, headerLines, '\n\n', bodyWithFallBack(body)].join('')
: '';
},
},
......
......@@ -2,6 +2,7 @@
import { GlLink, GlSprintf, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { SUPPORTING_MESSAGE_TYPES } from 'ee/vulnerabilities/constants';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import { bodyWithFallBack } from 'ee/vue_shared/security_reports/components/helpers';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import { __ } from '~/locale';
import DetailItem from './detail_item.vue';
......@@ -147,7 +148,7 @@ export default {
const headerLines = this.getHeadersAsCodeBlockLines(headers);
return statusCode && reasonPhrase && headerLines
? [`${statusCode} ${reasonPhrase}\n`, headerLines, '\n\n', body].join('')
? [`${statusCode} ${reasonPhrase}\n`, headerLines, '\n\n', bodyWithFallBack(body)].join('')
: '';
},
constructRequest(request) {
......@@ -155,7 +156,7 @@ export default {
const headerLines = this.getHeadersAsCodeBlockLines(headers);
return method && url && headerLines
? [`${method} ${url}\n`, headerLines, '\n\n', body].join('')
? [`${method} ${url}\n`, headerLines, '\n\n', bodyWithFallBack(body)].join('')
: '';
},
},
......
---
title: API Fuzzing Request/Responses show empty body message
merge_request: 50731
author:
type: changed
......@@ -5,6 +5,7 @@ import { SUPPORTING_MESSAGE_TYPES } from 'ee/vulnerabilities/constants';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import VulnerabilityDetails from 'ee/vue_shared/security_reports/components/vulnerability_details.vue';
import { TEST_HOST } from 'helpers/test_constants';
import { EMPTY_BODY_MESSAGE } from 'ee/vue_shared/security_reports/components/constants';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import { mockFindings } from '../mock_data';
......@@ -40,6 +41,8 @@ describe('VulnerabilityDetails component', () => {
const findCrashType = () => wrapper.find({ ref: 'crashType' });
const findStacktraceSnippet = () => wrapper.find({ ref: 'stacktraceSnippet' });
const USER_NOT_FOUND_MESSAGE = '{"message":"User not found."}';
afterEach(() => {
wrapper.destroy();
});
......@@ -165,7 +168,10 @@ describe('VulnerabilityDetails component', () => {
});
});
describe('with request information', () => {
describe.each([
['', EMPTY_BODY_MESSAGE],
[USER_NOT_FOUND_MESSAGE, USER_NOT_FOUND_MESSAGE],
])('with request information and body set to: %s', (body, renderedBody) => {
let vulnerability;
beforeEach(() => {
......@@ -177,6 +183,7 @@ describe('VulnerabilityDetails component', () => {
{ name: 'key1', value: 'value1' },
{ name: 'key2', value: 'value2' },
],
body,
},
});
componentFactory(vulnerability);
......@@ -192,6 +199,7 @@ describe('VulnerabilityDetails component', () => {
expect(findRequest().text()).toContain(method);
expect(findRequest().text()).toContain(url);
expect(findRequest().text()).toContain('key1: value1\nkey2: value2');
expect(findRequest().text()).toContain(renderedBody);
});
it('limits the code-blocks maximum height', () => {
......@@ -220,7 +228,10 @@ describe('VulnerabilityDetails component', () => {
});
});
describe('with response information', () => {
describe.each([
['', EMPTY_BODY_MESSAGE],
[USER_NOT_FOUND_MESSAGE, USER_NOT_FOUND_MESSAGE],
])('with response information and body set to: %s', (body, renderedBody) => {
let vulnerability;
beforeEach(() => {
......@@ -232,6 +243,7 @@ describe('VulnerabilityDetails component', () => {
{ name: 'key1', value: 'value1' },
{ name: 'key2', value: 'value2' },
],
body,
},
});
componentFactory(vulnerability);
......@@ -248,6 +260,7 @@ describe('VulnerabilityDetails component', () => {
expect(response.is(CodeBlock)).toBe(true);
expect(response.text()).toContain(reason_phrase);
expect(response.text()).toContain('key1: value1\nkey2: value2');
expect(response.text()).toContain(renderedBody);
});
});
......@@ -262,7 +275,10 @@ describe('VulnerabilityDetails component', () => {
});
});
describe('with recorded response information', () => {
describe.each([
['', EMPTY_BODY_MESSAGE],
[USER_NOT_FOUND_MESSAGE, USER_NOT_FOUND_MESSAGE],
])('with recorded response information and body set to: %s', (body, renderedBody) => {
let vulnerability;
beforeEach(() => {
......@@ -277,6 +293,7 @@ describe('VulnerabilityDetails component', () => {
{ name: 'key1', value: 'value1' },
{ name: 'key2', value: 'value2' },
],
body,
},
},
],
......@@ -284,17 +301,18 @@ describe('VulnerabilityDetails component', () => {
componentFactory(vulnerability);
});
it('renders the response status code', () => {
it('renders the recorded response status code', () => {
expect(findRecordedResponse().text()).toContain('200');
});
it('renders a code block containing the response', () => {
it('renders a code block containing the recorded response', () => {
const { reason_phrase } = vulnerability.supporting_messages[0].response;
const response = findRecordedResponse();
expect(response.is(CodeBlock)).toBe(true);
expect(response.text()).toContain(reason_phrase);
expect(response.text()).toContain('key1: value1\nkey2: value2');
expect(response.text()).toContain(renderedBody);
});
});
......
......@@ -200,18 +200,38 @@ describe('Vulnerability Details', () => {
isCode: true,
};
const EXPECT_REQUEST_WITHOUT_BODY = {
label: 'Sent request:',
content:
'GET http://www.gitlab.com\nName1: Value1\nName2: Value2\n\n<Message body is not provided>',
isCode: true,
};
const EXPECT_RESPONSE = {
label: 'Actual response:',
content: '500 INTERNAL SERVER ERROR\nName1: Value1\nName2: Value2\n\n[{"user_id":1,}]',
isCode: true,
};
const EXPECT_RESPONSE_WITHOUT_BODY = {
label: 'Actual response:',
content:
'500 INTERNAL SERVER ERROR\nName1: Value1\nName2: Value2\n\n<Message body is not provided>',
isCode: true,
};
const EXPECT_RECORDED_RESPONSE = {
label: 'Unmodified response:',
content: '200 OK\nName1: Value1\nName2: Value2\n\n[{"user_id":1,}]',
isCode: true,
};
const EXPECT_RECORDED_RESPONSE_WITHOUT_BODY = {
label: 'Unmodified response:',
content: '200 OK\nName1: Value1\nName2: Value2\n\n<Message body is not provided>',
isCode: true,
};
const getTextContent = (el) => el.textContent.trim();
const getLabel = (el) => getTextContent(getByTestId(el, 'label'));
const getContent = (el) => getTextContent(getByTestId(el, 'value'));
......@@ -238,6 +258,7 @@ describe('Vulnerability Details', () => {
${{ method: 'GET', url: 'http://www.gitlab.com' }} | ${null}
${{ method: 'GET', url: 'http://www.gitlab.com', body: '[{"user_id":1,}]' }} | ${null}
${{ headers: TEST_HEADERS, method: 'GET', url: 'http://www.gitlab.com', body: '[{"user_id":1,}]' }} | ${[EXPECT_REQUEST]}
${{ headers: TEST_HEADERS, method: 'GET', url: 'http://www.gitlab.com', body: '' }} | ${[EXPECT_REQUEST_WITHOUT_BODY]}
`('shows request data for $request', ({ request, expectedData }) => {
createWrapper({ request });
expect(getSectionData('request')).toEqual(expectedData);
......@@ -251,6 +272,7 @@ describe('Vulnerability Details', () => {
${{ headers: TEST_HEADERS, body: '[{"user_id":1,}]' }} | ${null}
${{ headers: TEST_HEADERS, body: '[{"user_id":1,}]', statusCode: '500' }} | ${null}
${{ headers: TEST_HEADERS, body: '[{"user_id":1,}]', statusCode: '500', reasonPhrase: 'INTERNAL SERVER ERROR' }} | ${[EXPECT_RESPONSE]}
${{ headers: TEST_HEADERS, body: '', statusCode: '500', reasonPhrase: 'INTERNAL SERVER ERROR' }} | ${[EXPECT_RESPONSE_WITHOUT_BODY]}
`('shows response data for $response', ({ response, expectedData }) => {
createWrapper({ response });
expect(getSectionData('response')).toEqual(expectedData);
......@@ -267,6 +289,7 @@ describe('Vulnerability Details', () => {
${[{}, { response: { headers: TEST_HEADERS, body: '[{"user_id":1,}]', status_code: '200' } }]} | ${null}
${[{}, { response: { headers: TEST_HEADERS, body: '[{"user_id":1,}]', status_code: '200', reason_phrase: 'OK' } }]} | ${null}
${[{}, { name: SUPPORTING_MESSAGE_TYPES.RECORDED, response: { headers: TEST_HEADERS, body: '[{"user_id":1,}]', statusCode: '200', reasonPhrase: 'OK' } }]} | ${[EXPECT_RECORDED_RESPONSE]}
${[{}, { name: SUPPORTING_MESSAGE_TYPES.RECORDED, response: { headers: TEST_HEADERS, body: '', statusCode: '200', reasonPhrase: 'OK' } }]} | ${[EXPECT_RECORDED_RESPONSE_WITHOUT_BODY]}
`('shows response data for $supporting_messages', ({ supportingMessages, expectedData }) => {
createWrapper({ supportingMessages });
expect(getSectionData('recorded-response')).toEqual(expectedData);
......
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