Commit 96c35ddb authored by Kushal Pandya's avatar Kushal Pandya

Merge branch...

Merge branch '33467-display-location-instead-of-project-name-in-the-security-project-dashboard' into 'master'

Display location in the Security Project Dashboard

Closes #33467

See merge request gitlab-org/gitlab!22376
parents 257ec0f3 4ccf6f1b
---
title: Display location in the Security Project Dashboard
merge_request: 22376
author:
type: other
import initSecurityDashboard from 'ee/security_dashboard/index'; import initSecurityDashboard from 'ee/security_dashboard/index';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initSecurityDashboard(); initSecurityDashboard(DASHBOARD_TYPES.GROUP);
}); });
<script> <script>
import { mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { GlButton, GlSkeletonLoading } from '@gitlab/ui'; import { GlButton, GlSkeletonLoading } from '@gitlab/ui';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue'; import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import VulnerabilityActionButtons from './vulnerability_action_buttons.vue'; import VulnerabilityActionButtons from './vulnerability_action_buttons.vue';
import VulnerabilityIssueLink from './vulnerability_issue_link.vue'; import VulnerabilityIssueLink from './vulnerability_issue_link.vue';
import { DASHBOARD_TYPES } from '../store/constants';
export default { export default {
name: 'SecurityDashboardTableRow', name: 'SecurityDashboardTableRow',
...@@ -35,9 +36,12 @@ export default { ...@@ -35,9 +36,12 @@ export default {
severity() { severity() {
return this.vulnerability.severity || ' '; return this.vulnerability.severity || ' ';
}, },
projectFullName() { vulnerabilityNamepace() {
const { project } = this.vulnerability; const { project, location } = this.vulnerability;
return project && project.full_name; if (this.dashboardType === DASHBOARD_TYPES.GROUP) {
return project && project.full_name;
}
return location && (location.image || location.file || location.path);
}, },
isDismissed() { isDismissed() {
return Boolean(this.vulnerability.dismissal_feedback); return Boolean(this.vulnerability.dismissal_feedback);
...@@ -55,6 +59,7 @@ export default { ...@@ -55,6 +59,7 @@ export default {
const path = this.vulnerability.create_vulnerability_feedback_issue_path; const path = this.vulnerability.create_vulnerability_feedback_issue_path;
return Boolean(path) && !this.hasIssue; return Boolean(path) && !this.hasIssue;
}, },
...mapState(['dashboardType']),
}, },
methods: { methods: {
...mapActions('vulnerabilities', ['openModal']), ...mapActions('vulnerabilities', ['openModal']),
...@@ -105,8 +110,8 @@ export default { ...@@ -105,8 +110,8 @@ export default {
:project-name="vulnerability.project.name" :project-name="vulnerability.project.name"
/> />
<br /> <br />
<span v-if="projectFullName" class="vulnerability-namespace"> <span v-if="vulnerabilityNamepace" class="vulnerability-namespace">
{{ projectFullName }} {{ vulnerabilityNamepace }}
</span> </span>
</template> </template>
</div> </div>
......
...@@ -6,7 +6,7 @@ import createRouter from './store/router'; ...@@ -6,7 +6,7 @@ import createRouter from './store/router';
import projectsPlugin from './store/plugins/projects'; import projectsPlugin from './store/plugins/projects';
import syncWithRouter from './store/plugins/sync_with_router'; import syncWithRouter from './store/plugins/sync_with_router';
export default function() { export default function(dashboardType) {
const el = document.getElementById('js-group-security-dashboard'); const el = document.getElementById('js-group-security-dashboard');
const { isUnavailable, dashboardDocumentation, emptyStateSvgPath } = el.dataset; const { isUnavailable, dashboardDocumentation, emptyStateSvgPath } = el.dataset;
...@@ -25,7 +25,10 @@ export default function() { ...@@ -25,7 +25,10 @@ export default function() {
} }
const router = createRouter(); const router = createRouter();
const store = createStore({ plugins: [projectsPlugin, syncWithRouter(router)] }); const store = createStore({
dashboardType,
plugins: [projectsPlugin, syncWithRouter(router)],
});
return new Vue({ return new Vue({
el, el,
store, store,
......
...@@ -28,3 +28,10 @@ export const REPORT_TYPES = { ...@@ -28,3 +28,10 @@ export const REPORT_TYPES = {
dependency_scanning: s__('ciReport|Dependency Scanning'), dependency_scanning: s__('ciReport|Dependency Scanning'),
sast: s__('ciReport|SAST'), sast: s__('ciReport|SAST'),
}; };
export const DASHBOARD_TYPES = {
PROJECT: 'project',
PIPELINE: 'pipeline',
GROUP: 'group',
INSTANCE: 'instance',
};
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { DASHBOARD_TYPES } from './constants';
import mediator from './plugins/mediator'; import mediator from './plugins/mediator';
import filters from './modules/filters/index'; import filters from './modules/filters/index';
...@@ -8,8 +10,11 @@ import vulnerableProjects from './modules/vulnerable_projects/index'; ...@@ -8,8 +10,11 @@ import vulnerableProjects from './modules/vulnerable_projects/index';
Vue.use(Vuex); Vue.use(Vuex);
export default ({ plugins = [] } = {}) => export default ({ dashboardType = DASHBOARD_TYPES.PROJECT, plugins = [] } = {}) =>
new Vuex.Store({ new Vuex.Store({
state: () => ({
dashboardType,
}),
modules: { modules: {
vulnerableProjects, vulnerableProjects,
filters, filters,
......
...@@ -163,7 +163,7 @@ exports[`DependenciesTableRow component when a dependency with vulnerabilities i ...@@ -163,7 +163,7 @@ exports[`DependenciesTableRow component when a dependency with vulnerabilities i
size="16" size="16"
/> />
7 vulnerabilities 8 vulnerabilities
</gl-button-stub> </gl-button-stub>
</div> </div>
......
...@@ -3,11 +3,12 @@ import component from 'ee/security_dashboard/components/security_dashboard_table ...@@ -3,11 +3,12 @@ import component from 'ee/security_dashboard/components/security_dashboard_table
import createStore from 'ee/security_dashboard/store'; import createStore from 'ee/security_dashboard/store';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import mockDataVulnerabilities from '../store/vulnerabilities/data/mock_data_vulnerabilities.json'; import mockDataVulnerabilities from '../store/vulnerabilities/data/mock_data_vulnerabilities.json';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
describe('Security Dashboard Table Row', () => { describe('Security Dashboard Table Row', () => {
let vm; let vm;
let props; let props;
const store = createStore(); let store = createStore();
const Component = Vue.extend(component); const Component = Vue.extend(component);
describe('when loading', () => { describe('when loading', () => {
...@@ -40,7 +41,7 @@ describe('Security Dashboard Table Row', () => { ...@@ -40,7 +41,7 @@ describe('Security Dashboard Table Row', () => {
}); });
describe('when loaded', () => { describe('when loaded', () => {
const vulnerability = mockDataVulnerabilities[0]; let vulnerability = mockDataVulnerabilities[0];
beforeEach(() => { beforeEach(() => {
props = { vulnerability }; props = { vulnerability };
...@@ -76,7 +77,7 @@ describe('Security Dashboard Table Row', () => { ...@@ -76,7 +77,7 @@ describe('Security Dashboard Table Row', () => {
it('should render the project namespace', () => { it('should render the project namespace', () => {
expect(vm.$el.querySelectorAll('.table-mobile-content')[2].textContent).toContain( expect(vm.$el.querySelectorAll('.table-mobile-content')[2].textContent).toContain(
props.vulnerability.project.full_name, props.vulnerability.location.file,
); );
}); });
...@@ -90,6 +91,46 @@ describe('Security Dashboard Table Row', () => { ...@@ -90,6 +91,46 @@ describe('Security Dashboard Table Row', () => {
}); });
}); });
}); });
describe('Group Security Dashboard', () => {
beforeEach(() => {
store = createStore({
dashboardType: DASHBOARD_TYPES.GROUP,
});
props = { vulnerability };
vm = mountComponentWithStore(Component, { store, props });
});
afterEach(() => {
vm.$destroy();
});
it('should contain project name as the namespace', () => {
expect(vm.$el.querySelectorAll('.table-mobile-content')[2].textContent).toContain(
props.vulnerability.project.full_name,
);
});
});
describe('Non-group Security Dashboard', () => {
beforeEach(() => {
store = createStore();
// eslint-disable-next-line prefer-destructuring
vulnerability = mockDataVulnerabilities[7];
props = { vulnerability };
vm = mountComponentWithStore(Component, { store, props });
});
afterEach(() => {
vm.$destroy();
});
it('should contain container image as the namespace', () => {
expect(vm.$el.querySelectorAll('.table-mobile-content')[2].textContent).toContain(
props.vulnerability.location.image,
);
});
});
}); });
describe('with a dismissed vulnerability', () => { describe('with a dismissed vulnerability', () => {
......
...@@ -168,7 +168,7 @@ ...@@ -168,7 +168,7 @@
"feedback_type": "dismissal", "feedback_type": "dismissal",
"branch": "master", "branch": "master",
"project_fingerprint": "4e5b6966dd100170b4b1ad599c7058cce91b57b4", "project_fingerprint": "4e5b6966dd100170b4b1ad599c7058cce91b57b4",
"destroy_vulnerability_feedback_dismissal_path": "https://example.com/feedback_dismissal_path" "destroy_vulnerability_feedback_dismissal_path": "https://example.com/feedback_dismissal_path"
}, },
"issue_feedback": null, "issue_feedback": null,
"create_vulnerability_feedback_issue_path": "https://example.com/vulnerability_feedback", "create_vulnerability_feedback_issue_path": "https://example.com/vulnerability_feedback",
...@@ -484,5 +484,57 @@ ...@@ -484,5 +484,57 @@
"url": "https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first" "url": "https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first"
} }
] ]
},
{
"id": 8,
"report_type": "container_scanning",
"name": "CVE-2018-1000001 in glibc",
"severity": "high",
"confidence": "unknown",
"scanner": {
"external_id": "clair",
"name": "Clair"
},
"identifiers": [
{
"external_type": "cve",
"external_id": "CVE-2018-1000001",
"name": "CVE-2018-1000001",
"url": "https://security-tracker.debian.org/tracker/CVE-2018-1000001"
}
],
"project_fingerprint": "af08ab5aa899af9e74318ebc23684c9aa728ab7c",
"create_vulnerability_feedback_issue_path": "/gitlab-org/sec-reports/vulnerability_feedback",
"create_vulnerability_feedback_merge_request_path": "/gitlab-org/sec-reports/vulnerability_feedback",
"create_vulnerability_feedback_dismissal_path": "/gitlab-org/sec-reports/vulnerability_feedback",
"project": {
"id": 19,
"name": "sec-reports",
"full_path": "/gitlab-org/sec-reports",
"full_name": "Gitlab Org / sec-reports"
},
"dismissal_feedback": null,
"issue_feedback": null,
"merge_request_feedback": null,
"description": "In glibc 2.26 and earlier there is confusion in the usage of getcwd() by realpath() which can be used to write before the destination buffer leading to a buffer underflow and potential code execution.",
"links": [
{
"url": "https://security-tracker.debian.org/tracker/CVE-2018-1000001"
}
],
"location": {
"image": "registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff",
"operating_system": "debian:9",
"dependency": {
"package": {
"name": "glibc"
},
"version": "2.24-11+deb9u3"
}
},
"remediations": null,
"solution": null,
"state": "opened",
"blob_path": ""
} }
] ]
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