EmberClone/apps/api/src/routes/webhooks.ts

128 lines
3.3 KiB
TypeScript

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 })
}
})
}