From ce6727460f24102e83e0f6bcec176dba6c4267bb Mon Sep 17 00:00:00 2001 From: Fang-Pen Lin Date: Mon, 10 Nov 2025 16:59:38 -0800 Subject: [PATCH] Block user if they don't have the feature in their plan --- .../CertificateProfilesTab.tsx | 21 +++++++++++-- .../CreateProfileModal.tsx | 31 ++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx index ab34abec8..c58a2fe20 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx @@ -1,6 +1,6 @@ -import { useState } from "react"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useState } from "react"; import { createNotification } from "@app/components/notifications"; import { Button, DeleteActionModal } from "@app/components/v2"; @@ -14,6 +14,8 @@ import { useDeleteCertificateProfile } from "@app/hooks/api/certificateProfiles"; +import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; +import { usePopUp } from "@app/hooks"; import { CreateProfileModal } from "./CreateProfileModal"; import { ProfileList } from "./ProfileList"; import { RevealAcmeEabSecretModal } from "./RevealAcmeEabSecretModal"; @@ -29,6 +31,10 @@ export const CertificateProfilesTab = () => { const [selectedProfile, setSelectedProfile] = useState( null ); + const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ + "enrollmentOptions", + "upgradePlan" + ] as const); const deleteProfile = useDeleteCertificateProfile(); @@ -99,7 +105,17 @@ export const CertificateProfilesTab = () => { onDeleteProfile={handleDeleteProfile} /> - setIsCreateModalOpen(false)} /> + setIsCreateModalOpen(false)} + handlePopUpOpen={handlePopUpOpen} + /> + handlePopUpToggle("upgradePlan", isOpen)} + isEnterpriseFeature={popUp.upgradePlan.data?.isEnterpriseFeature} + text="Your current plan does not include access to managing template enrollment options for ACME. To unlock this feature, please upgrade to Infisical Enterprise plan." + /> {selectedProfile && ( <> @@ -109,6 +125,7 @@ export const CertificateProfilesTab = () => { setIsEditModalOpen(false); setSelectedProfile(null); }} + handlePopUpOpen={handlePopUpOpen} profile={selectedProfile} mode="edit" /> diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx index f53084a4e..3214b1bb1 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx @@ -1,8 +1,8 @@ -import { useEffect } from "react"; -import { Controller, useForm } from "react-hook-form"; import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; @@ -19,7 +19,7 @@ import { Tooltip } from "@app/components/v2"; import { envConfig } from "@app/config/env"; -import { useProject } from "@app/context"; +import { useProject, useSubscription } from "@app/context"; import { useListCasByProjectId } from "@app/hooks/api/ca/queries"; import { TCertificateProfileWithDetails, @@ -29,6 +29,7 @@ import { useUpdateCertificateProfile } from "@app/hooks/api/certificateProfiles"; import { useListCertificateTemplatesV2 } from "@app/hooks/api/certificateTemplates/queries"; +import { UsePopUpState } from "@app/hooks/usePopUp"; const createSchema = z .object({ @@ -151,12 +152,25 @@ export type FormData = z.infer; interface Props { isOpen: boolean; onClose: () => void; + handlePopUpOpen: ( + popUpName: keyof UsePopUpState<["upgradePlan"]>, + data?: { + isEnterpriseFeature?: boolean; + } + ) => void; profile?: TCertificateProfileWithDetails; mode?: "create" | "edit"; } -export const CreateProfileModal = ({ isOpen, onClose, profile, mode = "create" }: Props) => { +export const CreateProfileModal = ({ + isOpen, + onClose, + handlePopUpOpen, + profile, + mode = "create" +}: Props) => { const { currentProject } = useProject(); + const { subscription } = useSubscription(); const { data: caData } = useListCasByProjectId(currentProject?.id || ""); const { data: templateData } = useListCertificateTemplatesV2({ @@ -248,6 +262,15 @@ export const CreateProfileModal = ({ isOpen, onClose, profile, mode = "create" } }, [isEdit, profile, reset]); const onFormSubmit = async (data: FormData) => { + if (!isEdit && !subscription?.pkiAcme && data.enrollmentType === "acme") { + reset(); + onClose(); + handlePopUpOpen("upgradePlan", { + isEnterpriseFeature: true + }); + return; + } + if (!currentProject?.id && !isEdit) return; if (isEdit) {