114 lines
5.4 KiB
TypeScript
114 lines
5.4 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import postgresClient from '@/lib/services/postgres-client';
|
|
|
|
export async function GET() {
|
|
const results: Record<string, any> = {};
|
|
|
|
// ── Veeam VSPC ──────────────────────────────────────────────────────────────
|
|
try {
|
|
const [orgs, agentJobs, backupJobs, workloads] = await Promise.all([
|
|
postgresClient.query('SELECT COUNT(*) as count, MAX(synced_at) as last_sync FROM veeam_organizations'),
|
|
postgresClient.query(`SELECT COUNT(*) as total,
|
|
COUNT(*) FILTER (WHERE status='Success') as success,
|
|
COUNT(*) FILTER (WHERE status='Running') as running,
|
|
COUNT(*) FILTER (WHERE status='Failed') as failed,
|
|
COUNT(*) FILTER (WHERE status='Warning') as warning
|
|
FROM veeam_backup_agent_jobs WHERE is_enabled = true`),
|
|
postgresClient.query(`SELECT COUNT(*) as total,
|
|
COUNT(*) FILTER (WHERE status='Success') as success,
|
|
COUNT(*) FILTER (WHERE status='Failed') as failed,
|
|
COUNT(*) FILTER (WHERE status='Warning') as warning
|
|
FROM veeam_backup_jobs WHERE is_enabled = true`),
|
|
postgresClient.query('SELECT COUNT(*) as count FROM veeam_protected_workloads'),
|
|
]);
|
|
results.veeam = {
|
|
configured: !!(process.env.VEEAM_VSPC_URL && process.env.VEEAM_VSPC_API_KEY),
|
|
organizations: parseInt(orgs.rows[0].count),
|
|
lastSync: orgs.rows[0].last_sync,
|
|
agentJobs: {
|
|
total: parseInt(agentJobs.rows[0].total),
|
|
success: parseInt(agentJobs.rows[0].success),
|
|
running: parseInt(agentJobs.rows[0].running),
|
|
failed: parseInt(agentJobs.rows[0].failed),
|
|
warning: parseInt(agentJobs.rows[0].warning),
|
|
},
|
|
backupJobs: {
|
|
total: parseInt(backupJobs.rows[0].total),
|
|
success: parseInt(backupJobs.rows[0].success),
|
|
failed: parseInt(backupJobs.rows[0].failed),
|
|
warning: parseInt(backupJobs.rows[0].warning),
|
|
},
|
|
protectedWorkloads: parseInt(workloads.rows[0].count),
|
|
};
|
|
} catch (e) {
|
|
results.veeam = { configured: false, error: String(e) };
|
|
}
|
|
|
|
// ── Datto RMM ───────────────────────────────────────────────────────────────
|
|
try {
|
|
const [sites, devices, openAlerts, lastSync] = await Promise.all([
|
|
postgresClient.query(`SELECT COUNT(*) as total,
|
|
COALESCE(SUM(number_of_devices),0) as total_devices,
|
|
COALESCE(SUM(number_of_online_devices),0) as online_devices,
|
|
COALESCE(SUM(number_of_offline_devices),0) as offline_devices
|
|
FROM datto_rmm_sites`),
|
|
postgresClient.query(`SELECT COUNT(*) as total,
|
|
COUNT(*) FILTER (WHERE online = true) as online,
|
|
COUNT(*) FILTER (WHERE online = false AND deleted = false) as offline
|
|
FROM datto_rmm_devices WHERE deleted = false`),
|
|
postgresClient.query(`SELECT COUNT(*) as total,
|
|
COUNT(*) FILTER (WHERE priority = 'Critical') as critical,
|
|
COUNT(*) FILTER (WHERE priority = 'High') as high,
|
|
COUNT(*) FILTER (WHERE priority = 'Moderate') as moderate,
|
|
COUNT(*) FILTER (WHERE priority = 'Low') as low,
|
|
COUNT(*) FILTER (WHERE ticket_number IS NOT NULL) as with_ticket
|
|
FROM datto_rmm_alerts WHERE resolved = false`),
|
|
postgresClient.query(`SELECT MAX(synced_at) as last_sync FROM datto_rmm_sites`),
|
|
]);
|
|
results.dattoRmm = {
|
|
configured: !!(process.env.DATTO_RMM_API_KEY && process.env.DATTO_RMM_API_SECRET),
|
|
apiUrl: process.env.DATTO_RMM_API_URL || 'https://concord-api.centrastage.net',
|
|
lastSync: lastSync.rows[0].last_sync,
|
|
sites: parseInt(sites.rows[0].total),
|
|
devices: {
|
|
total: parseInt(devices.rows[0].total),
|
|
online: parseInt(devices.rows[0].online),
|
|
offline: parseInt(devices.rows[0].offline),
|
|
},
|
|
openAlerts: {
|
|
total: parseInt(openAlerts.rows[0].total),
|
|
critical: parseInt(openAlerts.rows[0].critical),
|
|
high: parseInt(openAlerts.rows[0].high),
|
|
moderate: parseInt(openAlerts.rows[0].moderate),
|
|
low: parseInt(openAlerts.rows[0].low),
|
|
withTicket: parseInt(openAlerts.rows[0].with_ticket),
|
|
},
|
|
};
|
|
} catch (e) {
|
|
results.dattoRmm = { configured: !!(process.env.DATTO_RMM_API_KEY && process.env.DATTO_RMM_API_SECRET), error: String(e) };
|
|
}
|
|
|
|
// ── Auvik ───────────────────────────────────────────────────────────────────
|
|
try {
|
|
results.auvik = {
|
|
configured: !!(process.env.AUVIK_API_KEY && process.env.AUVIK_API_USER),
|
|
apiUrl: process.env.AUVIK_API_URL || 'https://auvikapi.us5.my.auvik.com',
|
|
lastSync: null,
|
|
};
|
|
} catch (e) {
|
|
results.auvik = { configured: false, error: String(e) };
|
|
}
|
|
|
|
// ── Addigy ──────────────────────────────────────────────────────────────────
|
|
try {
|
|
results.addigy = {
|
|
configured: !!(process.env.ADDIGY_API_TOKEN),
|
|
apiUrl: process.env.ADDIGY_API_URL || 'https://api.addigy.com/api/v2',
|
|
lastSync: null,
|
|
};
|
|
} catch (e) {
|
|
results.addigy = { configured: false, error: String(e) };
|
|
}
|
|
|
|
return NextResponse.json(results);
|
|
}
|