import { listClients, setOnlineState, upsertClientRow } from "./db"; import * as clientManager from "./clientManager"; import { ClientRole, ClientInfo } from "./types"; import { encodeMessage } from "./protocol"; import { v4 as uuidv4 } from "uuid"; import { metrics } from "./metrics"; import { logAudit, AuditAction } from "./auditLog"; const DEFAULT_PAGE_SIZE = 12; const CORS_HEADERS = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET,OPTIONS", "Access-Control-Allow-Headers": "Content-Type", }; export function handleClientsRequest(req: Request): Response { const url = new URL(req.url); const page = Math.max(1, Number(url.searchParams.get("page") || 1)); const pageSize = Math.max(1, Number(url.searchParams.get("pageSize") || DEFAULT_PAGE_SIZE)); const search = (url.searchParams.get("q") || "").toLowerCase().trim(); const sort = url.searchParams.get("sort") || "last_seen_desc"; const statusFilter = url.searchParams.get("status") || "all"; const osFilter = url.searchParams.get("os") || "all"; const result = listClients({ page, pageSize, search, sort, statusFilter, osFilter, enrollmentFilter: "approved" }); const items = result.items.map((item) => { const live = clientManager.getClient(item.id); if (live) { return { ...item, isAdmin: live.isAdmin ?? item.isAdmin, elevation: live.elevation ?? item.elevation, permissions: live.permissions ?? item.permissions, ...(live.monitorInfo?.length ? { monitors: live.monitorInfo.length, monitorInfo: live.monitorInfo, } : {}), }; } return item; }); return Response.json({ ...result, items }, { headers: CORS_HEADERS }); } export function handleCommand(target: ClientInfo, action: string, req: Request) { console.log(`[command] action=${action} clientId=${target.id}`); metrics.recordCommand(action); if (action === "ping") { const nonce = Date.now() + Math.floor(Math.random() * 1000); target.lastPingSent = Date.now(); target.lastPingNonce = nonce; target.ws.send(encodeMessage({ type: "ping", ts: nonce })); return Response.json({ ok: true }); } if (action === "desktop_start") { target.ws.send(encodeMessage({ type: "command", commandType: "desktop_start" as any, id: uuidv4() })); return Response.json({ ok: true }); } if (action === "desktop_stop") { target.ws.send(encodeMessage({ type: "command", commandType: "desktop_stop" as any, id: uuidv4() })); return Response.json({ ok: true }); } if (action === "desktop_select_display") { target.ws.send(encodeMessage({ type: "command", commandType: "desktop_select_display" as any, id: uuidv4(), payload: { display: 0 } })); return Response.json({ ok: true }); } if (action === "desktop_enable_mouse") { target.ws.send(encodeMessage({ type: "command", commandType: "desktop_enable_mouse" as any, id: uuidv4(), payload: { enabled: true } })); return Response.json({ ok: true }); } if (action === "desktop_enable_keyboard") { target.ws.send(encodeMessage({ type: "command", commandType: "desktop_enable_keyboard" as any, id: uuidv4(), payload: { enabled: true } })); return Response.json({ ok: true }); } if (action === "disconnect") { target.ws.send(encodeMessage({ type: "command", commandType: "disconnect", id: uuidv4() })); return Response.json({ ok: true }); } if (action === "reconnect") { target.ws.send(encodeMessage({ type: "command", commandType: "reconnect", id: uuidv4() })); return Response.json({ ok: true }); } if (action === "file_list") { const url = new URL(req.url); const path = url.searchParams.get("path") || ""; target.ws.send(encodeMessage({ type: "command", commandType: "file_list", id: uuidv4(), payload: { path } })); return Response.json({ ok: true }); } if (action === "file_download") { const url = new URL(req.url); const path = url.searchParams.get("path") || ""; target.ws.send(encodeMessage({ type: "command", commandType: "file_download", id: uuidv4(), payload: { path } })); return Response.json({ ok: true }); } if (action === "file_delete") { const url = new URL(req.url); const path = url.searchParams.get("path") || ""; target.ws.send(encodeMessage({ type: "command", commandType: "file_delete", id: uuidv4(), payload: { path } })); return Response.json({ ok: true }); } if (action === "file_mkdir") { const url = new URL(req.url); const path = url.searchParams.get("path") || ""; target.ws.send(encodeMessage({ type: "command", commandType: "file_mkdir", id: uuidv4(), payload: { path } })); return Response.json({ ok: true }); } if (action === "file_zip") { const url = new URL(req.url); const path = url.searchParams.get("path") || ""; target.ws.send(encodeMessage({ type: "command", commandType: "file_zip", id: uuidv4(), payload: { path } })); return Response.json({ ok: true }); } return new Response("Bad request", { status: 400 }); } export function markOffline(id: string) { setOnlineState(id, false); } export function markOnline(info: ClientInfo) { upsertClientRow({ id: info.id, role: info.role, lastSeen: info.lastSeen, online: 1 as any }); }