mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 18:26:16 +00:00
Add new option on legacy templates to issue new certificates
This commit is contained in:
@@ -90,7 +90,12 @@ export const useCreateCertTemplateV2 = () => {
|
|||||||
return data.certificateTemplate;
|
return data.certificateTemplate;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { projectId }) => {
|
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;
|
return data.certificateTemplate;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { projectId }) => {
|
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;
|
return data.certificateTemplate;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { projectId }) => {
|
onSuccess: (_, { projectId }) => {
|
||||||
queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) });
|
queryClient.invalidateQueries({
|
||||||
|
predicate: (query) => {
|
||||||
|
const [firstKey, queryProjectId] = query.queryKey;
|
||||||
|
return firstKey === "list-template" && queryProjectId === projectId;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ export type FormData = z.infer<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
popUp: UsePopUpState<["certificate"]>;
|
popUp: UsePopUpState<["certificate"]>;
|
||||||
handlePopUpToggle: (popUpName: keyof UsePopUpState<["certificate"]>, state?: boolean) => void;
|
handlePopUpToggle: (popUpName: keyof UsePopUpState<["certificate"]>, state?: boolean) => void;
|
||||||
|
preselectedTemplate?: { id: string; name: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
type TCertificateDetails = {
|
type TCertificateDetails = {
|
||||||
@@ -86,7 +87,7 @@ type TCertificateDetails = {
|
|||||||
|
|
||||||
const CERT_TEMPLATE_NONE_VALUE = "none";
|
const CERT_TEMPLATE_NONE_VALUE = "none";
|
||||||
|
|
||||||
export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
|
export const CertificateModal = ({ popUp, handlePopUpToggle, preselectedTemplate }: Props) => {
|
||||||
const [certificateDetails, setCertificateDetails] = useState<TCertificateDetails | null>(null);
|
const [certificateDetails, setCertificateDetails] = useState<TCertificateDetails | null>(null);
|
||||||
const { currentProject } = useProject();
|
const { currentProject } = useProject();
|
||||||
const { data: cert } = useGetCert(
|
const { data: cert } = useGetCert(
|
||||||
@@ -147,13 +148,15 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
(cert.extendedKeyUsages || []).map((name) => [name, true])
|
(cert.extendedKeyUsages || []).map((name) => [name, true])
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
} else {
|
} else if (popUp?.certificate?.isOpen) {
|
||||||
|
const templateId = preselectedTemplate?.id || CERT_TEMPLATE_NONE_VALUE;
|
||||||
|
|
||||||
reset({
|
reset({
|
||||||
caId: "",
|
caId: "",
|
||||||
commonName: "",
|
commonName: "",
|
||||||
subjectAltNames: "",
|
subjectAltNames: "",
|
||||||
ttl: "",
|
ttl: "",
|
||||||
certificateTemplateId: CERT_TEMPLATE_NONE_VALUE,
|
certificateTemplateId: templateId,
|
||||||
keyUsages: {
|
keyUsages: {
|
||||||
[CertKeyUsage.DIGITAL_SIGNATURE]: true,
|
[CertKeyUsage.DIGITAL_SIGNATURE]: true,
|
||||||
[CertKeyUsage.KEY_ENCIPHERMENT]: true
|
[CertKeyUsage.KEY_ENCIPHERMENT]: true
|
||||||
@@ -161,7 +164,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
extendedKeyUsages: {}
|
extendedKeyUsages: {}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [cert]);
|
}, [cert, preselectedTemplate, popUp?.certificate?.isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!cert && selectedCertTemplate) {
|
if (!cert && selectedCertTemplate) {
|
||||||
@@ -269,15 +272,25 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
isRequired
|
isRequired
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={field.value}
|
value={field.value}
|
||||||
{...field}
|
|
||||||
onValueChange={(e) => onChange(e)}
|
onValueChange={(e) => onChange(e)}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
isDisabled={Boolean(cert)}
|
isDisabled={Boolean(cert) || Boolean(preselectedTemplate)}
|
||||||
>
|
>
|
||||||
<SelectItem value={CERT_TEMPLATE_NONE_VALUE} key="cert-template-none">
|
<SelectItem value={CERT_TEMPLATE_NONE_VALUE} key="cert-template-none">
|
||||||
None
|
None
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
{preselectedTemplate &&
|
||||||
|
!templatesData?.certificateTemplates?.find(
|
||||||
|
(t) => t.id === preselectedTemplate.id
|
||||||
|
) && (
|
||||||
|
<SelectItem
|
||||||
|
value={preselectedTemplate.id}
|
||||||
|
key={`cert-template-preselected-${preselectedTemplate.id}`}
|
||||||
|
>
|
||||||
|
{preselectedTemplate.name}
|
||||||
|
</SelectItem>
|
||||||
|
)}
|
||||||
{(templatesData?.certificateTemplates || []).map(({ id, name }) => (
|
{(templatesData?.certificateTemplates || []).map(({ id, name }) => (
|
||||||
<SelectItem value={id} key={`cert-template-${id}`}>
|
<SelectItem value={id} key={`cert-template-${id}`}>
|
||||||
{name}
|
{name}
|
||||||
|
|||||||
+2
-13
@@ -17,7 +17,6 @@ import { CertificateImportModal } from "./CertificateImportModal";
|
|||||||
import { CertificateIssuanceModal } from "./CertificateIssuanceModal";
|
import { CertificateIssuanceModal } from "./CertificateIssuanceModal";
|
||||||
import { CertificateManagePkiSyncsModal } from "./CertificateManagePkiSyncsModal";
|
import { CertificateManagePkiSyncsModal } from "./CertificateManagePkiSyncsModal";
|
||||||
import { CertificateManageRenewalModal } from "./CertificateManageRenewalModal";
|
import { CertificateManageRenewalModal } from "./CertificateManageRenewalModal";
|
||||||
import { CertificateModal } from "./CertificateModal";
|
|
||||||
import { CertificateRenewalModal } from "./CertificateRenewalModal";
|
import { CertificateRenewalModal } from "./CertificateRenewalModal";
|
||||||
import { CertificateRevocationModal } from "./CertificateRevocationModal";
|
import { CertificateRevocationModal } from "./CertificateRevocationModal";
|
||||||
import { CertificatesTable } from "./CertificatesTable";
|
import { CertificatesTable } from "./CertificatesTable";
|
||||||
@@ -26,12 +25,8 @@ export const CertificatesSection = () => {
|
|||||||
const { currentProject } = useProject();
|
const { currentProject } = useProject();
|
||||||
const { mutateAsync: deleteCert } = useDeleteCert();
|
const { mutateAsync: deleteCert } = useDeleteCert();
|
||||||
|
|
||||||
// TODO: Use subscription.pkiLegacyTemplates to block legacy templates creation
|
|
||||||
const isLegacyTemplatesEnabled = true;
|
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||||
"certificateIssuance",
|
"certificateIssuance",
|
||||||
"certificate",
|
|
||||||
"certificateImport",
|
"certificateImport",
|
||||||
"certificateCert",
|
"certificateCert",
|
||||||
"deleteCertificate",
|
"deleteCertificate",
|
||||||
@@ -76,9 +71,7 @@ export const CertificatesSection = () => {
|
|||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
onClick={() =>
|
onClick={() => handlePopUpOpen("certificateIssuance")}
|
||||||
handlePopUpOpen(isLegacyTemplatesEnabled ? "certificate" : "certificateIssuance")
|
|
||||||
}
|
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Issue
|
Issue
|
||||||
@@ -88,11 +81,7 @@ export const CertificatesSection = () => {
|
|||||||
</ProjectPermissionCan>
|
</ProjectPermissionCan>
|
||||||
</div>
|
</div>
|
||||||
<CertificatesTable handlePopUpOpen={handlePopUpOpen} />
|
<CertificatesTable handlePopUpOpen={handlePopUpOpen} />
|
||||||
{isLegacyTemplatesEnabled ? (
|
<CertificateIssuanceModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
<CertificateModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
|
||||||
) : (
|
|
||||||
<CertificateIssuanceModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
|
||||||
)}
|
|
||||||
<CertificateImportModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
<CertificateImportModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
<CertificateCertModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
<CertificateCertModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
<CertificateManageRenewalModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
<CertificateManageRenewalModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ type Props = {
|
|||||||
handlePopUpOpen: (
|
handlePopUpOpen: (
|
||||||
popUpName: keyof UsePopUpState<
|
popUpName: keyof UsePopUpState<
|
||||||
[
|
[
|
||||||
"certificate",
|
"certificateIssuance",
|
||||||
"deleteCertificate",
|
"deleteCertificate",
|
||||||
"revokeCertificate",
|
"revokeCertificate",
|
||||||
"certificateCert",
|
"certificateCert",
|
||||||
@@ -297,7 +297,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||||
)}
|
)}
|
||||||
onClick={async () =>
|
onClick={async () =>
|
||||||
handlePopUpOpen("certificate", {
|
handlePopUpOpen("certificateIssuance", {
|
||||||
serialNumber: certificate.serialNumber
|
serialNumber: certificate.serialNumber
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
faCertificate,
|
faCertificate,
|
||||||
faCog,
|
faCog,
|
||||||
faEllipsis,
|
faEllipsis,
|
||||||
|
faFileContract,
|
||||||
faPencil,
|
faPencil,
|
||||||
faPlus,
|
faPlus,
|
||||||
faTrash
|
faTrash
|
||||||
@@ -40,6 +41,7 @@ import {
|
|||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import {
|
import {
|
||||||
|
ProjectPermissionCertificateActions,
|
||||||
ProjectPermissionPkiTemplateActions,
|
ProjectPermissionPkiTemplateActions,
|
||||||
ProjectPermissionSub,
|
ProjectPermissionSub,
|
||||||
useProject,
|
useProject,
|
||||||
@@ -50,6 +52,7 @@ import { useDeleteCertTemplateV2 } from "@app/hooks/api";
|
|||||||
import { useListCertificateTemplates } from "@app/hooks/api/certificateTemplates/queries";
|
import { useListCertificateTemplates } from "@app/hooks/api/certificateTemplates/queries";
|
||||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||||
|
|
||||||
|
import { CertificateModal } from "../CertificatesPage/components/CertificateModal";
|
||||||
import { CertificateTemplateEnrollmentModal } from "../CertificatesPage/components/CertificateTemplateEnrollmentModal";
|
import { CertificateTemplateEnrollmentModal } from "../CertificatesPage/components/CertificateTemplateEnrollmentModal";
|
||||||
import { PkiTemplateForm } from "./components/PkiTemplateForm";
|
import { PkiTemplateForm } from "./components/PkiTemplateForm";
|
||||||
|
|
||||||
@@ -64,7 +67,8 @@ export const PkiTemplateListPage = () => {
|
|||||||
"certificateTemplate",
|
"certificateTemplate",
|
||||||
"deleteTemplate",
|
"deleteTemplate",
|
||||||
"enrollmentOptions",
|
"enrollmentOptions",
|
||||||
"estUpgradePlan"
|
"estUpgradePlan",
|
||||||
|
"certificateFromTemplate"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
@@ -160,6 +164,27 @@ export const PkiTemplateListPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start" className="p-1">
|
<DropdownMenuContent align="start" className="p-1">
|
||||||
|
<ProjectPermissionCan
|
||||||
|
I={ProjectPermissionCertificateActions.Create}
|
||||||
|
a={ProjectPermissionSub.Certificates}
|
||||||
|
>
|
||||||
|
{(isAllowed) => (
|
||||||
|
<DropdownMenuItem
|
||||||
|
className={twMerge(
|
||||||
|
!isAllowed &&
|
||||||
|
"pointer-events-none cursor-not-allowed opacity-50"
|
||||||
|
)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePopUpOpen("certificateFromTemplate", template);
|
||||||
|
}}
|
||||||
|
disabled={!isAllowed}
|
||||||
|
icon={<FontAwesomeIcon icon={faFileContract} />}
|
||||||
|
>
|
||||||
|
Issue Certificate
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
</ProjectPermissionCan>
|
||||||
<ProjectPermissionCan
|
<ProjectPermissionCan
|
||||||
I={ProjectPermissionPkiTemplateActions.Edit}
|
I={ProjectPermissionPkiTemplateActions.Edit}
|
||||||
a={ProjectPermissionSub.CertificateTemplates}
|
a={ProjectPermissionSub.CertificateTemplates}
|
||||||
@@ -284,6 +309,16 @@ export const PkiTemplateListPage = () => {
|
|||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
<CertificateTemplateEnrollmentModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
<CertificateTemplateEnrollmentModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
|
<CertificateModal
|
||||||
|
popUp={{
|
||||||
|
certificate: {
|
||||||
|
isOpen: popUp.certificateFromTemplate.isOpen,
|
||||||
|
data: popUp.certificateFromTemplate.data
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
handlePopUpToggle={(_, state) => handlePopUpToggle("certificateFromTemplate", state)}
|
||||||
|
preselectedTemplate={popUp.certificateFromTemplate.data}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.estUpgradePlan.isOpen}
|
isOpen={popUp.estUpgradePlan.isOpen}
|
||||||
|
|||||||
Reference in New Issue
Block a user