Add API to manage webhook secrets for alert integrations
All checks were successful
CI — P3 Alert / test (push) Successful in 15s

This commit is contained in:
2026-03-02 05:00:40 +00:00
parent 9d33c536d5
commit 9f46b84257
2 changed files with 51 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import { withTenant } from '../data/db.js';
const createSecretSchema = z.object({
provider: z.enum(['datadog', 'pagerduty', 'opsgenie', 'grafana', 'custom']),
secret: z.string().min(1).max(500),
});
export function registerWebhookSecretRoutes(app: FastifyInstance) {
// List webhook secrets
app.get('/api/v1/webhooks/secrets', async (req, reply) => {
const tenantId = (req as any).tenantId;
const result = await withTenant(tenantId, async (client) => {
return client.query('SELECT provider, created_at FROM webhook_secrets ORDER BY provider');
});
return { secrets: result.rows };
});
// Create or update webhook secret
app.put('/api/v1/webhooks/secrets', async (req, reply) => {
const tenantId = (req as any).tenantId;
const { provider, secret } = createSecretSchema.parse(req.body);
await withTenant(tenantId, async (client) => {
await client.query(
`INSERT INTO webhook_secrets (tenant_id, provider, secret)
VALUES ($1, $2, $3)
ON CONFLICT (tenant_id, provider) DO UPDATE
SET secret = EXCLUDED.secret, created_at = now()`,
[tenantId, provider, secret]
);
});
return reply.status(200).send({ status: 'success', provider });
});
// Delete webhook secret
app.delete('/api/v1/webhooks/secrets/:provider', async (req, reply) => {
const tenantId = (req as any).tenantId;
const { provider } = req.params as { provider: string };
await withTenant(tenantId, async (client) => {
await client.query('DELETE FROM webhook_secrets WHERE provider = $1', [provider]);
});
return reply.status(200).send({ status: 'success', deleted: provider });
});
}