From 52f0712edacc45075f2c7834a739a972cac26db7 Mon Sep 17 00:00:00 2001 From: tamakyi Date: Sun, 18 Oct 2026 21:50:58 +0800 Subject: [PATCH] restrict v4 --- .workbuddy/memory/2026-10-18.md | 26 ++++++++++++++++++++++++++ route/question/question.go | 11 +++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/.workbuddy/memory/2026-10-18.md b/.workbuddy/memory/2026-10-18.md index 49ebc02..50aa0ac 100644 --- a/.workbuddy/memory/2026-10-18.md +++ b/.workbuddy/memory/2026-10-18.md @@ -187,3 +187,29 @@ L2/L3 的手测断言(比看 flash 可靠): - L2 后 `select is_private, answer from questions where id=` → `t` 且 answer 非空,公开页不显示; - L3 后 `answer` 仍为空串(未被写入),`is_read` 不变。 - 干扰项:回答会走七牛审核,审核不可用会 fail-closed 报「审核服务不可用」,那不是处置问题。 + +### L2 线上实测:功能生效,但「箱主无感知」被误判成没效果 + +用户报「L2 没效果」。我用匿名视角实测(这是我能独立做的部分): +- 公开页 `/_/admin6` 只出现 73,**不含 88**; +- 匿名访问 `/_/admin6/88` → **302 到首页**;对比 `/_/admin6/73` → 200。 + +结论:L2 私下里是生效的。用户误判的两个原因: +1. 他**以箱主身份**看单题页 —— 箱主本来就能看自己的私密内容,页面当然「一切正常」; +2. **我的 bug**:`question.flash.answeredPrivate` 只写进了 4 个 i18n 字典,**代码里从未使用**, + 成功后仍提示「回答发布成功」。已修:L2 分支改用 `forcedPrivate` 布尔切换 flash 文案。 + +教训:这些 i18n 键写完必须 grep 调用点;「加了文案」不等于「接上了逻辑」。 + +### 用测试账号自测(已跑通登录态全链路,不需要用户点击) + +用户提供测试箱主 `admin6`(密码不落盘)。用 python + urllib 跑通: +`GET /login` 取 `_csrf` → `GET /api/captcha/generate` 取 `{id, question}`(形如 `5 × 5 =`, +注意乘号是 `×` 不是 `*`)→ 算答案后提交 `g-recaptcha-response=":<答案>"` → 登录成功; +再 `GET /_/admin6` 取表单 csrf → `POST /_/admin6`(字段 `content`)发提问 → +`POST /_/admin6/{id}/answer`(字段 `answer`)。 + +实测结论(qid=89): +- **L2 服务端生效**:回答保存成功,但该题变私密 —— 匿名访问 302 到首页,公开页只有 73; +- **flash 仍是旧文案**「回答发布成功」→ 服务器跑的是 21:22 部署的二进制,我 21:45 的 flash 修复未部署。 +- 88(用户手测)与 89(我自检)都是测试数据,均已被 L2 强制转私密,测完需在后台清理或保持私密。 diff --git a/route/question/question.go b/route/question/question.go index fbeaf89..ca77920 100644 --- a/route/question/question.go +++ b/route/question/question.go @@ -193,7 +193,8 @@ func PublishAnswer(ctx context.Context, pageUser *db.User, question *db.Question // 顺序不能提前到审核之前 —— 审核失败(违规或审核源不可用,fail-closed)会直接返回, // 那时题目已经被改成私密,等于箱主一次失败的编辑让原有公开内容凭空消失。 // 放在这里仍然满足「任何时刻都不出现公开 + 已作答」:此刻它还是一条未作答的私密题。 - if db.RestrictionAtLeast(restrictionLevel, db.RestrictionL2) { + forcedPrivate := db.RestrictionAtLeast(restrictionLevel, db.RestrictionL2) + if forcedPrivate { if err := db.Questions.SetPrivate(ctx.Request().Context(), question.ID); err != nil { logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to force question private") ctx.SetInternalError() @@ -245,7 +246,13 @@ func PublishAnswer(ctx context.Context, pageUser *db.User, question *db.Question } }) - ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "question.flash.answered")) + // L2 下必须明确告知「已转为私密」:单题页对箱主本人仍是 200、内容照常显示, + // 若继续提示「回答发布成功」,箱主会以为一切照旧(实测就是这样误判的)。 + if forcedPrivate { + ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "question.flash.answeredPrivate")) + } else { + ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "question.flash.answered")) + } ctx.Redirect(fmt.Sprintf("/_/%s/%d", pageUser.Domain, question.ID)) }