banned cross device check
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
|
||||
function parseArgs(argv) {
|
||||
const result = {};
|
||||
for (let index = 2; index < argv.length; index += 1) {
|
||||
const arg = argv[index];
|
||||
if (!arg.startsWith("--")) continue;
|
||||
const [key, ...rest] = arg.slice(2).split("=");
|
||||
if (!key) continue;
|
||||
const value = rest.length ? rest.join("=") : "";
|
||||
result[key] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv);
|
||||
const BASE_URL = (args.baseUrl || process.env.BASE_URL || "http://127.0.0.1:3000").replace(/\/$/, "");
|
||||
const ADMIN_TOKEN = args.adminToken || process.env.ADMIN_TOKEN || "";
|
||||
const DEVICE_A = args.deviceA || process.env.DEVICE_A || "develop-test2/test1";
|
||||
const DEVICE_B = args.deviceB || process.env.DEVICE_B || "develop-test/test1";
|
||||
|
||||
if (!ADMIN_TOKEN) {
|
||||
console.error("[ERROR] 缺少 ADMIN_TOKEN 环境变量。");
|
||||
console.error("示例1: node scripts/test-cross-device-notification.js --adminToken=your-token");
|
||||
console.error("示例2: node scripts/test-cross-device-notification.js --adminToken=your-token --baseUrl=http://127.0.0.1:3000 --deviceA=develop-test2/test1 --deviceB=develop-test/test1");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function postJson(path, body) {
|
||||
const response = await fetch(`${BASE_URL}${path}`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = await response.json();
|
||||
} catch (_error) {
|
||||
data = { success: false, errMsg: "响应不是 JSON" };
|
||||
}
|
||||
|
||||
return { status: response.status, data };
|
||||
}
|
||||
|
||||
function assert(condition, message, details) {
|
||||
if (condition) return;
|
||||
const error = new Error(message);
|
||||
error.details = details;
|
||||
throw error;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log(`[INFO] BASE_URL=${BASE_URL}`);
|
||||
console.log(`[INFO] DEVICE_A=${DEVICE_A}`);
|
||||
console.log(`[INFO] DEVICE_B=${DEVICE_B}`);
|
||||
|
||||
console.log("\n[1/5] 为 DEVICE_A 生成一条通知(createVolumeConfigRequest)...");
|
||||
const createReq = await postJson("/", {
|
||||
type: "createVolumeConfigRequest",
|
||||
deviceId: DEVICE_A
|
||||
});
|
||||
assert(createReq.data.success === true, "createVolumeConfigRequest 失败", createReq);
|
||||
|
||||
console.log("[2/5] 读取 DEVICE_A 的 pending notification...");
|
||||
const pendingA = await postJson("/", {
|
||||
type: "getPendingPanelNotification",
|
||||
adminToken: ADMIN_TOKEN,
|
||||
deviceId: DEVICE_A
|
||||
});
|
||||
assert(pendingA.data.success === true, "getPendingPanelNotification(DEVICE_A) 调用失败", pendingA);
|
||||
assert(pendingA.data.pending === true, "DEVICE_A 没有待处理通知", pendingA);
|
||||
const notificationId = pendingA.data.notification?.notificationId;
|
||||
assert(Boolean(notificationId), "未拿到 notificationId", pendingA);
|
||||
console.log(`[INFO] notificationId=${notificationId}`);
|
||||
|
||||
console.log("[3/5] 使用 DEVICE_B 尝试确认 DEVICE_A 的 notificationId(预期失败)...");
|
||||
const crossAck = await postJson("/", {
|
||||
type: "ackPanelNotification",
|
||||
adminToken: ADMIN_TOKEN,
|
||||
deviceId: DEVICE_B,
|
||||
notificationId
|
||||
});
|
||||
assert(crossAck.data.success === false, "跨 deviceId 确认意外成功(存在越权风险)", crossAck);
|
||||
assert(crossAck.data.errMsg === "Panel 通知不存在", "跨 deviceId 失败文案非预期", crossAck);
|
||||
|
||||
console.log("[4/5] 使用 DEVICE_A 正常确认同一 notificationId(预期成功)...");
|
||||
const ownerAck = await postJson("/", {
|
||||
type: "ackPanelNotification",
|
||||
adminToken: ADMIN_TOKEN,
|
||||
deviceId: DEVICE_A,
|
||||
notificationId
|
||||
});
|
||||
assert(ownerAck.data.success === true, "DEVICE_A 确认自身通知失败", ownerAck);
|
||||
|
||||
console.log("[5/5] 再次读取 DEVICE_A pending,确认已被消费...");
|
||||
const pendingAfter = await postJson("/", {
|
||||
type: "getPendingPanelNotification",
|
||||
adminToken: ADMIN_TOKEN,
|
||||
deviceId: DEVICE_A
|
||||
});
|
||||
assert(pendingAfter.data.success === true, "二次查询 pending 失败", pendingAfter);
|
||||
|
||||
console.log("\n[PASS] 测试通过:notificationId 不能被其他 deviceId 确认。\n");
|
||||
console.log("关键结果:");
|
||||
console.log(`- crossAck.success = ${crossAck.data.success}`);
|
||||
console.log(`- crossAck.errMsg = ${crossAck.data.errMsg}`);
|
||||
console.log(`- ownerAck.success = ${ownerAck.data.success}`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error("\n[FAIL]", error.message);
|
||||
if (error.details) {
|
||||
console.error("details=");
|
||||
console.error(JSON.stringify(error.details, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user