Skip to content

Commit db86e02

Browse files
committed
feat: use mapping for security cards keys
1 parent 7161915 commit db86e02

File tree

9 files changed

+119
-96
lines changed

9 files changed

+119
-96
lines changed

src/Assets/Icon/ic-shield-check.svg

Lines changed: 3 additions & 5 deletions
Loading

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { ReactComponent as ICShieldWarning } from '@Icons/ic-shield-warning-outl
33
import { ReactComponent as ICShieldSecure } from '@Icons/ic-shield-check.svg'
44
import { ReactComponent as ICArrowRight } from '@Icons/ic-caret-down-small.svg'
55
import { SecurityCardProps } from './types'
6-
import { CATEGORIES, SeveritiesDTO, SUB_CATEGORIES } from '../SecurityModal/types'
6+
import { CATEGORIES, SUB_CATEGORIES } from '../SecurityModal/types'
7+
import { CATEGORY_LABELS, SEVERITIES } from '../SecurityModal/constants'
78
import './securityCard.scss'
8-
import { SEVERITIES } from '../SecurityModal/constants'
9+
import { getTotalSeverities } from '../utils'
910

1011
const SecurityCard = ({
1112
category,
@@ -14,9 +15,7 @@ const SecurityCard = ({
1415
handleCardClick,
1516
rootClassName = '',
1617
}: SecurityCardProps) => {
17-
const totalCount = Object.entries(severityCount)
18-
.filter(([key]) => key !== SeveritiesDTO.SUCCESSES)
19-
.reduce((acc, [, value]) => acc + value, 0)
18+
const totalCount = getTotalSeverities(severityCount)
2019

2120
const hasThreats: boolean = !!totalCount
2221

@@ -30,11 +29,11 @@ const SecurityCard = ({
3029
const getScanType = () => {
3130
switch (category) {
3231
case CATEGORIES.KUBERNETES_MANIFEST:
33-
return 'Manifest Scan'
32+
return CATEGORY_LABELS.KUBERNETES_MANIFEST
3433
case CATEGORIES.CODE_SCAN:
35-
return 'Code Scan'
34+
return CATEGORY_LABELS.CODE_SCAN
3635
default:
37-
return 'Image Scan'
36+
return CATEGORY_LABELS.IMAGE_SCAN
3837
}
3938
}
4039

@@ -64,12 +63,19 @@ const SecurityCard = ({
6463

6564
const { title, subtitle } = getTitleSubtitle()
6665

66+
const onKeyDown = (event) => {
67+
if (event.key === 'Enter' || event.key === 'Space') {
68+
handleCardClick()
69+
}
70+
}
71+
6772
return (
6873
<div
69-
className={`${rootClassName} min-w-500 w-50 bcn-0 p-20 flexbox-col dc__gap-16 br-8 dc__border security-card security-card${hasThreats ? '--threat' : '--secure'}`}
74+
className={`${rootClassName} w-100 bcn-0 p-20 flexbox-col dc__gap-16 br-8 dc__border security-card security-card${hasThreats ? '--threat' : '--secure'}`}
7075
role="button"
7176
tabIndex={0}
7277
onClick={handleCardClick}
78+
onKeyDown={onKeyDown}
7379
>
7480
<div className="flexbox dc__content-space">
7581
<div className="flexbox-col">
@@ -79,7 +85,11 @@ const SecurityCard = ({
7985
<ICArrowRight className="icon-dim-20 dc__flip-270 scb-5 arrow-right" />
8086
</div>
8187
</div>
82-
{hasThreats ? <ICShieldWarning className="icon-dim-24" /> : <ICShieldSecure className="icon-dim-24" />}
88+
{hasThreats ? (
89+
<ICShieldWarning className="icon-dim-24" />
90+
) : (
91+
<ICShieldSecure className="icon-dim-24 scg-5" />
92+
)}
8393
</div>
8494
<div className="flexbox-col dc__gap-12">
8595
{hasThreats || severityCount.success ? (

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

Lines changed: 54 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { CATEGORIES, SecurityModalStateType, SUB_CATEGORIES } from '../SecurityM
66
import { SecurityCardProps, SecurityDetailsCardsProps } from './types'
77
import { SecurityModal } from '../SecurityModal'
88
import { DEFAULT_SECURITY_MODAL_IMAGE_STATE } from '../SecurityModal/constants'
9+
import { ScanSubCategories } from '../types'
10+
import './securityCard.scss'
911

1012
const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps) => {
1113
const [showSecurityModal, setShowSecurityModal] = useState<boolean>(false)
@@ -33,6 +35,9 @@ const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps
3335
setShowSecurityModal(false)
3436
}
3537

38+
const isValidSubCategory = (subCategory: ScanSubCategories): boolean =>
39+
Object.values(SUB_CATEGORIES).includes(subCategory)
40+
3641
return (
3742
<>
3843
<div className="flexbox-col dc__gap-20">
@@ -42,21 +47,20 @@ const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps
4247
<span className="fs-13 fw-6 lh-1-5 cn-9">Image Scan</span>
4348
<ScannedByToolModal scanToolId={imageScanToolId} />
4449
</div>
45-
<div className="flexbox dc__gap-12">
46-
<SecurityCard
47-
category={CATEGORIES.IMAGE_SCAN}
48-
subCategory={SUB_CATEGORIES.VULNERABILITIES}
49-
severityCount={imageScan.vulnerability?.summary?.severities}
50-
handleCardClick={() =>
51-
handleCardClick(CATEGORIES.IMAGE_SCAN, SUB_CATEGORIES.VULNERABILITIES)
50+
<div className="dc__grid security-cards">
51+
{Object.keys(imageScan).map((subCategory: SecurityCardProps['subCategory']) => {
52+
if (!isValidSubCategory(subCategory)) {
53+
return null
5254
}
53-
/>
54-
<SecurityCard
55-
category={CATEGORIES.IMAGE_SCAN}
56-
subCategory={SUB_CATEGORIES.LICENSE}
57-
severityCount={imageScan.license?.summary?.severities}
58-
handleCardClick={() => handleCardClick(CATEGORIES.IMAGE_SCAN, SUB_CATEGORIES.LICENSE)}
59-
/>
55+
return (
56+
<SecurityCard
57+
category={CATEGORIES.IMAGE_SCAN}
58+
subCategory={subCategory}
59+
severityCount={imageScan[subCategory]?.summary.severities}
60+
handleCardClick={() => handleCardClick(CATEGORIES.IMAGE_SCAN, subCategory)}
61+
/>
62+
)
63+
})}
6064
</div>
6165
</div>
6266
) : null}
@@ -66,39 +70,24 @@ const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps
6670
<span className="fs-13 fw-6 lh-1-5 cn-9">Code Scan</span>
6771
<ScannedByToolModal scanToolId={codeScanToolId} />
6872
</div>
69-
<div className="flexbox dc__gap-12">
70-
<SecurityCard
71-
category={CATEGORIES.CODE_SCAN}
72-
subCategory={SUB_CATEGORIES.VULNERABILITIES}
73-
severityCount={codeScan.vulnerability?.summary.severities}
74-
handleCardClick={() =>
75-
handleCardClick(CATEGORIES.CODE_SCAN, SUB_CATEGORIES.VULNERABILITIES)
73+
<div className="dc__grid security-cards">
74+
{Object.keys(codeScan).map((subCategory: SecurityCardProps['subCategory']) => {
75+
if (!isValidSubCategory(subCategory)) {
76+
return null
7677
}
77-
/>
78-
<SecurityCard
79-
category={CATEGORIES.CODE_SCAN}
80-
subCategory={SUB_CATEGORIES.LICENSE}
81-
severityCount={codeScan.license?.summary?.severities}
82-
handleCardClick={() => handleCardClick(CATEGORIES.CODE_SCAN, SUB_CATEGORIES.LICENSE)}
83-
/>
84-
</div>
85-
<div className="flexbox dc__gap-12">
86-
<SecurityCard
87-
category={CATEGORIES.CODE_SCAN}
88-
subCategory={SUB_CATEGORIES.MISCONFIGURATIONS}
89-
severityCount={codeScan.misConfigurations?.misConfSummary?.status}
90-
handleCardClick={() =>
91-
handleCardClick(CATEGORIES.CODE_SCAN, SUB_CATEGORIES.MISCONFIGURATIONS)
92-
}
93-
/>
94-
<SecurityCard
95-
category={CATEGORIES.CODE_SCAN}
96-
subCategory={SUB_CATEGORIES.EXPOSED_SECRETS}
97-
severityCount={codeScan.exposedSecrets?.summary?.severities}
98-
handleCardClick={() =>
99-
handleCardClick(CATEGORIES.CODE_SCAN, SUB_CATEGORIES.EXPOSED_SECRETS)
100-
}
101-
/>
78+
const severityCount =
79+
subCategory === 'misConfigurations'
80+
? codeScan.misConfigurations?.misConfSummary?.status
81+
: codeScan[subCategory]?.summary?.severities
82+
return (
83+
<SecurityCard
84+
category={CATEGORIES.CODE_SCAN}
85+
subCategory={subCategory}
86+
severityCount={severityCount}
87+
handleCardClick={() => handleCardClick(CATEGORIES.CODE_SCAN, subCategory)}
88+
/>
89+
)
90+
})}
10291
</div>
10392
</div>
10493
) : null}
@@ -108,23 +97,26 @@ const SecurityDetailsCards = ({ scanResult, Sidebar }: SecurityDetailsCardsProps
10897
<span className="fs-13 fw-6 lh-1-5 cn-9">Manifest Scan</span>
10998
<ScannedByToolModal scanToolId={manifestScanToolId} />
11099
</div>
111-
<div className="flexbox dc__gap-12">
112-
<SecurityCard
113-
category={CATEGORIES.KUBERNETES_MANIFEST}
114-
subCategory={SUB_CATEGORIES.MISCONFIGURATIONS}
115-
severityCount={kubernetesManifest.misConfigurations?.misConfSummary?.status}
116-
handleCardClick={() =>
117-
handleCardClick(CATEGORIES.KUBERNETES_MANIFEST, SUB_CATEGORIES.MISCONFIGURATIONS)
118-
}
119-
/>
120-
<SecurityCard
121-
category={CATEGORIES.KUBERNETES_MANIFEST}
122-
subCategory={SUB_CATEGORIES.EXPOSED_SECRETS}
123-
severityCount={kubernetesManifest.exposedSecrets?.summary?.severities}
124-
handleCardClick={() =>
125-
handleCardClick(CATEGORIES.KUBERNETES_MANIFEST, SUB_CATEGORIES.EXPOSED_SECRETS)
100+
<div className="dc__grid security-cards">
101+
{Object.keys(kubernetesManifest).map((subCategory: SecurityCardProps['subCategory']) => {
102+
if (!isValidSubCategory(subCategory)) {
103+
return null
126104
}
127-
/>
105+
const severityCount =
106+
subCategory === 'misConfigurations'
107+
? kubernetesManifest.misConfigurations?.misConfSummary?.status
108+
: kubernetesManifest[subCategory]?.summary?.severities
109+
return (
110+
<SecurityCard
111+
category={CATEGORIES.KUBERNETES_MANIFEST}
112+
subCategory={subCategory}
113+
severityCount={severityCount}
114+
handleCardClick={() =>
115+
handleCardClick(CATEGORIES.KUBERNETES_MANIFEST, subCategory)
116+
}
117+
/>
118+
)
119+
})}
128120
</div>
129121
</div>
130122
) : null}

src/Shared/Components/Security/SecurityDetailsCards/securityCard.scss

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
.security-card {
22
&--threat {
3-
background: radial-gradient(25.91% 100% at 100% 0%, #FDE7E7 0%, #FFF 100%);
3+
background: radial-gradient(25.91% 100% at 100% 0%, var(--R100) 0%, var(--N0) 100%);
44
}
55
&--secure {
6-
background: radial-gradient(25.91% 100% at 100% 0%, #E9FBF4 0%, #FFF 100%);
6+
background: radial-gradient(25.91% 100% at 100% 0%, var(--G100) 0%, var(--N0) 100%);
77
}
88

99
.arrow-right {
@@ -19,4 +19,10 @@
1919
color: var(--B500);
2020
}
2121
}
22+
}
23+
24+
.security-cards {
25+
grid-template-columns: 1fr 1fr;
26+
grid-row-gap: 12px;
27+
grid-column-gap: 12px;
2228
}

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

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
1-
import {
2-
CATEGORIES,
3-
ScanResultDTO,
4-
SecurityModalPropsType,
5-
SeveritiesDTO,
6-
SUB_CATEGORIES,
7-
} from '../SecurityModal/types'
8-
9-
type Categories = keyof typeof CATEGORIES
10-
type SubCategories = keyof typeof SUB_CATEGORIES
1+
import { ScanResultDTO, SecurityModalPropsType, SeveritiesDTO } from '../SecurityModal/types'
2+
import { ScanCategories, ScanSubCategories } from '../types'
113

124
export interface SecurityCardProps {
13-
category: (typeof CATEGORIES)[Categories]
14-
subCategory: (typeof SUB_CATEGORIES)[SubCategories]
5+
category: ScanCategories
6+
subCategory: ScanSubCategories
157
severityCount: Partial<Record<SeveritiesDTO, number>>
168
handleCardClick: () => void
179
rootClassName?: string

src/Shared/Components/Security/SecurityModal/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ export type {
1515
SidebarDataType,
1616
GetResourceScanDetailsPayloadType,
1717
GetResourceScanDetailsResponseType,
18-
SeveritiesDTO,
1918
} from './types'
19+
export { SeveritiesDTO } from './types'
2020
export { getSidebarData, getProgressingStateForStatus } from './config'
2121
export { CATEGORY_LABELS } from './constants'
2222
export { getSecurityScan } from './service'

src/Shared/Components/Security/Vulnerabilities/Vulnerabilities.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,18 @@ const Vulnerabilities = ({
4747
}
4848
}, [scanResultResponse])
4949

50-
if (!isScanEnabled || !scanResultResponse?.result.isImageScanEnabled) {
50+
if (scanResultLoading) {
5151
return (
5252
<div className="security-tab-empty">
53-
<p className="security-tab-empty__title">Scan is Disabled</p>
53+
<Progressing />
5454
</div>
5555
)
5656
}
5757

58-
if (scanResultLoading) {
58+
if (!isScanEnabled || !scanResultResponse?.result?.isImageScanEnabled) {
5959
return (
6060
<div className="security-tab-empty">
61-
<Progressing />
61+
<p className="security-tab-empty__title">Scan is Disabled</p>
6262
</div>
6363
)
6464
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { CATEGORIES, SUB_CATEGORIES } from './SecurityModal/types'
2+
3+
export type ScanCategories = (typeof CATEGORIES)[keyof typeof CATEGORIES]
4+
export type ScanSubCategories = (typeof SUB_CATEGORIES)[keyof typeof SUB_CATEGORIES]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,23 @@
1+
import { ScanResultDTO, SeveritiesDTO } from './SecurityModal'
2+
13
export const getCVEUrlFromCVEName = (cveName: string): string =>
24
`https://cve.mitre.org/cgi-bin/cvename.cgi?name=${cveName}`
5+
6+
export const getTotalSeverities = (severityCount: Partial<Record<SeveritiesDTO, number>>) =>
7+
Object.entries(severityCount)
8+
.filter(([key]) => key !== SeveritiesDTO.SUCCESSES)
9+
.reduce((acc, [, value]) => acc + value, 0)
10+
11+
export const getSecurityThreatsArray = (scanResult: ScanResultDTO): Partial<Record<SeveritiesDTO, number>>[] => {
12+
const { imageScan, codeScan, kubernetesManifest } = scanResult
13+
return [
14+
imageScan?.vulnerability?.summary?.severities || {},
15+
imageScan?.license?.summary?.severities || {},
16+
codeScan?.vulnerability?.summary.severities || {},
17+
codeScan?.license?.summary?.severities || {},
18+
codeScan?.misConfigurations?.misConfSummary?.status || {},
19+
codeScan?.exposedSecrets?.summary?.severities || {},
20+
kubernetesManifest?.misConfigurations?.misConfSummary?.status || {},
21+
kubernetesManifest?.exposedSecrets?.summary?.severities || {},
22+
]
23+
}

0 commit comments

Comments
 (0)