53 lines
2.0 KiB
TypeScript
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 });
|
|
}
|
|
}
|