Skip to content

Commit 25e4287

Browse files
authored
fix(webhooks): use server-provided inboundUrl for copy on list page (#973)
## Summary - The webhook list page's "Copy URL" button was constructing inbound URLs client-side using a local `buildWebhookUrl` helper that always used `session.user.id` and hardcoded the `/inbound/user/` path prefix. For org webhooks, this produced URLs with the user's ID instead of the org's ID and the wrong path prefix (`/inbound/user/` instead of `/inbound/org/`). - Fix: the `webhookTriggers.list` tRPC endpoint now includes `inboundUrl` in each trigger's response (computed server-side via `buildInboundUrl`, which correctly branches on `organizationId` vs `userId`). The list page component now reads `trigger.inboundUrl` directly instead of constructing URLs client-side. This matches the pattern already used by the admin webhook list and the details page. - Removed the now-unused `buildWebhookUrl` helper, `useSession` import, and `encodeUserIdForPath` import from `WebhookTriggersListContent.tsx`. ## Verification - [x] `pnpm typecheck` passes cleanly across all workspace projects ## Visual Changes N/A ## Reviewer Notes - The admin list page (`AdminWebhookTriggersList.tsx`) already followed the correct pattern: its tRPC endpoint (`admin.webhookTriggers.list`) calls `buildInboundUrl` per trigger and returns `inboundUrl` in the response. This fix aligns the non-admin list endpoint to the same approach. - The details page was unaffected because it fetches via `webhookTriggers.get`, which already returned the server-computed `inboundUrl`.
2 parents cabcca1 + 806f2c4 commit 25e4287

2 files changed

Lines changed: 13 additions & 16 deletions

File tree

src/app/(app)/cloud/webhooks/WebhookTriggersListContent.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use client';
22

33
import { useState, useCallback, useMemo } from 'react';
4-
import { useSession } from 'next-auth/react';
54
import { toast } from 'sonner';
65
import { getWebhookRoutes } from '@/lib/webhook-routes';
76
import {
@@ -18,20 +17,12 @@ import {
1817
type StatusFilterValue,
1918
type DeleteTarget,
2019
} from '@/components/webhook-triggers';
21-
import { encodeUserIdForPath } from '@/lib/webhook-agent/user-id-encoding';
22-
23-
/** Build the inbound webhook URL for a trigger */
24-
function buildWebhookUrl(userId: string, triggerId: string): string {
25-
return `https://hooks.kilosessions.ai/inbound/user/${encodeUserIdForPath(userId)}/${triggerId}`;
26-
}
2720

2821
type WebhookTriggersListContentProps = {
2922
organizationId?: string;
3023
};
3124

3225
export function WebhookTriggersListContent({ organizationId }: WebhookTriggersListContentProps) {
33-
const { data: session } = useSession();
34-
3526
// State
3627
const [statusFilter, setStatusFilter] = useState<StatusFilterValue>('all');
3728
const [copiedTriggerId, setCopiedTriggerId] = useState<string | null>(null);
@@ -63,23 +54,22 @@ export function WebhookTriggersListContent({ organizationId }: WebhookTriggersLi
6354
// Copy webhook URL to clipboard
6455
const handleCopyUrl = useCallback(
6556
async (triggerId: string) => {
66-
const userId = session?.user?.id;
67-
if (!userId) {
68-
toast.error('User ID not available');
57+
const trigger = triggers.find(t => t.triggerId === triggerId);
58+
if (!trigger) {
59+
toast.error('Trigger not found');
6960
return;
7061
}
7162

72-
const url = buildWebhookUrl(userId, triggerId);
7363
try {
74-
await navigator.clipboard.writeText(url);
64+
await navigator.clipboard.writeText(trigger.inboundUrl);
7565
setCopiedTriggerId(triggerId);
7666
toast.success('Webhook URL copied to clipboard');
7767
setTimeout(() => setCopiedTriggerId(null), 2000);
7868
} catch {
7969
toast.error('Failed to copy URL');
8070
}
8171
},
82-
[session?.user?.id]
72+
[triggers]
8373
);
8474

8575
// Open delete confirmation dialog

src/routers/webhook-triggers-router.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,14 @@ export const webhookTriggersRouter = createTRPCRouter({
181181
.where(whereClause)
182182
.orderBy(cloud_agent_webhook_triggers.created_at);
183183

184-
return triggers;
184+
return triggers.map(trigger => ({
185+
...trigger,
186+
inboundUrl: buildInboundUrl(
187+
input.organizationId ? undefined : userId,
188+
input.organizationId,
189+
trigger.triggerId
190+
),
191+
}));
185192
}),
186193

187194
/**

0 commit comments

Comments
 (0)