with stripSchema and filterForSchema

This commit is contained in:
x032205
2025-05-13 23:08:54 -04:00
parent f6e1441dc0
commit bae62421ae
14 changed files with 275 additions and 151 deletions
@@ -10,7 +10,8 @@ import {
ModalClose,
ModalContent,
Select,
SelectItem
SelectItem,
Switch
} from "@app/components/v2";
import { SECRET_SYNC_IMPORT_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
import {
@@ -31,30 +32,49 @@ type ContentProps = {
};
const FormSchema = z.object({
importBehavior: z.nativeEnum(SecretSyncImportBehavior)
importBehavior: z.nativeEnum(SecretSyncImportBehavior),
filterForSchema: z.boolean(),
stripSchema: z.boolean()
});
type TFormData = z.infer<typeof FormSchema>;
const Content = ({ secretSync, onComplete }: ContentProps) => {
const { id: syncId, destination, projectId } = secretSync;
const {
id: syncId,
destination,
projectId,
syncOptions: { keySchema }
} = secretSync;
const destinationName = SECRET_SYNC_MAP[destination].name;
const {
handleSubmit,
control,
formState: { isSubmitting, isDirty }
} = useForm<TFormData>({ resolver: zodResolver(FormSchema) });
} = useForm<TFormData>({
resolver: zodResolver(FormSchema),
defaultValues: {
filterForSchema: false,
stripSchema: false
}
});
const triggerImportSecrets = useTriggerSecretSyncImportSecrets();
const handleTriggerImportSecrets = async ({ importBehavior }: TFormData) => {
const handleTriggerImportSecrets = async ({
importBehavior,
filterForSchema,
stripSchema
}: TFormData) => {
try {
await triggerImportSecrets.mutateAsync({
syncId,
destination,
importBehavior,
projectId
projectId,
filterForSchema,
stripSchema
});
createNotification({
@@ -131,6 +151,64 @@ const Content = ({ secretSync, onComplete }: ContentProps) => {
</FormControl>
)}
/>
{keySchema && (
<>
<Controller
control={control}
name="filterForSchema"
defaultValue
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
tooltipClassName="max-w-md"
tooltipText={
<div className="flex flex-col gap-2">
<p>
If enabled, Infisical will only import destination secrets that match your key
schema:
</p>
<code className="text-mineshaft-300">{keySchema}</code>
</div>
}
label="Filter Keys for Schema"
isError={Boolean(error)}
errorText={error?.message}
>
<Switch
id="filter-for-schema"
thumbClassName="bg-mineshaft-800"
isChecked={value}
onCheckedChange={onChange}
>
Only import destination secrets that match schema
</Switch>
</FormControl>
)}
/>
<Controller
control={control}
name="stripSchema"
defaultValue
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
tooltipClassName="max-w-md"
tooltipText="If enabled, Infisical will strip secret keys according to your schema. Keys that do not match the schema will not be affected."
label="Strip Schema"
isError={Boolean(error)}
errorText={error?.message}
>
<Switch
id="strip-schema"
thumbClassName="bg-mineshaft-800"
isChecked={value}
onCheckedChange={onChange}
>
Strip schema from imported secret keys
</Switch>
</FormControl>
)}
/>
</>
)}
<div className="mt-8 flex w-full items-center justify-between gap-2">
<ModalClose asChild>
<Button colorSchema="secondary" variant="plain">
@@ -3,7 +3,7 @@ import { Controller, useFormContext } from "react-hook-form";
import { faQuestionCircle, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FormControl, Select, SelectItem, Switch, Tooltip } from "@app/components/v2";
import { FormControl, Input, Select, SelectItem, Switch, Tooltip } from "@app/components/v2";
import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
import { SecretSync, useSecretSyncOption } from "@app/hooks/api/secretSyncs";
@@ -122,6 +122,22 @@ export const SecretSyncOptionsFields = ({ hideInitialSync }: Props) => {
)}
</>
)}
<Controller
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
tooltipClassName="max-w-md"
tooltipText="When a secret is synced, it's key will be injected into the key schema before it reaches the destination. This is useful for organization."
isError={Boolean(error)}
isOptional
errorText={error?.message}
label="Key Schema"
>
<Input value={value} onChange={onChange} placeholder="prefix/{{secretKey}}/suffix" />
</FormControl>
)}
control={control}
name="syncOptions.keySchema"
/>
{AdditionalSyncOptionsFieldsComponent}
<Controller
control={control}
@@ -161,34 +177,6 @@ export const SecretSyncOptionsFields = ({ hideInitialSync }: Props) => {
);
}}
/>
{/* <Controller
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isError={Boolean(error)}
isOptional
errorText={error?.message}
label="Prepend Prefix"
>
<Input className="uppercase" value={value} onChange={onChange} placeholder="INF_" />
</FormControl>
)}
control={control}
name="syncOptions.prependPrefix"
/>
<Controller
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isError={Boolean(error)}
isOptional
errorText={error?.message}
label="Append Suffix"
>
<Input className="uppercase" value={value} onChange={onChange} placeholder="_INF" />
</FormControl>
)}
control={control}
name="syncOptions.appendSuffix"
/> */}
</>
);
};
@@ -41,11 +41,7 @@ export const SecretSyncReviewFields = () => {
connection,
environment,
secretPath,
syncOptions: {
// appendSuffix, prependPrefix,
disableSecretDeletion,
initialSyncBehavior
},
syncOptions: { disableSecretDeletion, initialSyncBehavior, keySchema },
destination,
isAutoSyncEnabled
} = watch();
@@ -137,8 +133,7 @@ export const SecretSyncReviewFields = () => {
<GenericFieldLabel label="Initial Sync Behavior">
{SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP[initialSyncBehavior](destinationName).name}
</GenericFieldLabel>
{/* <SecretSyncLabel label="Prepend Prefix">{prependPrefix}</SecretSyncLabel>
<SecretSyncLabel label="Append Suffix">{appendSuffix}</SecretSyncLabel> */}
<GenericFieldLabel label="Key Schema">{keySchema}</GenericFieldLabel>
{AdditionalSyncOptionsFieldsComponent}
{disableSecretDeletion && (
<GenericFieldLabel label="Secret Deletion">
@@ -8,18 +8,17 @@ export const BaseSecretSyncSchema = <T extends AnyZodObject | undefined = undefi
) => {
const baseSyncOptionsSchema = z.object({
initialSyncBehavior: z.nativeEnum(SecretSyncInitialSyncBehavior),
disableSecretDeletion: z.boolean().optional().default(false)
// scott: removed temporarily for evaluation of template formatting
// prependPrefix: z
// .string()
// .trim()
// .transform((str) => str.toUpperCase())
// .optional(),
// appendSuffix: z
// .string()
// .trim()
// .transform((str) => str.toUpperCase())
// .optional()
disableSecretDeletion: z.boolean().optional().default(false),
keySchema: z
.string()
.optional()
.refine(
(val) => !val || /^(?:[a-zA-Z0-9\-/]*)(?:\{\{secretKey\}\})(?:[a-zA-Z0-9\-/]*)$/.test(val),
{
message:
"Key schema must include {{secretKey}} and only contain letters, numbers, dashes, slashes, and the {{secretKey}} placeholder."
}
)
});
const syncOptionsSchema = additionalSyncOptions