fix: validate swipe restaurant ids against room candidates
This commit is contained in:
@@ -38,7 +38,12 @@
|
|||||||
- 后端补充房间号格式校验与明确错误提示;
|
- 后端补充房间号格式校验与明确错误提示;
|
||||||
- 增加 E2E 用例覆盖“手输邀请码加入”。
|
- 增加 E2E 用例覆盖“手输邀请码加入”。
|
||||||
|
|
||||||
### P0-2 投票接口未校验 `restaurantId` 是否属于房间候选列表(可污染房间状态)
|
### P0-2 投票接口未校验 `restaurantId` 是否属于房间候选列表(可污染房间状态)【已完成】
|
||||||
|
- 修复状态:✅ 已完成(2026-03-03)
|
||||||
|
- 修复内容:
|
||||||
|
- `POST /api/room/[id]/swipe` 增加 `restaurantId` 必须属于当前房间候选列表的强校验;
|
||||||
|
- 对非法 `restaurantId` 返回 400;
|
||||||
|
- 增加对应 API 测试用例,防止状态污染回归。
|
||||||
- 证据:
|
- 证据:
|
||||||
- `src/app/api/room/[id]/swipe/route.ts:25`(仅查 index)
|
- `src/app/api/room/[id]/swipe/route.ts:25`(仅查 index)
|
||||||
- `src/app/api/room/[id]/swipe/route.ts:32-42`(即使 `restaurantIndex === -1` 仍可写入 `likes` 并可能设置 `match`)
|
- `src/app/api/room/[id]/swipe/route.ts:32-42`(即使 `restaurantIndex === -1` 仍可写入 `likes` 并可能设置 `match`)
|
||||||
|
|||||||
@@ -113,6 +113,21 @@ describe("POST /api/room/[id]/swipe", () => {
|
|||||||
expect(res.status).toBe(400);
|
expect(res.status).toBe(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("returns 400 when restaurantId is not in room candidates", async () => {
|
||||||
|
mockAtomicUpdate.mockImplementation(async (_id, updater) => {
|
||||||
|
const data = structuredClone(TEST_ROOM_DATA);
|
||||||
|
return updater(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
const req = createRequest("/api/room/ROOM01/swipe", {
|
||||||
|
method: "POST",
|
||||||
|
body: { userId: "user-1", restaurantId: "unknown-id", action: "like" },
|
||||||
|
});
|
||||||
|
const ctx = createRouteContext({ id: "ROOM01" });
|
||||||
|
const res = await POST(req, ctx);
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
});
|
||||||
|
|
||||||
it("returns 404 when room not found", async () => {
|
it("returns 404 when room not found", async () => {
|
||||||
mockAtomicUpdate.mockResolvedValue(null);
|
mockAtomicUpdate.mockResolvedValue(null);
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ export const POST = apiHandler(async (req, { params }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const restaurantIndex = data.restaurants.findIndex((r) => r.id === rid);
|
const restaurantIndex = data.restaurants.findIndex((r) => r.id === rid);
|
||||||
|
if (restaurantIndex < 0) {
|
||||||
|
throw new ApiError("restaurantId 不存在于该房间候选列表", 400);
|
||||||
|
}
|
||||||
const alreadySwiped =
|
const alreadySwiped =
|
||||||
restaurantIndex >= 0 &&
|
|
||||||
restaurantIndex < (data.swipeCounts[userId] ?? 0);
|
restaurantIndex < (data.swipeCounts[userId] ?? 0);
|
||||||
|
|
||||||
if (alreadySwiped) return data;
|
if (alreadySwiped) return data;
|
||||||
|
|||||||
Reference in New Issue
Block a user