mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 15:40:47 +00:00
Add preliminary dynamically generated CRLs on fetching CA CRL
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
export { CaStatus,CaType } from "./enums";
|
||||
export { CaStatus, CaType } from "./enums";
|
||||
export {
|
||||
useCreateCa,
|
||||
useCreateCertificate,
|
||||
useDeleteCa,
|
||||
useImportCaCertificate,
|
||||
useSignIntermediate,
|
||||
useUpdateCa} from "./mutations";
|
||||
export { useGetCaById, useGetCaCert, useGetCaCsr } from "./queries";
|
||||
useUpdateCa
|
||||
} from "./mutations";
|
||||
export { useGetCaById, useGetCaCert, useGetCaCrl,useGetCaCsr } from "./queries";
|
||||
|
||||
@@ -7,7 +7,8 @@ import { TCertificateAuthority } from "./types";
|
||||
export const caKeys = {
|
||||
getCaById: (caId: string) => [{ caId }, "ca"],
|
||||
getCaCert: (caId: string) => [{ caId }, "ca-cert"],
|
||||
getCaCsr: (caId: string) => [{ caId }, "ca-csr"]
|
||||
getCaCsr: (caId: string) => [{ caId }, "ca-csr"],
|
||||
getCaCrl: (caId: string) => [{ caId }, "ca-crl"]
|
||||
};
|
||||
|
||||
export const useGetCaById = (caId: string) => {
|
||||
@@ -52,3 +53,18 @@ export const useGetCaCsr = (caId: string) => {
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetCaCrl = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaCrl(caId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { crl }
|
||||
} = await apiRequest.get<{
|
||||
crl: string;
|
||||
}>(`/api/v1/pki/ca/${caId}/crl`);
|
||||
return crl;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CertKeyAlgorithm,CertStatus } from "./enums";
|
||||
import { CertKeyAlgorithm, CertStatus,CrlReason } from "./enums";
|
||||
|
||||
export const certStatusToNameMap: { [K in CertStatus]: string } = {
|
||||
[CertStatus.ACTIVE]: "Active",
|
||||
@@ -13,8 +13,48 @@ export const certKeyAlgorithmToNameMap: { [K in CertKeyAlgorithm]: string } = {
|
||||
};
|
||||
|
||||
export const certKeyAlgorithms = [
|
||||
{ label: "RSA 2048", value: CertKeyAlgorithm.RSA_2048 },
|
||||
{ label: "RSA 4096", value: CertKeyAlgorithm.RSA_4096 },
|
||||
{ label: "ECDSA P256", value: CertKeyAlgorithm.ECDSA_P256 },
|
||||
{ label: "ECDSA P384", value: CertKeyAlgorithm.ECDSA_P384 }
|
||||
{ label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.RSA_2048], value: CertKeyAlgorithm.RSA_2048 },
|
||||
{ label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.RSA_4096], value: CertKeyAlgorithm.RSA_4096 },
|
||||
{
|
||||
label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.ECDSA_P256],
|
||||
value: CertKeyAlgorithm.ECDSA_P256
|
||||
},
|
||||
{
|
||||
label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.ECDSA_P384],
|
||||
value: CertKeyAlgorithm.ECDSA_P384
|
||||
}
|
||||
];
|
||||
|
||||
export const crlReasonToNameMap: { [K in CrlReason]: string } = {
|
||||
[CrlReason.UNSPECIFIED]: "Unspecified",
|
||||
[CrlReason.KEY_COMPROMISE]: "Key Compromise",
|
||||
[CrlReason.CA_COMPROMISE]: "CA Compromise",
|
||||
[CrlReason.AFFILIATION_CHANGED]: "Affiliation Changed",
|
||||
[CrlReason.SUPERSEDED]: "Superseded",
|
||||
[CrlReason.CESSATION_OF_OPERATION]: "Cessation of Operation",
|
||||
[CrlReason.CERTIFICATE_HOLD]: "Certificate Hold",
|
||||
// [CrlReason.REMOVE_FROM_CRL]: "Remove from CRL",
|
||||
[CrlReason.PRIVILEGE_WITHDRAWN]: "Privilege Withdrawn",
|
||||
[CrlReason.A_A_COMPROMISE]: "A/A Compromise"
|
||||
};
|
||||
|
||||
export const crlReasons = [
|
||||
{ label: crlReasonToNameMap[CrlReason.UNSPECIFIED], value: CrlReason.UNSPECIFIED },
|
||||
{ label: crlReasonToNameMap[CrlReason.KEY_COMPROMISE], value: CrlReason.KEY_COMPROMISE },
|
||||
{ label: crlReasonToNameMap[CrlReason.CA_COMPROMISE], value: CrlReason.CA_COMPROMISE },
|
||||
{
|
||||
label: crlReasonToNameMap[CrlReason.AFFILIATION_CHANGED],
|
||||
value: CrlReason.AFFILIATION_CHANGED
|
||||
},
|
||||
{ label: crlReasonToNameMap[CrlReason.SUPERSEDED], value: CrlReason.SUPERSEDED },
|
||||
{
|
||||
label: crlReasonToNameMap[CrlReason.CESSATION_OF_OPERATION],
|
||||
value: CrlReason.CESSATION_OF_OPERATION
|
||||
},
|
||||
{ label: crlReasonToNameMap[CrlReason.CERTIFICATE_HOLD], value: CrlReason.CERTIFICATE_HOLD },
|
||||
{
|
||||
label: crlReasonToNameMap[CrlReason.PRIVILEGE_WITHDRAWN],
|
||||
value: CrlReason.PRIVILEGE_WITHDRAWN
|
||||
},
|
||||
{ label: crlReasonToNameMap[CrlReason.A_A_COMPROMISE], value: CrlReason.A_A_COMPROMISE }
|
||||
];
|
||||
|
||||
@@ -9,3 +9,16 @@ export enum CertKeyAlgorithm {
|
||||
ECDSA_P256 = "EC_prime256v1",
|
||||
ECDSA_P384 = "EC_secp384r1"
|
||||
}
|
||||
|
||||
export enum CrlReason {
|
||||
UNSPECIFIED = "UNSPECIFIED",
|
||||
KEY_COMPROMISE = "KEY_COMPROMISE",
|
||||
CA_COMPROMISE = "CA_COMPROMISE",
|
||||
AFFILIATION_CHANGED = "AFFILIATION_CHANGED",
|
||||
SUPERSEDED = "SUPERSEDED",
|
||||
CESSATION_OF_OPERATION = "CESSATION_OF_OPERATION",
|
||||
CERTIFICATE_HOLD = "CERTIFICATE_HOLD",
|
||||
// REMOVE_FROM_CRL = "REMOVE_FROM_CRL",
|
||||
PRIVILEGE_WITHDRAWN = "PRIVILEGE_WITHDRAWN",
|
||||
A_A_COMPROMISE = "A_A_COMPROMISE"
|
||||
}
|
||||
|
||||
@@ -25,11 +25,14 @@ export const useDeleteCert = () => {
|
||||
export const useRevokeCert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificate, {}, TRevokeCertDTO>({
|
||||
mutationFn: async ({ serialNumber }) => {
|
||||
mutationFn: async ({ serialNumber, revocationReason }) => {
|
||||
const {
|
||||
data: { certificate }
|
||||
} = await apiRequest.post<{ certificate: TCertificate }>(
|
||||
`/api/v1/pki/certificates/${serialNumber}/revoke`
|
||||
`/api/v1/pki/certificates/${serialNumber}/revoke`,
|
||||
{
|
||||
revocationReason
|
||||
}
|
||||
);
|
||||
return certificate;
|
||||
},
|
||||
|
||||
@@ -18,4 +18,5 @@ export type TDeleteCertDTO = {
|
||||
export type TRevokeCertDTO = {
|
||||
projectSlug: string;
|
||||
serialNumber: string;
|
||||
revocationReason: string;
|
||||
};
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
import { useEffect } from "react";
|
||||
import { faCheck, faCopy, faDownload } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { IconButton,Modal, ModalContent } from "@app/components/v2";
|
||||
import { useToggle } from "@app/hooks";
|
||||
import { useGetCaCrl } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
type Props = {
|
||||
popUp: UsePopUpState<["caCrl"]>;
|
||||
handlePopUpToggle: (popUpName: keyof UsePopUpState<["caCrl"]>, state?: boolean) => void;
|
||||
};
|
||||
|
||||
export const CaCrlModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const [isCrlCopied, setIsCrlCopied] = useToggle(false);
|
||||
const { data: crl } = useGetCaCrl((popUp?.caCrl?.data as { caId: string })?.caId || "");
|
||||
|
||||
useEffect(() => {
|
||||
let timer: NodeJS.Timeout;
|
||||
if (isCrlCopied) {
|
||||
timer = setTimeout(() => setIsCrlCopied.off(), 2000);
|
||||
}
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [isCrlCopied]);
|
||||
|
||||
const downloadTxtFile = (filename: string, content: string) => {
|
||||
const blob = new Blob([content], { type: "text/plain" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={popUp?.caCrl?.isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
handlePopUpToggle("caCrl", isOpen);
|
||||
}}
|
||||
>
|
||||
<ModalContent title="CA Certificate Revocation List (CRL)">
|
||||
<div>
|
||||
{crl && (
|
||||
<>
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<h2>CA CRL</h2>
|
||||
<div className="flex">
|
||||
<IconButton
|
||||
ariaLabel="copy icon"
|
||||
colorSchema="secondary"
|
||||
className="group relative"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(crl);
|
||||
setIsCrlCopied.on();
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={isCrlCopied ? faCheck : faCopy} />
|
||||
<span className="absolute -left-8 -top-20 hidden w-28 translate-y-full rounded-md bg-bunker-800 py-2 pl-3 text-center text-sm text-gray-400 group-hover:flex group-hover:animate-fadeIn">
|
||||
Copy
|
||||
</span>
|
||||
</IconButton>
|
||||
<IconButton
|
||||
ariaLabel="copy icon"
|
||||
colorSchema="secondary"
|
||||
className="group relative ml-2"
|
||||
onClick={() => {
|
||||
downloadTxtFile("crl.pem", crl);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faDownload} />
|
||||
<span className="absolute -left-8 -top-20 hidden w-28 translate-y-full rounded-md bg-bunker-800 py-2 pl-3 text-center text-sm text-gray-400 group-hover:flex group-hover:animate-fadeIn">
|
||||
Download
|
||||
</span>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-8 flex items-center justify-between rounded-md bg-white/[0.07] p-2 text-base text-gray-400">
|
||||
<p className="mr-4 whitespace-pre-wrap break-all">{crl}</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
+5
-2
@@ -5,10 +5,11 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { CaStatus,useDeleteCa, useUpdateCa } from "@app/hooks/api";
|
||||
import { CaStatus, useDeleteCa, useUpdateCa } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
import { CaCertModal } from "./CaCertModal";
|
||||
import { CaCrlModal } from "./CaCrlModal";
|
||||
import { CaInstallCertModal } from "./CaInstallCertModal";
|
||||
import { CaModal } from "./CaModal";
|
||||
import { CaTable } from "./CaTable";
|
||||
@@ -23,7 +24,8 @@ export const CaSection = () => {
|
||||
"caCert",
|
||||
"installCaCert",
|
||||
"deleteCa",
|
||||
"caStatus" // enable / disable
|
||||
"caStatus", // enable / disable
|
||||
"caCrl" // enable / disable
|
||||
] as const);
|
||||
|
||||
const onRemoveCaSubmit = async (caId: string) => {
|
||||
@@ -92,6 +94,7 @@ export const CaSection = () => {
|
||||
<CaModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<CaInstallCertModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<CaCertModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<CaCrlModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<CaTable handlePopUpOpen={handlePopUpOpen} />
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.deleteCa.isOpen}
|
||||
|
||||
+28
-3
@@ -3,6 +3,7 @@ import {
|
||||
faCertificate,
|
||||
faEllipsis,
|
||||
faEye,
|
||||
faFile,
|
||||
faTrash
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@@ -24,15 +25,18 @@ import {
|
||||
Th,
|
||||
THead,
|
||||
Tooltip,
|
||||
Tr} from "@app/components/v2";
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { CaStatus, useListWorkspaceCas } from "@app/hooks/api";
|
||||
import { caStatusToNameMap,caTypeToNameMap } from "@app/hooks/api/ca/constants";
|
||||
import { caStatusToNameMap, caTypeToNameMap } from "@app/hooks/api/ca/constants";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
type Props = {
|
||||
handlePopUpOpen: (
|
||||
popUpName: keyof UsePopUpState<["installCaCert", "caCert", "ca", "deleteCa", "caStatus"]>,
|
||||
popUpName: keyof UsePopUpState<
|
||||
["installCaCert", "caCert", "ca", "deleteCa", "caStatus", "caCrl"]
|
||||
>,
|
||||
data?: {
|
||||
caId?: string;
|
||||
dn?: string;
|
||||
@@ -129,6 +133,27 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
)}
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Read}
|
||||
a={ProjectPermissionSub.CertificateAuthorities}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<DropdownMenuItem
|
||||
className={twMerge(
|
||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||
)}
|
||||
onClick={async () =>
|
||||
handlePopUpOpen("caCrl", {
|
||||
caId: ca.id
|
||||
})
|
||||
}
|
||||
disabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faFile} />}
|
||||
>
|
||||
View CRL
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Read}
|
||||
a={ProjectPermissionSub.CertificateAuthorities}
|
||||
|
||||
+2
-2
@@ -98,7 +98,7 @@ export const CertificateContent = ({
|
||||
colorSchema="secondary"
|
||||
className="group relative ml-2"
|
||||
onClick={() => {
|
||||
downloadTxtFile("certificate.txt", certificate);
|
||||
downloadTxtFile("certificate.pem", certificate);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faDownload} />
|
||||
@@ -135,7 +135,7 @@ export const CertificateContent = ({
|
||||
colorSchema="secondary"
|
||||
className="group relative ml-2"
|
||||
onClick={() => {
|
||||
downloadTxtFile("certificate_chain.txt", certificateChain);
|
||||
downloadTxtFile("chain.pem", certificateChain);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faDownload} />
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Modal, ModalContent, Select, SelectItem } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useRevokeCert } from "@app/hooks/api";
|
||||
import { crlReasons } from "@app/hooks/api/certificates/constants";
|
||||
import { CrlReason } from "@app/hooks/api/certificates/enums";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
const schema = z.object({
|
||||
revocationReason: z.enum([
|
||||
CrlReason.UNSPECIFIED,
|
||||
CrlReason.KEY_COMPROMISE,
|
||||
CrlReason.CA_COMPROMISE,
|
||||
CrlReason.AFFILIATION_CHANGED,
|
||||
CrlReason.SUPERSEDED,
|
||||
CrlReason.CESSATION_OF_OPERATION,
|
||||
CrlReason.CERTIFICATE_HOLD,
|
||||
CrlReason.PRIVILEGE_WITHDRAWN,
|
||||
CrlReason.A_A_COMPROMISE
|
||||
])
|
||||
});
|
||||
|
||||
export type FormData = z.infer<typeof schema>;
|
||||
|
||||
type Props = {
|
||||
popUp: UsePopUpState<["revokeCertificate"]>;
|
||||
handlePopUpToggle: (
|
||||
popUpName: keyof UsePopUpState<["revokeCertificate"]>,
|
||||
state?: boolean
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const CertificateRevocationModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { mutateAsync: revokeCertificate } = useRevokeCert();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { isSubmitting }
|
||||
} = useForm<FormData>({
|
||||
resolver: zodResolver(schema)
|
||||
});
|
||||
|
||||
const onFormSubmit = async ({ revocationReason }: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
|
||||
const {serialNumber} = popUp.revokeCertificate.data as { serialNumber: string };
|
||||
|
||||
await revokeCertificate({
|
||||
projectSlug: currentWorkspace.slug,
|
||||
serialNumber,
|
||||
revocationReason
|
||||
});
|
||||
|
||||
reset();
|
||||
handlePopUpToggle("revokeCertificate", false);
|
||||
|
||||
createNotification({
|
||||
text: "Successfully revoked certificate",
|
||||
type: "success"
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
createNotification({
|
||||
text: "Failed to revoke certificate",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={popUp?.revokeCertificate?.isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
handlePopUpToggle("revokeCertificate", isOpen);
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
<ModalContent title="Revoke Certificate">
|
||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
name="revocationReason"
|
||||
defaultValue={CrlReason.UNSPECIFIED}
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Revocation Reason"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Select
|
||||
defaultValue={field.value}
|
||||
{...field}
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full"
|
||||
>
|
||||
{crlReasons.map(({ label, value }) => (
|
||||
<SelectItem value={String(value || "")} key={label}>
|
||||
{label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
className="mr-4"
|
||||
size="sm"
|
||||
type="submit"
|
||||
isLoading={isSubmitting}
|
||||
isDisabled={isSubmitting}
|
||||
>
|
||||
Revoke
|
||||
</Button>
|
||||
<Button colorSchema="secondary" variant="plain">
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
+3
-37
@@ -5,17 +5,17 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { useDeleteCert, useRevokeCert } from "@app/hooks/api";
|
||||
import { useDeleteCert } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
import { CertificateCertModal } from "./CertificateCertModal";
|
||||
import { CertificateModal } from "./CertificateModal";
|
||||
import { CertificateRevocationModal } from "./CertificateRevocationModal";
|
||||
import { CertificatesTable } from "./CertificatesTable";
|
||||
|
||||
export const CertificatesSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { mutateAsync: deleteCert } = useDeleteCert();
|
||||
const { mutateAsync: revokeCert } = useRevokeCert();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||
"certificate",
|
||||
@@ -45,27 +45,6 @@ export const CertificatesSection = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onRevokeCertificateSubmit = async (serialNumber: string) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
|
||||
await revokeCert({ serialNumber, projectSlug: currentWorkspace.slug });
|
||||
|
||||
await createNotification({
|
||||
text: "Successfully revoked certificate",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
handlePopUpClose("revokeCertificate");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
createNotification({
|
||||
text: "Failed to revoke certificate",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex justify-between">
|
||||
@@ -90,6 +69,7 @@ export const CertificatesSection = () => {
|
||||
<CertificatesTable handlePopUpOpen={handlePopUpOpen} />
|
||||
<CertificateModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<CertificateCertModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<CertificateRevocationModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.deleteCertificate.isOpen}
|
||||
title={`Are you sure want to remove the certificate ${
|
||||
@@ -103,20 +83,6 @@ export const CertificatesSection = () => {
|
||||
)
|
||||
}
|
||||
/>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.revokeCertificate.isOpen}
|
||||
title={`Are you sure want to revoke the certificate ${
|
||||
(popUp?.revokeCertificate?.data as { commonName: string })?.commonName || ""
|
||||
} from the project?`}
|
||||
subTitle="This action is irreversible and will add the certificate to the CRL"
|
||||
onChange={(isOpen) => handlePopUpToggle("revokeCertificate", isOpen)}
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={() =>
|
||||
onRevokeCertificateSubmit(
|
||||
(popUp?.revokeCertificate?.data as { serialNumber: string }).serialNumber
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user