Skip to content

Commit aee55e7

Browse files
authored
Merge pull request #234 from devtron-labs/feat/security-scan
feat: security scan v1 modal
2 parents 77266e5 + e073a8d commit aee55e7

File tree

16 files changed

+130
-196
lines changed

16 files changed

+130
-196
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "0.1.15",
3+
"version": "0.1.18-beta-2",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",

src/Common/Constants.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,3 +518,11 @@ export const DATE_TIME_FORMATS = {
518518
DD_MMM_YYYY_HH_MM: 'DD MMM YYYY, hh:mm',
519519
DD_MMM_YYYY: 'DD MMM YYYY',
520520
}
521+
522+
export const VULNERABILITIES_SORT_PRIORITY = {
523+
critical: 1,
524+
high: 2,
525+
medium: 3,
526+
low: 4,
527+
unknown: 5,
528+
}

src/Common/SearchBar/SearchBar.component.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import { ChangeEvent, useCallback, useRef, useState, KeyboardEvent, useEffect } from 'react'
18+
import { ComponentSizeType } from '@Shared/constants'
1819
import { ReactComponent as Search } from '@Icons/ic-search.svg'
1920
import { ReactComponent as Clear } from '@Icons/ic-error-cross.svg'
2021
import { SearchBarProps } from './types'
@@ -65,6 +66,7 @@ const SearchBar = ({
6566
debounceTimeout = 300,
6667
dataTestId = 'search-bar',
6768
noBackgroundAndBorder = false,
69+
componentSize = ComponentSizeType.medium,
6870
}: SearchBarProps) => {
6971
const [showClearButton, setShowClearButton] = useState(!!initialSearchText)
7072
const inputRef = useRef<HTMLInputElement>()
@@ -116,7 +118,7 @@ const SearchBar = ({
116118
return (
117119
<div className={containerClassName}>
118120
<div
119-
className={`search-bar ${noBackgroundAndBorder ? 'dc__no-border dc__no-background dc__hover-n50' : 'bc-n50 en-2 dc__hover-border-n300'} focus-within-border-b5 dc__block w-100 min-w-200 dc__position-rel br-4 bw-1 h-32`}
121+
className={`search-bar ${noBackgroundAndBorder ? 'dc__no-border dc__no-background dc__hover-n50' : 'bc-n50 en-2 dc__hover-border-n300'} focus-within-border-b5 dc__block w-100 min-w-200 dc__position-rel br-4 bw-1 ${componentSize === ComponentSizeType.large ? 'h-36' : 'h-32'}`}
120122
>
121123
<Search className="search-bar__icon dc__position-abs icon-color-n6 icon-dim-16" />
122124
<input

src/Common/SearchBar/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { ComponentSizeType } from '@Shared/constants'
18+
1719
export interface SearchBarProps {
1820
/**
1921
* Initial search text
@@ -55,4 +57,8 @@ export interface SearchBarProps {
5557
* Hide the background and border of the search
5658
*/
5759
noBackgroundAndBorder?: boolean
60+
/**
61+
* Height of the Search bar, Large is 36px and Medium is 32px
62+
*/
63+
componentSize?: ComponentSizeType.large | ComponentSizeType.medium
5864
}

src/Common/Security/ScanVulnerabilitiesTable.tsx

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,45 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react'
1817
import DOMPurify from 'dompurify'
1918
import { ScanVulnerabilitiesTableProps, VulnerabilityType } from '../Types'
2019
import './scanVulnerabilities.css'
20+
import { SortableTableHeaderCell } from '@Common/SortableTableHeaderCell'
21+
import { useMemo } from 'react'
22+
import { numberComparatorBySortOrder, stringComparatorBySortOrder } from '@Shared/Helpers'
23+
import { VulnerabilitiesTableSortKeys } from './types'
24+
import { VULNERABILITIES_SORT_PRIORITY } from '@Common/Constants'
25+
import { useStateFilters } from '@Common/Hooks'
26+
27+
// To be replaced with Scan V2 Modal Table
28+
export default function ScanVulnerabilitiesTable({
29+
vulnerabilities,
30+
hidePolicy,
31+
shouldStick,
32+
}: ScanVulnerabilitiesTableProps) {
33+
const { sortBy, sortOrder, handleSorting } = useStateFilters<VulnerabilitiesTableSortKeys>({
34+
initialSortKey: VulnerabilitiesTableSortKeys.SEVERITY,
35+
})
36+
37+
const sortedVulnerabilities = useMemo(
38+
() =>
39+
vulnerabilities.sort((a, b) => {
40+
if (sortBy === VulnerabilitiesTableSortKeys.PACKAGE) {
41+
return stringComparatorBySortOrder(a.package, b.package, sortOrder)
42+
}
43+
44+
return numberComparatorBySortOrder(
45+
VULNERABILITIES_SORT_PRIORITY[a.severity],
46+
VULNERABILITIES_SORT_PRIORITY[b.severity],
47+
sortOrder,
48+
)
49+
}),
50+
[sortBy, sortOrder, vulnerabilities],
51+
)
52+
53+
const triggerSeveritySorting = () => handleSorting(VulnerabilitiesTableSortKeys.SEVERITY)
54+
const triggerPackageSorting = () => handleSorting(VulnerabilitiesTableSortKeys.PACKAGE)
2155

22-
export default function ScanVulnerabilitiesTable({ vulnerabilities, hidePolicy, shouldStick }: ScanVulnerabilitiesTableProps) {
2356
const renderRow = (vulnerability: VulnerabilityType) => (
2457
<tr
2558
className="dc__security-tab__table-row cursor"
@@ -37,14 +70,21 @@ export default function ScanVulnerabilitiesTable({ vulnerabilities, hidePolicy,
3770
</a>
3871
</td>
3972
<td className="security-tab__cell-severity">
40-
<span className={`dc__fill-${vulnerability.severity?.toLowerCase()}`}>{vulnerability.severity}</span>
73+
<span
74+
className={`severity-chip severity-chip--${vulnerability.severity?.toLowerCase()} dc__capitalize dc__w-fit-content`}
75+
>
76+
{vulnerability.severity}
77+
</span>
4178
</td>
4279
<td className="security-tab__cell-package">{vulnerability.package}</td>
4380
{/* QUERY: Do we need to add DOMPurify at any other key for this table as well? */}
4481
<td className="security-tab__cell-current-ver">
45-
<p className="m-0 cn-9 fs-13 fw-4" dangerouslySetInnerHTML={{
46-
__html: DOMPurify.sanitize(vulnerability.version)
47-
}} />
82+
<p
83+
className="m-0 cn-9 fs-13 fw-4"
84+
dangerouslySetInnerHTML={{
85+
__html: DOMPurify.sanitize(vulnerability.version),
86+
}}
87+
/>
4888
</td>
4989
<td className="security-tab__cell-fixed-ver">{vulnerability.fixedVersion}</td>
5090
{!hidePolicy && (
@@ -60,17 +100,35 @@ export default function ScanVulnerabilitiesTable({ vulnerabilities, hidePolicy,
60100
return (
61101
<table className="security-tab__table">
62102
<tbody>
63-
<tr className={`security-tab__table-header ${shouldStick ? 'dc__position-sticky bcn-0 dc__zi-4 dc__top-0' : ''}`}>
103+
<tr
104+
className={`security-tab__table-header ${shouldStick ? 'dc__position-sticky bcn-0 dc__zi-4 dc__top-0' : ''}`}
105+
>
64106
<th className="security-cell-header security-tab__cell-cve">CVE</th>
65-
<th className="security-cell-header security-tab__cell-severity">Severity</th>
66-
<th className="security-cell-header security-tab__cell-package">Package</th>
107+
<th className="security-cell-header security-tab__cell-severity">
108+
<SortableTableHeaderCell
109+
title="Severity"
110+
isSorted={sortBy === VulnerabilitiesTableSortKeys.SEVERITY}
111+
isSortable
112+
sortOrder={sortOrder}
113+
triggerSorting={triggerSeveritySorting}
114+
disabled={false}
115+
/>
116+
</th>
117+
<th className="security-cell-header security-tab__cell-package">
118+
<SortableTableHeaderCell
119+
title="Package"
120+
isSorted={sortBy === VulnerabilitiesTableSortKeys.PACKAGE}
121+
isSortable
122+
sortOrder={sortOrder}
123+
triggerSorting={triggerPackageSorting}
124+
disabled={false}
125+
/>
126+
</th>
67127
<th className="security-cell-header security-tab__cell-current-ver">Current Version</th>
68128
<th className="security-cell-header security-tab__cell-fixed-ver">Fixed In Version</th>
69-
{!hidePolicy && (
70-
<th className="security-cell-header security-tab__cell-policy">Policy</th>
71-
)}
129+
{!hidePolicy && <th className="security-cell-header security-tab__cell-policy">Policy</th>}
72130
</tr>
73-
{vulnerabilities.map((vulnerability) => renderRow(vulnerability))}
131+
{sortedVulnerabilities.map((vulnerability) => renderRow(vulnerability))}
74132
</tbody>
75133
</table>
76134
)

src/Common/Security/types.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum VulnerabilitiesTableSortKeys {
2+
SEVERITY = 'severity',
3+
PACKAGE = 'package',
4+
}

src/Common/SegmentedBarChart/SegmentedBarChart.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,9 @@ const SegmentedBarChart: React.FC<SegmentedBarChartProps> = ({
2626
labelClassName,
2727
}) => {
2828
const total = entities.reduce((sum, entity) => entity.value + sum, 0)
29+
const filteredEntities = entities.filter((entity) => entity.value)
2930

30-
const calcSegmentWidth = (entity: Entity) => {
31-
if (!entity.value) {
32-
return '100%'
33-
}
34-
return `${(entity.value / total) * 100}%`
35-
}
31+
const calcSegmentWidth = (entity: Entity) => `${(entity.value / total) * 100}%`
3632

3733
return (
3834
<div className={`flexbox-col w-100 dc__gap-12 ${rootClassName}`}>
@@ -50,7 +46,7 @@ const SegmentedBarChart: React.FC<SegmentedBarChartProps> = ({
5046
))}
5147
</div>
5248
<div className="flexbox dc__gap-2">
53-
{entities?.map((entity, index, map) => (
49+
{filteredEntities?.map((entity, index, map) => (
5450
<div
5551
key={entity.label}
5652
className={`h-8 ${index === 0 ? 'dc__left-radius-4' : ''} ${

src/Common/Types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import React, { ReactNode, CSSProperties } from 'react'
1818
import { Placement } from 'tippy.js'
1919
import { ImageComment, ReleaseTag } from './ImageTags.Types'
2020
import { ACTION_STATE, DEPLOYMENT_WINDOW_TYPE, DockerConfigOverrideType, SortingOrder, TaskErrorObj } from '.'
21-
import { RegistryType } from '../Shared'
21+
import { RegistryType, Severity } from '../Shared'
2222

2323
/**
2424
* Generic response type object with support for overriding the result type
@@ -568,7 +568,7 @@ export enum DeploymentAppTypes {
568568

569569
export interface VulnerabilityType {
570570
name: string
571-
severity: 'CRITICAL' | 'MODERATE' | 'LOW'
571+
severity: Severity
572572
package: string
573573
version: string
574574
fixedVersion: string

src/Shared/Components/ScannedObjectBar/ScannedObjectBar.tsx

Lines changed: 0 additions & 59 deletions
This file was deleted.

0 commit comments

Comments
 (0)