All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s
110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
/**
|
|
* POST /api/webhooks/:id/test
|
|
* Test a webhook with a sample payload
|
|
*/
|
|
import { query } from '../../../utils/database'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const username = getHeader(event, 'x-authentik-username')
|
|
if (!username) {
|
|
throw createError({ statusCode: 401, message: 'Unauthorized' })
|
|
}
|
|
|
|
const id = getRouterParam(event, 'id')
|
|
|
|
// Get webhook
|
|
const result = await query<{ url: string; secret: string | null; headers: any }>(
|
|
'SELECT url, secret, headers FROM webhooks WHERE id = $1',
|
|
[id]
|
|
)
|
|
|
|
if (result.rows.length === 0) {
|
|
throw createError({ statusCode: 404, message: 'Webhook not found' })
|
|
}
|
|
|
|
const webhook = result.rows[0]
|
|
|
|
// Create test payload
|
|
const testPayload = {
|
|
event: 'test',
|
|
timestamp: new Date().toISOString(),
|
|
data: {
|
|
message: 'This is a test webhook delivery',
|
|
webhookId: id,
|
|
sentBy: username
|
|
}
|
|
}
|
|
|
|
const body = JSON.stringify(testPayload)
|
|
|
|
const headers: Record<string, string> = {
|
|
'Content-Type': 'application/json',
|
|
'X-Webhook-Event': 'test',
|
|
'X-Webhook-Timestamp': Date.now().toString(),
|
|
...(webhook.headers || {})
|
|
}
|
|
|
|
// Add signature if secret exists
|
|
if (webhook.secret) {
|
|
const crypto = await import('crypto')
|
|
const signature = crypto
|
|
.createHmac('sha256', webhook.secret)
|
|
.update(body)
|
|
.digest('hex')
|
|
headers['X-Webhook-Signature'] = `sha256=${signature}`
|
|
}
|
|
|
|
try {
|
|
const controller = new AbortController()
|
|
const timeout = setTimeout(() => controller.abort(), 10000)
|
|
|
|
// Check if the URL is pointing to our own debug receiver
|
|
// If so, use internal URL to bypass authentik
|
|
let targetUrl = webhook.url
|
|
if (webhook.url.includes('/api/debug/webhook-receiver')) {
|
|
// Use internal URL (works in Docker/local environments)
|
|
const internalPort = process.env.PORT || 3000
|
|
targetUrl = `http://localhost:${internalPort}/api/debug/webhook-receiver`
|
|
}
|
|
|
|
const response = await fetch(targetUrl, {
|
|
method: 'POST',
|
|
headers,
|
|
body,
|
|
signal: controller.signal
|
|
})
|
|
|
|
clearTimeout(timeout)
|
|
|
|
const responseText = await response.text()
|
|
|
|
// Log the test
|
|
await query(
|
|
`INSERT INTO webhook_logs (webhook_id, event_type, payload, response_status, response_body, attempt, delivered_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
|
[id, 'test', testPayload, response.status, responseText.slice(0, 1000), 1, new Date()]
|
|
)
|
|
|
|
return {
|
|
success: response.ok,
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
response: responseText.slice(0, 500)
|
|
}
|
|
} catch (error) {
|
|
const errorMessage = (error as Error).message
|
|
|
|
// Log the failure
|
|
await query(
|
|
`INSERT INTO webhook_logs (webhook_id, event_type, payload, response_status, error_message, attempt)
|
|
VALUES ($1, $2, $3, $4, $5, $6)`,
|
|
[id, 'test', testPayload, 0, errorMessage, 1]
|
|
)
|
|
|
|
return {
|
|
success: false,
|
|
error: errorMessage
|
|
}
|
|
}
|
|
})
|