Skip to content

Commit

Permalink
patch: signature display redesign
Browse files Browse the repository at this point in the history
Signed-off-by: Raul-Cristian Kele <[email protected]>
  • Loading branch information
raulkele committed Oct 13, 2023
1 parent 19e366e commit 20596fd
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 54 deletions.
1 change: 0 additions & 1 deletion src/components/Explore/Explore.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@ function Explore({ searchInputValue }) {
version={item.latestVersion}
description={item.description}
downloads={item.downloads}
isSigned={item.isSigned}
signatureInfo={item.signatureInfo}
isBookmarked={item.isBookmarked}
vendor={item.vendor}
Expand Down
1 change: 0 additions & 1 deletion src/components/Home/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ function Home() {
version={item.latestVersion}
description={item.description}
downloads={item.downloads}
isSigned={item.isSigned}
signatureInfo={item.signatureInfo}
isBookmarked={item.isBookmarked}
vendor={item.vendor}
Expand Down
32 changes: 21 additions & 11 deletions src/components/Repo/RepoDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ function RepoDetails() {
return lastDate;
};

const getSignatureChips = () => {
return repoDetailData.signatureInfo?.map((si, index) => (
<SignatureIconCheck key={`${si?.tool}${index}`} signatureInfo={[si]} />
));
};

return (
<>
{isLoading ? (
Expand Down Expand Up @@ -271,19 +277,23 @@ function RepoDetails() {
</Stack>
<Stack alignItems="center" sx={{ width: { xs: '100%', md: 'auto' } }} direction="row" spacing={2}>
<VulnerabilityIconCheck vulnerabilitySeverity={repoDetailData?.vulnerabilitySeverity} />
<SignatureIconCheck
isSigned={repoDetailData.isSigned}
signatureInfo={repoDetailData.signatureInfo}
/>
{getSignatureChips()}
</Stack>
{isAuthenticated() && (
<IconButton component="span" onClick={handleBookmarkClick} data-testid="bookmark-button">
{repoDetailData?.isBookmarked ? (
<BookmarkIcon data-testid="bookmarked" />
) : (
<BookmarkBorderIcon data-testid="not-bookmarked" />
)}
</IconButton>
<Stack
alignItems="center"
sx={{ width: { xs: '100%', md: 'auto' } }}
direction="row"
spacing={2}
>
<IconButton component="span" onClick={handleBookmarkClick} data-testid="bookmark-button">
{repoDetailData?.isBookmarked ? (
<BookmarkIcon data-testid="bookmarked" />
) : (
<BookmarkBorderIcon data-testid="not-bookmarked" />
)}
</IconButton>
</Stack>
)}
</Stack>
<Typography gutterBottom className={classes.repoTitle}>
Expand Down
5 changes: 2 additions & 3 deletions src/components/Shared/PreviewCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import repocube3 from '../../assets/repocube-3.png';
import repocube4 from '../../assets/repocube-4.png';

import { isEmpty } from 'lodash';
import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
import { VulnerabilityIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';

// temporary utility to get image
const randomIntFromInterval = (min, max) => {
Expand Down Expand Up @@ -67,7 +67,7 @@ const useStyles = makeStyles(() => ({
function PreviewCard(props) {
const classes = useStyles();
const navigate = useNavigate();
const { name, isSigned, vulnerabilityData, logo } = props;
const { name, vulnerabilityData, logo } = props;

const goToDetails = () => {
navigate(`/image/${encodeURIComponent(name)}`);
Expand Down Expand Up @@ -108,7 +108,6 @@ function PreviewCard(props) {
</Tooltip>
<Stack direction="row" spacing={0.5} sx={{ marginLeft: 'auto', marginRight: 0 }}>
<VulnerabilityIconCheck {...vulnerabilityData} />
<SignatureIconCheck isSigned={isSigned} />
</Stack>
</Stack>
</Grid>
Expand Down
24 changes: 19 additions & 5 deletions src/components/Shared/RepoCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {
import makeStyles from '@mui/styles/makeStyles';
import BookmarkIcon from '@mui/icons-material/Bookmark';
import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder';
import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
import { Markdown } from 'utilities/MarkdowntojsxWrapper';
import filterConstants from 'utilities/filterConstants';
import { useTheme } from '@emotion/react';

// placeholder images
Expand All @@ -36,9 +39,6 @@ import repocube2 from '../../assets/repocube-2.png';
import repocube3 from '../../assets/repocube-3.png';
import repocube4 from '../../assets/repocube-4.png';

import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
import { Markdown } from 'utilities/MarkdowntojsxWrapper';

// temporary utility to get image
const randomIntFromInterval = (min, max) => {
return Math.floor(Math.random() * (max - min + 1) + min);
Expand Down Expand Up @@ -183,7 +183,6 @@ function RepoCard(props) {
platforms,
description,
downloads,
isSigned,
signatureInfo,
lastUpdated,
version,
Expand Down Expand Up @@ -291,7 +290,22 @@ function RepoCard(props) {
<VulnerabilityIconCheck {...vulnerabilityData} className="hide-on-mobile" />
</div>
<div className="hide-on-mobile">
<SignatureIconCheck isSigned={isSigned} signatureInfo={signatureInfo} className="hide-on-mobile" />
{signatureInfo?.map((s) => s.tool).includes(filterConstants.signatureToolConstants.COSIGN) && (
<SignatureIconCheck
signatureInfo={signatureInfo.filter(
(si) => si.tool == filterConstants.signatureToolConstants.COSIGN
)}
/>
)}
</div>
<div className="hide-on-mobile">
{signatureInfo?.map((s) => s.tool).includes(filterConstants.signatureToolConstants.NOTATION) && (
<SignatureIconCheck
signatureInfo={signatureInfo.filter(
(si) => si.tool == filterConstants.signatureToolConstants.NOTATION
)}
/>
)}
</div>
</Stack>
<Tooltip title={description || 'Description not available'} placement="top">
Expand Down
16 changes: 6 additions & 10 deletions src/components/Shared/SignatureTooltip.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import React from 'react';
import React, { useMemo } from 'react';
import { Typography, Stack } from '@mui/material';

import { isEmpty } from 'lodash';
import { getStrongestSignature } from 'utilities/vulnerabilityAndSignatureCheck';

function SignatureTooltip({ isSigned, signatureInfo }) {
const { tool, isTrusted, author } = !isEmpty(signatureInfo)
? signatureInfo[0]
: { tool: 'Unknown', isTrusted: 'Unknown', author: 'Unknown' };
function SignatureTooltip({ signatureInfo }) {
const strongestSignature = useMemo(() => getStrongestSignature(signatureInfo));

return (
<Stack direction="column">
<Typography>{isSigned ? 'Verified Signature' : 'Unverified Signature'}</Typography>
<Typography>Tool: {tool}</Typography>
<Typography>Trusted: {!isEmpty(isTrusted) ? isTrusted : 'Unknown'}</Typography>
<Typography>Author: {!isEmpty(author) ? author : 'Unknown'}</Typography>
<Typography>Tool: {!isEmpty(strongestSignature) ? strongestSignature.tool : 'Unknown'}</Typography>
<Typography>Author: {strongestSignature.author || 'Unknown'}</Typography>
</Stack>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Tag/Tabs/DependsOn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function DependsOn(props) {
repoName={dependence.repoName}
tag={dependence.tag}
vendor={dependence.vendor}
isSigned={dependence.isSigned}
signatureInfo={dependence.signatureInfo}
manifests={dependence.manifests}
key={index}
lastUpdated={dependence.lastUpdated}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Tag/Tabs/IsDependentOn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function IsDependentOn(props) {
repoName={dependence.repoName}
tag={dependence.tag}
vendor={dependence.vendor}
isSigned={dependence.isSigned}
signatureInfo={dependence.signatureInfo}
manifests={dependence.manifests}
key={index}
lastUpdated={dependence.lastUpdated}
Expand Down
11 changes: 7 additions & 4 deletions src/components/Tag/TagDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@ function TagDetails() {
}
};

const getSignatureChips = () => {
return imageDetailData.signatureInfo?.map((si, index) => (
<SignatureIconCheck key={`${si?.tool}${index}`} signatureInfo={[si]} />
));
};

return (
<>
{isLoading ? (
Expand Down Expand Up @@ -260,10 +266,7 @@ function TagDetails() {
vulnerabilitySeverity={imageDetailData.vulnerabiltySeverity}
count={imageDetailData.vulnerabilityCount}
/>
<SignatureIconCheck
isSigned={imageDetailData.isSigned}
signatureInfo={imageDetailData.signatureInfo}
/>
{getSignatureChips()}
</Stack>
</Stack>
<Stack direction="row" alignItems="center" spacing="1rem">
Expand Down
7 changes: 6 additions & 1 deletion src/utilities/filterConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ const archFilters = [
}
];

const filterConstants = { osFilters, imageFilters, archFilters };
const signatureToolConstants = {
COSIGN: 'cosign',
NOTATION: 'notation'
};

const filterConstants = { osFilters, imageFilters, archFilters, signatureToolConstants };

export default filterConstants;
4 changes: 2 additions & 2 deletions src/utilities/objectModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ const mapSignatureInfo = (signatureInfo) => {
return signatureInfo
? {
tool: signatureInfo.Tool,
isTrusted: signatureInfo.IsTrusted?.toString(),
isTrusted: signatureInfo.IsTrusted,
author: signatureInfo.Author
}
: {
tool: 'Unknown',
isTrusted: 'Unknown',
isTrusted: false,
author: 'Unknown'
};
};
Expand Down
42 changes: 28 additions & 14 deletions src/utilities/vulnerabilityAndSignatureCheck.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isEmpty } from 'lodash';
import React from 'react';
import {
NoneVulnerabilityIcon,
Expand All @@ -17,9 +18,18 @@ import {
UnknownVulnerabilityIcon,
UnknownVulnerabilityChip,
FailedScanIcon,
FailedScanChip
FailedScanChip,
NotTrustedSignatureIcon,
NotTrustedSignatureChip
} from './vulnerabilityAndSignatureComponents';

const getStrongestSignature = (signatureInfo) => {
if (isEmpty(signatureInfo)) return null;
const trusted = signatureInfo.find((si) => si.isTrusted);
if (!isEmpty(trusted)) return trusted;
return signatureInfo[0];
};

const VulnerabilityIconCheck = ({ vulnerabilitySeverity }) => {
let result;
let vulnerabilityStringTitle = '';
Expand Down Expand Up @@ -84,20 +94,24 @@ const VulnerabilityChipCheck = ({ vulnerabilitySeverity }) => {
return result;
};

const SignatureIconCheck = ({ isSigned, signatureInfo }) => {
if (isSigned) {
return <VerifiedSignatureIcon signatureInfo={signatureInfo} />;
} else {
return <UnverifiedSignatureIcon signatureInfo={signatureInfo} />;
}
const SignatureIconCheck = ({ signatureInfo }) => {
const strongestSignature = getStrongestSignature(signatureInfo);
if (strongestSignature === null) return <UnverifiedSignatureIcon signatureInfo={signatureInfo} />;
if (strongestSignature.isTrusted) return <VerifiedSignatureIcon signatureInfo={signatureInfo} />;
return <NotTrustedSignatureIcon signatureInfo={signatureInfo} />;
};

const SignatureChipCheck = ({ isSigned }) => {
if (isSigned) {
return <VerifiedSignatureChip />;
} else {
return <UnverifiedSignatureChip />;
}
const SignatureChipCheck = ({ signatureInfo }) => {
const strongestSignature = getStrongestSignature(signatureInfo);
if (strongestSignature === null) return <UnverifiedSignatureChip signatureInfo={signatureInfo} />;
if (strongestSignature.isTrusted) return <VerifiedSignatureChip signatureInfo={signatureInfo} />;
return <NotTrustedSignatureChip signatureInfo={signatureInfo} />;
};

export { VulnerabilityIconCheck, VulnerabilityChipCheck, SignatureIconCheck, SignatureChipCheck };
export {
VulnerabilityIconCheck,
VulnerabilityChipCheck,
SignatureIconCheck,
SignatureChipCheck,
getStrongestSignature
};
39 changes: 39 additions & 0 deletions src/utilities/vulnerabilityAndSignatureComponents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,28 @@ const UnverifiedSignatureIcon = ({ signatureInfo }) => {
</Tooltip>
);
};

const NotTrustedSignatureIcon = ({ signatureInfo }) => {
return (
<Tooltip title={<SignatureTooltip isSigned={true} signatureInfo={signatureInfo} />} placement="top">
<VerifiedShieldIcon
viewBox="0 0 24 24"
sx={{
backgroundColor: '#FCE2B8!important',
color: '#FB8C00',
alignSelf: 'center',
padding: '0.2rem',
background: '#E8F5E9',
borderRadius: '1rem',
height: '1.5rem',
width: '1.6rem'
}}
data-testid="verified-icon"
/>
</Tooltip>
);
};

const VerifiedSignatureIcon = ({ signatureInfo }) => {
return (
<Tooltip title={<SignatureTooltip isSigned={true} signatureInfo={signatureInfo} />} placement="top">
Expand Down Expand Up @@ -291,6 +313,21 @@ const UnverifiedSignatureChip = () => {
/>
);
};

const NotTrustedSignatureChip = () => {
return (
<Chip
label="Signature not trusted"
sx={{ backgroundColor: '#FCE2B8!important', color: '#FB8C00', fontSize: '0.8125rem' }}
variant="filled"
onDelete={() => {
return;
}}
deleteIcon={<NotTrustedSignatureIcon sx={{ color: '#FB8C00!important' }} />}
/>
);
};

const VerifiedSignatureChip = () => {
return (
<Chip
Expand Down Expand Up @@ -319,8 +356,10 @@ export {
HighVulnerabilityChip,
CriticalVulnerabilityChip,
UnverifiedSignatureIcon,
NotTrustedSignatureIcon,
VerifiedSignatureIcon,
UnverifiedSignatureChip,
NotTrustedSignatureChip,
VerifiedSignatureChip,
FailedScanIcon,
FailedScanChip
Expand Down

0 comments on commit 20596fd

Please sign in to comment.