Skip to content
File

Blob: src/client/components/webhooks/rotate-secret-dialog.tsx

typescript78 lines
1import type { WebhookSummary } from "@/contracts";
2import { useState } from "react";
3import { RotateCw } from "lucide-react";
4import { ConfirmDialog } from "@/client/components/ui";
5import { SecretRevealDialog } from "@/client/components/webhooks/secret-reveal-dialog";
6import { formatApiError, getApiClient } from "@/client/lib";
7import { useToast } from "@/client/toast";
8import { webhookProviderCatalog } from "@/lib/webhooks";
9 
10interface RotateSecretDialogProps {
11 open: boolean;
12 onClose: () => void;
13 webhook: WebhookSummary;
14 webhookUrl: string;
15 onRotated: () => void;
16}
17 
18export const RotateSecretDialog = ({ open, onClose, webhook, webhookUrl, onRotated }: RotateSecretDialogProps) => {
19 const { pushToast } = useToast();
20 const [rotating, setRotating] = useState(false);
21 const [newSecret, setNewSecret] = useState<string | null>(null);
22 
23 const catalog = webhookProviderCatalog[webhook.provider];
24 
25 const handleConfirm = () => {
26 setRotating(true);
27 
28 void getApiClient()
29 .rotateWebhookSecret(webhook.projectId, webhook.provider)
30 .then((response) => {
31 setNewSecret(response.secret);
32 onRotated();
33 pushToast({
34 tone: "success",
35 title: "Secret rotated",
36 message: `Update your ${catalog.displayName} webhook configuration.`,
37 });
38 })
39 .catch((reason: unknown) => {
40 pushToast({ tone: "error", title: "Rotation failed", message: formatApiError(reason) });
41 onClose();
42 })
43 .finally(() => {
44 setRotating(false);
45 });
46 };
47 
48 const handleClose = () => {
49 setNewSecret(null);
50 onClose();
51 };
52 
53 if (newSecret) {
54 return (
55 <SecretRevealDialog
56 open
57 onClose={handleClose}
58 secret={newSecret}
59 provider={webhook.provider}
60 webhookUrl={webhookUrl}
61 />
62 );
63 }
64 
65 return (
66 <ConfirmDialog
67 open={open}
68 onConfirm={handleConfirm}
69 onCancel={onClose}
70 title="Rotate webhook secret"
71 description={`This will generate a new secret and invalidate the current one. You will need to update your ${catalog.displayName} webhook configuration immediately. This action cannot be undone.`}
72 confirmLabel={rotating ? "Rotating..." : "Rotate Secret"}
73 variant="warning"
74 icon={<RotateCw className="h-5 w-5" />}
75 />
76 );
77};