UNPKG

@directus/api

Version:

Directus is a real-time API and App dashboard for managing SQL database content

88 lines (86 loc) 3.34 kB
import async_handler_default from "../utils/async-handler.js"; import { useLogger } from "../logger/index.js"; import { DEPLOYMENT_PROVIDER_TYPES } from "../packages/types/dist/index.js"; import database_default from "../database/index.js"; import emitter_default from "../emitter.js"; import { getSchema } from "../utils/get-schema.js"; import { getDeploymentDriver } from "../deployment.js"; import { DeploymentProjectsService } from "../services/deployment-projects.js"; import { DeploymentRunsService } from "../services/deployment-runs.js"; import { DeploymentService } from "../services/deployment.js"; import express from "express"; //#region src/controllers/deployment-webhooks.ts const router = express.Router(); router.post("/:provider", async_handler_default(async (req, res) => { const logger = useLogger(); const provider = req.params["provider"]; if (!DEPLOYMENT_PROVIDER_TYPES.includes(provider)) return res.sendStatus(404); const rawBody = req.rawBody; if (!rawBody) { logger.debug(`[webhook:${provider}] No raw body`); return res.sendStatus(400); } const schema = await getSchema(); const knex = database_default(); const deploymentService = new DeploymentService({ schema, knex, accountability: null }); let webhookConfig; try { webhookConfig = await deploymentService.getWebhookConfig(provider); } catch { logger.warn(`[webhook:${provider}] No webhook config found`); return res.sendStatus(404); } if (!webhookConfig.webhook_secret) { logger.warn(`[webhook:${provider}] No webhook secret configured`); return res.sendStatus(404); } const driver = getDeploymentDriver(provider, webhookConfig.credentials, webhookConfig.options); const headers = { ...req.headers }; const queryToken = req.query["token"]; if (typeof queryToken === "string") headers["x-webhook-token"] = queryToken; const event = driver.verifyAndParseWebhook(rawBody, headers, webhookConfig.webhook_secret); if (!event) { logger.warn(`[webhook:${provider}] Verification failed or unknown event`); try { const body = JSON.parse(rawBody.toString("utf-8")); logger.warn(`[webhook:${provider}] Raw event type: ${body.type ?? body.state ?? "unknown"}`); } catch { logger.warn(`[webhook:${provider}] Unparseable body: ${rawBody.toString("utf-8").slice(0, 200)}`); } return res.sendStatus(401); } const project = await new DeploymentProjectsService({ schema, knex, accountability: null }).readByExternalId(webhookConfig.deployment_id, event.project_external_id); if (!project) { logger.info(`[webhook:${provider}] Project ${event.project_external_id} not tracked`); return res.sendStatus(410); } const runId = await new DeploymentRunsService({ schema, knex, accountability: null }).processWebhookEvent(project.id, event); const eventPayload = { provider, project_id: project.id, run_id: runId, external_id: event.deployment_external_id, status: event.status, url: event.url, target: event.target, timestamp: event.timestamp }; emitter_default.emitAction(["deployment.webhook", `deployment.webhook.${event.type}`], eventPayload, null); logger.info(`[webhook:${provider}] Processed: ${event.type} → run ${runId}`); return res.sendStatus(200); })); var deployment_webhooks_default = router; //#endregion export { deployment_webhooks_default as default };