Skip to content

Commit cf80c78

Browse files
authored
fix: callbacks cleanup and credential timestamp validation (#1669)
* fix(rpc): clean callbacks when sending failed * chore: format * fix(pty): handle ws message properly * fix(webui-backend): unify credential timestamp validation Store credential CreatedTime in seconds and validate expiry using the same unit. Keep backward compatibility for legacy millisecond timestamps. * chore: format * Revert "chore: format" This reverts commit 6f2e9f1. * fix: naming Rename ONE_HOUR_SECONDS to MAX_CREDENTIAL_VALID_SECONDS for clearer intent. Simplify CreatedTime parsing by using Math.floor(Number(...)) and remove the legacy millisecond-to-second conversion branch. Update the time-difference check to use the new constant name.
1 parent 7b58681 commit cf80c78

File tree

4 files changed

+39
-10
lines changed

4 files changed

+39
-10
lines changed

packages/napcat-rpc/src/transport.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class MessageTransport implements RpcTransport {
6767
resolve: (response: RpcResponse) => void;
6868
reject: (error: Error) => void;
6969
}>();
70+
7071
private callbackHandler?: (callbackId: string, args: SerializedValue[]) => Promise<SerializedValue>;
7172
private sendMessage: (message: string) => void | Promise<void>;
7273

@@ -113,15 +114,25 @@ export class MessageTransport implements RpcTransport {
113114
}
114115

115116
async send (request: RpcRequest): Promise<RpcResponse> {
116-
return new Promise((resolve, reject) => {
117-
this.pendingRequests.set(request.id, { resolve, reject });
117+
// eslint-disable-next-line no-async-promise-executor
118+
return new Promise(async (resolve, _reject) => {
119+
const id = request.id;
120+
const reject = (error: any) => {
121+
this.pendingRequests.delete(id);
122+
_reject(error);
123+
};
124+
this.pendingRequests.set(id, { resolve, reject });
118125

119126
const message = JSON.stringify({
120127
type: 'request',
121128
request,
122129
});
123130

124-
Promise.resolve(this.sendMessage(message)).catch(reject);
131+
try {
132+
await this.sendMessage(message);
133+
} catch (error) {
134+
reject(error);
135+
}
125136
});
126137
}
127138

packages/napcat-webui-backend/src/helper/SignToken.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import store from 'napcat-common/src/store';
33
import type { WebUiCredentialJson, WebUiCredentialInnerJson } from '@/napcat-webui-backend/src/types';
44
export class AuthHelper {
55
private static readonly secretKey = process.env['NAPCAT_WEBUI_JWT_SECRET_KEY'] || Math.random().toString(36).slice(2);
6+
private static readonly MAX_CREDENTIAL_VALID_SECONDS = 3600;
67

78
public static getSecretKey (): string {
89
return AuthHelper.secretKey;
@@ -15,7 +16,8 @@ export class AuthHelper {
1516
*/
1617
public static signCredential (hash: string): WebUiCredentialJson {
1718
const innerJson: WebUiCredentialInnerJson = {
18-
CreatedTime: Date.now(),
19+
// 统一使用秒级时间戳,避免与校验逻辑出现单位不一致
20+
CreatedTime: Math.floor(Date.now() / 1000),
1921
HashEncoded: hash,
2022
};
2123
const jsonString = JSON.stringify(innerJson);
@@ -59,10 +61,11 @@ export class AuthHelper {
5961
return false;
6062
}
6163

62-
const currentTime = Date.now() / 1000;
63-
const createdTime = credentialJson.Data.CreatedTime;
64-
const timeDifference = currentTime - createdTime;
65-
return timeDifference <= 3600 && credentialJson.Data.HashEncoded === AuthHelper.generatePasswordHash(token);
64+
const currentTimeSeconds = Math.floor(Date.now() / 1000);
65+
const createdTimeSeconds = Math.floor(Number(credentialJson.Data.CreatedTime));
66+
const timeDifferenceSeconds = currentTimeSeconds - createdTimeSeconds;
67+
const isWithinOneHour = timeDifferenceSeconds >= 0 && timeDifferenceSeconds <= AuthHelper.MAX_CREDENTIAL_VALID_SECONDS;
68+
return isWithinOneHour && credentialJson.Data.HashEncoded === AuthHelper.generatePasswordHash(token);
6669
}
6770

6871
/**

packages/napcat-webui-backend/src/terminal/terminal_manager.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,13 @@ class TerminalManager {
8484

8585
ws.on('message', (data) => {
8686
if (instance) {
87-
const result = JSON.parse(data.toString());
87+
let text: string;
88+
if (Array.isArray(data)) {
89+
text = Buffer.concat(data).toString();
90+
} else {
91+
text = data.toString();
92+
}
93+
const result = JSON.parse(text);
8894
if (result.type === 'input') {
8995
instance.pty.write(result.data);
9096
}

pnpm-workspace.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
11
packages:
2-
- 'packages/*'
2+
- packages/*
3+
4+
onlyBuiltDependencies:
5+
- '@heroui/shared-utils'
6+
- '@homebridge/node-pty-prebuilt-multiarch'
7+
- '@swc/core'
8+
- esbuild
9+
- sharp
10+
- ttf2woff2
11+
- unrs-resolver

0 commit comments

Comments
 (0)