65 lines
1.7 KiB
TypeScript
65 lines
1.7 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { randomBytes } from "crypto";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { getBaseUrl } from "@/lib/appUrl";
|
|
import { normalizePairingCode } from "@/lib/pairingCode";
|
|
import { z } from "zod";
|
|
|
|
const pairSchema = z.object({
|
|
code: z.string().trim().max(16).optional(),
|
|
pairingCode: z.string().trim().max(16).optional(),
|
|
});
|
|
|
|
export async function POST(req: Request) {
|
|
const body = await req.json().catch(() => ({}));
|
|
const parsed = pairSchema.safeParse(body);
|
|
if (!parsed.success) {
|
|
return NextResponse.json({ ok: false, error: "Invalid pairing payload" }, { status: 400 });
|
|
}
|
|
const rawCode = String(parsed.data.code || parsed.data.pairingCode || "").trim();
|
|
const code = normalizePairingCode(rawCode);
|
|
|
|
if (!code || code.length !== 5) {
|
|
return NextResponse.json({ ok: false, error: "Invalid pairing code" }, { status: 400 });
|
|
}
|
|
|
|
const now = new Date();
|
|
|
|
const machine = await prisma.machine.findFirst({
|
|
where: {
|
|
pairingCode: code,
|
|
pairingCodeUsedAt: null,
|
|
pairingCodeExpiresAt: { gt: now },
|
|
},
|
|
select: { id: true, orgId: true, apiKey: true },
|
|
});
|
|
|
|
if (!machine) {
|
|
return NextResponse.json({ ok: false, error: "Pairing code not found or expired" }, { status: 404 });
|
|
}
|
|
|
|
let apiKey = machine.apiKey;
|
|
if (!apiKey) {
|
|
apiKey = randomBytes(24).toString("hex");
|
|
}
|
|
|
|
await prisma.machine.update({
|
|
where: { id: machine.id },
|
|
data: {
|
|
apiKey,
|
|
pairingCode: null,
|
|
pairingCodeExpiresAt: null,
|
|
pairingCodeUsedAt: now,
|
|
},
|
|
});
|
|
|
|
return NextResponse.json({
|
|
ok: true,
|
|
config: {
|
|
cloudBaseUrl: getBaseUrl(req),
|
|
machineId: machine.id,
|
|
apiKey,
|
|
},
|
|
});
|
|
}
|