import { FastifyInstance } from "fastify" import { db } from "../db" import { webhooks } from "../db/schema" import { eq } from "drizzle-orm" import { z } from "zod" const WebhookCreateSchema = z.object({ url: z.string().url(), event: z.string(), secret: z.string().min(1).optional(), active: z.boolean().optional() }) const WebhookUpdateSchema = z.object({ url: z.string().url().optional(), event: z.string().optional(), secret: z.string().optional(), active: z.boolean().optional() }) export default async function webhookRoutes(fastify: FastifyInstance) { fastify.addHook("preHandler", async (request, reply) => { try { await request.jwtVerify() } catch (err) { return reply.code(401).send({ message: "Unauthorized" }) } }) const isAdmin = (request: any) => { return (request.user as { sub: string, role: string })?.role === "admin" } fastify.get("/", async (request, reply) => { if (!isAdmin(request)) { return reply.code(403).send({ message: "Forbidden: Admin role required" }) } return await db.select().from(webhooks) }) fastify.post("/", async (request, reply) => { if (!isAdmin(request)) { return reply.code(403).send({ message: "Forbidden: Admin role required" }) } const body = WebhookCreateSchema.parse(request.body) const [webhook] = await db .insert(webhooks) .values(body) .returning() return reply.code(201).send(webhook) }) fastify.patch("/:id", async (request, reply) => { if (!isAdmin(request)) { return reply.code(403).send({ message: "Forbidden: Admin role required" }) } const { id } = request.params as { id: string } const body = WebhookUpdateSchema.parse(request.body) const [webhook] = await db .update(webhooks) .set(body) .where(eq(webhooks.id, id)) .returning() if (!webhook) { return reply.code(404).send({ message: "Webhook not found" }) } return webhook }) fastify.delete("/:id", async (request, reply) => { if (!isAdmin(request)) { return reply.code(403).send({ message: "Forbidden: Admin role required" }) } const { id } = request.params as { id: string } const result = await db .delete(webhooks) .where(eq(webhooks.id, id)) if (result.rowCount === 0) { return reply.code(404).send({ message: "Webhook not found" }) } return reply.send({ message: "Webhook deleted successfully" }) }) fastify.post("/:id/test", async (request, reply) => { if (!isAdmin(request)) { return reply.code(403).send({ message: "Forbidden: Admin role required" }) } const { id } = request.params as { id: string } const [webhook] = await db .select() .from(webhooks) .where(eq(webhooks.id, id)) .limit(1) if (!webhook) { return reply.code(404).send({ message: "Webhook not found" }) } try { await fastify.inject({ method: 'POST', url: webhook.url, payload: { event: "webhook.test", timestamp: new Date().toISOString(), data: { message: "This is a test payload from EmberClone" } } }) return reply.send({ message: "Test payload sent successfully" }) } catch (error) { return reply.code(500).send({ message: "Failed to send test payload", error }) } }) }