Files
lunarfront-manager/src/routes/customers.ts
Ryan Moon 6e68cb83c0
Some checks failed
Build & Release / build (push) Failing after 1m3s
feat: restrict customer DB user permissions on provision
2026-04-03 06:25:51 -05:00

50 lines
1.7 KiB
TypeScript

import type { FastifyInstance } from "fastify";
import { z } from "zod";
import { createDatabase, createDatabaseUser, deleteDatabase, deleteDatabaseUser } from "../services/do";
import { addCustomerToPool, removeCustomerFromPool } from "../services/pgbouncer";
import { addCustomerChart, removeCustomerChart } from "../services/git";
import { setupCustomerDatabase, teardownCustomerDatabase } from "../services/db";
const ProvisionSchema = z.object({
name: z.string().min(2).max(32).regex(/^[a-z0-9-]+$/, "lowercase letters, numbers, and hyphens only"),
appVersion: z.string().default("latest"),
});
export async function customerRoutes(app: FastifyInstance) {
app.post("/customers", async (req, reply) => {
const body = ProvisionSchema.parse(req.body);
const slug = body.name;
app.log.info({ slug }, "provisioning customer");
const [, user] = await Promise.all([
createDatabase(slug),
createDatabaseUser(slug),
]);
await setupCustomerDatabase(slug, user.name);
await addCustomerToPool(slug, user.password);
addCustomerChart(slug, body.appVersion);
app.log.info({ slug }, "customer provisioned");
return reply.code(201).send({ slug, status: "provisioned" });
});
app.delete("/customers/:slug", async (req, reply) => {
const { slug } = req.params as { slug: string };
app.log.info({ slug }, "deprovisioning customer");
removeCustomerChart(slug);
await removeCustomerFromPool(slug);
await teardownCustomerDatabase(slug, slug);
await Promise.all([
deleteDatabase(slug),
deleteDatabaseUser(slug),
]);
app.log.info({ slug }, "customer deprovisioned");
return reply.code(204).send();
});
}