- URL does not match -
- )} -- {error ? error : 'No webhooks added yet'} -
-{name}
+ ++ {createdAt} +
+| + |
|---|
+
We'll send a POST request with a JSON payload to{' '} - + {form.watch('url') || 'https://example.com/postreceive'} {' '} for each event. Example:
-- Signature Secret -
+Secret
- This secret is used to verify webhook authenticity. Each request
- includes an e2b-signature header
- generated with HMAC SHA-256. Validate this in your endpoint to
- ensure requests are from E2B and untampered.
+ A secret verifies that webhooks are from us and untampered. Use
+ our pre-generated one or add your own.
- Store this secret securely. You won't be able to view it - again after creating the webhook. + Copy and store it now. You won't be able to view it + again.
- {'> 32 characters'} -
-+ {'> 32 characters'} +
+ )} )} /> diff --git a/src/features/dashboard/settings/webhooks/upsert-webhook-dialog.tsx b/src/features/dashboard/settings/webhooks/upsert-webhook-dialog.tsx new file mode 100644 index 000000000..a4c43fc74 --- /dev/null +++ b/src/features/dashboard/settings/webhooks/upsert-webhook-dialog.tsx @@ -0,0 +1,354 @@ +'use client' + +import { zodResolver } from '@hookform/resolvers/zod' +import { useMutation, useQueryClient } from '@tanstack/react-query' +import { useState } from 'react' +import { useForm } from 'react-hook-form' +import { + type SandboxLifecycleEventType, + SandboxLifecycleEventTypeSchema, +} from '@/core/modules/sandboxes/lifecycle-event-types' +import { + type UpsertWebhookInput, + UpsertWebhookInputSchema, +} from '@/core/server/functions/webhooks/schema' +import { + defaultErrorToast, + defaultSuccessToast, + toast, +} from '@/lib/hooks/use-toast' +import { useTRPC } from '@/trpc/client' +import { Button } from '@/ui/primitives/button' +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/ui/primitives/dialog' +import { Form } from '@/ui/primitives/form' +import { AddIcon, CheckIcon } from '@/ui/primitives/icons' +import { Loader } from '@/ui/primitives/loader' +import { useDashboard } from '../../context' +import { DiscardWebhookChangesDialog } from './discard-webhook-changes-dialog' +import { FinishWebhookSetupDialog } from './finish-webhook-setup-dialog' +import type { Webhook } from './types' +import { + type SecretType, + UpsertWebhookDialogSteps, +} from './upsert-webhook-dialog-steps' + +type UpsertWebhookDialogProps = + | { + children: React.ReactNode + mode: 'create' + webhook?: undefined + } + | { + children: React.ReactNode + mode: 'update' + webhook: Webhook + } + +export function UpsertWebhookDialog({ + children: trigger, + mode, + webhook, +}: UpsertWebhookDialogProps) { + 'use no memo' + + const { team } = useDashboard() + const trpc = useTRPC() + const queryClient = useQueryClient() + const [open, setOpen] = useState(false) + const [currentStep, setCurrentStep] = useState(1) + const [lastSelectedEvent, setLastSelectedEvent] = + useState{label}
+} + +const WebhooksTableContent = ({ query }: { query: string }) => { + const { data } = useWebhooksQuery() + const { webhooks } = data + const normalizedQuery = query.trim().toLowerCase() + + const filtered = useMemo(() => { + if (!normalizedQuery) return webhooks + return webhooks.filter(({ events, name, url }) => + [name, url, ...events].some((value) => + value.toLowerCase().includes(normalizedQuery) + ) + ) + }, [normalizedQuery, webhooks]) + + return ( ++ Receive POST requests to your URLs when sandbox lifecycle events + occur. +
+