Files
go_bt/tests/recharge_credentials_route.test.js

168 lines
5.9 KiB
JavaScript

'use strict';
const assert = require('assert');
const {
createRechargeCredentialHandlers,
isLocalRequest,
} = require('../src/routes/recharge_credentials');
function createResponse() {
return {
headers: {},
statusCode: 200,
payload: undefined,
set(name, value) {
this.headers[String(name).toLowerCase()] = String(value);
return this;
},
status(code) {
this.statusCode = code;
return this;
},
json(payload) {
this.payload = payload;
return this;
},
};
}
function createRequest(remoteAddress, body, forwardedFor) {
return {
socket: { remoteAddress },
body,
headers: forwardedFor ? { 'x-forwarded-for': forwardedFor } : {},
};
}
function assertNoStore(res) {
assert.strictEqual(res.headers['cache-control'], 'no-store');
assert.strictEqual(res.headers.pragma, 'no-cache');
assert.strictEqual(res.headers.expires, '0');
}
(async () => {
assert.strictEqual(isLocalRequest(createRequest('127.0.0.1')), true);
assert.strictEqual(isLocalRequest(createRequest('127.255.42.9')), true);
assert.strictEqual(isLocalRequest(createRequest('::1')), true);
assert.strictEqual(isLocalRequest(createRequest('0:0:0:0:0:0:0:1')), true);
assert.strictEqual(isLocalRequest(createRequest('::ffff:127.0.0.1')), true);
assert.strictEqual(isLocalRequest(createRequest('192.0.2.10')), false);
assert.strictEqual(isLocalRequest(createRequest('127.999.0.1')), false);
assert.strictEqual(
isLocalRequest(createRequest('192.0.2.10', undefined, '127.0.0.1')),
false,
'不得信任 X-Forwarded-For 伪造的本机地址',
);
assert.strictEqual(
isLocalRequest({ ip: '127.0.0.1', socket: { remoteAddress: '192.0.2.10' } }),
false,
'必须以 TCP 对端地址为准',
);
const fullKeyId = 'kid-route-full-value-1234';
const fullSecret = 'route-secret-never-return';
const updatedAt = '2026-08-21T01:02:03.000Z';
let getCalls = 0;
let saveArgs = null;
let deleteCalls = 0;
const store = {
getRechargeCredentialMeta() {
getCalls += 1;
return { configured: true, keyIdMasked: 'kid-••••1234', updatedAt };
},
async saveRechargeCredentials(keyId, secret) {
saveArgs = { keyId, secret };
return { configured: true, keyIdMasked: 'kid-••••1234', updatedAt };
},
async deleteRechargeCredentials() {
deleteCalls += 1;
return { configured: false, keyIdMasked: '', updatedAt: null };
},
};
const handlers = createRechargeCredentialHandlers(store);
const getResponse = createResponse();
handlers.get(createRequest('127.0.0.1'), getResponse);
assert.strictEqual(getResponse.statusCode, 200);
assert.deepStrictEqual(getResponse.payload, {
success: true,
data: { configured: true, keyIdMasked: 'kid-••••1234', updatedAt },
});
assertNoStore(getResponse);
assert.strictEqual(getCalls, 1);
const putResponse = createResponse();
await handlers.put(createRequest('::1', { keyId: fullKeyId, secret: fullSecret }), putResponse);
assert.strictEqual(putResponse.statusCode, 200);
assert.deepStrictEqual(saveArgs, { keyId: fullKeyId, secret: fullSecret });
assert.deepStrictEqual(putResponse.payload, {
success: true,
data: { configured: true, keyIdMasked: 'kid-••••1234', updatedAt },
});
assertNoStore(putResponse);
const putJson = JSON.stringify(putResponse.payload);
assert(!putJson.includes(fullKeyId), 'PUT 响应不得返回完整 Key ID');
assert(!putJson.includes(fullSecret), 'PUT 响应不得返回 Secret');
const deleteResponse = createResponse();
await handlers.remove(createRequest('::ffff:127.0.0.1'), deleteResponse);
assert.strictEqual(deleteResponse.statusCode, 200);
assert.deepStrictEqual(deleteResponse.payload, {
success: true,
data: { configured: false, keyIdMasked: '', updatedAt: null },
});
assertNoStore(deleteResponse);
assert.strictEqual(deleteCalls, 1);
const missingResponse = createResponse();
await handlers.put(createRequest('127.0.0.1', { keyId: fullKeyId }), missingResponse);
assert.strictEqual(missingResponse.statusCode, 400);
assertNoStore(missingResponse);
const validationHandlers = createRechargeCredentialHandlers({
async saveRechargeCredentials() {
const error = new Error('Secret 格式无效');
error.code = 'RECHARGE_SECRET_INVALID';
throw error;
},
});
const validationResponse = createResponse();
await validationHandlers.put(
createRequest('127.0.0.1', { keyId: fullKeyId, secret: fullSecret }),
validationResponse,
);
assert.strictEqual(validationResponse.statusCode, 400);
assert(!JSON.stringify(validationResponse.payload).includes(fullSecret));
assertNoStore(validationResponse);
const remoteResponse = createResponse();
handlers.get(createRequest('192.0.2.10', undefined, '127.0.0.1'), remoteResponse);
assert.strictEqual(remoteResponse.statusCode, 403);
assert.strictEqual(getCalls, 1, '远程请求不应触发凭据存储读取');
assertNoStore(remoteResponse);
assert(!JSON.stringify(remoteResponse.payload).includes('kid-••••1234'));
const errorHandlers = createRechargeCredentialHandlers({
getRechargeCredentialMeta() { throw new Error(fullSecret); },
async saveRechargeCredentials() { throw new Error(fullSecret); },
async deleteRechargeCredentials() { throw new Error(fullSecret); },
});
for (const [handlerName, body] of [
['get', undefined],
['put', { keyId: fullKeyId, secret: fullSecret }],
['remove', undefined],
]) {
const response = createResponse();
await errorHandlers[handlerName](createRequest('127.0.0.1', body), response);
assert.strictEqual(response.statusCode, 500);
assert(!JSON.stringify(response.payload).includes(fullSecret), '错误响应不得泄露 Secret');
assertNoStore(response);
}
console.log('recharge_credentials_route.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});