Skip to content

Commit

Permalink
re-adjust structure of sbom component filtering
Browse files Browse the repository at this point in the history
Signed-off-by: Kaden Emley <[email protected]>
  • Loading branch information
kemley76 committed Aug 13, 2024
1 parent 79777b6 commit 5270436
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 173 deletions.
32 changes: 28 additions & 4 deletions apps/frontend/src/components/cards/sbomview/ComponentContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,32 @@
<tr>
<td>Name</td>
<td>Description</td>
<td />
<td />
<td>
<v-chip
small
outlined
@click="
$emit(
'show-components-in-table',
tab.relatedComponents.map((c) => c['bom-ref'])
)
"
>View All</v-chip
>
</td>
<td>
<v-chip
small
outlined
@click="
$emit(
'show-components-in-tree',
tab.relatedComponents.map((c) => c['bom-ref'])
)
"
>View All</v-chip
>
</td>
</tr>
</thead>
<tbody>
Expand All @@ -69,7 +93,7 @@
small
outlined
@click="
$emit('show-component-in-table', component['bom-ref'])
$emit('show-components-in-table', [component['bom-ref']])
"
>Go to Component Table</v-chip
>
Expand All @@ -79,7 +103,7 @@
small
outlined
@click="
$emit('show-component-in-tree', component['bom-ref'])
$emit('show-components-in-tree', [component['bom-ref']])
"
>Go to Dependency Tree</v-chip
>
Expand Down
161 changes: 20 additions & 141 deletions apps/frontend/src/components/cards/sbomview/ComponentTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<v-data-table
:items="components"
:headers="headers"
:search="searchTerm"
:expanded.sync="expanded"
show-expand
:items-per-page="-1"
Expand All @@ -16,61 +15,7 @@
<!-- fixed-header
height="calc(100vh - 250px)" -->
<template #top>
<v-card-title>
Components
<v-spacer />

<!-- Table settings menu -->
<v-menu offset-y offset-overflow :close-on-content-click="false">
<template #activator="{on}">
<v-btn fab small v-on="on">
<v-icon> mdi-cog-outline </v-icon>
</v-btn>
</template>
<v-card max-width="400" class="px-5">
<v-card-title class="py-5">Column Select</v-card-title>
<v-chip-group
v-model="headerColumns"
active-class="primary--text"
center-active
column
multiple
>
<v-chip
v-for="field in headerOptions"
:key="field.key"
:value="field.key"
>
{{ field.name }}
</v-chip>
</v-chip-group>
<v-divider />
<v-card-title class="py-2">Severity Filters</v-card-title>
<v-chip-group
v-model="severityFilter"
active-class="primary--text"
center-active
column
multiple
>
<v-chip
v-for="severity in severities"
:key="severity"
:value="severity"
>
{{ severityName(severity) }}
</v-chip>
</v-chip-group>
</v-card>
</v-menu>
</v-card-title>
</template>

<template #[`item.name`]="{item}">
{{ item.name }}
<template v-if="componentRef == item['bom-ref']">
<a id="scroll-to" />
</template>
<v-card-title> Components </v-card-title>
</template>

<template #[`item.affectingVulnerabilities`]="{item}">
Expand Down Expand Up @@ -105,8 +50,8 @@
<ComponentContent
:component="item"
:vulnerabilities="affectingVulns.get(item['bom-ref'])"
@show-component-in-table="showComponentInTable"
@show-component-in-tree="showComponentInTree"
@show-components-in-table="showComponentsInTable"
@show-components-in-tree="showComponentsInTree"
/>
</td>
</template>
Expand All @@ -117,7 +62,7 @@
</template>

<script lang="ts">
import {Filter, FilteredDataModule} from '@/store/data_filters';
import {FilteredDataModule, SBOMFilter} from '@/store/data_filters';
import {SnackbarModule} from '@/store/snackbar';
import {ContextualizedControl, severities, Severity} from 'inspecjs';
import _ from 'lodash';
Expand All @@ -136,95 +81,33 @@ import {
}
})
export default class ComponentTable extends Vue {
@Prop({type: String, required: false}) readonly searchTerm!: string;
@Prop({type: Object, required: true}) readonly filter!: SBOMFilter;
@Prop({type: Array, required: true}) currentHeaders!: string[];
componentRef = this.$route.query.componentRef ?? null;
severityFilter: Severity[] = this.severities;
expanded: ContextualizedSBOMComponent[] = [];
/** The list of columns that are currently displayed */
headerColumns = [
'name',
'version',
'group',
'type',
'description',
'affectingVulnerabilities'
];
/**
* A list of options (selectable in the column select menu) for which
* headers to display
*/
headerOptions = [
'name',
'version',
'description',
'author',
'affectingVulnerabilities',
'type',
'bom-ref',
'copyright',
'purl',
'cpe',
'group',
'publisher',
'scope',
'mime-type'
].map((option) => ({name: _.startCase(option), key: option}));
mounted() {
this.$nextTick(() => {
if (!this.componentRef) return;
try {
this.$vuetify.goTo(`#scroll-to`, {duration: 300});
} catch (e) {
SnackbarModule.failure(
`The component you are trying to view is not currently loaded (bom-ref: ${this.componentRef})`
);
return;
}
const item = this.components.find(
(i) => i['bom-ref'] === this.componentRef
);
if (item) {
this.expanded = [item];
}
});
}
headerIndex(str: string) {
return this.headerOptions.findIndex((option) => option.key === str);
}
get headers() {
// ensure that the header columns are in a consistent order and not determined by
// ensure that the header columns are in a consistent order and not determined by
// the order in which they are selected
this.headerColumns.sort((a, b) => this.headerIndex(a) - this.headerIndex(b))
let h = this.headerColumns.map((v) => {
let h = this.currentHeaders.map((v) => {
return {value: v, class: 'header-box', text: _.startCase(v)};
});
h.push({value: 'data-table-expand', text: 'More', class: 'header-box'});
return h;
}
get components(): readonly ContextualizedSBOMComponent[] {
return FilteredDataModule.components(this.all_filter);
}
get all_filter(): Filter {
return {
fromFile: FilteredDataModule.selected_sbom_ids,
severity: this.severityFilter
};
// TODO: Change this to have a refernece to the source evaluation in some way. File name?? Like List ELT in result table
return FilteredDataModule.components(this.filter);
}
get affectingVulns(): Map<string, ContextualizedControl[]> {
let vulnMap: Map<string, ContextualizedControl[]> = new Map();
for (const c of this.components) {
// get the component's affecting vulnerabilities
const componentVulns = [];
const controls = FilteredDataModule.controls(this.all_filter);
const controls = FilteredDataModule.controls(this.filter);
for (const vulnBomRef of c.affectingVulnerabilities || []) {
let result = getVulnsFromBomRef(vulnBomRef, controls);
if (result.ok) componentVulns.push(result.value); // TODO: show components with unloaded vulns as errors?
Expand All @@ -239,21 +122,12 @@ export default class ComponentTable extends Vue {
return `severity${_.startCase(severity)}`;
}
severityName(severity: string): string {
return _.startCase(severity);
}
get severities(): Severity[] {
// returns the list of severities defined by inspecJS
return [...severities];
showComponentsInTable(bomRefs: string[]) {
this.$emit('show-components-in-table', bomRefs);
}
showComponentInTable(ref: string) {
this.$emit('show-component-in-table', ref);
}
showComponentInTree(ref: string) {
this.$emit('show-component-in-tree', ref);
showComponentsInTree(bomRefs: string[]) {
this.$emit('show-components-in-tree', bomRefs);
}
}
</script>
Expand All @@ -276,6 +150,11 @@ export default class ComponentTable extends Vue {
border-left: 5px solid var(--v-primary-base);
}
/** Blue bar on the bottom to show where expanded content ends */
::v-deep .v-data-table__expanded__content {
border-bottom: 5px solid var(--v-primary-base) !important;
}
/** Allows blue bar to be visible */
::v-deep .v-data-table__wrapper table {
border-collapse: collapse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<template #append="{item, active}">
<v-chip
v-if="active"
@click="$emit('show-component-in-table', item.ref)"
@click="$emit('show-component-in-table', item.component['bom-ref'])"
>
Open in Component Table
</v-chip>
Expand All @@ -24,6 +24,7 @@
</template>

<script lang="ts">
import {SBOMFilter} from '@/store/data_filters';
import {ContextualizedSBOMComponent, SBOMData} from '@/utilities/sbom_util';
import _ from 'lodash';
import Vue from 'vue';
Expand All @@ -41,10 +42,10 @@ interface TreeNode {
components: {}
})
export default class DependencyTree extends Vue {
@Prop({type: Object, required: true}) readonly filter!: SBOMFilter;
@Prop({type: Object, required: true}) readonly sbomData!: SBOMData;
@Prop({type: String, required: false}) readonly searchTerm!: string;
@Prop({type: String, required: false}) readonly targetComponent!:
| string
@Prop({type: Array, required: false}) readonly targetComponents!:
| string[]
| null;
loadedDependencies: TreeNode[] = [];
Expand Down
Loading

0 comments on commit 5270436

Please sign in to comment.