Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add info dialog & login/logout for provider #212

Merged
merged 47 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
48d7a54
Add ProviderInfoDialog component
aleksandr-slobodian Sep 6, 2024
eacecca
Add useProviderInfoDialog hook
aleksandr-slobodian Sep 6, 2024
e600385
Add Info button to topbar
aleksandr-slobodian Sep 6, 2024
3866823
Add providerInfoDialog to app
aleksandr-slobodian Sep 6, 2024
414431c
Add login/logout provider button
aleksandr-slobodian Sep 9, 2024
3fcc07e
Merge branch 'main' into aslobodian/add-provider-info-dialog
aleksandr-slobodian Sep 11, 2024
329dcc8
Fix login/logout provider
aleksandr-slobodian Sep 16, 2024
fc914e7
Improve add/remove provider
aleksandr-slobodian Sep 17, 2024
050f0f4
Improve CertificatesTopbar
aleksandr-slobodian Sep 17, 2024
5628978
Merge branch 'main' into aslobodian/add-provider-info-dialog
aleksandr-slobodian Sep 18, 2024
9e58e05
Fix and add tests for CertificatesTopbar
aleksandr-slobodian Sep 18, 2024
030d2dd
Fix certificate list loading skeleton
aleksandr-slobodian Sep 18, 2024
678aa2f
Fix dialogs display
aleksandr-slobodian Sep 18, 2024
fa19dab
Add more properties to ProviderInfoDialog
aleksandr-slobodian Sep 18, 2024
0c7dc2c
Add isRemovable propertie to ProviderInfoDialog
aleksandr-slobodian Sep 18, 2024
11bea41
Refactoring useApp hook
aleksandr-slobodian Sep 19, 2024
4be1db6
Closes the dialogs belonging to the extracted token
aleksandr-slobodian Sep 19, 2024
e164734
Disable the "Delete Certificate" button when you are not logged in
aleksandr-slobodian Sep 19, 2024
be6cad7
Add certificate with privat key icon to certificate list item
aleksandr-slobodian Sep 19, 2024
1c3dcbc
Add title to copy certificate button in certificates list
aleksandr-slobodian Sep 19, 2024
3a6bd48
Add certificate with privat key label to certificate list item
aleksandr-slobodian Sep 19, 2024
077f0af
Change information button text
aleksandr-slobodian Sep 19, 2024
134f6d9
Add toast when provider doesn’t support signing in
aleksandr-slobodian Sep 19, 2024
0319208
Add action buttons overlay for certificate list item
aleksandr-slobodian Sep 19, 2024
e632b3c
Hide "New" & "Delete" certificate buttons when provider is readOnly
aleksandr-slobodian Sep 20, 2024
a8d0307
Add tests for ProviderInfoDialog component
aleksandr-slobodian Sep 20, 2024
cd8cbe5
Improve CertificatesTopbar tests
aleksandr-slobodian Sep 20, 2024
0b84428
Add test for useProviderInfoDialog hook
aleksandr-slobodian Sep 20, 2024
2a3161d
Merge branch 'main' into aslobodian/add-provider-info-dialog
aleksandr-slobodian Sep 24, 2024
765be04
Add tests for CertificateDeleteDialog component
aleksandr-slobodian Sep 24, 2024
2282471
Add test for useCertificateDeleteDialog hook
aleksandr-slobodian Sep 24, 2024
1ec9381
Add tests for CertificateViewerDialog component
aleksandr-slobodian Sep 24, 2024
ee5b67e
Add test for useCertificateViewerDialog hook
aleksandr-slobodian Sep 24, 2024
177ca9e
Change version
aleksandr-slobodian Sep 24, 2024
3311fc2
Fix certificate type label
aleksandr-slobodian Sep 26, 2024
f833573
Fix certificate creation button
aleksandr-slobodian Sep 26, 2024
52403df
Fix certificate creation button
aleksandr-slobodian Sep 27, 2024
687297f
Fix reload provider
aleksandr-slobodian Oct 1, 2024
97ba205
Fix tests
aleksandr-slobodian Oct 1, 2024
8eeb8df
Merge branch 'main' into aslobodian/add-provider-info-dialog
aleksandr-slobodian Oct 8, 2024
13518aa
Change version
aleksandr-slobodian Oct 9, 2024
fca8da0
Merge branch 'main' into aslobodian/add-provider-info-dialog
aleksandr-slobodian Oct 11, 2024
2dceb4e
Fix get data
aleksandr-slobodian Oct 14, 2024
9214e4d
Fix certificate type label styles
aleksandr-slobodian Oct 14, 2024
a86a35d
Remove console
aleksandr-slobodian Oct 14, 2024
8371efc
Merge branch 'main' into aslobodian/add-provider-info-dialog
aleksandr-slobodian Oct 17, 2024
4c95032
Change version
aleksandr-slobodian Oct 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@peculiar/fortify-tools",
"homepage": "https://tools.fortifyapp.com",
"version": "2.0.3",
"version": "2.0.5",
"author": "PeculiarVentures Team",
"license": "MIT",
"private": true,
Expand Down
44 changes: 36 additions & 8 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useSortList } from "./hooks/sort-list";
import { useSearchList } from "./hooks/search-list";
import { useCertificateImportDialog } from "./dialogs/certificate-import-dialog";
import { useCertificateCreateDialog } from "./dialogs/certificate-create-dialog";
import { useProviderInfoDialog } from "./dialogs/provider-info-dialog";

import styles from "./app.module.scss";

Expand All @@ -21,13 +22,19 @@ export function App() {
fetching,
challenge,
providers,
currentProviderId,
currentProvider,
certificates,
isCurrentProviderLogedin,
handleCertificatesDataReload,
handleProviderChange,
handleRetryConection,
handleProviderLoginLogout,
handleProviderResetAndRefreshList,
} = useApp();

const currentProviderId = currentProvider?.id;
const isCurrentProviderReadOnly = Boolean(currentProvider?.readOnly);

const {
searchedText,
list: searchedCertificate,
Expand All @@ -38,6 +45,7 @@ export function App() {
open: handleCertificateDeleteDialogOpen,
dialog: certificateDeleteDialog,
} = useCertificateDeleteDialog({
providers,
fortifyClient,
onSuccess: (providerId) => {
handleCertificatesDataReload(providerId);
Expand Down Expand Up @@ -78,7 +86,12 @@ export function App() {
const {
open: handleCertificateViewerDialogOpen,
dialog: certificateViewerDialog,
} = useCertificateViewerDialog();
} = useCertificateViewerDialog({
providers,
});

const { open: handleProviderInfoDialogOpen, dialog: providerInfoDialog } =
useProviderInfoDialog({ providers });

return (
<>
Expand All @@ -92,13 +105,20 @@ export function App() {
</CertificatesSidebar>
<CertificatesTopbar
searchValue={searchedText}
isDisabled={!currentProviderId}
isReadOnly={
isCurrentProviderReadOnly || fetching.certificates === "rejected"
}
className={styles.top_bar}
onSearch={handleSearch}
onImport={handleCertificateImportDialogOpen}
onCreate={handleCertificateCreateDialogOpen}
onReload={() =>
currentProviderId && handleCertificatesDataReload(currentProviderId)
onReload={handleProviderResetAndRefreshList}
onInfo={() =>
currentProvider && handleProviderInfoDialogOpen(currentProvider)
}
isLoggedIn={isCurrentProviderLogedin}
onLoginLogout={handleProviderLoginLogout}
></CertificatesTopbar>
<CertificatesList
currentSortName={currentSortName}
Expand All @@ -110,16 +130,24 @@ export function App() {
onViewDetails={handleCertificateViewerDialogOpen}
loading={!fetching.certificates || fetching.certificates === "pending"}
highlightedText={searchedText}
isLoggedIn={isCurrentProviderLogedin}
isReadOnly={isCurrentProviderReadOnly}
/>
<FetchingStatusOwerlay
fetching={fetching}
challenge={challenge}
onReload={handleRetryConection}
/>
{certificateViewerDialog()}
{certificateDeleteDialog()}
{certificateImportDialog()}
{certificateCreateDialog()}
{providers.length ? (
<>
{certificateViewerDialog()}
{certificateDeleteDialog()}
{certificateImportDialog()}
{certificateCreateDialog()}
{providerInfoDialog()}
</>
) : null}

<div className={styles.certificate_list_corners_backdrop}></div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CertificateDeleteDialog } from "./CertificateDeleteDialog";
const meta: Meta<typeof CertificateDeleteDialog> = {
title: "Components/CertificateDeleteDialog",
component: CertificateDeleteDialog,
tags: ["!autodocs"],
};

export default meta;
Expand All @@ -15,11 +16,3 @@ export const Default: Story = {
certificateId: "12345",
},
};

export const Loading: Story = {
args: {
certificateName: "Certificate Name",
certificateId: "12345",
loading: true,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ComponentProps } from "react";
import { render, userEvent, screen } from "@testing";
import { CertificateDeleteDialog } from "./CertificateDeleteDialog";

describe("<CertificateDeleteDialog />", () => {
const defaultProps: ComponentProps<typeof CertificateDeleteDialog> = {
certificateName: "Certificate Name",
certificateId: "1",
onDialogClose: vi.fn(),
onDeleteClick: vi.fn((data) => data),
};

it("Should render and handle buttons click", async () => {
render(<CertificateDeleteDialog {...defaultProps} />);

expect(
screen.getByText(
`Are you sure you want to delete “${defaultProps.certificateName}”?`
)
).toBeInTheDocument();

await userEvent.click(screen.getByRole("button", { name: /Cancel/ }));

expect(defaultProps.onDialogClose).toBeCalledTimes(1);

await userEvent.click(screen.getByRole("button", { name: /Delete/ }));

expect(defaultProps.onDeleteClick).toBeCalledTimes(1);
expect(defaultProps.onDeleteClick).toBeCalledWith(
defaultProps.certificateId
);
});

it("Should render loading", () => {
render(<CertificateDeleteDialog {...defaultProps} loading={true} />);

expect(screen.getByText(/Deleting certificate/)).toBeInTheDocument();
});
});
30 changes: 24 additions & 6 deletions src/components/certificate-type-label/CertificateTypeLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,48 @@ import { ICertificate } from "@peculiar/fortify-client-core";
import { useTranslation } from "react-i18next";
import clsx from "clsx";
import { Typography } from "@peculiar/react-components";
import CertificateIcon from "../../icons/certificate.svg?react";
import CertificateIcon from "../../icons/certificate-30.svg?react";
import CertificateWithKeyIcon from "../../icons/certificate-with-key-30.svg?react";
import styles from "./styles/index.module.scss";

interface CertificateTypeLabelProps {
type: ICertificate["type"];
withPrivatKey: boolean;
className?: ComponentProps<"div">["className"];
}

export const CertificateTypeLabel: React.FunctionComponent<
CertificateTypeLabelProps
> = (props) => {
const { type, className } = props;
const { type, className, withPrivatKey } = props;
const { t } = useTranslation();

return (
<div className={clsx(className, styles.certificate_type_label)}>
{type === "x509" ? (
<>
<span className={styles.icon_wrapper}>
<CertificateIcon />
{withPrivatKey ? <CertificateWithKeyIcon /> : <CertificateIcon />}
</span>
<span>
<Typography
variant="s2"
color="black"
className={styles.label_part}
>
{t("certificates.list.cell.certificate")}
</Typography>
{withPrivatKey ? (
<Typography
variant="b2"
color="black"
className={styles.label_part}
>
{" "}
{t("certificates.list.cell.with-privat-key")}
</Typography>
) : undefined}
</span>
<Typography variant="s2" color="black">
{t("certificates.list.cell.certificate")}
</Typography>
</>
) : (
<Typography variant="s2" color="black">
Expand Down
20 changes: 12 additions & 8 deletions src/components/certificate-type-label/styles/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@
display: flex;
gap: var(--pv-size-base-2);
align-items: center;
.icon_wrapper {
display: flex;
flex-direction: column;
justify-content: center;
}
.icon_wrapper {
display: flex;
flex-direction: column;
justify-content: center;
color: var(--pv-color-gray-9);

width: var(--pv-size-base-6);
svg {
width: var(--pv-size-base-6);
svg {
width: var(--pv-size-base-6);
height: var(--pv-size-base-6);
}
height: var(--pv-size-base-6);
}
}
.label_part {
display: inline;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { render, userEvent, screen } from "@testing";
import { CertificateViewerDialog } from "./CertificateViewerDialog";
import { CertificateProps } from "../../types";

vi.mock("@peculiar/certificates-viewer-react", () => ({
PeculiarCertificateViewer: () => "x509 certificate viewer component",
PeculiarCsrViewer: () => "CSR certificate viewer component",
}));

describe("<CertificateViewerDialog />", () => {
const certificate = {
raw: new ArrayBuffer(0),
subjectName: "Certificate name",
type: "x509",
label: "Certificate name",
subject: {
commonName: "Certificate name",
},
} as unknown as CertificateProps;

it("Should render as x509 and handle close", async () => {
const onCloseMock = vi.fn();

render(
<CertificateViewerDialog
certificate={certificate}
onClose={onCloseMock}
/>
);

expect(screen.getByText(`“${certificate.label}” details`));
expect(screen.getByText(/x509 certificate viewer component/));

await userEvent.click(screen.getByRole("button", { name: /Cancel/ }));

expect(onCloseMock).toBeCalledTimes(1);
});

it("Should render as CSR", async () => {
render(
<CertificateViewerDialog
certificate={
{ ...certificate, type: "csr" } as unknown as CertificateProps
}
onClose={vi.fn()}
/>
);
expect(screen.getByText(/CSR certificate viewer component/));
});
});
Loading