From 65a41ccc681da662d6089e2eb1c75934d4b36ebe Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Mon, 21 Jul 2025 16:40:42 +0200 Subject: [PATCH 1/2] fix: add try/catch around websocket message event handler --- src/middleware/errorHandler.ts | 9 +-- src/services/wsService.ts | 107 +++++++++++++++++---------------- src/utils/logger.ts | 10 +++ 3 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/middleware/errorHandler.ts b/src/middleware/errorHandler.ts index 3ffb61cf..92b30f6f 100644 --- a/src/middleware/errorHandler.ts +++ b/src/middleware/errorHandler.ts @@ -1,16 +1,11 @@ import { NextFunction, Request, Response } from "express"; -import { logger } from "@/src/utils/logger"; +import { logError } from "@/src/utils/logger"; export const errorHandler = (err: Error, req: Request, res: Response, _next: NextFunction): void => { if (err.message == "Invalid accountId-nonce pair") { res.status(400).send("Log-in expired"); - } else if (err.stack) { - const stackArr = err.stack.split("\n"); - stackArr[0] += ` while processing ${req.path} request`; - logger.error(stackArr.join("\n")); - res.status(500).end(); } else { - logger.error(`uncaught error while processing ${req.path} request: ${err.message}`); + logError(err, `processing ${req.path} request`); res.status(500).end(); } }; diff --git a/src/services/wsService.ts b/src/services/wsService.ts index 1b49ae3e..28dd204a 100644 --- a/src/services/wsService.ts +++ b/src/services/wsService.ts @@ -5,6 +5,7 @@ import { Account } from "@/src/models/loginModel"; import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "@/src/services/loginService"; import { IDatabaseAccountJson } from "@/src/types/loginTypes"; import { HydratedDocument } from "mongoose"; +import { logError } from "../utils/logger"; let wsServer: ws.Server | undefined; let wssServer: ws.Server | undefined; @@ -88,63 +89,67 @@ const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => { // eslint-disable-next-line @typescript-eslint/no-misused-promises ws.on("message", async msg => { - const data = JSON.parse(String(msg)) as IWsMsgFromClient; - if (data.auth) { - let account: IDatabaseAccountJson | null = await Account.findOne({ email: data.auth.email }); - if (account) { - if (isCorrectPassword(data.auth.password, account.password)) { - if (!account.Nonce) { - account.ClientType = "webui"; - account.Nonce = createNonce(); - await (account as HydratedDocument).save(); + try { + const data = JSON.parse(String(msg)) as IWsMsgFromClient; + if (data.auth) { + let account: IDatabaseAccountJson | null = await Account.findOne({ email: data.auth.email }); + if (account) { + if (isCorrectPassword(data.auth.password, account.password)) { + if (!account.Nonce) { + account.ClientType = "webui"; + account.Nonce = createNonce(); + await (account as HydratedDocument).save(); + } + } else { + account = null; } + } else if (data.auth.isRegister) { + const name = await getUsernameFromEmail(data.auth.email); + account = await createAccount({ + email: data.auth.email, + password: data.auth.password, + ClientType: "webui", + LastLogin: new Date(), + DisplayName: name, + Nonce: createNonce() + }); + } + if (account) { + (ws as IWsCustomData).accountId = account.id; + ws.send( + JSON.stringify({ + auth_succ: { + id: account.id, + DisplayName: account.DisplayName, + Nonce: account.Nonce + } + } satisfies IWsMsgToClient) + ); } else { - account = null; + ws.send( + JSON.stringify({ + auth_fail: { + isRegister: data.auth.isRegister + } + } satisfies IWsMsgToClient) + ); } - } else if (data.auth.isRegister) { - const name = await getUsernameFromEmail(data.auth.email); - account = await createAccount({ - email: data.auth.email, - password: data.auth.password, - ClientType: "webui", - LastLogin: new Date(), - DisplayName: name, - Nonce: createNonce() - }); } - if (account) { - (ws as IWsCustomData).accountId = account.id; - ws.send( - JSON.stringify({ - auth_succ: { - id: account.id, - DisplayName: account.DisplayName, - Nonce: account.Nonce - } - } satisfies IWsMsgToClient) - ); - } else { - ws.send( - JSON.stringify({ - auth_fail: { - isRegister: data.auth.isRegister - } - } satisfies IWsMsgToClient) + if (data.logout) { + const accountId = (ws as IWsCustomData).accountId; + (ws as IWsCustomData).accountId = undefined; + await Account.updateOne( + { + _id: accountId, + ClientType: "webui" + }, + { + Nonce: 0 + } ); } - } - if (data.logout) { - const accountId = (ws as IWsCustomData).accountId; - (ws as IWsCustomData).accountId = undefined; - await Account.updateOne( - { - _id: accountId, - ClientType: "webui" - }, - { - Nonce: 0 - } - ); + } catch (e) { + logError(e as Error, `processing websocket message`); } }); }; diff --git a/src/utils/logger.ts b/src/utils/logger.ts index f02c0db4..75366808 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -108,3 +108,13 @@ errorLog.on("new", filename => logger.info(`Using error log file: ${filename}`)) combinedLog.on("new", filename => logger.info(`Using combined log file: ${filename}`)); errorLog.on("rotate", filename => logger.info(`Rotated error log file: ${filename}`)); combinedLog.on("rotate", filename => logger.info(`Rotated combined log file: ${filename}`)); + +export const logError = (err: Error, context: string): void => { + if (err.stack) { + const stackArr = err.stack.split("\n"); + stackArr[0] += ` while ${context}`; + logger.error(stackArr.join("\n")); + } else { + logger.error(`uncaught error while ${context}: ${err.message}`); + } +}; -- 2.47.2 From 40f56e3f5db9838a1f2acee05c8fd6365ed8a772 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Mon, 21 Jul 2025 16:42:59 +0200 Subject: [PATCH 2/2] fix --- src/services/wsService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/wsService.ts b/src/services/wsService.ts index 28dd204a..fb4bbee3 100644 --- a/src/services/wsService.ts +++ b/src/services/wsService.ts @@ -5,7 +5,7 @@ import { Account } from "@/src/models/loginModel"; import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "@/src/services/loginService"; import { IDatabaseAccountJson } from "@/src/types/loginTypes"; import { HydratedDocument } from "mongoose"; -import { logError } from "../utils/logger"; +import { logError } from "@/src/utils/logger"; let wsServer: ws.Server | undefined; let wssServer: ws.Server | undefined; -- 2.47.2