From d2b909b72b8fb0426c7b6cf6a3ca603802670768 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 10 Dec 2024 04:01:17 +0400 Subject: [PATCH 1/7] fix(dashboard): pasting secrets into create secret modal --- frontend/src/helpers/parseEnvVar.ts | 23 +++++++++++++++---- .../CreateSecretForm/CreateSecretForm.tsx | 17 +++++++++++--- .../CreateSecretForm/CreateSecretForm.tsx | 17 +++++++++++--- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/frontend/src/helpers/parseEnvVar.ts b/frontend/src/helpers/parseEnvVar.ts index 27640b515..6b056d5e9 100644 --- a/frontend/src/helpers/parseEnvVar.ts +++ b/frontend/src/helpers/parseEnvVar.ts @@ -1,14 +1,29 @@ /** Extracts the key and value from a passed in env string based on the provided delimiters. */ export const getKeyValue = (pastedContent: string, delimiters: string[]) => { - const foundDelimiter = delimiters.find((delimiter) => pastedContent.includes(delimiter)); + if (!pastedContent) { + return { key: "", value: "" }; + } - if (!foundDelimiter) { + let firstDelimiterIndex = -1; + let foundDelimiter = ""; + + delimiters.forEach((delimiter) => { + const index = pastedContent.indexOf(delimiter); + if (index !== -1 && (firstDelimiterIndex === -1 || index < firstDelimiterIndex)) { + firstDelimiterIndex = index; + foundDelimiter = delimiter; + } + }); + + if (firstDelimiterIndex === -1) { return { key: pastedContent.trim(), value: "" }; } - const [key, value] = pastedContent.split(foundDelimiter); + const key = pastedContent.substring(0, firstDelimiterIndex); + const value = pastedContent.substring(firstDelimiterIndex + foundDelimiter.length); + return { key: key.trim(), - value: (value ?? "").trim() + value: value.trim() }; }; diff --git a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx index 53b00f34a..17c99ac8c 100644 --- a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -46,6 +46,7 @@ export const CreateSecretForm = ({ control, reset, setValue, + watch, formState: { errors, isSubmitting } } = useForm({ resolver: zodResolver(typeSchema) }); const { closePopUp } = usePopUpAction(); @@ -59,6 +60,9 @@ export const CreateSecretForm = ({ canReadTags ? workspaceId : "" ); + const secretValue = watch("value"); + const secretKey = watch("key"); + const slugSchema = z.string().trim().toLowerCase().min(1); const createNewTag = async (slug: string) => { // TODO: Replace with slugSchema generic @@ -108,13 +112,20 @@ export const CreateSecretForm = ({ }; const handlePaste = (e: ClipboardEvent) => { - e.preventDefault(); const delimitters = [":", "="]; const pastedContent = e.clipboardData.getData("text"); const { key, value } = getKeyValue(pastedContent, delimitters); - setValue("key", key); - setValue("value", value); + if (!secretKey) { + setValue("key", key); + } + if (!secretValue) { + setValue("value", value); + } + + if (!secretKey) { + e.preventDefault(); + } }; return ( diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx index 36e430205..ce44c9881 100644 --- a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -46,6 +46,7 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { control, reset, setValue, + watch, formState: { isSubmitting, errors } } = useForm({ resolver: zodResolver(typeSchema) }); @@ -61,6 +62,9 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { canReadTags ? workspaceId : "" ); + const secretValue = watch("value"); + const secretKey = watch("key"); + const handleFormSubmit = async ({ key, value, environments: selectedEnv, tags }: TFormSchema) => { const promises = selectedEnv.map(async (env) => { const environment = env.slug; @@ -152,13 +156,20 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { }; const handlePaste = (e: ClipboardEvent) => { - e.preventDefault(); const delimitters = [":", "="]; const pastedContent = e.clipboardData.getData("text"); const { key, value } = getKeyValue(pastedContent, delimitters); - setValue("key", key); - setValue("value", value); + if (!secretKey) { + setValue("key", key); + } + if (!secretValue) { + setValue("value", value); + } + + if (!secretKey) { + e.preventDefault(); + } }; const createWsTag = useCreateWsTag(); From 3a8219db03868a13ccf60f90c20d3c6f2c104c02 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Wed, 11 Dec 2024 08:32:10 +0400 Subject: [PATCH 2/7] fix: requested changes --- .../CreateSecretForm/CreateSecretForm.tsx | 15 +++++++++------ .../CreateSecretForm/CreateSecretForm.tsx | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx index 17c99ac8c..1d2d1ead1 100644 --- a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -1,4 +1,4 @@ -import { ClipboardEvent } from "react"; +import { ClipboardEvent, useRef } from "react"; import { Controller, useForm } from "react-hook-form"; import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -60,7 +60,7 @@ export const CreateSecretForm = ({ canReadTags ? workspaceId : "" ); - const secretValue = watch("value"); + const secretKeyInputRef = useRef(null); const secretKey = watch("key"); const slugSchema = z.string().trim().toLowerCase().min(1); @@ -116,13 +116,15 @@ export const CreateSecretForm = ({ const pastedContent = e.clipboardData.getData("text"); const { key, value } = getKeyValue(pastedContent, delimitters); - if (!secretKey) { + const isWholeKeyHighlighted = + secretKeyInputRef.current && + secretKeyInputRef.current.selectionStart === 0 && + secretKeyInputRef.current.selectionEnd === secretKeyInputRef.current.value.length; + + if (!secretKey || isWholeKeyHighlighted) { setValue("key", key); - } - if (!secretValue) { setValue("value", value); } - if (!secretKey) { e.preventDefault(); } @@ -138,6 +140,7 @@ export const CreateSecretForm = ({ > { canReadTags ? workspaceId : "" ); - const secretValue = watch("value"); + const secretKeyInputRef = useRef(null); const secretKey = watch("key"); const handleFormSubmit = async ({ key, value, environments: selectedEnv, tags }: TFormSchema) => { @@ -160,13 +160,15 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { const pastedContent = e.clipboardData.getData("text"); const { key, value } = getKeyValue(pastedContent, delimitters); - if (!secretKey) { + const isWholeKeyHighlighted = + secretKeyInputRef.current && + secretKeyInputRef.current.selectionStart === 0 && + secretKeyInputRef.current.selectionEnd === secretKeyInputRef.current.value.length; + + if (!secretKey || isWholeKeyHighlighted) { setValue("key", key); - } - if (!secretValue) { setValue("value", value); } - if (!secretKey) { e.preventDefault(); } @@ -201,6 +203,7 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { > Date: Wed, 11 Dec 2024 21:44:42 +0400 Subject: [PATCH 3/7] fix: requested changes --- .../CreateSecretForm/CreateSecretForm.tsx | 18 +++++++++++++----- .../CreateSecretForm/CreateSecretForm.tsx | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx index 1d2d1ead1..a3f0ef323 100644 --- a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -61,6 +61,8 @@ export const CreateSecretForm = ({ ); const secretKeyInputRef = useRef(null); + const { ref: setSecretKeyHookRef, ...secretKeyRegisterRest } = register("key"); + const secretKey = watch("key"); const slugSchema = z.string().trim().toLowerCase().min(1); @@ -122,12 +124,11 @@ export const CreateSecretForm = ({ secretKeyInputRef.current.selectionEnd === secretKeyInputRef.current.value.length; if (!secretKey || isWholeKeyHighlighted) { + e.preventDefault(); + setValue("key", key); setValue("value", value); } - if (!secretKey) { - e.preventDefault(); - } }; return ( @@ -139,8 +140,15 @@ export const CreateSecretForm = ({ errorText={errors?.key?.message} > { + setSecretKeyHookRef(e); + // Can't directly set secretKeyInputRef.current = e, because of read-only property definitions + Object.defineProperty(secretKeyInputRef, "current", { + value: e, + writable: true + }); + }} placeholder="Type your secret name" onPaste={handlePaste} autoCapitalization={autoCapitalize} diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx index 48a8bc9f6..9633472cc 100644 --- a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -63,6 +63,8 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { ); const secretKeyInputRef = useRef(null); + const { ref: setSecretKeyHookRef, ...secretKeyRegisterRest } = register("key"); + const secretKey = watch("key"); const handleFormSubmit = async ({ key, value, environments: selectedEnv, tags }: TFormSchema) => { @@ -166,12 +168,11 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { secretKeyInputRef.current.selectionEnd === secretKeyInputRef.current.value.length; if (!secretKey || isWholeKeyHighlighted) { + e.preventDefault(); + setValue("key", key); setValue("value", value); } - if (!secretKey) { - e.preventDefault(); - } }; const createWsTag = useCreateWsTag(); @@ -202,8 +203,15 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { errorText={errors?.key?.message} > { + setSecretKeyHookRef(e); + // Can't directly set secretKeyInputRef.current = e, because of read-only property definitions + Object.defineProperty(secretKeyInputRef, "current", { + value: e, + writable: true + }); + }} placeholder="Type your secret name" onPaste={handlePaste} autoCapitalization={currentWorkspace?.autoCapitalization} From 3b3482b28052123677db79569dbdc6904ce0bb02 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Wed, 11 Dec 2024 21:51:20 +0400 Subject: [PATCH 4/7] fix: improve ref handling --- .../components/CreateSecretForm/CreateSecretForm.tsx | 7 ++----- .../components/CreateSecretForm/CreateSecretForm.tsx | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx index a3f0ef323..0710bb533 100644 --- a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -143,11 +143,8 @@ export const CreateSecretForm = ({ {...secretKeyRegisterRest} ref={(e) => { setSecretKeyHookRef(e); - // Can't directly set secretKeyInputRef.current = e, because of read-only property definitions - Object.defineProperty(secretKeyInputRef, "current", { - value: e, - writable: true - }); + // @ts-expect-error this is for multiple ref single component + secretKeyInputRef.current = e; }} placeholder="Type your secret name" onPaste={handlePaste} diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx index 9633472cc..ea6cbe61e 100644 --- a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -206,11 +206,8 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { {...secretKeyRegisterRest} ref={(e) => { setSecretKeyHookRef(e); - // Can't directly set secretKeyInputRef.current = e, because of read-only property definitions - Object.defineProperty(secretKeyInputRef, "current", { - value: e, - writable: true - }); + // @ts-expect-error this is for multiple ref single component + secretKeyInputRef.current = e; }} placeholder="Type your secret name" onPaste={handlePaste} From 1ace8eebf8e4b93109594d9baea9a8b28b58976f Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Thu, 12 Dec 2024 03:27:07 +0400 Subject: [PATCH 5/7] fix(k8s): dynamic secret bugs --- frontend/src/helpers/parseEnvVar.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/helpers/parseEnvVar.ts b/frontend/src/helpers/parseEnvVar.ts index 6b056d5e9..d2e39899e 100644 --- a/frontend/src/helpers/parseEnvVar.ts +++ b/frontend/src/helpers/parseEnvVar.ts @@ -15,7 +15,10 @@ export const getKeyValue = (pastedContent: string, delimiters: string[]) => { } }); - if (firstDelimiterIndex === -1) { + // Check if there's any content after the delimiter + const hasValueAfterDelimiter = pastedContent.length > firstDelimiterIndex + foundDelimiter.length; + + if (firstDelimiterIndex === -1 || !hasValueAfterDelimiter) { return { key: pastedContent.trim(), value: "" }; } From c000a6f707fb01c25be0121fdbeae3ee470aa309 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Thu, 12 Dec 2024 03:34:08 +0400 Subject: [PATCH 6/7] more requested changes --- .../components/CreateSecretForm/CreateSecretForm.tsx | 4 +++- .../components/CreateSecretForm/CreateSecretForm.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx index 0710bb533..db53d26ae 100644 --- a/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretMainPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -127,7 +127,9 @@ export const CreateSecretForm = ({ e.preventDefault(); setValue("key", key); - setValue("value", value); + if (value) { + setValue("value", value); + } } }; diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx index ea6cbe61e..aabd7899e 100644 --- a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -171,7 +171,9 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => { e.preventDefault(); setValue("key", key); - setValue("value", value); + if (value) { + setValue("value", value); + } } }; From 456837055266aa6e62dd3f685984c35f8438c8cf Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Thu, 12 Dec 2024 03:55:27 +0400 Subject: [PATCH 7/7] Update parseEnvVar.ts --- frontend/src/helpers/parseEnvVar.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/helpers/parseEnvVar.ts b/frontend/src/helpers/parseEnvVar.ts index d2e39899e..8bde05084 100644 --- a/frontend/src/helpers/parseEnvVar.ts +++ b/frontend/src/helpers/parseEnvVar.ts @@ -15,7 +15,6 @@ export const getKeyValue = (pastedContent: string, delimiters: string[]) => { } }); - // Check if there's any content after the delimiter const hasValueAfterDelimiter = pastedContent.length > firstDelimiterIndex + foundDelimiter.length; if (firstDelimiterIndex === -1 || !hasValueAfterDelimiter) {