misc: integrated custom key usages for issue-cert endpoint

This commit is contained in:
Sheen Capadngan
2024-09-11 01:57:16 +08:00
parent 6fab7d9507
commit 4e6b289e1b
12 changed files with 192 additions and 36 deletions
@@ -7,7 +7,12 @@ import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
Button,
Checkbox,
FormControl,
FormLabel,
Input,
@@ -28,6 +33,7 @@ import {
useListWorkspacePkiCollections
} from "@app/hooks/api";
import { caTypeToNameMap } from "@app/hooks/api/ca/constants";
import { CertKeyUsage, KEY_USAGES_OPTIONS } from "@app/hooks/api/certificates/types";
import { UsePopUpState } from "@app/hooks/usePopUp";
import { CertificateContent } from "./CertificateContent";
@@ -39,7 +45,18 @@ const schema = z.object({
friendlyName: z.string(),
commonName: z.string().trim().min(1),
altNames: z.string(),
ttl: z.string().trim()
ttl: z.string().trim(),
keyUsages: z.object({
[CertKeyUsage.DIGITAL_SIGNATURE]: z.boolean().optional(),
[CertKeyUsage.KEY_ENCIPHERMENT]: z.boolean().optional(),
[CertKeyUsage.NON_REPUDIATION]: z.boolean().optional(),
[CertKeyUsage.DATA_ENCIPHERMENT]: z.boolean().optional(),
[CertKeyUsage.KEY_AGREEMENT]: z.boolean().optional(),
[CertKeyUsage.KEY_CERT_SIGN]: z.boolean().optional(),
[CertKeyUsage.CRL_SIGN]: z.boolean().optional(),
[CertKeyUsage.ENCIPHER_ONLY]: z.boolean().optional(),
[CertKeyUsage.DECIPHER_ONLY]: z.boolean().optional()
})
});
export type FormData = z.infer<typeof schema>;
@@ -88,7 +105,13 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
setValue,
watch
} = useForm<FormData>({
resolver: zodResolver(schema)
resolver: zodResolver(schema),
defaultValues: {
keyUsages: {
[CertKeyUsage.DIGITAL_SIGNATURE]: true,
[CertKeyUsage.KEY_ENCIPHERMENT]: true
}
}
});
const selectedCertTemplateId = watch("certificateTemplateId");
@@ -107,7 +130,8 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
commonName: cert.commonName,
altNames: cert.altNames,
certificateTemplateId: cert.certificateTemplateId ?? CERT_TEMPLATE_NONE_VALUE,
ttl: ""
ttl: "",
keyUsages: Object.fromEntries(cert.keyUsages.map((name) => [name, true]))
});
} else {
reset({
@@ -116,7 +140,11 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
commonName: "",
altNames: "",
ttl: "",
certificateTemplateId: CERT_TEMPLATE_NONE_VALUE
certificateTemplateId: CERT_TEMPLATE_NONE_VALUE,
keyUsages: {
[CertKeyUsage.DIGITAL_SIGNATURE]: true,
[CertKeyUsage.KEY_ENCIPHERMENT]: true
}
});
}
}, [cert]);
@@ -124,6 +152,10 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
useEffect(() => {
if (!cert && selectedCertTemplate) {
setValue("ttl", selectedCertTemplate.ttl);
setValue(
"keyUsages",
Object.fromEntries(selectedCertTemplate.keyUsages.map((name) => [name, true]))
);
}
}, [selectedCertTemplate, cert]);
@@ -133,7 +165,8 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
collectionId,
commonName,
altNames,
ttl
ttl,
keyUsages
}: FormData) => {
try {
if (!currentWorkspace?.slug) return;
@@ -146,7 +179,10 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
friendlyName,
commonName,
altNames,
ttl
ttl,
keyUsages: Object.entries(keyUsages)
.filter(([, value]) => value)
.map(([key]) => key as CertKeyUsage)
});
reset();
@@ -363,8 +399,52 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
</FormControl>
)}
/>
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="key-usages" className="data-[state=open]:border-none">
<AccordionTrigger className="h-fit flex-none pl-1 text-sm">
<div className="order-1 ml-3">Key Usages</div>
</AccordionTrigger>
<AccordionContent>
<Controller
control={control}
name="keyUsages"
render={({ field: { onChange, value }, fieldState: { error } }) => {
return (
<FormControl
label="Key Usages"
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
id={optionValue}
key={optionValue}
className="data-[state=checked]:bg-primary"
isDisabled={Boolean(cert)}
isChecked={value[optionValue]}
onCheckedChange={(state) => {
onChange({
...value,
[optionValue]: state
});
}}
>
{label}
</Checkbox>
);
})}
</div>
</FormControl>
);
}}
/>
</AccordionContent>
</AccordionItem>
</Accordion>
{!cert && (
<div className="flex items-center">
<div className="mt-4 flex items-center">
<Button
className="mr-4"
size="sm"
@@ -33,7 +33,7 @@ import {
useUpdateCertTemplate
} from "@app/hooks/api";
import { caTypeToNameMap } from "@app/hooks/api/ca/constants";
import { CertKeyUsage } from "@app/hooks/api/certificates/types";
import { CertKeyUsage, KEY_USAGES_OPTIONS } from "@app/hooks/api/certificates/types";
import { UsePopUpState } from "@app/hooks/usePopUp";
const validateTemplateRegexField = z
@@ -77,18 +77,6 @@ type Props = {
) => void;
};
const KEY_USAGES_OPTIONS = [
{ value: CertKeyUsage.DIGITAL_SIGNATURE, label: "Digital Signature" },
{ value: CertKeyUsage.KEY_ENCIPHERMENT, label: "Key Encipherment" },
{ value: CertKeyUsage.NON_REPUDIATION, label: "Non Repudiation" },
{ value: CertKeyUsage.DATA_ENCIPHERMENT, label: "Data Encipherment" },
{ value: CertKeyUsage.KEY_AGREEMENT, label: "Key Agreement" },
{ value: CertKeyUsage.KEY_CERT_SIGN, label: "Key Certification Sign" },
{ value: CertKeyUsage.CRL_SIGN, label: "CRL Sign" },
{ value: CertKeyUsage.ENCIPHER_ONLY, label: "Encipher Only" },
{ value: CertKeyUsage.DECIPHER_ONLY, label: "Decipher Only" }
] as const;
export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Props) => {
const { currentWorkspace } = useWorkspace();