Refactored the signatures and vulnerabilities

Signed-off-by: Amelia-Maria Breda <ambreda@cisco.com>
This commit is contained in:
Amelia-Maria Breda 2022-10-20 15:24:07 +01:00 committed by Raul Kele
parent 1579ddd1f6
commit fd0f8c1b82
11 changed files with 438 additions and 708 deletions

View File

@ -150,24 +150,24 @@ describe('Explore component', () => {
expect(await screen.findByText(/Looks like/i)).toBeInTheDocument();
});
it('renders signature chips', async () => {
it('renders signature icons', async () => {
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
render(<StateExploreWrapper />);
expect(await screen.findAllByTestId('unverified-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('verified-chip')).toHaveLength(5);
expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('verified-icon')).toHaveLength(5);
});
it('renders vulnerability chips', async () => {
it('renders vulnerability icons', async () => {
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
render(<StateExploreWrapper />);
expect(await screen.findAllByTestId('low-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('high-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('critical-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('none-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('medium-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('unknown-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('none-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('medium-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('unknown-vulnerability-icon')).toHaveLength(1);
});
it("should log an error when data can't be fetched", async () => {

View File

@ -137,22 +137,20 @@ describe('Home component', () => {
await waitFor(() => expect(screen.getAllByText(/node/i)).toHaveLength(1));
});
it('renders signature chips', async () => {
it('renders signature icons', async () => {
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
render(<Home />);
expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('verified-icon')).toHaveLength(3);
expect(await screen.findAllByTestId('unverified-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('verified-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(2);
expect(await screen.findAllByTestId('verified-icon')).toHaveLength(4);
});
it('renders vulnerability icons', async () => {
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
render(<Home />);
expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(2);
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(2);
expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1);
expect(await screen.findAllByTestId('none-vulnerability-icon')).toHaveLength(1);
});

View File

@ -167,31 +167,31 @@ describe('Repo details component', () => {
expect(await screen.findByText('test')).toBeInTheDocument();
});
it('renders vulnerability chips', async () => {
it('renders vulnerability icons', async () => {
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } });
render(<RepoDetails />);
expect(await screen.findAllByTestId('critical-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsNone } });
render(<RepoDetails />);
expect(await screen.findAllByTestId('none-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('none-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsUnknown } });
render(<RepoDetails />);
expect(await screen.findAllByTestId('unknown-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('unknown-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsLow } });
render(<RepoDetails />);
expect(await screen.findAllByTestId('low-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsMedium } });
render(<RepoDetails />);
expect(await screen.findAllByTestId('medium-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('medium-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsHigh } });
render(<RepoDetails />);
expect(await screen.findAllByTestId('high-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(1);
});
it("should log error if data can't be fetched", async () => {

View File

@ -216,31 +216,31 @@ describe('Tags details', () => {
expect(await screen.findByTestId('tagDetailsMetadata-container')).toBeInTheDocument();
});
it('renders vulnerability chips', async () => {
it('renders vulnerability icons', async () => {
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } });
render(<TagDetails />);
expect(await screen.findAllByTestId('critical-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageNone } });
render(<TagDetails />);
expect(await screen.findAllByTestId('none-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('none-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageUnknown } });
render(<TagDetails />);
expect(await screen.findAllByTestId('unknown-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('unknown-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageLow } });
render(<TagDetails />);
expect(await screen.findAllByTestId('low-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageMedium } });
render(<TagDetails />);
expect(await screen.findAllByTestId('medium-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('medium-vulnerability-icon')).toHaveLength(1);
// @ts-ignore
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageHigh } });
render(<TagDetails />);
expect(await screen.findAllByTestId('high-vulnerability-chip')).toHaveLength(1);
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(1);
});
it('should copy the pull string to clipboard', async () => {

View File

@ -9,13 +9,8 @@ import repocube2 from '../assets/repocube-2.png';
import repocube3 from '../assets/repocube-3.png';
import repocube4 from '../assets/repocube-4.png';
//icons
import GppBadOutlinedIcon from '@mui/icons-material/GppBadOutlined';
import GppGoodOutlinedIcon from '@mui/icons-material/GppGoodOutlined';
import PestControlOutlinedIcon from '@mui/icons-material/PestControlOutlined';
import PestControlIcon from '@mui/icons-material/PestControl';
import { isEmpty } from 'lodash';
//import GppMaybeOutlinedIcon from '@mui/icons-material/GppMaybeOutlined';
import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
// temporary utility to get image
const randomIntFromInterval = (min, max) => {
@ -72,151 +67,12 @@ const useStyles = makeStyles(() => ({
function PreviewCard(props) {
const classes = useStyles();
const navigate = useNavigate();
const { name, isSigned, vulnerabiltySeverity, vulnerabilityCount, logo } = props;
const { name, isSigned, vulnerabiltySeverity, logo } = props;
const goToDetails = () => {
navigate(`/image/${encodeURIComponent(name)}`);
};
const vulnerabilityCheck = () => {
const noneVulnerability = (
<PestControlOutlinedIcon
sx={{
color: '#43A047!important',
padding: '0.2rem',
background: '#E8F5E9',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="none-vulnerability-icon"
/>
);
const unknownVulnerability = (
<PestControlOutlinedIcon
sx={{
color: '#52637A!important',
padding: '0.2rem',
background: '#ECEFF1',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="unknown-vulnerability-icon"
/>
);
const lowVulnerability = (
<PestControlOutlinedIcon
sx={{
color: '#FB8C00!important',
padding: '0.2rem',
background: '#FFF3E0',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="low-vulnerability-icon"
/>
);
const mediumVulnerability = (
<PestControlIcon
sx={{
color: '#FB8C00!important',
padding: '0.2rem',
background: '#FFF3E0',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="medium-vulnerability-icon"
/>
);
const highVulnerability = (
<PestControlOutlinedIcon
sx={{
color: '#E53935!important',
padding: '0.2rem',
background: '#FEEBEE',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="high-vulnerability-icon"
/>
);
const criticalVulnerability = (
<PestControlIcon
sx={{
color: '#E53935!important',
padding: '0.2rem',
background: '#FEEBEE',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="critical-vulnerability-icon"
/>
);
let result;
switch (vulnerabiltySeverity) {
case 'NONE':
result = noneVulnerability;
break;
case 'LOW':
result = lowVulnerability;
break;
case 'MEDIUM':
result = mediumVulnerability;
break;
case 'HIGH':
result = highVulnerability;
break;
case 'CRITICAL':
result = criticalVulnerability;
break;
default:
result = unknownVulnerability;
}
return result;
};
const signatureCheck = () => {
const unverifiedSignature = (
<GppBadOutlinedIcon
sx={{
color: '#E53935!important',
padding: '0.2rem',
background: '#FEEBEE',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="unverified-icon"
/>
);
//const untrustedSignature = <GppMaybeOutlinedIcon sx={{ color: "#52637A!important", padding:"0.2rem", background: "#ECEFF1", borderRadius: "1rem", height:"1.5rem", width:"1.6rem" }} />;
const verifiedSignature = (
<GppGoodOutlinedIcon
sx={{
color: '#43A047!important',
padding: '0.2rem',
background: '#E8F5E9',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="verified-icon"
/>
);
if (isSigned) {
return verifiedSignature;
} else {
return unverifiedSignature;
}
};
return (
<Card variant="outlined" className={classes.card}>
<CardActionArea onClick={() => goToDetails()} className={classes.cardBtn}>
@ -251,10 +107,8 @@ function PreviewCard(props) {
</Typography>
</Tooltip>
<Stack direction="row" spacing={0.5} sx={{ marginLeft: 'auto', marginRight: 0 }}>
<Tooltip title={!isNaN(vulnerabilityCount) ? vulnerabilityCount : ''} placement="top">
{vulnerabilityCheck()}
</Tooltip>
{signatureCheck()}
<VulnerabilityIconCheck vulnerabilitySeverity={vulnerabiltySeverity} />
<SignatureIconCheck isSigned={isSigned} />
</Stack>
</Stack>
</Grid>

View File

@ -14,12 +14,8 @@ import repocube2 from '../assets/repocube-2.png';
import repocube3 from '../assets/repocube-3.png';
import repocube4 from '../assets/repocube-4.png';
//icons
import GppBadOutlinedIcon from '@mui/icons-material/GppBadOutlined';
import GppGoodOutlinedIcon from '@mui/icons-material/GppGoodOutlined';
import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
import { Markdown } from 'utilities/MarkdowntojsxWrapper';
import PestControlOutlinedIcon from '@mui/icons-material/PestControlOutlined';
import PestControlIcon from '@mui/icons-material/PestControl';
import { isEmpty } from 'lodash';
// temporary utility to get image
@ -104,144 +100,13 @@ function RepoCard(props) {
lastUpdated,
logo,
version,
vulnerabiltySeverity,
vulnerabilityCount
vulnerabiltySeverity
} = props;
const goToDetails = () => {
navigate(`/image/${encodeURIComponent(name)}`);
};
const vulnerabilityCheck = () => {
const noneVulnerability = (
<Chip
label="None Vulnerability"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#388E3C!important' }} />}
data-testid="none-vulnerability-chip"
/>
);
const unknownVulnerability = (
<Chip
label="Unknown Vulnerability"
sx={{ backgroundColor: '#ECEFF1', color: '#52637A', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#52637A!important' }} />}
data-testid="unknown-vulnerability-chip"
/>
);
const lowVulnerability = (
<Chip
label="Low Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="low-vulnerability-chip"
/>
);
const mediumVulnerability = (
<Chip
label="Medium Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="medium-vulnerability-chip"
/>
);
const highVulnerability = (
<Chip
label="High Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#E53935!important' }} />}
data-testid="high-vulnerability-chip"
/>
);
const criticalVulnerability = (
<Chip
label="Critical Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#E53935!important' }} />}
data-testid="critical-vulnerability-chip"
/>
);
let result;
switch (vulnerabiltySeverity) {
case 'NONE':
result = noneVulnerability;
break;
case 'LOW':
result = lowVulnerability;
break;
case 'MEDIUM':
result = mediumVulnerability;
break;
case 'HIGH':
result = highVulnerability;
break;
case 'CRITICAL':
result = criticalVulnerability;
break;
default:
result = unknownVulnerability;
}
return result;
};
const signatureCheck = () => {
const unverifiedSignature = (
<Chip
label="Unverified Signature"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppBadOutlinedIcon sx={{ color: '#E53935!important' }} />}
data-testid="unverified-chip"
/>
);
//const untrustedSignature = <Chip label="Untrusted Signature" sx={{backgroundColor: "#ECEFF1",color: "#52637A",fontSize: "0.8125rem",}} variant="filled" onDelete={() => { return; }} deleteIcon={ <GppMaybeOutlinedIcon sx={{ color: "#52637A!important" }} />}/>;
const verifiedSignature = (
<Chip
label="Verified Signature"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppGoodOutlinedIcon sx={{ color: '#388E3C!important' }} />}
data-testid="verified-chip"
/>
);
if (isSigned) {
return verifiedSignature;
} else {
return unverifiedSignature;
}
};
const platformChips = () => {
// if platforms not received, mock data
const platformsOsArch = platforms || [];
@ -301,10 +166,8 @@ function RepoCard(props) {
{name}
</Typography>
</Tooltip>
<Tooltip title={!isNaN(vulnerabilityCount) ? vulnerabilityCount : ''} placement="top">
{vulnerabilityCheck()}
</Tooltip>
{signatureCheck()}
<VulnerabilityIconCheck vulnerabilitySeverity={vulnerabiltySeverity} />
<SignatureIconCheck isSigned={isSigned} />
{/* <Chip label="Verified licensee" sx={{ backgroundColor: "#E8F5E9", color: "#388E3C" }} variant="filled" onDelete={() => { return }} deleteIcon={vulnerabilityCheck()} /> */}
</Stack>
<Tooltip title={description || 'Description not available'} placement="top">

View File

@ -7,7 +7,7 @@ import { api, endpoints } from '../api';
// components
import Tags from './Tags.jsx';
import { Box, Card, CardContent, CardMedia, Chip, Grid, Stack, Tab, Tooltip, Typography } from '@mui/material';
import { Box, Card, CardContent, CardMedia, Chip, Grid, Stack, Tab, Typography } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import { host } from '../host';
@ -18,14 +18,10 @@ import repocube3 from '../assets/repocube-3.png';
import repocube4 from '../assets/repocube-4.png';
import { TabContext, TabList, TabPanel } from '@mui/lab';
//icons
import GppBadOutlinedIcon from '@mui/icons-material/GppBadOutlined';
import GppGoodOutlinedIcon from '@mui/icons-material/GppGoodOutlined';
import PestControlOutlinedIcon from '@mui/icons-material/PestControlOutlined';
import PestControlIcon from '@mui/icons-material/PestControl';
import RepoDetailsMetadata from './RepoDetailsMetadata';
import Loading from './Loading';
import { isEmpty } from 'lodash';
import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
// @ts-ignore
const useStyles = makeStyles(() => ({
@ -176,135 +172,6 @@ function RepoDetails() {
};
}, [name]);
const signatureCheck = () => {
const unverifiedSignature = (
<Chip
label="Unverified Signature"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppBadOutlinedIcon sx={{ color: '#E53935!important' }} />}
/>
);
const verifiedSignature = (
<Chip
label="Verified Signature"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppGoodOutlinedIcon sx={{ color: '#388E3C!important' }} />}
/>
);
// @ts-ignore
if (repoDetailData.isSigned) {
return verifiedSignature;
} else {
return unverifiedSignature;
}
};
const vulnerabilityCheck = () => {
const noneVulnerability = (
<Chip
label="None Vulnerability"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#388E3C!important' }} />}
data-testid="none-vulnerability-chip"
/>
);
const unknownVulnerability = (
<Chip
label="Unknown Vulnerability"
sx={{ backgroundColor: '#ECEFF1', color: '#52637A', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#52637A!important' }} />}
data-testid="unknown-vulnerability-chip"
/>
);
const lowVulnerability = (
<Chip
label="Low Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="low-vulnerability-chip"
/>
);
const mediumVulnerability = (
<Chip
label="Medium Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="medium-vulnerability-chip"
/>
);
const highVulnerability = (
<Chip
label="High Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#E53935!important' }} />}
data-testid="high-vulnerability-chip"
/>
);
const criticalVulnerability = (
<Chip
label="Critical Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#E53935!important' }} />}
data-testid="critical-vulnerability-chip"
/>
);
let result;
// @ts-ignore
switch (repoDetailData.vulnerabiltySeverity) {
case 'NONE':
result = noneVulnerability;
break;
case 'LOW':
result = lowVulnerability;
break;
case 'MEDIUM':
result = mediumVulnerability;
break;
case 'HIGH':
result = highVulnerability;
break;
case 'CRITICAL':
result = criticalVulnerability;
break;
default:
result = unknownVulnerability;
}
return result;
};
const platformChips = () => {
// @ts-ignore
const platforms = repoDetailData?.platforms || [];
@ -382,22 +249,30 @@ function RepoDetails() {
component="img"
// @ts-ignore
// eslint-disable-next-line prettier/prettier
image={!isEmpty(repoDetailData?.logo) ? `data:image/png;base64, ${repoDetailData?.logo}` : randomImage()}
image={
// @ts-ignore
!isEmpty(repoDetailData?.logo)
? // @ts-ignore
`data:image/png;base64, ${repoDetailData?.logo}`
: randomImage()
}
alt="icon"
/>
<Typography variant="h3" className={classes.repoName}>
{name}
</Typography>
<Tooltip
title={
<VulnerabilityIconCheck
vulnerabilitySeverity={
// @ts-ignore
!isNaN(repoDetailData.vulnerabilityCount) ? repoDetailData.vulnerabilityCount : ''
repoDetailData.vulnerabiltySeverity
}
placement="top"
>
{vulnerabilityCheck()}
</Tooltip>
{signatureCheck()}
/>
<SignatureIconCheck
isSigned={
// @ts-ignore
repoDetailData.isSigned
}
/>
{/* <BookmarkIcon sx={{color:"#52637A"}}/> */}
</Stack>
<Typography

View File

@ -10,7 +10,6 @@ import {
Card,
CardContent,
CardMedia,
Chip,
Grid,
FormControl,
IconButton,
@ -18,7 +17,6 @@ import {
Select,
MenuItem,
Tab,
Tooltip,
Typography,
Snackbar,
Alert
@ -27,12 +25,6 @@ import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import makeStyles from '@mui/styles/makeStyles';
import { host } from '../host';
//icons
import GppBadOutlinedIcon from '@mui/icons-material/GppBadOutlined';
import GppGoodOutlinedIcon from '@mui/icons-material/GppGoodOutlined';
import PestControlOutlinedIcon from '@mui/icons-material/PestControlOutlined';
import PestControlIcon from '@mui/icons-material/PestControl';
// placeholder images
import repocube1 from '../assets/repocube-1.png';
import repocube2 from '../assets/repocube-2.png';
@ -47,6 +39,7 @@ import IsDependentOn from './IsDependentOn';
import { isEmpty } from 'lodash';
import Loading from './Loading';
import { dockerPull, podmanPull, skopeoPull } from 'utilities/pullStrings';
import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
// @ts-ignore
const useStyles = makeStyles(() => ({
@ -206,135 +199,6 @@ function TagDetails() {
};
}, [name, tag]);
const signatureCheck = () => {
const unverifiedSignature = (
<Chip
label="Unverified Signature"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppBadOutlinedIcon sx={{ color: '#E53935!important' }} />}
/>
);
const verifiedSignature = (
<Chip
label="Verified Signature"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppGoodOutlinedIcon sx={{ color: '#388E3C!important' }} />}
/>
);
// @ts-ignore
if (imageDetailData.isSigned) {
return verifiedSignature;
} else {
return unverifiedSignature;
}
};
const vulnerabilityCheck = () => {
const noneVulnerability = (
<Chip
label="None Vulnerability"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#388E3C!important' }} />}
data-testid="none-vulnerability-chip"
/>
);
const unknownVulnerability = (
<Chip
label="Unknown Vulnerability"
sx={{ backgroundColor: '#ECEFF1', color: '#52637A', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#52637A!important' }} />}
data-testid="unknown-vulnerability-chip"
/>
);
const lowVulnerability = (
<Chip
label="Low Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="low-vulnerability-chip"
/>
);
const mediumVulnerability = (
<Chip
label="Medium Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="medium-vulnerability-chip"
/>
);
const highVulnerability = (
<Chip
label="High Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#E53935!important' }} />}
data-testid="high-vulnerability-chip"
/>
);
const criticalVulnerability = (
<Chip
label="Critical Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#E53935!important' }} />}
data-testid="critical-vulnerability-chip"
/>
);
let result;
// @ts-ignore
switch (imageDetailData.vulnerabiltySeverity) {
case 'NONE':
result = noneVulnerability;
break;
case 'LOW':
result = lowVulnerability;
break;
case 'MEDIUM':
result = mediumVulnerability;
break;
case 'HIGH':
result = highVulnerability;
break;
case 'CRITICAL':
result = criticalVulnerability;
break;
default:
result = unknownVulnerability;
}
return result;
};
const getPlatform = () => {
// @ts-ignore
return imageDetailData?.platform ? imageDetailData.platform : '--/--';
@ -377,23 +241,28 @@ function TagDetails() {
image={
// @ts-ignore
// eslint-disable-next-line prettier/prettier
!isEmpty(imageDetailData?.logo) ? `data:image/ png;base64, ${imageDetailData?.logo}` : randomImage()
!isEmpty(imageDetailData?.logo)
? // @ts-ignore
`data:image/ png;base64, ${imageDetailData?.logo}`
: randomImage()
}
alt="icon"
/>
<Typography variant="h3" className={classes.repoName}>
{name}:{tag}
</Typography>
<Tooltip
title={
<VulnerabilityIconCheck
vulnerabilitySeverity={
// @ts-ignore
!isNaN(imageDetailData.vulnerabilityCount) ? imageDetailData.vulnerabilityCount : ''
imageDetailData.vulnerabiltySeverity
}
placement="top"
>
{vulnerabilityCheck()}
</Tooltip>
{signatureCheck()}
/>
<SignatureIconCheck
isSigned={
// @ts-ignore
imageDetailData.isSigned
}
/>
{/* <BookmarkIcon sx={{color:"#52637A"}}/> */}
</Stack>
<Typography

View File

@ -5,15 +5,14 @@ import { api, endpoints } from '../api';
// components
import Collapse from '@mui/material/Collapse';
import { Box, Card, CardContent, Divider, Chip, Stack, Typography } from '@mui/material';
import { Box, Card, CardContent, Divider, Stack, Typography } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import { host } from '../host';
import PestControlOutlinedIcon from '@mui/icons-material/PestControlOutlined';
import PestControlIcon from '@mui/icons-material/PestControl';
import { isEmpty } from 'lodash';
import { Link } from 'react-router-dom';
import Loading from './Loading';
import { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material';
import { VulnerabilityChipCheck } from 'utilities/vulnerabilityAndSignatureCheck';
const useStyles = makeStyles(() => ({
card: {
@ -83,98 +82,6 @@ const useStyles = makeStyles(() => ({
}
}));
const vulnerabilityCheck = (status) => {
const noneVulnerability = (
<Chip
label="None"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#388E3C!important' }} />}
/>
);
const unknownVulnerability = (
<Chip
label="Unknown"
sx={{ backgroundColor: '#ECEFF1', color: '#52637A', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#52637A!important' }} />}
/>
);
const lowVulnerability = (
<Chip
label="Low"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#FB8C00!important' }} />}
/>
);
const mediumVulnerability = (
<Chip
label="Medium"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#FB8C00!important' }} />}
/>
);
const highVulnerability = (
<Chip
label="High"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#E53935!important' }} />}
/>
);
const criticalVulnerability = (
<Chip
label="Critical"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#E53935!important' }} />}
/>
);
let result;
switch (status) {
case 'NONE':
result = noneVulnerability;
break;
case 'LOW':
result = lowVulnerability;
break;
case 'MEDIUM':
result = mediumVulnerability;
break;
case 'HIGH':
result = highVulnerability;
break;
case 'CRITICAL':
result = criticalVulnerability;
break;
default:
result = unknownVulnerability;
}
return result;
};
function VulnerabilitiyCard(props) {
const classes = useStyles();
const { cve, name } = props;
@ -225,7 +132,7 @@ function VulnerabilitiyCard(props) {
{cve.Id}
</Typography>
</Stack>
{vulnerabilityCheck(cve.Severity)}
<VulnerabilityChipCheck vulnerabilitySeverity={cve.Severity} />
<Stack sx={{ flexDirection: 'row' }}>
<Typography variant="body1" align="left" className={classes.values}>
{' '}

View File

@ -0,0 +1,89 @@
import React from 'react';
import {
NoneVulnerabilityIcon,
UnknownVulnerabilityIcon,
LowVulnerabilityIcon,
MediumVulnerabilityIcon,
HighVulnerabilityIcon,
CriticalVulnerabilityIcon,
NoneVulnerabilityChip,
UnknownVulnerabilityChip,
LowVulnerabilityChip,
MediumVulnerabilityChip,
HighVulnerabilityChip,
CriticalVulnerabilityChip,
UnverifiedSignatureIcon,
VerifiedSignatureIcon,
UnverifiedSignatureChip,
VerifiedSignatureChip
} from './vulnerabilityAndSignatureComponents';
const VulnerabilityIconCheck = ({ vulnerabilitySeverity }) => {
let result;
let vulnerabilityStringTitle = '';
if (vulnerabilitySeverity) {
vulnerabilityStringTitle = vulnerabilitySeverity.charAt(0) + vulnerabilitySeverity.substring(1).toLowerCase();
}
switch (vulnerabilitySeverity) {
case 'NONE':
result = <NoneVulnerabilityIcon vulnerabilityStringTitle={vulnerabilityStringTitle} />;
break;
case 'LOW':
result = <LowVulnerabilityIcon vulnerabilityStringTitle={vulnerabilityStringTitle} />;
break;
case 'MEDIUM':
result = <MediumVulnerabilityIcon vulnerabilityStringTitle={vulnerabilityStringTitle} />;
break;
case 'HIGH':
result = <HighVulnerabilityIcon vulnerabilityStringTitle={vulnerabilityStringTitle} />;
break;
case 'CRITICAL':
result = <CriticalVulnerabilityIcon vulnerabilityStringTitle={vulnerabilityStringTitle} />;
break;
default:
result = <UnknownVulnerabilityIcon vulnerabilityStringTitle={vulnerabilityStringTitle} />;
}
return result;
};
const VulnerabilityChipCheck = ({ vulnerabilitySeverity }) => {
let result;
switch (vulnerabilitySeverity) {
case 'NONE':
result = <NoneVulnerabilityChip />;
break;
case 'LOW':
result = <LowVulnerabilityChip />;
break;
case 'MEDIUM':
result = <MediumVulnerabilityChip />;
break;
case 'HIGH':
result = <HighVulnerabilityChip />;
break;
case 'CRITICAL':
result = <CriticalVulnerabilityChip />;
break;
default:
result = <UnknownVulnerabilityChip />;
}
return result;
};
const SignatureIconCheck = ({ isSigned }) => {
if (isSigned) {
return <VerifiedSignatureIcon />;
} else {
return <UnverifiedSignatureIcon />;
}
};
const SignatureChipCheck = ({ isSigned }) => {
if (isSigned) {
return <VerifiedSignatureChip />;
} else {
return <UnverifiedSignatureChip />;
}
};
export { VulnerabilityIconCheck, VulnerabilityChipCheck, SignatureIconCheck, SignatureChipCheck };

View File

@ -0,0 +1,275 @@
import React from 'react';
import { Chip, Tooltip } from '@mui/material';
import PestControlOutlinedIcon from '@mui/icons-material/PestControlOutlined';
import PestControlIcon from '@mui/icons-material/PestControl';
import GppBadOutlinedIcon from '@mui/icons-material/GppBadOutlined';
import GppGoodOutlinedIcon from '@mui/icons-material/GppGoodOutlined';
const NoneVulnerabilityIcon = ({ vulnerabilityStringTitle }) => {
return (
<Tooltip title={`${vulnerabilityStringTitle} Vulnerability`} placement="top">
<PestControlOutlinedIcon
sx={{
color: '#43A047!important',
padding: '0.2rem',
background: '#E8F5E9',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="none-vulnerability-icon"
/>
</Tooltip>
);
};
const UnknownVulnerabilityIcon = ({ vulnerabilityStringTitle }) => {
return (
<Tooltip title={`${vulnerabilityStringTitle} Vulnerability`} placement="top">
<PestControlOutlinedIcon
sx={{
color: '#52637A!important',
padding: '0.2rem',
background: '#ECEFF1',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="unknown-vulnerability-icon"
/>
</Tooltip>
);
};
const LowVulnerabilityIcon = ({ vulnerabilityStringTitle }) => {
return (
<Tooltip title={`${vulnerabilityStringTitle} Vulnerability`} placement="top">
<PestControlOutlinedIcon
sx={{
color: '#FB8C00!important',
padding: '0.2rem',
background: '#FFF3E0',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="low-vulnerability-icon"
/>
</Tooltip>
);
};
const MediumVulnerabilityIcon = ({ vulnerabilityStringTitle }) => {
return (
<Tooltip title={`${vulnerabilityStringTitle} Vulnerability`} placement="top">
<PestControlIcon
sx={{
color: '#FB8C00!important',
padding: '0.2rem',
background: '#FFF3E0',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="medium-vulnerability-icon"
/>
</Tooltip>
);
};
const HighVulnerabilityIcon = ({ vulnerabilityStringTitle }) => {
return (
<Tooltip title={`${vulnerabilityStringTitle} Vulnerability`} placement="top">
<PestControlOutlinedIcon
sx={{
color: '#E53935!important',
padding: '0.2rem',
background: '#FEEBEE',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="high-vulnerability-icon"
/>
</Tooltip>
);
};
const CriticalVulnerabilityIcon = ({ vulnerabilityStringTitle }) => {
return (
<Tooltip title={`${vulnerabilityStringTitle} Vulnerability`} placement="top">
<PestControlIcon
sx={{
color: '#E53935!important',
padding: '0.2rem',
background: '#FEEBEE',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="critical-vulnerability-icon"
/>
</Tooltip>
);
};
const NoneVulnerabilityChip = () => {
return (
<Chip
label="None Vulnerability"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#388E3C!important' }} />}
data-testid="none-vulnerability-chip"
/>
);
};
const UnknownVulnerabilityChip = () => {
return (
<Chip
label="Unknown Vulnerability"
sx={{ backgroundColor: '#ECEFF1', color: '#52637A', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#52637A!important' }} />}
data-testid="unknown-vulnerability-chip"
/>
);
};
const LowVulnerabilityChip = () => {
return (
<Chip
label="Low Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="low-vulnerability-chip"
/>
);
};
const MediumVulnerabilityChip = () => {
return (
<Chip
label="Medium Vulnerability"
sx={{ backgroundColor: '#FFF3E0', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#FB8C00!important' }} />}
data-testid="medium-vulnerability-chip"
/>
);
};
const HighVulnerabilityChip = () => {
return (
<Chip
label="High Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlOutlinedIcon sx={{ color: '#E53935!important' }} />}
data-testid="high-vulnerability-chip"
/>
);
};
const CriticalVulnerabilityChip = () => {
return (
<Chip
label="Critical Vulnerability"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<PestControlIcon sx={{ color: '#E53935!important' }} />}
data-testid="critical-vulnerability-chip"
/>
);
};
const UnverifiedSignatureIcon = () => {
return (
<Tooltip title="Unverified Signature" placement="top">
<GppBadOutlinedIcon
sx={{
color: '#E53935!important',
padding: '0.2rem',
background: '#FEEBEE',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="unverified-icon"
/>
</Tooltip>
);
};
const VerifiedSignatureIcon = () => {
return (
<Tooltip title="Verified Signature" placement="top">
<GppGoodOutlinedIcon
sx={{
color: '#43A047!important',
padding: '0.2rem',
background: '#E8F5E9',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="verified-icon"
/>
</Tooltip>
);
};
const UnverifiedSignatureChip = () => {
return (
<Chip
label="Unverified Signature"
sx={{ backgroundColor: '#FEEBEE', color: '#E53935', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppBadOutlinedIcon sx={{ color: '#E53935!important' }} />}
/>
);
};
const VerifiedSignatureChip = () => {
return (
<Chip
label="Verified Signature"
sx={{ backgroundColor: '#E8F5E9', color: '#388E3C', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<GppGoodOutlinedIcon sx={{ color: '#388E3C!important' }} />}
/>
);
};
export {
NoneVulnerabilityIcon,
UnknownVulnerabilityIcon,
LowVulnerabilityIcon,
MediumVulnerabilityIcon,
HighVulnerabilityIcon,
CriticalVulnerabilityIcon,
NoneVulnerabilityChip,
UnknownVulnerabilityChip,
LowVulnerabilityChip,
MediumVulnerabilityChip,
HighVulnerabilityChip,
CriticalVulnerabilityChip,
UnverifiedSignatureIcon,
VerifiedSignatureIcon,
UnverifiedSignatureChip,
VerifiedSignatureChip
};