mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
PKI Syncs improvements
This commit is contained in:
@@ -11,21 +11,24 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
onOpenChange: (isOpen: boolean) => void;
|
||||
selectSync?: PkiSync | null;
|
||||
initialData?: any;
|
||||
};
|
||||
|
||||
type ContentProps = {
|
||||
onComplete: (pkiSync: TPkiSync) => void;
|
||||
selectedSync: PkiSync | null;
|
||||
setSelectedSync: (selectedSync: PkiSync | null) => void;
|
||||
initialData?: any;
|
||||
};
|
||||
|
||||
const Content = ({ onComplete, setSelectedSync, selectedSync }: ContentProps) => {
|
||||
const Content = ({ onComplete, setSelectedSync, selectedSync, initialData }: ContentProps) => {
|
||||
if (selectedSync) {
|
||||
return (
|
||||
<CreatePkiSyncForm
|
||||
onComplete={onComplete}
|
||||
onCancel={() => setSelectedSync(null)}
|
||||
destination={selectedSync}
|
||||
initialData={initialData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -33,7 +36,12 @@ const Content = ({ onComplete, setSelectedSync, selectedSync }: ContentProps) =>
|
||||
return <PkiSyncSelect onSelect={setSelectedSync} />;
|
||||
};
|
||||
|
||||
export const CreatePkiSyncModal = ({ onOpenChange, selectSync = null, ...props }: Props) => {
|
||||
export const CreatePkiSyncModal = ({
|
||||
onOpenChange,
|
||||
selectSync = null,
|
||||
initialData,
|
||||
...props
|
||||
}: Props) => {
|
||||
const [selectedSync, setSelectedSync] = useState<PkiSync | null>(selectSync);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -69,6 +77,7 @@ export const CreatePkiSyncModal = ({ onOpenChange, selectSync = null, ...props }
|
||||
}}
|
||||
selectedSync={selectedSync}
|
||||
setSelectedSync={setSelectedSync}
|
||||
initialData={initialData}
|
||||
/>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
@@ -23,6 +23,7 @@ type Props = {
|
||||
onComplete: (pkiSync: TPkiSync) => void;
|
||||
destination: PkiSync;
|
||||
onCancel: () => void;
|
||||
initialData?: any;
|
||||
};
|
||||
|
||||
const FORM_TABS: { name: string; key: string; fields: (keyof TPkiSyncForm)[] }[] = [
|
||||
@@ -33,7 +34,7 @@ const FORM_TABS: { name: string; key: string; fields: (keyof TPkiSyncForm)[] }[]
|
||||
{ name: "Review", key: "review", fields: [] }
|
||||
];
|
||||
|
||||
export const CreatePkiSyncForm = ({ destination, onComplete, onCancel }: Props) => {
|
||||
export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialData }: Props) => {
|
||||
const createPkiSync = useCreatePkiSync();
|
||||
const { currentProject } = useProject();
|
||||
const { name: destinationName } = PKI_SYNC_MAP[destination];
|
||||
@@ -55,7 +56,8 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel }: Props)
|
||||
canRemoveCertificates: false,
|
||||
preserveArn: true,
|
||||
certificateNameSchema: syncOption?.defaultCertificateNameSchema
|
||||
}
|
||||
},
|
||||
...initialData
|
||||
} as Partial<TPkiSyncForm>,
|
||||
reValidateMode: "onChange"
|
||||
});
|
||||
|
||||
@@ -27,12 +27,16 @@ export const EditPkiSyncForm = ({ pkiSync, fields, onComplete }: Props) => {
|
||||
const formMethods = useForm<TUpdatePkiSyncForm>({
|
||||
resolver: zodResolver(UpdatePkiSyncFormSchema),
|
||||
defaultValues: {
|
||||
...pkiSync,
|
||||
name: pkiSync.name,
|
||||
destination: pkiSync.destination,
|
||||
description: pkiSync.description ?? "",
|
||||
connection: {
|
||||
id: pkiSync.connectionId,
|
||||
name: pkiSync.appConnectionName
|
||||
}
|
||||
},
|
||||
syncOptions: pkiSync.syncOptions,
|
||||
destinationConfig: pkiSync.destinationConfig,
|
||||
isAutoSyncEnabled: pkiSync.isAutoSyncEnabled
|
||||
} as Partial<TUpdatePkiSyncForm>,
|
||||
reValidateMode: "onChange"
|
||||
});
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { SingleValue } from "react-select";
|
||||
import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { useRouterState } from "@tanstack/react-router";
|
||||
|
||||
import { AppConnectionOption } from "@app/components/app-connections";
|
||||
import { FilterableSelect, FormControl } from "@app/components/v2";
|
||||
import { ProjectPermissionSub, useProject, useProjectPermission } from "@app/context";
|
||||
import { ProjectPermissionAppConnectionActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
|
||||
import { PKI_SYNC_CONNECTION_MAP } from "@app/helpers/pkiSyncs";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useListAvailableAppConnections } from "@app/hooks/api/appConnections";
|
||||
import { AddAppConnectionModal } from "@app/pages/organization/AppConnections/AppConnectionsPage/components";
|
||||
|
||||
import { TPkiSyncForm } from "./schemas/pki-sync-schema";
|
||||
|
||||
@@ -18,12 +22,30 @@ type Props = {
|
||||
|
||||
export const PkiSyncConnectionField = ({ onChange: callback }: Props) => {
|
||||
const { permission } = useProjectPermission();
|
||||
const { control, watch } = useFormContext<TPkiSyncForm>();
|
||||
const { currentProject } = useProject();
|
||||
const { control, watch, setValue } = useFormContext<TPkiSyncForm>();
|
||||
|
||||
const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp(["addConnection"] as const);
|
||||
|
||||
const destination = watch("destination");
|
||||
const app = PKI_SYNC_CONNECTION_MAP[destination];
|
||||
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const {
|
||||
location: { pathname }
|
||||
} = useRouterState();
|
||||
|
||||
const getPkiSyncReturnUrl = () => {
|
||||
if (pathname.includes("selectedTab=secret-syncs")) {
|
||||
return pathname.replace("selectedTab=secret-syncs", "selectedTab=pki-syncs");
|
||||
}
|
||||
if (!pathname.includes("selectedTab=")) {
|
||||
const separator = pathname.includes("?") ? "&" : "?";
|
||||
return `${pathname}${separator}selectedTab=pki-syncs`;
|
||||
}
|
||||
return pathname;
|
||||
};
|
||||
|
||||
const { data: availableConnections, isPending } = useListAvailableAppConnections(
|
||||
app,
|
||||
currentProject.id
|
||||
@@ -47,6 +69,7 @@ export const PkiSyncConnectionField = ({ onChange: callback }: Props) => {
|
||||
<Controller
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
tooltipText="App Connections can be created from the Organization Settings page."
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
label={`${connectionName} Connection`}
|
||||
@@ -54,36 +77,54 @@ export const PkiSyncConnectionField = ({ onChange: callback }: Props) => {
|
||||
<FilterableSelect
|
||||
value={value}
|
||||
onChange={(newValue) => {
|
||||
if ((newValue as SingleValue<{ id: string; name: string }>)?.id === "_create") {
|
||||
handlePopUpOpen("addConnection");
|
||||
onChange(null);
|
||||
const formData = { ...watch(), returnUrl: getPkiSyncReturnUrl() };
|
||||
localStorage.setItem("pkiSyncFormData", JSON.stringify(formData));
|
||||
if (callback) callback();
|
||||
return;
|
||||
}
|
||||
|
||||
onChange(newValue);
|
||||
if (callback) callback();
|
||||
}}
|
||||
isLoading={isPending}
|
||||
options={availableConnections}
|
||||
options={[
|
||||
...(canCreateConnection ? [{ id: "_create", name: "Create Connection" }] : []),
|
||||
...(availableConnections ?? [])
|
||||
]}
|
||||
placeholder="Select connection..."
|
||||
getOptionLabel={(option) => option.name}
|
||||
getOptionValue={(option) => option.id}
|
||||
components={{ Option: AppConnectionOption }}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
control={control}
|
||||
name="connection"
|
||||
/>
|
||||
{availableConnections?.length === 0 && (
|
||||
{!isPending && !availableConnections?.length && !canCreateConnection && (
|
||||
<p className="-mt-2.5 mb-2.5 text-xs text-yellow">
|
||||
<FontAwesomeIcon className="mr-1" size="xs" icon={faInfoCircle} />
|
||||
{canCreateConnection ? (
|
||||
<>
|
||||
You do not have access to any {appName} Connections. Create one from the{" "}
|
||||
<Link to="/organization/app-connections" className="underline">
|
||||
App Connections
|
||||
</Link>{" "}
|
||||
page.
|
||||
</>
|
||||
) : (
|
||||
`You do not have access to any ${appName} Connections. Contact an admin to create one.`
|
||||
)}
|
||||
You do not have access to any {appName} Connections. Contact an admin to create one.
|
||||
</p>
|
||||
)}
|
||||
<AddAppConnectionModal
|
||||
isOpen={popUp.addConnection.isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
localStorage.removeItem("pkiSyncFormData");
|
||||
handlePopUpToggle("addConnection", isOpen);
|
||||
}}
|
||||
projectType={currentProject.type}
|
||||
projectId={currentProject.id}
|
||||
app={app}
|
||||
onComplete={(connection) => {
|
||||
if (connection) {
|
||||
setValue("connection", connection);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -71,7 +71,7 @@ export const PkiSyncOptionsFields = ({ destination }: Props) => {
|
||||
isChecked={value}
|
||||
>
|
||||
<p>
|
||||
Enable Inactive Certificate Removal{" "}
|
||||
Enable Removal of Active/Revoked Certificates{" "}
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
@@ -138,6 +138,51 @@ export const PkiSyncOptionsFields = ({ destination }: Props) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
{currentDestination === PkiSync.AzureKeyVault && (
|
||||
<Controller
|
||||
control={control}
|
||||
name="syncOptions.preserveVersion"
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl isError={Boolean(error)} errorText={error?.message}>
|
||||
<Switch
|
||||
className="bg-mineshaft-400/80 shadow-inner data-[state=checked]:bg-green/80"
|
||||
id="preserve-version"
|
||||
thumbClassName="bg-mineshaft-800"
|
||||
onCheckedChange={onChange}
|
||||
isChecked={value}
|
||||
>
|
||||
<p>
|
||||
Preserve Version on Renewal{" "}
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
<>
|
||||
<p>
|
||||
When enabled, Infisical will create a new version of the existing
|
||||
certificate in Azure Key Vault during certificate renewal syncs,
|
||||
preserving the certificate name.
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
This allows consuming services to continue using the same certificate name
|
||||
while automatically using the latest version without requiring manual
|
||||
updates.
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
When disabled, new certificates will be created with new names, and old
|
||||
certificates will be removed.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faQuestionCircle} size="sm" className="ml-1" />
|
||||
</Tooltip>
|
||||
</p>
|
||||
</Switch>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="syncOptions.certificateNameSchema"
|
||||
|
||||
@@ -4,7 +4,46 @@ import { PkiSync } from "@app/hooks/api/pkiSyncs";
|
||||
|
||||
import { BasePkiSyncSchema } from "./base-pki-sync-schema";
|
||||
|
||||
export const AzureKeyVaultPkiSyncDestinationSchema = BasePkiSyncSchema().merge(
|
||||
const AzureKeyVaultSyncOptionsSchema = z.object({
|
||||
canImportCertificates: z.boolean().default(false),
|
||||
canRemoveCertificates: z.boolean().default(true),
|
||||
preserveVersion: z.boolean().default(true),
|
||||
certificateNameSchema: z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(
|
||||
(val) => {
|
||||
if (!val) return true;
|
||||
|
||||
const allowedOptionalPlaceholders = ["{{environment}}"];
|
||||
|
||||
const allowedPlaceholdersRegexPart = ["{{certificateId}}", ...allowedOptionalPlaceholders]
|
||||
.map((p) => p.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"))
|
||||
.join("|");
|
||||
|
||||
const allowedContentRegex = new RegExp(
|
||||
`^([a-zA-Z0-9_\\-/]|${allowedPlaceholdersRegexPart})*$`
|
||||
);
|
||||
const contentIsValid = allowedContentRegex.test(val);
|
||||
|
||||
if (val.trim()) {
|
||||
const certificateIdRegex = /\{\{certificateId\}\}/;
|
||||
const certificateIdIsPresent = certificateIdRegex.test(val);
|
||||
return contentIsValid && certificateIdIsPresent;
|
||||
}
|
||||
|
||||
return contentIsValid;
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Certificate name schema must include exactly one {{certificateId}} placeholder. It can also include {{environment}} placeholders. Only alphanumeric characters (a-z, A-Z, 0-9), dashes (-), underscores (_), and slashes (/) are allowed besides the placeholders."
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
export const AzureKeyVaultPkiSyncDestinationSchema = BasePkiSyncSchema(
|
||||
AzureKeyVaultSyncOptionsSchema
|
||||
).merge(
|
||||
z.object({
|
||||
destination: z.literal(PkiSync.AzureKeyVault),
|
||||
destinationConfig: z.object({
|
||||
|
||||
@@ -124,7 +124,7 @@ type Props = {
|
||||
|
||||
const caTypes = [
|
||||
{ label: "ACME", value: CaType.ACME },
|
||||
{ label: "Azure AD Certificate Service", value: CaType.AZURE_AD_CS }
|
||||
{ label: "Active Directory Certificate Services (AD CS)", value: CaType.AZURE_AD_CS }
|
||||
];
|
||||
|
||||
export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { faPlus, faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
@@ -18,12 +19,15 @@ import {
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
PkiSync,
|
||||
useAddCertificatesToPkiSync,
|
||||
useListPkiSyncsWithCertificate,
|
||||
useRemoveCertificatesFromPkiSync
|
||||
} from "@app/hooks/api/pkiSyncs";
|
||||
import { IntegrationsListPageTabs } from "@app/types/integrations";
|
||||
|
||||
type Props = {
|
||||
popUp: {
|
||||
@@ -46,6 +50,7 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
|
||||
const { currentProject } = useProject();
|
||||
const navigate = useNavigate();
|
||||
const { certificateId, commonName } = popUp.data || {};
|
||||
|
||||
const { data: pkiSyncs = [], isPending } = useListPkiSyncsWithCertificate(
|
||||
@@ -81,6 +86,32 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleNavigateToPkiSyncs = () => {
|
||||
if (!currentProject?.id) return;
|
||||
|
||||
navigate({
|
||||
to: ROUTE_PATHS.CertManager.IntegrationsListPage.path,
|
||||
params: {
|
||||
projectId: currentProject.id
|
||||
},
|
||||
search: {
|
||||
selectedTab: IntegrationsListPageTabs.PkiSyncs
|
||||
}
|
||||
});
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const getDestinationDisplayName = (destination: string) => {
|
||||
switch (destination) {
|
||||
case PkiSync.AzureKeyVault:
|
||||
return "Azure Key Vault";
|
||||
case PkiSync.AwsCertificateManager:
|
||||
return "AWS Certificate Manager";
|
||||
default:
|
||||
return destination;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!certificateId || !pkiSyncs || pkiSyncs.length === 0) return;
|
||||
|
||||
@@ -161,7 +192,7 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
placeholder="Search PKI syncs by name..."
|
||||
/>
|
||||
</div>
|
||||
<div className="max-h-96 overflow-y-auto">
|
||||
<div className="mt-4 max-h-96 overflow-y-auto">
|
||||
{isPending && (
|
||||
<div className="flex h-32 items-center justify-center">
|
||||
<div className="text-bunker-300">Loading PKI syncs...</div>
|
||||
@@ -169,12 +200,24 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
)}
|
||||
{!isPending && pkiSyncs.length === 0 && (
|
||||
<EmptyState title="No PKI syncs available" icon={faPlus}>
|
||||
Create a PKI sync first to manage certificate syncing.
|
||||
<div className="mt-1">
|
||||
Create a{" "}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleNavigateToPkiSyncs}
|
||||
className="cursor-pointer underline hover:text-mineshaft-300"
|
||||
>
|
||||
PKI sync
|
||||
</button>{" "}
|
||||
first to manage certificate syncing.
|
||||
</div>
|
||||
</EmptyState>
|
||||
)}
|
||||
{!isPending && pkiSyncs.length > 0 && filteredSyncs.length === 0 && searchTerm && (
|
||||
<EmptyState title="No PKI syncs found" icon={faSearch}>
|
||||
No PKI syncs match your search criteria. Try a different search term.
|
||||
<div className="mt-1">
|
||||
No PKI syncs match your search criteria. Try a different search term.
|
||||
</div>
|
||||
</EmptyState>
|
||||
)}
|
||||
{!isPending && filteredSyncs.length > 0 && (
|
||||
@@ -209,9 +252,9 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
<Td className="w-1/2 max-w-0">
|
||||
<div
|
||||
className="truncate capitalize"
|
||||
title={sync.destination.replace(/-/g, " ")}
|
||||
title={getDestinationDisplayName(sync.destination)}
|
||||
>
|
||||
{sync.destination.replace(/-/g, " ")}
|
||||
{getDestinationDisplayName(sync.destination)}
|
||||
</div>
|
||||
</Td>
|
||||
</Tr>
|
||||
|
||||
@@ -478,7 +478,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
disabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faLink} />}
|
||||
>
|
||||
PKI Syncs
|
||||
Manage PKI Syncs
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
|
||||
@@ -12,13 +12,14 @@ import { ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { ProjectPermissionPkiSyncActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useListPkiSyncs } from "@app/hooks/api/pkiSyncs";
|
||||
import { IntegrationsListPageTabs } from "@app/types/integrations";
|
||||
|
||||
import { PkiSyncsTable } from "./PkiSyncTable";
|
||||
|
||||
export const PkiSyncsTab = () => {
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["addSync"] as const);
|
||||
|
||||
const { addSync, ...search } = useSearch({
|
||||
const { addSync, connectionId, connectionName, ...search } = useSearch({
|
||||
from: ROUTE_PATHS.CertManager.IntegrationsListPage.id
|
||||
});
|
||||
|
||||
@@ -45,6 +46,42 @@ export const PkiSyncsTab = () => {
|
||||
navigateToBase();
|
||||
}, [addSync, handlePopUpOpen, navigateToBase]);
|
||||
|
||||
useEffect(() => {
|
||||
const storedFormData = localStorage.getItem("pkiSyncFormData");
|
||||
if (storedFormData && !popUp.addSync.isOpen) {
|
||||
try {
|
||||
const parsedData = JSON.parse(storedFormData);
|
||||
if (connectionId && connectionName) {
|
||||
const initialData = {
|
||||
...parsedData,
|
||||
connection: { id: connectionId, name: connectionName }
|
||||
};
|
||||
handlePopUpOpen("addSync", { destination: parsedData.destination, initialData });
|
||||
navigate({
|
||||
to: ROUTE_PATHS.CertManager.IntegrationsListPage.path,
|
||||
params: { projectId: currentProject?.id },
|
||||
search: { selectedTab: IntegrationsListPageTabs.PkiSyncs },
|
||||
replace: true
|
||||
});
|
||||
} else {
|
||||
handlePopUpOpen("addSync", { destination: parsedData.destination });
|
||||
}
|
||||
localStorage.removeItem("pkiSyncFormData");
|
||||
} catch (error) {
|
||||
console.error("Failed to parse stored PKI sync form data:", error);
|
||||
localStorage.removeItem("pkiSyncFormData");
|
||||
handlePopUpOpen("addSync");
|
||||
}
|
||||
}
|
||||
}, [
|
||||
handlePopUpOpen,
|
||||
popUp.addSync.isOpen,
|
||||
connectionId,
|
||||
connectionName,
|
||||
navigate,
|
||||
currentProject?.id
|
||||
]);
|
||||
|
||||
const { data: pkiSyncs = [], isPending: isPkiSyncsPending } = useListPkiSyncs(
|
||||
currentProject?.id || "",
|
||||
{
|
||||
@@ -94,7 +131,8 @@ export const PkiSyncsTab = () => {
|
||||
<PkiSyncsTable pkiSyncs={pkiSyncs} />
|
||||
</div>
|
||||
<CreatePkiSyncModal
|
||||
selectSync={popUp.addSync.data}
|
||||
selectSync={popUp.addSync.data?.destination || popUp.addSync.data}
|
||||
initialData={popUp.addSync.data?.initialData}
|
||||
isOpen={popUp.addSync.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("addSync", isOpen)}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,9 @@ import { IntegrationsListPage } from "./IntegrationsListPage";
|
||||
|
||||
const IntegrationsListPageQuerySchema = z.object({
|
||||
selectedTab: z.nativeEnum(IntegrationsListPageTabs).optional(),
|
||||
addSync: z.nativeEnum(PkiSync).optional()
|
||||
addSync: z.nativeEnum(PkiSync).optional(),
|
||||
connectionId: z.string().optional(),
|
||||
connectionName: z.string().optional()
|
||||
});
|
||||
|
||||
export const Route = createFileRoute(
|
||||
|
||||
@@ -418,7 +418,7 @@ export const CreateProfileModal = ({ isOpen, onClose, profile, mode = "create" }
|
||||
name="enrollmentType"
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Enrollment Type"
|
||||
label="Enrollment Method"
|
||||
isRequired
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
|
||||
@@ -633,7 +633,9 @@ export const OAuthCallbackPage = () => {
|
||||
connectionName: data.connection.name,
|
||||
...(data.returnUrl.includes("integrations")
|
||||
? {
|
||||
selectedTab: IntegrationsListPageTabs.SecretSyncs
|
||||
selectedTab: localStorage.getItem("pkiSyncFormData")
|
||||
? IntegrationsListPageTabs.PkiSyncs
|
||||
: IntegrationsListPageTabs.SecretSyncs
|
||||
}
|
||||
: {})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user