Files
nekonest-cloud/app/api/internal/relay/register-device/route.ts
T

46 lines
1.7 KiB
TypeScript

import { authenticateRelayNode } from "@/db/relay-control-plane";
import { claimDevice, DomainError } from "@/db/repository";
import { apiError, readJsonMutation } from "../../../respond";
export async function POST(request: Request) {
try {
await authenticateRelayNode(request);
const payload = await readJsonMutation<{
bootstrap_token?: string;
source_hash?: string;
os?: string;
ed25519_public?: string;
x25519_public?: string;
identity_fingerprint?: string;
transport_mode?: string;
registration_proof?: string;
daemon_version?: string;
registration_retry_key?: string;
}>(request);
const sourceHash = payload.source_hash?.trim().toLowerCase() ?? "";
if (!/^[0-9a-f]{64}$/u.test(sourceHash)) {
throw new DomainError("registration_rate_limited", "注册来源摘要无效", 429, true, 60);
}
const result = await claimDevice({
bootstrapToken: payload.bootstrap_token ?? "",
trustedSourceHash: sourceHash,
os: payload.os ?? "",
ed25519Public: payload.ed25519_public ?? "",
x25519Public: payload.x25519_public ?? "",
identityFingerprint: payload.identity_fingerprint ?? "",
transportMode: payload.transport_mode ?? "",
registrationProof: payload.registration_proof ?? "",
daemonVersion: payload.daemon_version ?? "",
registrationRetryKey: payload.registration_retry_key ?? "",
});
return Response.json(result, {
status: 200,
headers: { "cache-control": "no-store" },
});
} catch (error) {
const response = apiError(error);
response.headers.set("cache-control", "no-store");
return response;
}
}