feat(notify,log): 催报分钟级限流 + 学生微信登录写登录日志(两处合规补漏)

一、催报分钟级限流(F-29,契约 §3「10 次/分钟/任务」此前未实现)
  · UrgeService 加 Redis 计数:定向与一键催报共用,超限 42901
    且话说清等多久、24h 去重还在(去重防「学生被重复催」,限流防「老师连点
    把系统打爆」—— 两件事);限流放在「确实有活可干」之后(空结果连点不计数)
  · Redis 不可用时放行不瘫痪(限流是保护,不是业务前提)

二、学生微信登录也写 sys_login_log(F-31 —— 此前只有 PC 账号密码登录留痕,
   按 §13.4 查「学生登录记录」永远为空,合规缺口)
  · 新增 WechatLoginLogger:小程序登录(MpLoginService)与 H5 授权回调/
    打桩登录(MpH5AuthController)三条路径都写
  · login_type=2 与 DDL 注释对齐(1 PC 2 小程序 3 开放接口);H5 与小程序
    共用 2(DDL 只定义到 3,不造新值),要区分看 userAgent —— 字段里本来就带着
  · 写失败不影响登录(日志表满了不能没人能登录);不记 code/openid

验证:e2e-m5-urge → 42/42(新增「连点第 11 次被限流」断言,先清计数保证确定性)
      e2e-m3-h5-auth → 24/24(新增「两次 stub-login 各留一条 login_type=2」断言,
      清理时连登录日志一起清)
This commit is contained in:
2026-09-30 12:38:48 +08:00
parent 8f80744d63
commit 57bf39d5a1
7 changed files with 165 additions and 10 deletions
+25
View File
@@ -344,6 +344,31 @@ def main() -> int:
# ── 9. 边界与权限 ──
print("\n[9] 权限与边界")
# ── 9a. 分钟级限流(§3「催报 10 次/分钟/任务」,2026-09-30 补上,F-29)──
# 先清计数再连打 11 次:断言必须**确定**第 11 次是 42901,
# 而"前面已经打了几次"取决于本脚本之前的用例 —— 靠清零把变量拿掉
print(" [9a] 分钟级限流(10 次/分钟/任务)")
os.system('docker exec xt-redis redis-cli -a redis_dev_pwd --no-auth-warning '
'DEL xt:urge:task:%d > NUL 2>&1' % task_id)
got_limit = None
for i in range(11):
rl = body_of("POST", f"/api/v1/mp/teacher/notify/unsubmitted", t1,
{"orgIds": [org_a["id"]], "taskId": task_id, "excludeRecentHours": 0})
if rl.get("code") == 42901:
got_limit = i + 1
break
check("⭐ 连点到第 11 次被限流(42901,而不是白跑 11 次全表查询)",
got_limit == 11, "第 %s 次触发(应为 11,前 10 次都要正常)" % got_limit)
check("限流的话说清等多久",
"频繁" in (body_of("POST", f"/api/v1/mp/teacher/notify/unsubmitted", t1,
{"orgIds": [org_a["id"]], "taskId": task_id,
"excludeRecentHours": 0}).get("msg") or ""),
"(再打一次仍应是 42901)")
# 清掉计数,别影响后续/重复运行
os.system('docker exec xt-redis redis-cli -a redis_dev_pwd --no-auth-warning '
'DEL xt:urge:task:%d > NUL 2>&1' % task_id)
stok = mp(S1)
b = body_of("POST", f"/api/v1/mp/teacher/notify/unsubmitted", stok, {"taskId": task_id})
check("学生不能催报 → 403", b.get("code") in (40101, 40301, 403),