69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
"use server";
|
|
import { revalidatePath } from "next/cache";
|
|
import { requireAdminAccess } from "@/lib/session";
|
|
import {
|
|
saveCertificate,
|
|
deleteCertificate,
|
|
ProvisionError,
|
|
} from "@/lib/certificates";
|
|
import {
|
|
createInstallation,
|
|
installationSchema,
|
|
revokeInstallation,
|
|
} from "@/lib/provisioning";
|
|
|
|
async function run(action: () => Promise<unknown>) {
|
|
await requireAdminAccess();
|
|
try {
|
|
await action();
|
|
} catch (error) {
|
|
if (error instanceof ProvisionError) return { error: error.message };
|
|
throw error;
|
|
}
|
|
revalidatePath("/admin/certificates");
|
|
revalidatePath("/admin/nodes");
|
|
}
|
|
export async function uploadCertificateAction(data: FormData) {
|
|
return run(async () => {
|
|
const crt = data.get("certificate"),
|
|
key = data.get("private_key");
|
|
if (
|
|
!(crt instanceof File) ||
|
|
!(key instanceof File) ||
|
|
crt.size > 128 * 1024 ||
|
|
key.size > 32 * 1024
|
|
)
|
|
throw new ProvisionError(
|
|
"请选择 PEM 格式的 CRT(最多 128 KB)和 KEY(最多 32 KB)文件。",
|
|
);
|
|
await saveCertificate(
|
|
String(data.get("name") ?? ""),
|
|
await crt.text(),
|
|
await key.text(),
|
|
);
|
|
});
|
|
}
|
|
export async function deleteCertificateAction(data: FormData) {
|
|
return run(() => deleteCertificate(Number(data.get("id"))));
|
|
}
|
|
export async function createInstallationAction(data: FormData) {
|
|
return run(async () => {
|
|
const input = installationSchema.safeParse({
|
|
name: data.get("name"),
|
|
protocol: data.get("protocol") || "hy2",
|
|
slug: data.get("slug"),
|
|
certificateId: data.get("certificate_id"),
|
|
});
|
|
if (!input.success)
|
|
throw new ProvisionError(
|
|
"请检查输入:Slug 使用小写字母、数字或连字符,并选择覆盖 *.p.xn--876a.net 的证书。",
|
|
);
|
|
await createInstallation(input.data);
|
|
});
|
|
}
|
|
export async function revokeInstallationAction(data: FormData) {
|
|
return run(() =>
|
|
revokeInstallation(String(data.get("id")), data.get("remove") === "yes"),
|
|
);
|
|
}
|