返回提交历史
Modified
src/middleware/errorHandler.ts
+2
-7
Modified
src/services/wsService.ts
+56
-51
Modified
src/utils/logger.ts
+10
-0
XFEstudio/XFESpaceNinjaServer
fix: add try/catch around websocket message event handler (#2529)
Re #2528 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2529 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
c0ca9d93
代码差异
3 个文件
+68
-58
@@ -1,16 +1,11 @@
1
1
import { NextFunction, Request, Response } from "express";
2
import { logger } from "@/src/utils/logger";
2
import { logError } from "@/src/utils/logger";
3
3
4
4
export const errorHandler = (err: Error, req: Request, res: Response, _next: NextFunction): void => {
5
5
if (err.message == "Invalid accountId-nonce pair") {
6
6
res.status(400).send("Log-in expired");
7
} else if (err.stack) {
8
const stackArr = err.stack.split("\n");
9
stackArr[0] += ` while processing ${req.path} request`;
10
logger.error(stackArr.join("\n"));
11
res.status(500).end();
12
7
} else {
13
logger.error(`uncaught error while processing ${req.path} request: ${err.message}`);
8
logError(err, `processing ${req.path} request`);
14
9
res.status(500).end();
15
10
}
16
11
};
@@ -5,6 +5,7 @@ import { Account } from "@/src/models/loginModel";
5
5
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "@/src/services/loginService";
6
6
import { IDatabaseAccountJson } from "@/src/types/loginTypes";
7
7
import { HydratedDocument } from "mongoose";
8
import { logError } from "@/src/utils/logger";
8
9
9
10
let wsServer: ws.Server | undefined;
10
11
let wssServer: ws.Server | undefined;
@@ -88,63 +89,67 @@ const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
88
89
89
90
// eslint-disable-next-line @typescript-eslint/no-misused-promises
90
91
ws.on("message", async msg => {
91
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
92
if (data.auth) {
93
let account: IDatabaseAccountJson | null = await Account.findOne({ email: data.auth.email });
94
if (account) {
95
if (isCorrectPassword(data.auth.password, account.password)) {
96
if (!account.Nonce) {
97
account.ClientType = "webui";
98
account.Nonce = createNonce();
99
await (account as HydratedDocument<IDatabaseAccountJson>).save();
92
try {
93
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
94
if (data.auth) {
95
let account: IDatabaseAccountJson | null = await Account.findOne({ email: data.auth.email });
96
if (account) {
97
if (isCorrectPassword(data.auth.password, account.password)) {
98
if (!account.Nonce) {
99
account.ClientType = "webui";
100
account.Nonce = createNonce();
101
await (account as HydratedDocument<IDatabaseAccountJson>).save();
102
}
103
} else {
104
account = null;
100
105
}
106
} else if (data.auth.isRegister) {
107
const name = await getUsernameFromEmail(data.auth.email);
108
account = await createAccount({
109
email: data.auth.email,
110
password: data.auth.password,
111
ClientType: "webui",
112
LastLogin: new Date(),
113
DisplayName: name,
114
Nonce: createNonce()
115
});
116
}
117
if (account) {
118
(ws as IWsCustomData).accountId = account.id;
119
ws.send(
120
JSON.stringify({
121
auth_succ: {
122
id: account.id,
123
DisplayName: account.DisplayName,
124
Nonce: account.Nonce
125
}
126
} satisfies IWsMsgToClient)
127
);
101
128
} else {
102
account = null;
129
ws.send(
130
JSON.stringify({
131
auth_fail: {
132
isRegister: data.auth.isRegister
133
}
134
} satisfies IWsMsgToClient)
135
);
103
136
}
104
} else if (data.auth.isRegister) {
105
const name = await getUsernameFromEmail(data.auth.email);
106
account = await createAccount({
107
email: data.auth.email,
108
password: data.auth.password,
109
ClientType: "webui",
110
LastLogin: new Date(),
111
DisplayName: name,
112
Nonce: createNonce()
113
});
114
137
}
115
if (account) {
116
(ws as IWsCustomData).accountId = account.id;
117
ws.send(
118
JSON.stringify({
119
auth_succ: {
120
id: account.id,
121
DisplayName: account.DisplayName,
122
Nonce: account.Nonce
123
}
124
} satisfies IWsMsgToClient)
125
);
126
} else {
127
ws.send(
128
JSON.stringify({
129
auth_fail: {
130
isRegister: data.auth.isRegister
131
}
132
} satisfies IWsMsgToClient)
138
if (data.logout) {
139
const accountId = (ws as IWsCustomData).accountId;
140
(ws as IWsCustomData).accountId = undefined;
141
await Account.updateOne(
142
{
143
_id: accountId,
144
ClientType: "webui"
145
},
146
{
147
Nonce: 0
148
}
133
149
);
134
150
}
135
}
136
if (data.logout) {
137
const accountId = (ws as IWsCustomData).accountId;
138
(ws as IWsCustomData).accountId = undefined;
139
await Account.updateOne(
140
{
141
_id: accountId,
142
ClientType: "webui"
143
},
144
{
145
Nonce: 0
146
}
147
);
151
} catch (e) {
152
logError(e as Error, `processing websocket message`);
148
153
}
149
154
});
150
155
};
@@ -108,3 +108,13 @@ errorLog.on("new", filename => logger.info(`Using error log file: ${filename}`))
108
108
combinedLog.on("new", filename => logger.info(`Using combined log file: ${filename}`));
109
109
errorLog.on("rotate", filename => logger.info(`Rotated error log file: ${filename}`));
110
110
combinedLog.on("rotate", filename => logger.info(`Rotated combined log file: ${filename}`));
111
112
export const logError = (err: Error, context: string): void => {
113
if (err.stack) {
114
const stackArr = err.stack.split("\n");
115
stackArr[0] += ` while ${context}`;
116
logger.error(stackArr.join("\n"));
117
} else {
118
logger.error(`uncaught error while ${context}: ${err.message}`);
119
}
120
};