Add API to manage webhook secrets for alert integrations
All checks were successful
CI — P3 Alert / test (push) Successful in 15s
All checks were successful
CI — P3 Alert / test (push) Successful in 15s
This commit is contained in:
49
products/03-alert-intelligence/src/api/webhook_secrets.ts
Normal file
49
products/03-alert-intelligence/src/api/webhook_secrets.ts
Normal 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 });
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { config } from './config/index.js';
|
||||
import { pool } from './data/db.js';
|
||||
import { registerAuth, registerAuthRoutes } from './auth/middleware.js';
|
||||
import { registerWebhookRoutes } from './api/webhooks.js';
|
||||
import { registerWebhookSecretRoutes } from './api/webhook_secrets.js';
|
||||
import { registerIncidentRoutes } from './api/incidents.js';
|
||||
import { registerNotificationRoutes } from './api/notifications.js';
|
||||
|
||||
@@ -22,6 +23,7 @@ app.get('/health', async () => ({ status: 'ok', service: 'dd0c-alert' }));
|
||||
|
||||
registerAuthRoutes(app, config.JWT_SECRET, pool);
|
||||
registerWebhookRoutes(app);
|
||||
registerWebhookSecretRoutes(app);
|
||||
registerIncidentRoutes(app);
|
||||
registerNotificationRoutes(app);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user