1
0
mirror of https://github.com/Infisical/infisical.git synced 2025-03-19 06:52:36 +00:00

Compare commits

...

5 Commits

3 changed files with 85 additions and 10 deletions
frontend/src/views
SecretMainPage/components
CreateSecretForm
SecretListView
SecretOverviewPage/components/CreateSecretForm

@ -1,9 +1,19 @@
import { Controller, useForm } from "react-hook-form";
import { faCircleQuestion } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
import {
Button,
FormControl,
Input,
Modal,
ModalContent,
Switch,
Tooltip
} from "@app/components/v2";
import { InfisicalSecretInput } from "@app/components/v2/InfisicalSecretInput";
import { useCreateSecretV3 } from "@app/hooks/api";
import { UserWsKeyPair } from "@app/hooks/api/types";
@ -12,7 +22,8 @@ import { PopUpNames, usePopUpAction, usePopUpState } from "../../SecretMainPage.
const typeSchema = z.object({
key: z.string(),
value: z.string().optional()
value: z.string().optional(),
skipMultilineEncoding: z.boolean().optional()
});
type TFormSchema = z.infer<typeof typeSchema>;
@ -22,7 +33,6 @@ type Props = {
workspaceId: string;
decryptFileKey: UserWsKeyPair;
secretPath?: string;
// modal props
autoCapitalize?: boolean;
isProtectedBranch?: boolean;
};
@ -40,14 +50,17 @@ export const CreateSecretForm = ({
handleSubmit,
control,
reset,
watch,
formState: { errors, isSubmitting }
} = useForm<TFormSchema>({ resolver: zodResolver(typeSchema) });
const { isOpen } = usePopUpState(PopUpNames.CreateSecretForm);
const { closePopUp, togglePopUp } = usePopUpAction();
const newSecretValue = watch("value");
const isMultiline = newSecretValue?.includes("\n");
const { mutateAsync: createSecretV3 } = useCreateSecretV3();
const handleFormSubmit = async ({ key, value }: TFormSchema) => {
const handleFormSubmit = async ({ key, value, skipMultilineEncoding }: TFormSchema) => {
try {
await createSecretV3({
environment,
@ -57,7 +70,8 @@ export const CreateSecretForm = ({
secretValue: value || "",
secretComment: "",
type: "shared",
latestFileKey: decryptFileKey
latestFileKey: decryptFileKey,
skipMultilineEncoding
});
closePopUp(PopUpNames.CreateSecretForm);
reset();
@ -111,6 +125,31 @@ export const CreateSecretForm = ({
</FormControl>
)}
/>
{isMultiline && (
<div className="my-2 mb-6 ml-1 border-b border-mineshaft-600 pb-4">
<Controller
control={control}
name="skipMultilineEncoding"
render={({ field: { value, onChange, onBlur } }) => (
<Switch
id="skipmultiencoding-option"
onCheckedChange={(isChecked) => onChange(!isChecked)}
isChecked={!value}
onBlur={onBlur}
className="items-center"
>
Enable multi line encoding
<Tooltip
content="When enabled, secrets are escaped and wrapped in quotes"
className="z-[100]"
>
<FontAwesomeIcon icon={faCircleQuestion} className="ml-1" size="sm" />
</Tooltip>
</Switch>
)}
/>
</div>
)}
<div className="mt-7 flex items-center">
<Button
isDisabled={isSubmitting}

@ -401,7 +401,7 @@ export const SecretDetailSidebar = ({
>
Multi line encoding
<Tooltip
content="When enabled, multiline secrets will be handled by escaping newlines and enclosing the entire value in double quotes."
content="When enabled, secrets are escaped and wrapped in quotes"
className="z-[100]"
>
<FontAwesomeIcon icon={faCircleQuestion} className="ml-1" size="sm" />

@ -1,5 +1,5 @@
import { Controller, useForm } from "react-hook-form";
import { faWarning } from "@fortawesome/free-solid-svg-icons";
import { faCircleQuestion, faWarning } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
@ -13,6 +13,7 @@ import {
Input,
Modal,
ModalContent,
Switch,
Tooltip
} from "@app/components/v2";
import { InfisicalSecretInput } from "@app/components/v2/InfisicalSecretInput";
@ -24,6 +25,7 @@ const typeSchema = z
.object({
key: z.string().min(1, "Key is required"),
value: z.string().optional(),
skipMultilineEncoding: z.boolean().optional(),
environments: z.record(z.boolean().optional())
})
.refine((data) => data.key !== undefined, {
@ -59,6 +61,8 @@ export const CreateSecretForm = ({
formState: { isSubmitting, errors }
} = useForm<TFormSchema>({ resolver: zodResolver(typeSchema) });
const newSecretKey = watch("key");
const newSecretValue = watch("value");
const isMultiline = newSecretValue?.includes("\n");
const { currentWorkspace } = useWorkspace();
const workspaceId = currentWorkspace?.id || "";
@ -68,7 +72,12 @@ export const CreateSecretForm = ({
const { mutateAsync: updateSecretV3 } = useUpdateSecretV3();
const { mutateAsync: createFolder } = useCreateFolder();
const handleFormSubmit = async ({ key, value, environments: selectedEnv }: TFormSchema) => {
const handleFormSubmit = async ({
key,
value,
skipMultilineEncoding,
environments: selectedEnv
}: TFormSchema) => {
const environmentsSelected = environments.filter(({ slug }) => selectedEnv[slug]);
const isEnvironmentsSelected = environmentsSelected.length;
@ -104,7 +113,8 @@ export const CreateSecretForm = ({
secretName: key,
secretValue: value || "",
type: "shared",
latestFileKey: decryptFileKey
latestFileKey: decryptFileKey,
skipMultilineEncoding
});
}
@ -116,7 +126,8 @@ export const CreateSecretForm = ({
secretValue: value || "",
secretComment: "",
type: "shared",
latestFileKey: decryptFileKey
latestFileKey: decryptFileKey,
skipMultilineEncoding
});
});
@ -168,6 +179,31 @@ export const CreateSecretForm = ({
</FormControl>
)}
/>
{isMultiline && (
<div className="my-2 mb-6 ml-1 border-b border-mineshaft-600 pb-4">
<Controller
control={control}
name="skipMultilineEncoding"
render={({ field: { value, onChange, onBlur } }) => (
<Switch
id="skipmultiencoding-option"
onCheckedChange={(isChecked) => onChange(!isChecked)}
isChecked={!value}
onBlur={onBlur}
className="items-center"
>
Enable multi line encoding
<Tooltip
content="When enabled, secrets are escaped and wrapped in quotes"
className="z-[100]"
>
<FontAwesomeIcon icon={faCircleQuestion} className="ml-1" size="sm" />
</Tooltip>
</Switch>
)}
/>
</div>
)}
<FormLabel label="Environments" className="mb-2" />
<div className="thin-scrollbar grid max-h-64 grid-cols-3 gap-4 overflow-auto py-2">
{environments.map((env) => {