Skip to content

Commit e0f6d1a

Browse files
committed
Merge branch 'feat/integrate-scan-tool-url' of https://github.com/devtron-labs/devtron-fe-common-lib into feat/security-drawer-threat-count
2 parents 359aa06 + a1da34e commit e0f6d1a

File tree

13 files changed

+129
-101
lines changed

13 files changed

+129
-101
lines changed

src/Assets/Icon/ic-scan-fallback.svg

Lines changed: 4 additions & 0 deletions
Loading

src/Shared/Components/ScannedByToolModal/ScannedByToolModal.tsx

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,32 @@
1515
*/
1616

1717
import React from 'react'
18-
import { IMAGE_SCAN_TOOL, SCAN_TOOL_ID_TRIVY } from '../../constants'
18+
import { ReactComponent as ICScanFallback } from '@Icons/ic-scan-fallback.svg'
1919
import { ScannedByToolModalProps } from './types'
20-
import { ReactComponent as ICClair } from '../../../Assets/Icon/ic-clair.svg'
21-
import { ReactComponent as ICTrivy } from '../../../Assets/Icon/ic-trivy.svg'
20+
import { ImageWithFallback } from '../ImageWithFallback'
2221

2322
const ScannedByToolModal: React.FC<ScannedByToolModalProps> = ({
24-
scanToolId,
23+
scanToolName,
24+
scanToolUrl,
2525
fontSize = 13,
2626
spacingBetweenTextAndIcon = 6,
27-
}) => {
28-
const isTrivy = scanToolId === SCAN_TOOL_ID_TRIVY
29-
30-
return (
31-
<div className="flexbox" style={{ gap: `${spacingBetweenTextAndIcon}px` }}>
32-
<span className={`dc__italic-font-style fs-${fontSize}`}>
33-
Scanned by
34-
<span className="fw-6 ml-4" data-testid="scanned-by-tool">
35-
{isTrivy ? IMAGE_SCAN_TOOL.Trivy : IMAGE_SCAN_TOOL.Clair}
36-
</span>
27+
}) => (
28+
<div className="flexbox" style={{ gap: `${spacingBetweenTextAndIcon}px` }}>
29+
<span className={`dc__italic-font-style fs-${fontSize}`}>
30+
Scanned by
31+
<span className="fw-6 ml-4" data-testid="scanned-by-tool">
32+
{scanToolName}
3733
</span>
38-
{isTrivy ? (
39-
<ICTrivy className="icon-dim-20 dc__no-shrink" />
40-
) : (
41-
<ICClair className="icon-dim-20 dc__no-shrink" />
42-
)}
43-
</div>
44-
)
45-
}
34+
</span>
35+
<ImageWithFallback
36+
imageProps={{
37+
src: scanToolUrl,
38+
className: 'icon-dim-20-imp',
39+
alt: 'scan-tool',
40+
}}
41+
fallbackImage={<ICScanFallback className="icon-dim-20-imp dc__no-shrink" />}
42+
/>
43+
</div>
44+
)
4645

4746
export default ScannedByToolModal

src/Shared/Components/ScannedByToolModal/types.ts

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

1717
export interface ScannedByToolModalProps {
18-
scanToolId?: number
18+
scanToolName: string
19+
scanToolUrl: string
1920
fontSize?: number
2021
spacingBetweenTextAndIcon?: number
2122
}

src/Shared/Components/Security/SecurityDetailsCards/SecurityDetailsCards.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ScannedByToolModal } from '@Shared/Components/ScannedByToolModal'
2-
import { EMPTY_STATE_STATUS, SCAN_TOOL_ID_CLAIR, SCAN_TOOL_ID_TRIVY } from '@Shared/constants'
2+
import { EMPTY_STATE_STATUS } from '@Shared/constants'
33
import { useState } from 'react'
44
import { GenericEmptyState } from '@Common/index'
55
import { ReactComponent as NoVulnerability } from '@Icons/ic-vulnerability-not-found.svg'
@@ -37,18 +37,18 @@ const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps
3737
kubernetesManifest: !!kubernetesManifest,
3838
})
3939

40-
const getScanToolId = (category: string) => {
40+
const getScanToolInfo = (category: string): { scanToolName: string; scanToolUrl: string } => {
41+
const image = imageScan?.vulnerability?.list?.[0]
4142
switch (category) {
4243
case CATEGORIES.CODE_SCAN:
43-
return codeScan?.scanToolName === 'TRIVY' ? SCAN_TOOL_ID_TRIVY : SCAN_TOOL_ID_CLAIR
44+
return { scanToolName: codeScan?.scanToolName, scanToolUrl: codeScan?.scanToolUrl }
4445
case CATEGORIES.KUBERNETES_MANIFEST:
45-
return kubernetesManifest?.scanToolName === 'TRIVY' ? SCAN_TOOL_ID_TRIVY : SCAN_TOOL_ID_CLAIR
46-
case CATEGORIES.IMAGE_SCAN:
47-
return imageScan?.vulnerability?.list?.[0].scanToolName === 'TRIVY'
48-
? SCAN_TOOL_ID_TRIVY
49-
: SCAN_TOOL_ID_CLAIR
46+
return { scanToolName: kubernetesManifest?.scanToolName, scanToolUrl: kubernetesManifest?.scanToolUrl }
5047
default:
51-
return SCAN_TOOL_ID_TRIVY
48+
return {
49+
scanToolName: image?.scanToolName,
50+
scanToolUrl: image?.scanToolUrl,
51+
}
5252
}
5353
}
5454

@@ -80,11 +80,13 @@ const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps
8080
category !== CATEGORIES.IMAGE_SCAN &&
8181
(scanResult.codeScan?.status === 'Failed' || scanResult.kubernetesManifest?.status === 'Failed')
8282

83+
const { scanToolName, scanToolUrl } = getScanToolInfo(category)
84+
8385
return (
8486
<div className="flexbox-col dc__gap-12" key={category}>
8587
<div className="flexbox dc__content-space pb-8 dc__border-bottom-n1">
8688
<span className="fs-13 fw-6 lh-1-5 cn-9">{SECURITY_CONFIG[category].label}</span>
87-
<ScannedByToolModal scanToolId={getScanToolId(category)} />
89+
<ScannedByToolModal scanToolName={scanToolName} scanToolUrl={scanToolUrl} />
8890
</div>
8991
{categoryFailed ? (
9092
<div className="dc__border br-8">

src/Shared/Components/Security/SecurityModal/SecurityModal.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,18 @@ const SecurityModal: React.FC<SecurityModalPropsType> = ({
119119
selectedDetailViewData ||
120120
getTableData(data, state.category, state.subCategory, setDetailViewData, hidePolicy)
121121

122-
const { entities, lastScanTimeString, scanToolId } =
122+
const { entities, lastScanTimeString, scanToolName, scanToolUrl } =
123123
selectedDetailViewData || getInfoCardData(data, state.category, state.subCategory)
124124

125125
return (
126126
<div className="flexbox-col p-20 dc__gap-16">
127127
{!entities?.length ? null : (
128-
<InfoCard entities={entities} lastScanTimeString={lastScanTimeString} scanToolId={scanToolId} />
128+
<InfoCard
129+
entities={entities}
130+
lastScanTimeString={lastScanTimeString}
131+
scanToolName={scanToolName}
132+
scanToolUrl={scanToolUrl}
133+
/>
129134
)}
130135
<Table
131136
// NOTE: this key is important. Whenever data changes the table should be remounted

src/Shared/Components/Security/SecurityModal/components/InfoCard.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import { ReactComponent as ICClock } from '@Icons/ic-clock.svg'
1010
import { ZERO_TIME_STRING, DATE_TIME_FORMATS } from '../../../../../Common/Constants'
1111
import { InfoCardPropsType } from '../types'
1212

13-
const InfoCard: React.FC<InfoCardPropsType> = ({ entities, lastScanTimeString, scanToolId }) => (
13+
const InfoCard: React.FC<InfoCardPropsType> = ({ entities, lastScanTimeString, scanToolName, scanToolUrl }) => (
1414
<div className="info-card">
1515
<SegmentedBarChart entities={entities} rootClassName="p-16 fs-13" countClassName="fw-6" />
1616

17-
{(lastScanTimeString || scanToolId) && (
17+
{(lastScanTimeString || scanToolName) && (
1818
<>
1919
<div className="dc__border-bottom-n1 w-100 h-1" />
2020

@@ -28,8 +28,13 @@ const InfoCard: React.FC<InfoCardPropsType> = ({ entities, lastScanTimeString, s
2828
>{`Scanned on ${dayjs(lastScanTimeString).format(DATE_TIME_FORMATS.TWELVE_HOURS_FORMAT)}`}</span>
2929
</div>
3030
)}
31-
{scanToolId && (
32-
<ScannedByToolModal scanToolId={scanToolId} fontSize={12} spacingBetweenTextAndIcon={8} />
31+
{scanToolName && (
32+
<ScannedByToolModal
33+
scanToolName={scanToolName}
34+
scanToolUrl={scanToolUrl}
35+
fontSize={12}
36+
spacingBetweenTextAndIcon={8}
37+
/>
3338
)}
3439
</div>
3540
</>

src/Shared/Components/Security/SecurityModal/config/CodeScan.tsx

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@ import {
1010
mapSeveritiesToSegmentedBarChartEntities,
1111
stringifySeverities,
1212
} from '../utils'
13-
import {
14-
MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID,
15-
SCAN_FAILED_EMPTY_STATE,
16-
SCAN_IN_PROGRESS_EMPTY_STATE,
17-
SEVERITY_DEFAULT_SORT_ORDER,
18-
} from '../constants'
13+
import { SCAN_FAILED_EMPTY_STATE, SCAN_IN_PROGRESS_EMPTY_STATE, SEVERITY_DEFAULT_SORT_ORDER } from '../constants'
1914
import {
2015
ScanResultDTO,
2116
CATEGORIES,
@@ -164,6 +159,7 @@ const getMisconfigurationsDetail = (
164159
lastScanTimeString: string,
165160
status: StatusType['status'],
166161
scanToolName: StatusType['scanToolName'],
162+
scanToolUrl: StatusType['scanToolUrl'],
167163
) => ({
168164
titlePrefix: 'File path',
169165
title: element.filePath,
@@ -231,7 +227,8 @@ const getMisconfigurationsDetail = (
231227
defaultSortIndex: 1,
232228
entities: mapSeveritiesToSegmentedBarChartEntities(element.misConfSummary.status),
233229
lastScanTimeString,
234-
scanToolId: MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[scanToolName],
230+
scanToolName,
231+
scanToolUrl,
235232
hasExpandableRows: true,
236233
status,
237234
})
@@ -242,6 +239,7 @@ export const getCodeScanMisconfigurations = (
242239
lastScanTimeString: string,
243240
status: StatusType['status'],
244241
scanToolName: StatusType['scanToolName'],
242+
scanToolUrl: StatusType['scanToolUrl'],
245243
) => ({
246244
headers: [
247245
{ headerText: 'file path (relative)', isSortable: true, width: 289 },
@@ -262,6 +260,7 @@ export const getCodeScanMisconfigurations = (
262260
lastScanTimeString,
263261
status,
264262
scanToolName,
263+
scanToolUrl,
265264
)}
266265
setDetailViewData={setDetailViewData}
267266
>
@@ -287,6 +286,7 @@ const getExposedSecretsDetail = (
287286
lastScanTimeString: string,
288287
status: StatusType['status'],
289288
scanToolName: StatusType['scanToolName'],
289+
scanToolUrl: StatusType['scanToolUrl'],
290290
) => ({
291291
titlePrefix: 'File',
292292
title: element.filePath,
@@ -336,7 +336,8 @@ const getExposedSecretsDetail = (
336336
defaultSortIndex: 1,
337337
entities: mapSeveritiesToSegmentedBarChartEntities(element.summary.severities),
338338
lastScanTimeString,
339-
scanToolId: MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[scanToolName],
339+
scanToolName,
340+
scanToolUrl,
340341
hasExpandableRows: true,
341342
status,
342343
})
@@ -347,6 +348,7 @@ export const getCodeScanExposedSecrets = (
347348
lastScanTimeString: string,
348349
status: StatusType['status'],
349350
scanToolName: StatusType['scanToolName'],
351+
scanToolUrl: StatusType['scanToolUrl'],
350352
) => ({
351353
headers: [
352354
{ headerText: 'file path (relative)', isSortable: true, width: 372 },
@@ -366,6 +368,7 @@ export const getCodeScanExposedSecrets = (
366368
lastScanTimeString,
367369
status,
368370
scanToolName,
371+
scanToolUrl,
369372
)}
370373
setDetailViewData={setDetailViewData}
371374
>
@@ -400,6 +403,7 @@ export const getCodeScanTableData = (
400403
data.StartedOn,
401404
data.status,
402405
data.scanToolName,
406+
data.scanToolUrl,
403407
)
404408
case SUB_CATEGORIES.EXPOSED_SECRETS:
405409
return getCodeScanExposedSecrets(
@@ -408,6 +412,7 @@ export const getCodeScanTableData = (
408412
data.StartedOn,
409413
data.status,
410414
data.scanToolName,
415+
data.scanToolUrl,
411416
)
412417
default:
413418
return null
@@ -418,30 +423,32 @@ export const getCodeScanInfoCardData = (
418423
data: CodeScan,
419424
subCategory: SecurityModalStateType['subCategory'],
420425
): InfoCardPropsType => {
426+
const { StartedOn, scanToolName, scanToolUrl } = data
427+
const scanInfo: Omit<InfoCardPropsType, 'entities'> = {
428+
lastScanTimeString: StartedOn,
429+
scanToolName,
430+
scanToolUrl,
431+
}
421432
switch (subCategory) {
422433
case SUB_CATEGORIES.VULNERABILITIES:
423434
return {
424435
entities: mapSeveritiesToSegmentedBarChartEntities(data[subCategory]?.summary.severities),
425-
lastScanTimeString: data.StartedOn,
426-
scanToolId: MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[data.scanToolName],
436+
...scanInfo,
427437
}
428438
case SUB_CATEGORIES.LICENSE:
429439
return {
430440
entities: mapSeveritiesToSegmentedBarChartEntities(data[subCategory]?.summary.severities),
431-
lastScanTimeString: data.StartedOn,
432-
scanToolId: MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[data.scanToolName],
441+
...scanInfo,
433442
}
434443
case SUB_CATEGORIES.MISCONFIGURATIONS:
435444
return {
436445
entities: mapSeveritiesToSegmentedBarChartEntities(data[subCategory]?.misConfSummary.status),
437-
lastScanTimeString: data.StartedOn,
438-
scanToolId: MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[data.scanToolName],
446+
...scanInfo,
439447
}
440448
case SUB_CATEGORIES.EXPOSED_SECRETS:
441449
return {
442450
entities: mapSeveritiesToSegmentedBarChartEntities(data[subCategory]?.summary.severities),
443-
lastScanTimeString: data.StartedOn,
444-
scanToolId: MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[data.scanToolName],
451+
...scanInfo,
445452
}
446453
default:
447454
return null
@@ -460,27 +467,28 @@ const getCompletedEmptyState = (
460467

461468
const detailViewTitleText = detailViewData ? `${detailViewData.titlePrefix}: ${detailViewData.title}` : ''
462469
const subTitleText = detailViewTitleText || 'code scan'
463-
const scanToolId = MAP_SCAN_TOOL_NAME_TO_SCAN_TOOL_ID[data.scanToolName]
470+
const { scanToolName, scanToolUrl } = data
471+
const scanCompletedState = getScanCompletedEmptyState(scanToolName, scanToolUrl)
464472

465473
switch (subCategory) {
466474
case SUB_CATEGORIES.VULNERABILITIES:
467475
return {
468-
...getScanCompletedEmptyState(scanToolId),
476+
...scanCompletedState,
469477
subTitle: `No security vulnerability found in ${subTitleText}`,
470478
}
471479
case SUB_CATEGORIES.LICENSE:
472480
return {
473-
...getScanCompletedEmptyState(scanToolId),
481+
...scanCompletedState,
474482
subTitle: `No license risks found in ${subTitleText}`,
475483
}
476484
case SUB_CATEGORIES.MISCONFIGURATIONS:
477485
return {
478-
...getScanCompletedEmptyState(scanToolId),
486+
...scanCompletedState,
479487
subTitle: `No misconfigurations found in ${subTitleText}`,
480488
}
481489
case SUB_CATEGORIES.EXPOSED_SECRETS:
482490
return {
483-
...getScanCompletedEmptyState(scanToolId),
491+
...scanCompletedState,
484492
subTitle: `No exposed secrets found in ${subTitleText}`,
485493
}
486494
default:

0 commit comments

Comments
 (0)