restrict v4
This commit is contained in:
@@ -187,3 +187,29 @@ L2/L3 的手测断言(比看 flash 可靠):
|
|||||||
- L2 后 `select is_private, answer from questions where id=<qid>` → `t` 且 answer 非空,公开页不显示;
|
- L2 后 `select is_private, answer from questions where id=<qid>` → `t` 且 answer 非空,公开页不显示;
|
||||||
- L3 后 `answer` 仍为空串(未被写入),`is_read` 不变。
|
- L3 后 `answer` 仍为空串(未被写入),`is_read` 不变。
|
||||||
- 干扰项:回答会走七牛审核,审核不可用会 fail-closed 报「审核服务不可用」,那不是处置问题。
|
- 干扰项:回答会走七牛审核,审核不可用会 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="<id>:<答案>"` → 登录成功;
|
||||||
|
再 `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 强制转私密,测完需在后台清理或保持私密。
|
||||||
|
|||||||
@@ -193,7 +193,8 @@ func PublishAnswer(ctx context.Context, pageUser *db.User, question *db.Question
|
|||||||
// 顺序不能提前到审核之前 —— 审核失败(违规或审核源不可用,fail-closed)会直接返回,
|
// 顺序不能提前到审核之前 —— 审核失败(违规或审核源不可用,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 {
|
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")
|
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to force question private")
|
||||||
ctx.SetInternalError()
|
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))
|
ctx.Redirect(fmt.Sprintf("/_/%s/%d", pageUser.Domain, question.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user