()
| 1107 | * Create webhook routes router |
| 1108 | */ |
| 1109 | export function createWebhooksRouter(): Router { |
| 1110 | const router = Router(); |
| 1111 | |
| 1112 | // ========================================================================= |
| 1113 | // Luma Webhooks |
| 1114 | // ========================================================================= |
| 1115 | |
| 1116 | router.post('/luma', async (req: Request, res: Response) => { |
| 1117 | const requestStartTime = Date.now(); |
| 1118 | |
| 1119 | // Verify webhook authenticity via signing secret |
| 1120 | const LUMA_WEBHOOK_SECRET = process.env.LUMA_WEBHOOK_SECRET; |
| 1121 | if (!LUMA_WEBHOOK_SECRET) { |
| 1122 | logger.warn('Luma webhook rejected: LUMA_WEBHOOK_SECRET not configured'); |
| 1123 | return res.status(503).json({ error: 'Webhook validation not configured' }); |
| 1124 | } |
| 1125 | const providedSecret = req.headers['x-luma-signing-secret'] as string | undefined; |
| 1126 | if (providedSecret !== LUMA_WEBHOOK_SECRET) { |
| 1127 | logger.warn('Luma webhook rejected: invalid signing secret'); |
| 1128 | return res.status(401).json({ error: 'Unauthorized' }); |
| 1129 | } |
| 1130 | |
| 1131 | try { |
| 1132 | logger.debug({ action: (req.body as Record<string, unknown>)?.action }, 'Received Luma webhook'); |
| 1133 | |
| 1134 | const payload = parseLumaWebhook(req.body); |
| 1135 | if (!payload) { |
| 1136 | logger.warn('Invalid Luma webhook payload structure'); |
| 1137 | return res.status(400).json({ error: 'Invalid payload' }); |
| 1138 | } |
| 1139 | |
| 1140 | logger.info({ |
| 1141 | action: payload.action, |
| 1142 | apiId: payload.data.api_id, |
| 1143 | }, 'Processing Luma webhook'); |
| 1144 | |
| 1145 | switch (payload.action) { |
| 1146 | case 'guest.created': |
| 1147 | await handleLumaGuestCreated(payload); |
| 1148 | break; |
| 1149 | case 'guest.updated': |
| 1150 | await handleLumaGuestUpdated(payload); |
| 1151 | break; |
| 1152 | case 'event.updated': |
| 1153 | await handleLumaEventUpdated(payload); |
| 1154 | break; |
| 1155 | case 'event.created': |
| 1156 | await handleLumaEventCreated(payload); |
| 1157 | break; |
| 1158 | case 'event.deleted': |
| 1159 | case 'event.cancelled': |
| 1160 | await handleLumaEventCancelled(payload); |
| 1161 | break; |
| 1162 | default: |
| 1163 | logger.warn({ action: payload.action }, 'Unknown Luma webhook action'); |
| 1164 | } |
| 1165 | |
| 1166 | const totalDurationMs = Date.now() - requestStartTime; |
no test coverage detected