diff --git a/backend/src/services/secret/secret-service.ts b/backend/src/services/secret/secret-service.ts index 4c14edc0c..ecd13dae1 100644 --- a/backend/src/services/secret/secret-service.ts +++ b/backend/src/services/secret/secret-service.ts @@ -375,6 +375,10 @@ export const secretServiceFactory = ({ await projectDAL.checkProjectUpgradeStatus(projectId); + if (inputSecret.newSecretName === "") { + throw new BadRequestError({ message: "New secret name cannot be empty" }); + } + const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new BadRequestError({ message: "Folder not found", name: "Create secret" }); const folderId = folder.id; diff --git a/frontend/src/views/SecretMainPage/components/SecretListView/SecretItem.tsx b/frontend/src/views/SecretMainPage/components/SecretListView/SecretItem.tsx index a72463c9a..d165b4bd5 100644 --- a/frontend/src/views/SecretMainPage/components/SecretListView/SecretItem.tsx +++ b/frontend/src/views/SecretMainPage/components/SecretListView/SecretItem.tsx @@ -1,24 +1,4 @@ /* eslint-disable simple-import-sort/imports */ -import { memo, useEffect } from "react"; -import { Controller, useFieldArray, useForm } from "react-hook-form"; -import { subject } from "@casl/ability"; -import { faCheckCircle } from "@fortawesome/free-regular-svg-icons"; -import { - faCheck, - faClock, - faClose, - faCodeBranch, - faComment, - faCopy, - faEllipsis, - faKey, - faTag, - faTags -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { AnimatePresence, motion } from "framer-motion"; -import { twMerge } from "tailwind-merge"; import { ProjectPermissionCan } from "@app/components/permissions"; import { Button, @@ -48,9 +28,29 @@ import { import { useToggle } from "@app/hooks"; import { DecryptedSecret } from "@app/hooks/api/secrets/types"; import { WsTag } from "@app/hooks/api/types"; +import { subject } from "@casl/ability"; +import { faCheckCircle } from "@fortawesome/free-regular-svg-icons"; +import { + faCheck, + faClock, + faClose, + faCodeBranch, + faComment, + faCopy, + faEllipsis, + faKey, + faTag, + faTags +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { AnimatePresence, motion } from "framer-motion"; +import { memo, useEffect } from "react"; +import { Controller, useFieldArray, useForm } from "react-hook-form"; +import { twMerge } from "tailwind-merge"; -import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils"; import { CreateReminderForm } from "./CreateReminderForm"; +import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils"; type Props = { secret: DecryptedSecret; @@ -104,7 +104,8 @@ export const SecretItem = memo( setValue, reset, getValues, - formState: { isDirty, isSubmitting } + trigger, + formState: { isDirty, isSubmitting, errors } } = useForm({ defaultValues: secret, values: secret, @@ -235,15 +236,18 @@ export const SecretItem = memo( ( + render={({ field, fieldState: { error } }) => ( trigger("key")} {...field} - className="w-full px-0 focus:text-bunker-100 focus:ring-transparent" + className="w-full px-0 placeholder:text-red-500 focus:text-bunker-100 focus:ring-transparent" /> )} /> @@ -497,7 +501,7 @@ export const SecretItem = memo( animate={{ x: 0, opacity: 1 }} exit={{ x: -10, opacity: 0 }} > - + {isSubmitting ? ( ) : ( - + )} diff --git a/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.tsx b/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.tsx index 780e49448..db57cb144 100644 --- a/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.tsx +++ b/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.tsx @@ -206,7 +206,7 @@ export const SecretListView = ({ reminderRepeatDays, reminderNote } = modSecret; - const hasKeyChanged = oldKey !== key; + const hasKeyChanged = oldKey !== key && key; const tagIds = tags?.map(({ id }) => id); const oldTagIds = (orgSecret?.tags || []).map(({ id }) => id); diff --git a/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.utils.ts b/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.utils.ts index fc8a745d5..40e949bc8 100644 --- a/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.utils.ts +++ b/frontend/src/views/SecretMainPage/components/SecretListView/SecretListView.utils.ts @@ -8,7 +8,7 @@ export enum SecretActionType { } export const formSchema = z.object({ - key: z.string().trim(), + key: z.string().trim().min(1, { message: "Secret key is required" }), value: z.string().transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())), idOverride: z.string().trim().optional(), valueOverride: z