yuetsh
ff31f7abd1
fix(题单): 补回加入题单前旧提交的遮挡
旧栈的 SubmissionListSerializer.get_show_link 有一条防作弊规则:学生加入含某道题的
题单后,他在加入之前留下的 AC 代码就摆在提交列表里,复制粘贴即可过关,所以要把这段
旧提交藏起来。重写时整条丢了 —— canViewSubmission 里 grep 不到一个 problemset,
自己的提交第一行就无条件 return true。
前端反而把 UI 留着了:ProblemSubmission.vue 那个锁图标的 tooltip 一直写着「这道题在
你已经加入的题单中,只有在题单中完成此题,代码才可见」,而后端永远不会给出
showLink: false,图标一次都没亮过 —— 提示语本身成了操作指引。
题单的 end_time 也因此成了孤儿字段:它不是「截止后不能提交」,是这道闸门的时间边界。
影响面不是边角:8-07 的快照里 1734 人次、188 名学生在加入题单之前就已经 AC 过题单
里的题,占全部已解题次的 22.5%。
补回来的同时改了三处旧栈的做法:
- 判断放进 canViewSubmission,列表和详情一起挡。旧栈只挡列表链接,
SubmissionAPI.get 光走 check_user_permission,知道 submission id 直接访问照样
拿得到代码,遮挡是虚的。
- 一题落在多个已加入题单里时取 max(join_time),「存在任一题单要求遮挡就遮挡」等价于
「早于最晚的那次加入」。旧栈用 .first() 取任意一条,行为不确定。
- 比赛提交列表不挂闸门。题单里的题必定是非比赛题(加题时卡了 contestId IS NULL),
而那条列表只出比赛提交,交集恒空,挂上去就是每页白跑一次查询 —— 而比赛进行中它是
被刷得最狠的。旧栈 ContestSubmissionListAPI 照抄了 bulk_fetch,那边同样是死代码。
闸门只挡「看代码」这一路,不挡 allowShared=false 那一路 —— 后者是分享开关的归属校验,
与作弊无关,挡了学生连自己旧提交的分享都动不了。管理员不受限,对齐旧栈的
is_regular_user() 前提。
解锁三条路实跑验证过:在题单里做出该题、题单过 end_time、题单归档。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqqZwxtXLo2GTqMi51C94D
2026-08-31 08:23:13 -06:00
..
2026-08-31 08:23:13 -06:00
2026-08-31 07:41:44 -06:00