Skip to content

Commit e4c50ce

Browse files
laktekclaude
andauthored
feat: Add duplicate key check with confirmation dialog for Edge Function secrets (supabase#36793)
- Created DuplicateSecretWarningModal component following the pattern of DeployEdgeFunctionWarningModal - Added duplicate key detection logic to AddNewSecretForm before secret creation - Shows confirmation dialog when attempting to create a secret with an existing name - Allows users to proceed with replacing the existing secret or cancel the operation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude <[email protected]>
1 parent 39fe55e commit e4c50ce

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/AddNewSecretForm.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import z from 'zod'
77
import { useParams } from 'common'
88
import Panel from 'components/ui/Panel'
99
import { useSecretsCreateMutation } from 'data/secrets/secrets-create-mutation'
10+
import { useSecretsQuery } from 'data/secrets/secrets-query'
1011
import { Eye, EyeOff, MinusCircle } from 'lucide-react'
12+
import { DuplicateSecretWarningModal } from './DuplicateSecretWarningModal'
1113
import {
1214
Button,
1315
Form_Shadcn_,
@@ -44,6 +46,8 @@ const defaultValues = {
4446
const AddNewSecretForm = () => {
4547
const { ref: projectRef } = useParams()
4648
const [showSecretValue, setShowSecretValue] = useState(false)
49+
const [duplicateSecretName, setDuplicateSecretName] = useState<string>('')
50+
const [pendingSecrets, setPendingSecrets] = useState<z.infer<typeof FormSchema> | null>(null)
4751

4852
const form = useForm({
4953
resolver: zodResolver(FormSchema),
@@ -55,6 +59,10 @@ const AddNewSecretForm = () => {
5559
name: 'secrets',
5660
})
5761

62+
const { data: existingSecrets } = useSecretsQuery({
63+
projectRef: projectRef,
64+
})
65+
5866
function handlePaste(e: ClipboardEvent) {
5967
e.preventDefault()
6068
const text = e.clipboardData?.getData('text')
@@ -114,9 +122,32 @@ const AddNewSecretForm = () => {
114122
})
115123

116124
const onSubmit: SubmitHandler<z.infer<typeof FormSchema>> = async (data) => {
125+
// Check for duplicate secret names
126+
const existingSecretNames = existingSecrets?.map((secret) => secret.name) || []
127+
const duplicateSecret = data.secrets.find((secret) => existingSecretNames.includes(secret.name))
128+
129+
if (duplicateSecret) {
130+
setDuplicateSecretName(duplicateSecret.name)
131+
setPendingSecrets(data)
132+
return
133+
}
134+
117135
createSecret({ projectRef, secrets: data.secrets })
118136
}
119137

138+
const handleConfirmDuplicate = () => {
139+
if (pendingSecrets) {
140+
createSecret({ projectRef, secrets: pendingSecrets.secrets })
141+
setDuplicateSecretName('')
142+
setPendingSecrets(null)
143+
}
144+
}
145+
146+
const handleCancelDuplicate = () => {
147+
setDuplicateSecretName('')
148+
setPendingSecrets(null)
149+
}
150+
120151
return (
121152
<Panel>
122153
<Panel.Content className="grid gap-4">
@@ -202,6 +233,14 @@ const AddNewSecretForm = () => {
202233
</form>
203234
</Form_Shadcn_>
204235
</Panel.Content>
236+
237+
<DuplicateSecretWarningModal
238+
visible={!!duplicateSecretName}
239+
onCancel={handleCancelDuplicate}
240+
onConfirm={handleConfirmDuplicate}
241+
isCreating={isCreating}
242+
secretName={duplicateSecretName}
243+
/>
205244
</Panel>
206245
)
207246
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
2+
3+
interface DuplicateSecretWarningModalProps {
4+
visible: boolean
5+
onCancel: () => void
6+
onConfirm: () => void
7+
isCreating: boolean
8+
secretName: string
9+
}
10+
11+
export const DuplicateSecretWarningModal = ({
12+
visible,
13+
onCancel,
14+
onConfirm,
15+
isCreating,
16+
secretName,
17+
}: DuplicateSecretWarningModalProps) => {
18+
return (
19+
<ConfirmationModal
20+
visible={visible}
21+
size="medium"
22+
title="Confirm replacing existing secret"
23+
confirmLabel="Replace secret"
24+
confirmLabelLoading="Replacing secret"
25+
variant="warning"
26+
loading={isCreating}
27+
onCancel={onCancel}
28+
onConfirm={onConfirm}
29+
>
30+
<p className="text-sm text-foreground-light">
31+
A secret with the name "{secretName}" already exists. Continuing will replace the existing
32+
secret with the new value. This action cannot be undone. Are you sure you want to proceed?
33+
</p>
34+
</ConfirmationModal>
35+
)
36+
}

0 commit comments

Comments
 (0)