Files
multiverse/jumpa-iam/app/api/superadmin/xcu-tls-switch/route.ts
T

53 lines
2.0 KiB
TypeScript

import { NextResponse } from 'next/server';
import { cookies } from 'next/headers';
import jwt from 'jsonwebtoken';
const XCU_NODES = [
{ name: 'ALPHA', host: '160.187.143.253' },
{ name: 'BETA', host: '160.187.143.133' },
{ name: 'GAMMA', host: '160.187.143.172' },
];
export const dynamic = 'force-dynamic';
async function fetchNodeStatus(node: typeof XCU_NODES[0]) {
const hosts = ['127.0.0.1', node.host];
for (const h of hosts) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 2500);
try {
const [certResp, telResp] = await Promise.all([
fetch(`http://${h}:8081/api/v1/system/cert`, { signal: controller.signal }),
fetch(`http://${h}:8081/api/v1/telemetry/snapshot`, { signal: controller.signal }),
]);
clearTimeout(timeout);
const cert = await certResp.json();
const tel = await telResp.json();
return {
name: node.name, host: node.host, online: true,
certHash: cert.hash || 'UNKNOWN', tlsMode: cert.tlsMode || 'LETSENCRYPT',
cpu: tel.cpu_usage, ram: tel.ram_usage, status: tel.status,
};
} catch {
clearTimeout(timeout);
}
}
return { name: node.name, host: node.host, online: false, certHash: null, tlsMode: null, cpu: 0, ram: 0, status: 'OFFLINE' };
}
export async function GET() {
try {
const cookieStore = await cookies();
const token = cookieStore.get('jumpa_token')?.value;
if (!token) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
const decoded = jwt.verify(token, process.env.JWT_SECRET as string) as { role: string };
if (decoded.role !== 'superadmin') return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
const results = await Promise.allSettled(XCU_NODES.map(fetchNodeStatus));
const nodes = results.map(r => r.status === 'fulfilled' ? r.value : { name: '?', online: false });
return NextResponse.json({ nodes });
} catch (_e) {
return NextResponse.json({ error: 'Internal Error' }, { status: 500 });
}
}