Skip to content

Commit 37567b4

Browse files
authored
feat[webhook]: added generic webhook (#130)
* added logic to support generic webhooks * fixed style of generic webhook * fixed style of generic webhook
1 parent 2db6c82 commit 37567b4

File tree

8 files changed

+714
-68
lines changed

8 files changed

+714
-68
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# Pull Request Template
2-
31
## Description
42

53
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.

package-lock.json

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"framer-motion": "^12.5.0"
4+
}
5+
}

sim/app/api/webhooks/test/route.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,60 @@ export async function GET(request: NextRequest) {
170170
})
171171
}
172172

173+
case 'generic': {
174+
// Get the general webhook configuration
175+
const token = providerConfig.token
176+
const secretHeaderName = providerConfig.secretHeaderName
177+
const requireAuth = providerConfig.requireAuth
178+
const allowedIps = providerConfig.allowedIps
179+
180+
// Generate sample curl command for testing
181+
let curlCommand = `curl -X POST "${webhookUrl}" -H "Content-Type: application/json"`
182+
183+
// Add auth headers to the curl command if required
184+
if (requireAuth && token) {
185+
if (secretHeaderName) {
186+
curlCommand += ` -H "${secretHeaderName}: ${token}"`
187+
} else {
188+
curlCommand += ` -H "Authorization: Bearer ${token}"`
189+
}
190+
}
191+
192+
// Add a sample payload
193+
curlCommand += ` -d '{"event":"test_event","timestamp":"${new Date().toISOString()}"}'`
194+
195+
logger.info(`[${requestId}] General webhook test successful: ${webhookId}`)
196+
return NextResponse.json({
197+
success: true,
198+
webhook: {
199+
id: foundWebhook.id,
200+
url: webhookUrl,
201+
isActive: foundWebhook.isActive,
202+
},
203+
message:
204+
'General webhook configuration is valid. Use the URL and authentication details as needed.',
205+
details: {
206+
requireAuth: requireAuth || false,
207+
hasToken: !!token,
208+
hasCustomHeader: !!secretHeaderName,
209+
customHeaderName: secretHeaderName,
210+
hasIpRestrictions: Array.isArray(allowedIps) && allowedIps.length > 0,
211+
},
212+
test: {
213+
curlCommand,
214+
headers: requireAuth
215+
? secretHeaderName
216+
? { [secretHeaderName]: token }
217+
: { Authorization: `Bearer ${token}` }
218+
: {},
219+
samplePayload: {
220+
event: 'test_event',
221+
timestamp: new Date().toISOString(),
222+
},
223+
},
224+
})
225+
}
226+
173227
default: {
174228
// Generic webhook test
175229
logger.info(`[${requestId}] Generic webhook test successful: ${webhookId}`)

sim/app/api/webhooks/trigger/[path]/route.ts

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ import { Serializer } from '@/serializer'
1313

1414
const logger = createLogger('WebhookTriggerAPI')
1515

16-
// Force dynamic rendering for webhook endpoints
1716
export const dynamic = 'force-dynamic'
18-
// Increase the response size limit for webhook payloads
1917
export const maxDuration = 300 // 5 minutes max execution time for long-running webhooks
2018

2119
/**
@@ -306,8 +304,58 @@ async function processWebhook(
306304
// Stripe verification would go here if needed
307305
break
308306

307+
case 'generic':
308+
// Enhanced general webhook authentication
309+
if (providerConfig.requireAuth) {
310+
let isAuthenticated = false
311+
312+
// Check for token in Authorization header (Bearer token)
313+
if (providerConfig.token) {
314+
const providedToken = authHeader?.startsWith('Bearer ')
315+
? authHeader.substring(7)
316+
: null
317+
if (providedToken === providerConfig.token) {
318+
isAuthenticated = true
319+
}
320+
321+
// Check for token in custom header if specified
322+
if (!isAuthenticated && providerConfig.secretHeaderName) {
323+
const customHeaderValue = request.headers.get(providerConfig.secretHeaderName)
324+
if (customHeaderValue === providerConfig.token) {
325+
isAuthenticated = true
326+
}
327+
}
328+
329+
// Return 401 if authentication failed
330+
if (!isAuthenticated) {
331+
logger.warn(`[${requestId}] Unauthorized webhook access attempt - invalid token`)
332+
return new NextResponse('Unauthorized', { status: 401 })
333+
}
334+
}
335+
}
336+
337+
// IP restriction check
338+
if (
339+
providerConfig.allowedIps &&
340+
Array.isArray(providerConfig.allowedIps) &&
341+
providerConfig.allowedIps.length > 0
342+
) {
343+
const clientIp =
344+
request.headers.get('x-forwarded-for')?.split(',')[0].trim() ||
345+
request.headers.get('x-real-ip') ||
346+
'unknown'
347+
348+
if (clientIp === 'unknown' || !providerConfig.allowedIps.includes(clientIp)) {
349+
logger.warn(
350+
`[${requestId}] Forbidden webhook access attempt - IP not allowed: ${clientIp}`
351+
)
352+
return new NextResponse('Forbidden - IP not allowed', { status: 403 })
353+
}
354+
}
355+
break
356+
309357
default:
310-
// For generic webhooks, check for a token if provided in providerConfig
358+
// For other generic webhooks, check for a token if provided in providerConfig
311359
if (providerConfig.token) {
312360
const providedToken = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : null
313361
if (!providedToken || providedToken !== providerConfig.token) {

sim/app/blocks/blocks/starter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ export const StarterBlock: BlockConfig<StarterBlockOutput> = {
4040
options: [
4141
{ label: 'Generic', id: 'generic' },
4242
{ label: 'WhatsApp', id: 'whatsapp' },
43-
{ label: 'GitHub', id: 'github' },
44-
{ label: 'Stripe', id: 'stripe' },
43+
// { label: 'GitHub', id: 'github' },
44+
// { label: 'Stripe', id: 'stripe' },
4545
],
4646
value: () => 'generic',
4747
condition: { field: 'startWorkflow', value: 'webhook' },

0 commit comments

Comments
 (0)