128 lines
3.3 KiB
TypeScript
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 })
|
|
}
|
|
})
|
|
} |