Commit Graph

259 Commits

Author SHA1 Message Date
eed0e630e6 chore: 删掉 17 个确认无人调用的端点(净 -472 行)
阶段 0 盘点时判为 CUT 的 17 条,当时只在代码里标了 DEPRECATED(2026-05-26),
没删。这次删掉:15 个视图类整体移除,2 条只删 URL。

## 为什么有两条只能删 URL

ProblemSetProblemAPI 和 ProblemSetProgressAPI **各有一条在用的路径**:

  ProblemSetProblemAPI    /problemset/<id>/problems          在用
                          /problemset/<id>/problems/<pid>    废弃
  ProblemSetProgressAPI   /problemset/progress               在用
                          /problemset/<id>/progress          废弃

删类会直接搞挂"看题单题目"和"加入题单"。清单里记的是**路径**不是视图类,
这个区别不看一眼就动手会出事。

## 核实过程

不敢只信清单 —— 今天已经因为"读过文档还是漏了盲点"栽过一次(前端 /api2 前缀
漏改 5 处)。所以:

1. 用 ast(不是正则)建「视图类 → 它的所有 URL」映射,判定哪些类的全部 URL
   都废弃。正则版把 B 组算成 0 个,而我明知至少有 2 个 —— 那种"看起来干净"的
   结果最危险。
2. DEPRECATED 检测最初往前多看一行,把上一条的行内注释算到了下一条头上,
   于是 /hitokoto、/profile、/reset_password 被误判成废弃。这三个明显在用,
   才发现范围错了。
3. 按端点字符串精确搜整个 ojnext(覆盖 http.get、原生 fetch、独立 axios、
   模板插值),16/16 确认无调用。**并且用 5 个明确在用的端点反测了检测器本身** ——
   未经验证的检测器报"全部无调用"是没有意义的。

## 验证

起本地 Django + PostgreSQL 实跑 33 条断言,全过:
- 保留的端点还能用(13 条,含那两个"类保留"的路径,加入题单确认真的成功)
- 删掉的端点确实 404(17 条)
- reverse() 也解析不到了(3 条)

`ruff check .` 全绿(顺手清掉 44 个因此变成未使用的 import)。

## 一个差点造成的意外

脚本无条件重写所有 urls.py,把 class_pk/ 和 message/ 下三个 **CRLF** 文件
静默转成了 LF —— 内容没变但整文件显示为改动。已原样恢复,最终 diff 是
纯删除,零意外改动。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 06:59:00 -06:00
4ebcecfab4 fix: 修掉重写期间在旧后端发现的 6 个问题
这些是做 Bun 重写时逐行对照发现的,旧后端现在还在线上跑,学生今天就在踩。
每条都在本地起 Django + postgres 实跑验证过,**正反两面都验**:越权要挡住、
正常操作要还能用。合计 14 条断言全过。

## 越权(跨教师)

**ACMContestHelper.put** — 只按 pk 取 rank,任何老师都能改**别人比赛**里的
检查标记。而 `contest_id` 明明在 ACMContesHelperSerializer 里、客户端一直在传,
视图完全没用它。改成按 (pk, contest_id) 取 + ensure_created_by。
同类的 get 本来就有 ensure_created_by,是 put 漏了。

**AddContestProblemAPI.post** — 一个权限装饰器都没有,导致两件事:
  - 少 problem_permission_required:problem_permission=None 的学生管理员也能建题
  - 少 ensure_created_by:任何管理员都能往**别人的比赛**里塞题
另外源题只按 id 取,能把别人比赛里的赛题(或别人未公开的草稿)拷进自己的比赛,
连 answers 参考答案一起拿到。改成源题必须是公开题库题,不可见的要求归属。
(中间件 AdminRoleRequiredMiddleware 只保证"是管理员身份",挡不住这些。)

## 会 500

**ProblemVisibleAPI.put** — `self.error(...)` 漏写 return,题不存在时继续执行到
未赋值的 problem,抛 UnboundLocalError → 500。

## 数据正确性

**ProblemSetAdminAPI.get** — 后台列表写死 filter(visible=True),而列表里就有
可见性开关:一旦关掉,题单从后台消失,教师再也找不到、也无法在界面上打开回来。
后台列表不该过滤 visible,前台该。

**增删题单题目不重算进度** — 题目数是进度的分母。不重算的话学生进度百分比全是
虚高的,原本标"已完成"的人会一直是已完成。更麻烦的是那个手动同步接口
(ProblemSetSyncAPI)前端没有调用点,等于**界面上根本没办法修**。
改成增删之后直接 sync_all_progress_for_problemset。

**移除用户留下孤儿奖章** — 只删了 ProblemSetProgress,UserBadge 还在。学生个人页
会一直挂着一个自己已不在的题单的奖章,而且重新加入时因唯一约束拿不到第二次。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 06:50:47 -06:00
8557f8a5f5 refactor: python-dateutil 换成标准库
- contest 后台创建/编辑:dateutil.parser.parse 换成
  datetime.fromisoformat。serializer 里 start_time/end_time 声明的是
  DateTimeField,而 validate_serializer 做的是 request.data = s.data,
  即重新序列化一遍,所以视图拿到的必定是 DRF 规范化后的 ISO 8601,
  dateutil 的宽容解析能力在这里从来没用上
- AI 学情统计:relativedelta 换成 shift_months 辅助函数,复刻月末
  收缩语义(1月31日 + 1个月 = 2月28/29日)。_parse_duration 的配置
  由 delta 对象改为 rewind/advance 可调用,周档和月档统一

删除依赖:python-dateutil、six

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:05:50 -06:00
3a9ab83ba5 style: ruff format 全仓库
行宽 180 下把历史遗留的折行表达式合并,无语义改动。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 04:45:26 -06:00
180d75cb97 fix 2026-06-29 06:41:18 -06:00
d7e04adf07 fix 2026-06-05 09:46:49 -06:00
b28301bbb1 fix 2026-06-04 05:31:23 -06:00
d1fdbcf52b fix 2026-06-02 23:13:06 -06:00
f94d29cf93 feat: add Teacher Admin role to four-tier permission system
Introduces a four-tier role system: Regular User → Student Admin →
Teacher Admin → Super Admin. Teacher Admin can manage own contests,
problemsets, and view classroom data. Student Admin (renamed from Admin)
retains problem management only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-02 18:13:33 -06:00
6ab2886f77 remove contest type 2026-05-26 23:10:27 -06:00
57c0572fd9 async 2026-05-26 21:25:26 -06:00
980b803517 feat: update all query filters to treat AST_CHECK_FAILED as accepted
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 20:45:15 -06:00
fdf4bb1ad9 fix 2026-05-21 19:30:22 -06:00
083747c241 fix: use pk=None pattern for problem cloning, consistent with AddContestProblemAPI 2026-05-21 19:24:08 -06:00
9c1b958444 feat: add contest clone API endpoint 2026-05-21 19:21:04 -06:00
a744baf4c9 fix 2026-05-17 07:31:05 -06:00
e4e8b7759d update for django6 2026-05-09 05:57:30 -06:00
c466dfd3c6 change enum 2026-05-09 02:30:47 -06:00
e2d566436f add index for models 2026-04-23 14:10:48 -06:00
028ea6e5f9 fmt 2026-04-23 13:57:56 -06:00
24ff67ec0c fix 2026-03-30 09:34:38 -06:00
cbe0e297fd update acm helper 2025-10-06 00:06:59 +08:00
a6d76a64c4 重构用户权限 2025-09-25 18:41:23 +08:00
8436a4602f add heatmap 2025-09-25 15:25:39 +08:00
45d727a9e0 删掉旧的数据库迁移文件 2025-06-14 17:08:52 +08:00
a19f02f2cc 取消缓存 2025-05-16 13:34:12 +08:00
yuetsh
77cf8db4c4 比赛添加标签 2024-07-01 16:09:27 +08:00
yuetsh
c497d511dc refactor 2024-07-01 12:17:43 +08:00
yuetsh
bef87ed554 add tag for announcement 2024-06-13 15:30:21 +08:00
6cf7087339 update Django to v5 2024-06-05 17:40:45 +08:00
helsonxiao
a4a66d2271 fix(test): 修复错误提示 2020-11-29 14:00:17 +08:00
virusdefender
d57cf64afa 修复比赛修改密码之后,之前保存的 session 仍然可以使用的问题 2019-09-22 16:54:40 +08:00
virusdefender
6f8e68846c check is id 2019-03-26 10:02:49 +08:00
virusdefender
7e4132bed1 尝试修复 submission 中的竞争问题 2019-03-26 10:02:49 +08:00
virusdefender
a5f0c8eb31 remove celery and use dramatiq 2019-03-11 17:59:24 +08:00
virusdefender
6b7654a0c3 update to django 2.0 2019-03-11 11:25:10 +08:00
zema1
03c68419b0 remove restriction when using open api 2018-12-16 10:36:43 +08:00
zema1
7aeec10391 fix error path in download submissions 2018-09-26 17:48:46 +08:00
zema1
c1a4ce147f Added: contest submissions download view 2018-08-28 20:56:03 +08:00
virusdefender
29f75a011b add export contest rank to csv 2018-05-06 04:25:53 +08:00
virusdefender
3bb3becfcf alter to text field 2018-05-01 12:56:23 +08:00
virusdefender
8454b36792 fix permission 2018-01-04 19:39:24 +08:00
zema1
417337c4d2 修复几处visible未过滤的问题 2017-12-15 20:54:30 +08:00
zema1
4ebfa0d021 fix disabled users in contest rankings 2017-12-06 16:06:36 +08:00
zema1
fc35e5ed79 filter admin users in all rankings 2017-12-06 15:54:08 +08:00
zema1
0f9f34df65 支持选取已有题目作为比赛题目 2017-12-03 18:52:32 +08:00
zema1
4c2db34b9d add ACM contest admin helper api 2017-12-03 15:39:02 +08:00
zema1
27a9b1144b 封榜后管理员可以通过force_update查看最新rankings 2017-12-03 15:36:31 +08:00
zema1
ee89df9ff2 去除不必要的serializer 2017-12-01 17:19:31 +08:00
zema1
13e3260fd3 添加UserSerailizer admin返回real_name 2017-11-29 14:06:32 +08:00