diff --git a/src/__tests__/Explore/Explore.test.js b/src/__tests__/Explore/Explore.test.js
index b19c54b9..8568cd73 100644
--- a/src/__tests__/Explore/Explore.test.js
+++ b/src/__tests__/Explore/Explore.test.js
@@ -1,4 +1,4 @@
-import { render, screen, waitFor } from '@testing-library/react';
+import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { api } from 'api';
import Explore from 'components/Explore/Explore';
@@ -38,7 +38,7 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: 'w',
- IsSigned: false,
+ SignatureInfo: [],
Licenses: '',
Vendor: '',
Labels: '',
@@ -63,7 +63,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: false,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: false,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -88,7 +99,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -113,7 +135,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -138,7 +171,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -167,7 +211,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -192,7 +247,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: 'author1'
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: 'author2'
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -225,7 +291,7 @@ const filteredMockImageListWindows = () => {
};
const filteredMockImageListSigned = () => {
- const filteredRepos = mockImageList.GlobalSearch.Repos.filter((r) => r.NewestImage.IsSigned);
+ const filteredRepos = mockImageList.GlobalSearch.Repos.filter((r) => r.NewestImage.SignatureInfo?.length > 0);
return {
GlobalSearch: {
Page: { TotalCount: 6, ItemCount: 6 },
@@ -273,7 +339,22 @@ describe('Explore component', () => {
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
render();
expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(1);
- expect(await screen.findAllByTestId('verified-icon')).toHaveLength(6);
+ expect(await screen.findAllByTestId('untrusted-icon')).toHaveLength(2);
+ expect(await screen.findAllByTestId('verified-icon')).toHaveLength(10);
+
+ const allUntrustedSignaturesIcons = await screen.findAllByTestId("untrusted-icon");
+ fireEvent.mouseOver(allUntrustedSignaturesIcons[0]);
+ expect(await screen.findByText("Signed-by: Unknown")).toBeInTheDocument();
+ const allTrustedSignaturesIcons = await screen.findAllByTestId("verified-icon");
+ fireEvent.mouseOver(allTrustedSignaturesIcons[8]);
+ expect(await screen.findByText("Tool: cosign")).toBeInTheDocument();
+ expect(await screen.findByText("Signed-by: author1")).toBeInTheDocument();
+ fireEvent.mouseOver(allTrustedSignaturesIcons[9]);
+ expect(await screen.findByText("Tool: notation")).toBeInTheDocument();
+ expect(await screen.findByText("Signed-by: author2")).toBeInTheDocument();
+ const allNoSignedIcons = await screen.findAllByTestId("unverified-icon");
+ fireEvent.mouseOver(allNoSignedIcons[0]);
+ expect(await screen.findByText("Not signed")).toBeInTheDocument();
});
it('renders vulnerability icons', async () => {
diff --git a/src/__tests__/HomePage/Home.test.js b/src/__tests__/HomePage/Home.test.js
index 0ef55a52..3a5073f0 100644
--- a/src/__tests__/HomePage/Home.test.js
+++ b/src/__tests__/HomePage/Home.test.js
@@ -32,7 +32,7 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: 'w',
- IsSigned: false,
+ SignatureInfo: [],
Licenses: '',
Vendor: '',
Labels: '',
@@ -49,7 +49,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -66,7 +77,18 @@ const mockImageList = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -91,7 +113,7 @@ const mockImageListRecent = {
NewestImage: {
Tag: 'latest',
Description: 'w',
- IsSigned: false,
+ SignatureInfo: [],
Licenses: '',
Vendor: '',
Labels: '',
@@ -108,7 +130,18 @@ const mockImageListRecent = {
NewestImage: {
Tag: 'latest',
Description: '',
- IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: ''
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: ''
+ }
+ ],
Licenses: '',
Vendor: '',
Labels: '',
@@ -230,7 +263,7 @@ describe('Home component', () => {
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageListRecent } });
render();
expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(4);
- expect(await screen.findAllByTestId('verified-icon')).toHaveLength(5);
+ expect(await screen.findAllByTestId('verified-icon')).toHaveLength(10);
});
it('renders vulnerability icons', async () => {
diff --git a/src/__tests__/RepoPage/Repo.test.js b/src/__tests__/RepoPage/Repo.test.js
index b95d357c..98f5b175 100644
--- a/src/__tests__/RepoPage/Repo.test.js
+++ b/src/__tests__/RepoPage/Repo.test.js
@@ -51,6 +51,18 @@ const mockRepoDetailsData = {
NewestImage: {
RepoName: 'mongo',
IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: 'author1'
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: 'author2'
+ }
+ ],
Vulnerabilities: {
MaxSeverity: 'CRITICAL',
Count: 15
@@ -285,6 +297,20 @@ describe('Repo details component', () => {
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(1);
});
+ it('renders signature icons', async () => {
+ jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } });
+ render();
+ expect(await screen.findAllByTestId('verified-icon')).toHaveLength(2);
+
+ const allTrustedSignaturesIcons = await screen.findAllByTestId("verified-icon");
+ fireEvent.mouseOver(allTrustedSignaturesIcons[0]);
+ expect(await screen.findByText("Tool: cosign")).toBeInTheDocument();
+ expect(await screen.findByText("Signed-by: author1")).toBeInTheDocument();
+ fireEvent.mouseOver(allTrustedSignaturesIcons[1]);
+ expect(await screen.findByText("Tool: notation")).toBeInTheDocument();
+ expect(await screen.findByText("Signed-by: author2")).toBeInTheDocument();
+ });
+
it("should log error if data can't be fetched", async () => {
jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} });
const error = jest.spyOn(console, 'error').mockImplementation(() => {});
diff --git a/src/__tests__/TagPage/TagDetails.test.js b/src/__tests__/TagPage/TagDetails.test.js
index d04cd1aa..e1143dd5 100644
--- a/src/__tests__/TagPage/TagDetails.test.js
+++ b/src/__tests__/TagPage/TagDetails.test.js
@@ -174,7 +174,20 @@ const mockImage = {
MaxSeverity: 'CRITICAL',
Count: 10
},
- Vendor: 'CentOS'
+ Vendor: 'CentOS',
+ IsSigned: true,
+ SignatureInfo: [
+ {
+ Tool: 'cosign',
+ IsTrusted: true,
+ Author: 'author1'
+ },
+ {
+ Tool: 'notation',
+ IsTrusted: true,
+ Author: 'author2'
+ }
+ ]
}
};
@@ -963,6 +976,20 @@ describe('Tags details', () => {
expect(await screen.findByTestId('high-vulnerability-icon')).toBeInTheDocument();
});
+ it('renders signature icons', async () => {
+ jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } });
+ render();
+ expect(await screen.findAllByTestId('verified-icon')).toHaveLength(2);
+
+ const allTrustedSignaturesIcons = await screen.findAllByTestId("verified-icon");
+ fireEvent.mouseOver(allTrustedSignaturesIcons[0]);
+ expect(await screen.findByText("Tool: cosign")).toBeInTheDocument();
+ expect(await screen.findByText("Signed-by: author1")).toBeInTheDocument();
+ fireEvent.mouseOver(allTrustedSignaturesIcons[1]);
+ expect(await screen.findByText("Tool: notation")).toBeInTheDocument();
+ expect(await screen.findByText("Signed-by: author2")).toBeInTheDocument();
+ });
+
it('should copy the docker pull string to clipboard', async () => {
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } });
render();
diff --git a/src/components/Explore/Explore.jsx b/src/components/Explore/Explore.jsx
index 8ccfaf5f..ccaf3931 100644
--- a/src/components/Explore/Explore.jsx
+++ b/src/components/Explore/Explore.jsx
@@ -221,7 +221,6 @@ function Explore({ searchInputValue }) {
description={item.description}
downloads={item.downloads}
stars={item.stars}
- isSigned={item.isSigned}
signatureInfo={item.signatureInfo}
isBookmarked={item.isBookmarked}
isStarred={item.isStarred}
diff --git a/src/components/Home/Home.jsx b/src/components/Home/Home.jsx
index addd47d2..c36424d5 100644
--- a/src/components/Home/Home.jsx
+++ b/src/components/Home/Home.jsx
@@ -261,7 +261,6 @@ function Home() {
description={item.description}
downloads={item.downloads}
stars={item.stars}
- isSigned={item.isSigned}
signatureInfo={item.signatureInfo}
isBookmarked={item.isBookmarked}
isStarred={item.isStarred}
diff --git a/src/components/Repo/RepoDetails.jsx b/src/components/Repo/RepoDetails.jsx
index f31d2dc2..d04b76b1 100644
--- a/src/components/Repo/RepoDetails.jsx
+++ b/src/components/Repo/RepoDetails.jsx
@@ -11,6 +11,7 @@ import { host } from '../../host';
import { useParams, useNavigate, createSearchParams } from 'react-router-dom';
import { mapToRepoFromRepoInfo } from 'utilities/objectModels';
import { isAuthenticated } from 'utilities/authUtilities';
+import filterConstants from 'utilities/filterConstants';
// components
import { Card, CardContent, CardMedia, Chip, Grid, Stack, Tooltip, Typography, IconButton } from '@mui/material';
@@ -260,6 +261,28 @@ function RepoDetails() {
return lastDate;
};
+ const getSignatureChips = () => {
+ const cosign = repoDetailData.signatureInfo
+ ?.map((s) => s.tool)
+ .includes(filterConstants.signatureToolConstants.COSIGN)
+ ? repoDetailData.signatureInfo.filter((si) => si.tool == filterConstants.signatureToolConstants.COSIGN)
+ : null;
+ const notation = repoDetailData.signatureInfo
+ ?.map((s) => s.tool)
+ .includes(filterConstants.signatureToolConstants.NOTATION)
+ ? repoDetailData.signatureInfo.filter((si) => si.tool == filterConstants.signatureToolConstants.NOTATION)
+ : null;
+ const sigArray = [];
+ if (cosign) sigArray.push(cosign);
+ if (notation) sigArray.push(notation);
+ if (sigArray.length === 0) return ;
+ return sigArray.map((sig, index) => (
+
+
+
+ ));
+ };
+
return (
<>
{isLoading ? (
@@ -288,10 +311,7 @@ function RepoDetails() {
-
+ {getSignatureChips()}
{isAuthenticated() && (
@@ -304,13 +324,20 @@ function RepoDetails() {
)}
{isAuthenticated() && (
-
- {repoDetailData?.isBookmarked ? (
-
- ) : (
-
- )}
-
+
+
+ {repoDetailData?.isBookmarked ? (
+
+ ) : (
+
+ )}
+
+
)}
diff --git a/src/components/Shared/PreviewCard.jsx b/src/components/Shared/PreviewCard.jsx
index 919d91c2..380f3081 100644
--- a/src/components/Shared/PreviewCard.jsx
+++ b/src/components/Shared/PreviewCard.jsx
@@ -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) => {
@@ -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)}`);
@@ -108,7 +108,6 @@ function PreviewCard(props) {
-
diff --git a/src/components/Shared/RepoCard.jsx b/src/components/Shared/RepoCard.jsx
index 57188857..e196a092 100644
--- a/src/components/Shared/RepoCard.jsx
+++ b/src/components/Shared/RepoCard.jsx
@@ -32,15 +32,16 @@ import StarIcon from '@mui/icons-material/Star';
import StarBorderIcon from '@mui/icons-material/StarBorder';
import { useTheme } from '@emotion/react';
+import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck';
+import { Markdown } from 'utilities/MarkdowntojsxWrapper';
+import filterConstants from 'utilities/filterConstants';
+
// placeholder images
import repocube1 from '../../assets/repocube-1.png';
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);
@@ -186,7 +187,6 @@ function RepoCard(props) {
description,
downloads,
stars,
- isSigned,
signatureInfo,
lastUpdated,
version,
@@ -296,6 +296,24 @@ function RepoCard(props) {
);
};
+ const getSignatureChips = () => {
+ const cosign = signatureInfo?.map((s) => s.tool).includes(filterConstants.signatureToolConstants.COSIGN)
+ ? signatureInfo.filter((si) => si.tool == filterConstants.signatureToolConstants.COSIGN)
+ : null;
+ const notation = signatureInfo?.map((s) => s.tool).includes(filterConstants.signatureToolConstants.NOTATION)
+ ? signatureInfo.filter((si) => si.tool == filterConstants.signatureToolConstants.NOTATION)
+ : null;
+ const sigArray = [];
+ if (cosign) sigArray.push(cosign);
+ if (notation) sigArray.push(notation);
+ if (sigArray.length === 0) return ;
+ return sigArray.map((sig, index) => (
+
+
+
+ ));
+ };
+
return (
-
+
-
-
-
+ {getSignatureChips()}
diff --git a/src/components/Shared/SignatureTooltip.jsx b/src/components/Shared/SignatureTooltip.jsx
index c4433b48..bde8ae17 100644
--- a/src/components/Shared/SignatureTooltip.jsx
+++ b/src/components/Shared/SignatureTooltip.jsx
@@ -1,19 +1,17 @@
-import React from 'react';
+import React, { useMemo } from 'react';
import { Typography, Stack } from '@mui/material';
-
import { isEmpty } from 'lodash';
+import { getStrongestSignature, getAllAuthorsOfSignatures } 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 (
+ return isEmpty(strongestSignature) ? (
+ Not signed
+ ) : (
- {isSigned ? 'Verified Signature' : 'Unverified Signature'}
- Tool: {tool}
- Trusted: {!isEmpty(isTrusted) ? isTrusted : 'Unknown'}
- Author: {!isEmpty(author) ? author : 'Unknown'}
+ Tool: {strongestSignature?.tool || 'Unknown'}
+ Signed-by: {getAllAuthorsOfSignatures(signatureInfo) || 'Unknown'}
);
}
diff --git a/src/components/Tag/Tabs/DependsOn.jsx b/src/components/Tag/Tabs/DependsOn.jsx
index 56b0ed51..1cfafb37 100644
--- a/src/components/Tag/Tabs/DependsOn.jsx
+++ b/src/components/Tag/Tabs/DependsOn.jsx
@@ -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}
diff --git a/src/components/Tag/Tabs/IsDependentOn.jsx b/src/components/Tag/Tabs/IsDependentOn.jsx
index 4afaf675..03ec2b3d 100644
--- a/src/components/Tag/Tabs/IsDependentOn.jsx
+++ b/src/components/Tag/Tabs/IsDependentOn.jsx
@@ -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}
diff --git a/src/components/Tag/TagDetails.jsx b/src/components/Tag/TagDetails.jsx
index 8242edc5..abe90d48 100644
--- a/src/components/Tag/TagDetails.jsx
+++ b/src/components/Tag/TagDetails.jsx
@@ -5,6 +5,7 @@ import React, { useEffect, useMemo, useState, useRef } from 'react';
import { api, endpoints } from '../../api';
import { host } from '../../host';
import { mapToImage } from '../../utilities/objectModels';
+import filterConstants from 'utilities/filterConstants';
import { isEmpty, head } from 'lodash';
// components
@@ -224,6 +225,28 @@ function TagDetails() {
}
};
+ const getSignatureChips = () => {
+ const cosign = imageDetailData.signatureInfo
+ ?.map((s) => s.tool)
+ .includes(filterConstants.signatureToolConstants.COSIGN)
+ ? imageDetailData.signatureInfo.filter((si) => si.tool == filterConstants.signatureToolConstants.COSIGN)
+ : null;
+ const notation = imageDetailData.signatureInfo
+ ?.map((s) => s.tool)
+ .includes(filterConstants.signatureToolConstants.NOTATION)
+ ? imageDetailData.signatureInfo.filter((si) => si.tool == filterConstants.signatureToolConstants.NOTATION)
+ : null;
+ const sigArray = [];
+ if (cosign) sigArray.push(cosign);
+ if (notation) sigArray.push(notation);
+ if (sigArray.length === 0) return ;
+ return sigArray.map((sig, index) => (
+
+
+
+ ));
+ };
+
return (
<>
{isLoading ? (
@@ -256,15 +279,12 @@ function TagDetails() {
-
+
-
+ {getSignatureChips()}
diff --git a/src/utilities/filterConstants.js b/src/utilities/filterConstants.js
index 8a95591f..25d0501e 100644
--- a/src/utilities/filterConstants.js
+++ b/src/utilities/filterConstants.js
@@ -69,6 +69,11 @@ const archFilters = [
}
];
-const filterConstants = { osFilters, imageFilters, archFilters };
+const signatureToolConstants = {
+ COSIGN: 'cosign',
+ NOTATION: 'notation'
+};
+
+const filterConstants = { osFilters, imageFilters, archFilters, signatureToolConstants };
export default filterConstants;
diff --git a/src/utilities/objectModels.js b/src/utilities/objectModels.js
index 03403858..c8c5d6bb 100644
--- a/src/utilities/objectModels.js
+++ b/src/utilities/objectModels.js
@@ -132,12 +132,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'
};
};
diff --git a/src/utilities/vulnerabilityAndSignatureCheck.jsx b/src/utilities/vulnerabilityAndSignatureCheck.jsx
index 5f679199..dff55ef0 100644
--- a/src/utilities/vulnerabilityAndSignatureCheck.jsx
+++ b/src/utilities/vulnerabilityAndSignatureCheck.jsx
@@ -1,3 +1,4 @@
+import { isEmpty } from 'lodash';
import React from 'react';
import {
NoneVulnerabilityIcon,
@@ -12,14 +13,26 @@ import {
CriticalVulnerabilityChip,
UnverifiedSignatureIcon,
VerifiedSignatureIcon,
- UnverifiedSignatureChip,
- VerifiedSignatureChip,
UnknownVulnerabilityIcon,
UnknownVulnerabilityChip,
FailedScanIcon,
- FailedScanChip
+ FailedScanChip,
+ NotTrustedSignatureIcon
} 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 getAllAuthorsOfSignatures = (signatureInfo) => {
+ if (isEmpty(signatureInfo)) return '';
+ const signatureAuthors = signatureInfo.filter((si) => si.isTrusted).map((si) => si.author);
+ return signatureAuthors.join(',');
+};
+
const VulnerabilityIconCheck = ({ vulnerabilitySeverity }) => {
let result;
let vulnerabilityStringTitle = '';
@@ -84,20 +97,17 @@ const VulnerabilityChipCheck = ({ vulnerabilitySeverity }) => {
return result;
};
-const SignatureIconCheck = ({ isSigned, signatureInfo }) => {
- if (isSigned) {
- return ;
- } else {
- return ;
- }
+const SignatureIconCheck = ({ signatureInfo }) => {
+ const strongestSignature = getStrongestSignature(signatureInfo);
+ if (strongestSignature === null) return ;
+ if (strongestSignature.isTrusted) return ;
+ return ;
};
-const SignatureChipCheck = ({ isSigned }) => {
- if (isSigned) {
- return ;
- } else {
- return ;
- }
+export {
+ VulnerabilityIconCheck,
+ VulnerabilityChipCheck,
+ SignatureIconCheck,
+ getStrongestSignature,
+ getAllAuthorsOfSignatures
};
-
-export { VulnerabilityIconCheck, VulnerabilityChipCheck, SignatureIconCheck, SignatureChipCheck };
diff --git a/src/utilities/vulnerabilityAndSignatureComponents.jsx b/src/utilities/vulnerabilityAndSignatureComponents.jsx
index 76e55177..1ec4e344 100644
--- a/src/utilities/vulnerabilityAndSignatureComponents.jsx
+++ b/src/utilities/vulnerabilityAndSignatureComponents.jsx
@@ -1,9 +1,10 @@
import React from 'react';
-import { Chip, Tooltip } from '@mui/material';
+import { Chip, Tooltip, Badge } from '@mui/material';
import SvgIcon from '@mui/material/SvgIcon';
import { ReactComponent as failedScanBug } from '../assets/failedScan.svg';
import { createSvgIcon } from '@mui/material/utils';
import SignatureTooltip from 'components/Shared/SignatureTooltip';
+import filterConstants from 'utilities/filterConstants';
const FilledBugIcon = createSvgIcon(
,
@@ -14,11 +15,15 @@ const OutlinedBugIcon = createSvgIcon(
'OutlinedBug'
);
const UnverifiedShieldIcon = createSvgIcon(
- ,
+ ,
'UnverifiedShield'
);
-const VerifiedShieldIcon = createSvgIcon(
- ,
+const CVerifiedShieldIcon = createSvgIcon(
+ ,
+ 'VerifiedShield'
+);
+const NVerifiedShieldIcon = createSvgIcon(
+ ,
'VerifiedShield'
);
@@ -222,8 +227,9 @@ const CriticalVulnerabilityChip = () => {
const UnverifiedSignatureIcon = ({ signatureInfo }) => {
return (
- } placement="top">
+ } placement="top">
{
);
};
+
+const NotTrustedSignatureIcon = ({ signatureInfo }) => {
+ return (
+
} placement="top">
+ {(signatureInfo[0]?.tool && signatureInfo[0].tool == filterConstants.signatureToolConstants.NOTATION && (
+
+
+
+ )) ||
+ (signatureInfo[0]?.tool && signatureInfo[0].tool == filterConstants.signatureToolConstants.COSIGN && (
+
+
+
+ ))}
+
+ );
+};
+
const VerifiedSignatureIcon = ({ signatureInfo }) => {
return (
-
} placement="top">
-
+
} placement="top">
+ {(signatureInfo[0]?.tool && signatureInfo[0].tool == filterConstants.signatureToolConstants.NOTATION && (
+
+
+
+ )) ||
+ (signatureInfo[0]?.tool && signatureInfo[0].tool == filterConstants.signatureToolConstants.COSIGN && (
+
+
+
+ ))}
);
};
@@ -270,19 +373,6 @@ const UnverifiedSignatureChip = () => {
/>
);
};
-const VerifiedSignatureChip = () => {
- return (
-
{
- return;
- }}
- deleteIcon={}
- />
- );
-};
export {
NoneVulnerabilityIcon,
@@ -298,9 +388,9 @@ export {
HighVulnerabilityChip,
CriticalVulnerabilityChip,
UnverifiedSignatureIcon,
+ NotTrustedSignatureIcon,
VerifiedSignatureIcon,
UnverifiedSignatureChip,
- VerifiedSignatureChip,
FailedScanIcon,
FailedScanChip
};
diff --git a/tests/utils/test-data-parser.js b/tests/utils/test-data-parser.js
index 24420ec4..fad0971e 100644
--- a/tests/utils/test-data-parser.js
+++ b/tests/utils/test-data-parser.js
@@ -149,7 +149,7 @@ const getRepoListOrderedAlpha = () => {
// };
const getRepoCardNameForLocator = (repo) => {
- return `${repo?.repo} ${repo?.tags[0]?.description?.slice(0, 10)}`;
+ return new RegExp(`${repo?.repo} \\d${repo?.tags[0]?.description?.slice(0, 10)}`);
};
export {