数字我 Digital Me:全量入库(大文件走 Git LFS)
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
// 回归测试 #3:订单查询 IDOR。GET /store/order/:id 只有携带正确的一次性 pollSecret
|
||||
// 才下发 redeemToken —— 枚举订单 id 偷不到他人登录令牌。
|
||||
// 需要本地 MongoDB;连不上则整组 skip(不阻塞无 DB 的 CI)。
|
||||
process.env.NODE_ENV = 'test'; // 非生产 → stub checkout 会立即开通,便于构造已支付订单
|
||||
process.env.MONGO_DB = process.env.MONGO_DB_TEST || 'digital_me_test';
|
||||
|
||||
import { test, before, after } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import express from 'express';
|
||||
import http from 'node:http';
|
||||
|
||||
let server, base, db, closeDb, mongoUp = true;
|
||||
|
||||
before(async () => {
|
||||
const dbm = await import('../src/db.js');
|
||||
closeDb = dbm.closeDb;
|
||||
try { db = await dbm.connectDb(); }
|
||||
catch { mongoUp = false; return; }
|
||||
const { storeRouter } = await import('../src/routes/store.js');
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use('/api/store', storeRouter);
|
||||
server = http.createServer(app).listen(0);
|
||||
await new Promise((ok) => server.once('listening', ok));
|
||||
base = `http://127.0.0.1:${server.address().port}`;
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
if (server) server.close();
|
||||
if (mongoUp && closeDb) await closeDb();
|
||||
});
|
||||
|
||||
const j = async (p, opts) => (await fetch(base + p, opts)).json();
|
||||
|
||||
test('order IDOR:无/错 secret 不下发 redeemToken,正确 secret 才下发', async (t) => {
|
||||
if (!mongoUp) return t.skip('无本地 MongoDB,跳过 DB 集成测试');
|
||||
const prods = await j('/api/store/products');
|
||||
const sku = (prods.products.find((p) => p.available) || {}).id;
|
||||
if (!sku) return t.skip('无可售商品');
|
||||
|
||||
const co = await j('/api/store/checkout', {
|
||||
method: 'POST', headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ sku, email: `buyer_${Date.now()}@example.com` }),
|
||||
});
|
||||
assert.ok(co.orderId, 'checkout 应返回 orderId');
|
||||
|
||||
// 攻击者视角:只有订单 id
|
||||
const noSecret = await j(`/api/store/order/${co.orderId}`);
|
||||
assert.equal(noSecret.status, 'paid');
|
||||
assert.equal(noSecret.redeemToken, '', 'IDOR:无 secret 不应下发 redeemToken');
|
||||
|
||||
const wrong = await j(`/api/store/order/${co.orderId}?secret=not-the-secret`);
|
||||
assert.equal(wrong.redeemToken, '', '错误 secret 也不应下发');
|
||||
|
||||
// 本人视角:拿到正确 pollSecret(stub 响应里不含,从 DB 取真实值)
|
||||
const { ObjectId } = await import('mongodb');
|
||||
const order = await db.collection('store_orders').findOne({ _id: new ObjectId(co.orderId) });
|
||||
const ok = await j(`/api/store/order/${co.orderId}?secret=${order.pollSecret}`);
|
||||
assert.ok(ok.redeemToken && ok.redeemToken.length > 0, '正确 secret 应下发 redeemToken');
|
||||
|
||||
await db.collection('store_orders').deleteOne({ _id: new ObjectId(co.orderId) });
|
||||
});
|
||||
Reference in New Issue
Block a user