Files
cve-dashboard/backend/routes/webhooks.js

74 lines
3.1 KiB
JavaScript
Raw Normal View History

// GitLab Webhook Routes — receives issue lifecycle events from GitLab
// Used to notify users via Webex when their feedback issues are closed.
const express = require('express');
const pool = require('../db');
const { sendDirectMessage } = require('../helpers/webexBot');
const GITLAB_WEBHOOK_SECRET = process.env.GITLAB_WEBHOOK_SECRET || '';
function createWebhooksRouter() {
const router = express.Router();
// POST /api/webhooks/gitlab — GitLab issue webhook receiver
router.post('/gitlab', express.json(), async (req, res) => {
// Always return 200 — webhooks should not retry on app-level failures
try {
// Validate webhook secret token
const token = req.headers['x-gitlab-token'];
if (!GITLAB_WEBHOOK_SECRET || token !== GITLAB_WEBHOOK_SECRET) {
console.warn('[Webhook] Invalid or missing X-Gitlab-Token');
return res.status(200).json({ status: 'ignored', reason: 'invalid token' });
}
const { object_attributes } = req.body || {};
// Only process issue close events
if (!object_attributes || object_attributes.action !== 'close') {
return res.status(200).json({ status: 'ignored', reason: 'not a close event' });
}
const issueTitle = object_attributes.title || 'Untitled';
const issueNumber = object_attributes.iid;
const description = object_attributes.description || '';
// Parse submitter username from issue description
// Format: **Submitted by:** username
const submitterMatch = description.match(/\*\*Submitted by:\*\*\s*(\S+)/);
if (!submitterMatch) {
console.log('[Webhook] No submitter found in issue description — skipping DM');
return res.status(200).json({ status: 'ignored', reason: 'no submitter in description' });
}
const username = submitterMatch[1];
// Look up user email in database
const { rows } = await pool.query(
'SELECT email FROM users WHERE username = $1',
[username]
);
if (!rows || rows.length === 0 || !rows[0].email) {
console.log(`[Webhook] No email found for user "${username}" — skipping DM`);
return res.status(200).json({ status: 'ignored', reason: 'user email not found' });
}
const email = rows[0].email;
// Send Webex DM notification
const message = `Hey! Your bug report **${issueTitle}** (Issue #${issueNumber}) has been resolved and deployed. — Patches O'Houlihan`;
sendDirectMessage(email, message);
console.log(`[Webhook] Issue #${issueNumber} closed — notified ${username} (${email})`);
return res.status(200).json({ status: 'ok', notified: username });
} catch (err) {
console.error('[Webhook] Error processing GitLab webhook:', err.message);
return res.status(200).json({ status: 'error', message: err.message });
}
});
return router;
}
module.exports = createWebhooksRouter;