"use server"; import { auth } from "@/auth"; import { db } from "@/lib/db"; import { revalidatePath } from "next/cache"; import { z } from "zod"; const HETZNER_KEYS = [ "hetzner_endpoint", "hetzner_access_key", "hetzner_secret_key", "hetzner_bucket_name", ] as const; type HetznerKey = (typeof HETZNER_KEYS)[number]; async function requireAdmin() { const session = await auth(); if (!session?.user) throw new Error("Unauthorized"); if (session.user.role !== "ADMIN") throw new Error("Admin access required"); return session; } /** Returns the current Hetzner config values (secret key masked for display). */ export async function getHetznerConfig(): Promise<{ hetzner_endpoint: string; hetzner_access_key: string; hetzner_secret_key: string; hetzner_bucket_name: string; }> { await requireAdmin(); const rows = await db.systemConfig.findMany({ where: { key: { in: [...HETZNER_KEYS] } }, }); const map = Object.fromEntries(rows.map((r) => [r.key, r.value])) as Partial< Record >; return { hetzner_endpoint: map.hetzner_endpoint ?? process.env.HETZNER_ENDPOINT ?? "", hetzner_access_key: map.hetzner_access_key ?? process.env.HETZNER_ACCESS_KEY ?? "", hetzner_secret_key: map.hetzner_secret_key ?? process.env.HETZNER_SECRET_KEY ?? "", hetzner_bucket_name: map.hetzner_bucket_name ?? process.env.HETZNER_BUCKET_NAME ?? "", }; } const hetznerConfigSchema = z.object({ hetzner_endpoint: z.string().url("Must be a valid URL").or(z.literal("")), hetzner_access_key: z.string().min(1, "Required"), hetzner_secret_key: z.string().min(1, "Required"), hetzner_bucket_name: z.string().min(1, "Required"), }); /** Upserts all four Hetzner config values into system_config. */ export async function saveHetznerConfig( data: z.infer ): Promise<{ success: true }> { await requireAdmin(); const parsed = hetznerConfigSchema.parse(data); await db.$transaction( (Object.entries(parsed) as [HetznerKey, string][]).map(([key, value]) => db.systemConfig.upsert({ where: { key }, create: { key, value }, update: { value }, }) ) ); revalidatePath("/settings"); return { success: true }; }