diff --git a/frontend/src/hooks/api/ca/types.ts b/frontend/src/hooks/api/ca/types.ts index 696e72494..31d35e904 100644 --- a/frontend/src/hooks/api/ca/types.ts +++ b/frontend/src/hooks/api/ca/types.ts @@ -159,8 +159,8 @@ export type TCreateCertificateDTO = { ttl: string; // string compatible with ms notBefore?: string; notAfter?: string; - keyUsages: CertKeyUsage[]; - extendedKeyUsages: CertExtendedKeyUsage[]; + keyUsages: string[]; + extendedKeyUsages: string[]; }; export type TCreateCertificateResponse = { diff --git a/frontend/src/hooks/api/certificateTemplates/mutations.tsx b/frontend/src/hooks/api/certificateTemplates/mutations.tsx index 0355d9d87..998194ddc 100644 --- a/frontend/src/hooks/api/certificateTemplates/mutations.tsx +++ b/frontend/src/hooks/api/certificateTemplates/mutations.tsx @@ -90,7 +90,12 @@ export const useCreateCertTemplateV2 = () => { return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { - queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) }); + queryClient.invalidateQueries({ + predicate: (query) => { + const [firstKey, queryProjectId] = query.queryKey; + return firstKey === "list-template" && queryProjectId === projectId; + } + }); } }); }; @@ -107,7 +112,12 @@ export const useUpdateCertTemplateV2 = () => { return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { - queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) }); + queryClient.invalidateQueries({ + predicate: (query) => { + const [firstKey, queryProjectId] = query.queryKey; + return firstKey === "list-template" && queryProjectId === projectId; + } + }); } }); }; @@ -127,7 +137,12 @@ export const useDeleteCertTemplateV2 = () => { return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { - queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) }); + queryClient.invalidateQueries({ + predicate: (query) => { + const [firstKey, queryProjectId] = query.queryKey; + return firstKey === "list-template" && queryProjectId === projectId; + } + }); } }); }; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx index b854bc899..81bc5461f 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx @@ -94,9 +94,9 @@ const createSchema = (shouldShowSubjectSection: boolean) => { export type FormData = z.infer>; type Props = { - popUp: UsePopUpState<["certificateIssuance"]>; + popUp: UsePopUpState<["issueCertificate"]>; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["certificateIssuance"]>, + popUpName: keyof UsePopUpState<["issueCertificate"]>, state?: boolean ) => void; profileId?: string; @@ -115,7 +115,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } const { currentProject } = useProject(); const inputSerialNumber = - (popUp?.certificateIssuance?.data as { serialNumber: string })?.serialNumber || ""; + (popUp?.issueCertificate?.data as { serialNumber: string })?.serialNumber || ""; const sanitizedSerialNumber = inputSerialNumber.replace(/[^a-fA-F0-9:]/g, ""); const { data: cert } = useGetCert(sanitizedSerialNumber); @@ -181,7 +181,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } } = useCertificateTemplate( templateData, actualSelectedProfile, - popUp?.certificateIssuance?.isOpen || false, + popUp?.issueCertificate?.isOpen || false, setValue, watch ); @@ -227,10 +227,10 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } }, [cert, reset]); useEffect(() => { - if (popUp?.certificateIssuance?.isOpen && profileId && !cert) { + if (popUp?.issueCertificate?.isOpen && profileId && !cert) { setValue("profileId", profileId); } - }, [popUp?.certificateIssuance?.isOpen, profileId, cert, setValue]); + }, [popUp?.issueCertificate?.isOpen, profileId, cert, setValue]); const onFormSubmit = useCallback( async ({ @@ -332,9 +332,9 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } return ( { - handlePopUpToggle("certificateIssuance", isOpen); + handlePopUpToggle("issueCertificate", isOpen); if (!isOpen) { resetAllState(); } @@ -503,7 +503,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } colorSchema="secondary" variant="plain" onClick={() => { - handlePopUpToggle("certificateIssuance", false); + handlePopUpToggle("issueCertificate", false); }} > Cancel diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx index f56f0fde8..75ae0e848 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx @@ -75,6 +75,7 @@ export type FormData = z.infer; type Props = { popUp: UsePopUpState<["certificate"]>; handlePopUpToggle: (popUpName: keyof UsePopUpState<["certificate"]>, state?: boolean) => void; + preselectedTemplate?: { id: string; name: string }; }; type TCertificateDetails = { @@ -86,7 +87,7 @@ type TCertificateDetails = { const CERT_TEMPLATE_NONE_VALUE = "none"; -export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { +export const CertificateModal = ({ popUp, handlePopUpToggle, preselectedTemplate }: Props) => { const [certificateDetails, setCertificateDetails] = useState(null); const { currentProject } = useProject(); const { data: cert } = useGetCert( @@ -147,13 +148,15 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { (cert.extendedKeyUsages || []).map((name) => [name, true]) ) }); - } else { + } else if (popUp?.certificate?.isOpen) { + const templateId = preselectedTemplate?.id || CERT_TEMPLATE_NONE_VALUE; + reset({ caId: "", commonName: "", subjectAltNames: "", ttl: "", - certificateTemplateId: CERT_TEMPLATE_NONE_VALUE, + certificateTemplateId: templateId, keyUsages: { [CertKeyUsage.DIGITAL_SIGNATURE]: true, [CertKeyUsage.KEY_ENCIPHERMENT]: true @@ -161,7 +164,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { extendedKeyUsages: {} }); } - }, [cert]); + }, [cert, preselectedTemplate, popUp?.certificate?.isOpen]); useEffect(() => { if (!cert && selectedCertTemplate) { @@ -198,10 +201,14 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { ttl, keyUsages: Object.entries(keyUsages) .filter(([, value]) => value) - .map(([key]) => key as CertKeyUsage), + .map(([key]) => + key === CertKeyUsage.CRL_SIGN + ? "cRLSign" + : key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()) + ), extendedKeyUsages: Object.entries(extendedKeyUsages) .filter(([, value]) => value) - .map(([key]) => key as CertExtendedKeyUsage) + .map(([key]) => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())) }); reset(); @@ -269,15 +276,25 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { isRequired >