GET /api/openclaw/datto-rmm/sites GET /api/openclaw/datto-rmm/devices (filters: siteUid, online, deleted, page, limit) GET /api/openclaw/datto-rmm/devices/[uid] GET /api/openclaw/datto-rmm/devices/[uid]/audit (always live) GET /api/openclaw/datto-rmm/alerts (filters: resolved, siteUid, deviceUid, limit) GET /api/openclaw/datto-rmm/alerts/open - All protected by x-openclaw-key header - Default: queries Pulse DB (datto_rmm_devices/alerts/sites tables) - ?live=true: proxies to Datto RMM API via DattoRMMClient - Responses include source:'db'|'live' for data freshness awareness
110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { validateOpenClawKey } from '@/lib/utils/openclaw-auth';
|
|
import { Pool } from 'pg';
|
|
import { getDattoRMMClient } from '@/lib/services/datto-rmm-factory';
|
|
|
|
const pool = new Pool({
|
|
host: process.env.POSTGRES_HOST,
|
|
port: parseInt(process.env.POSTGRES_PORT || '5432'),
|
|
database: process.env.POSTGRES_DB,
|
|
user: process.env.POSTGRES_USER,
|
|
password: process.env.POSTGRES_PASSWORD,
|
|
});
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const authError = validateOpenClawKey(request);
|
|
if (authError) return authError;
|
|
|
|
const params = request.nextUrl.searchParams;
|
|
const live = params.get('live') === 'true';
|
|
const siteUid = params.get('siteUid');
|
|
const online = params.get('online');
|
|
const deleted = params.get('deleted');
|
|
const page = Math.max(1, parseInt(params.get('page') || '1', 10));
|
|
const limit = Math.min(500, Math.max(1, parseInt(params.get('limit') || '100', 10)));
|
|
const offset = (page - 1) * limit;
|
|
|
|
try {
|
|
if (live) {
|
|
const client = getDattoRMMClient();
|
|
let devices = siteUid
|
|
? await client.getDevicesBySite(siteUid)
|
|
: await client.getAllDevices();
|
|
|
|
if (online !== null) {
|
|
const onlineBool = online === 'true';
|
|
devices = devices.filter(d => d.online === onlineBool);
|
|
}
|
|
if (deleted !== null) {
|
|
const deletedBool = deleted === 'true';
|
|
devices = devices.filter(d => d.deleted === deletedBool);
|
|
}
|
|
|
|
const total = devices.length;
|
|
const paged = devices.slice(offset, offset + limit);
|
|
|
|
return NextResponse.json({
|
|
data: paged,
|
|
total,
|
|
page,
|
|
limit,
|
|
source: 'live',
|
|
});
|
|
}
|
|
|
|
const conditions: string[] = [];
|
|
const values: unknown[] = [];
|
|
|
|
if (siteUid) {
|
|
values.push(siteUid);
|
|
conditions.push(`site_uid = $${values.length}`);
|
|
}
|
|
if (online !== null) {
|
|
values.push(online === 'true');
|
|
conditions.push(`online = $${values.length}`);
|
|
}
|
|
if (deleted !== null) {
|
|
values.push(deleted === 'true');
|
|
conditions.push(`deleted = $${values.length}`);
|
|
}
|
|
|
|
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
|
|
const countResult = await pool.query(
|
|
`SELECT COUNT(*) FROM datto_rmm_devices ${where}`,
|
|
values
|
|
);
|
|
const total = parseInt(countResult.rows[0].count, 10);
|
|
|
|
values.push(limit, offset);
|
|
const dataResult = await pool.query(
|
|
`SELECT
|
|
id, uid, site_id, site_uid, site_name, hostname, description,
|
|
device_type_category, device_type, operating_system, domain,
|
|
int_ip_address, ext_ip_address, last_logged_in_user,
|
|
last_seen, last_reboot, last_audit_date, creation_date,
|
|
online, suspended, deleted, reboot_required,
|
|
cag_version, display_version,
|
|
antivirus_product, antivirus_status,
|
|
patch_status, patches_approved_pending, patches_not_approved, patches_installed,
|
|
portal_url, web_remote_url, warranty_date, device_class,
|
|
udf, synced_at, updated_at
|
|
FROM datto_rmm_devices
|
|
${where}
|
|
ORDER BY hostname
|
|
LIMIT $${values.length - 1} OFFSET $${values.length}`,
|
|
values
|
|
);
|
|
|
|
return NextResponse.json({
|
|
data: dataResult.rows,
|
|
total,
|
|
page,
|
|
limit,
|
|
source: 'db',
|
|
});
|
|
} catch (error) {
|
|
const msg = error instanceof Error ? error.message : String(error);
|
|
return NextResponse.json({ error: msg }, { status: 500 });
|
|
}
|
|
}
|