修复升级后站主降级为 reader:EnsureOwner 纠正历史身份行的角色

多用户之前以 admin 会话评论会留下 provider=admin、role=reader 的历史行,
升级后 EnsureOwner 找到该行时未纠正角色,站主登录即拿 reader 角色,
用户管理 403。现在 GetOwner 优先取 owner 行,EnsureOwner 登录即把
历史行纠正成 owner。存量会话角色每请求查库,重启后重登一次即恢复。
This commit is contained in:
Sakurasan committed 2026-10-01 23:33:16 +08:00
1 parent 1b5022aefb
commit 0fb897c0b9
2 files changed
+50 -1

No files matched your search

+39
View File
@@ -490,3 +490,42 @@ func TestProjectCRUD(t *testing.T) {
t.Errorf("after delete: got %v, want ErrNotFound", err)
}
}
// 老库升级:多用户之前以 admin 会话评论会留下 provider=admin、role=reader
// 的历史身份行。升级后 EnsureOwner 必须把它纠正成 owner——否则站主登录
// 拿到的是 reader 角色,用户管理直接 403(真实事故)。
func TestEnsureOwnerPromotesLegacyReaderRow(t *testing.T) {
d, err := db.Open("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer d.Close()
st, err := New(d)
if err != nil {
t.Fatal(err)
}
// 模拟老库:站主发过评论,留下 role=reader 的 admin 身份行
if _, err := st.UpsertReader(model.Reader{Provider: "admin", Handle: "admin", Name: "站主"}); err != nil {
t.Fatal(err)
}
legacy, err := st.GetStaffByHandle("admin")
if err != nil {
t.Fatal(err)
}
if legacy.Role != model.RoleReader {
t.Fatalf("setup: legacy role = %q, want reader", legacy.Role)
}
owner, err := st.EnsureOwner("admin")
if err != nil {
t.Fatal(err)
}
if owner.Role != model.RoleOwner {
t.Fatalf("after EnsureOwner: role = %q, want owner", owner.Role)
}
// 行上是真的改了,不是只改返回值
again, _ := st.GetStaffByHandle("admin")
if again.Role != model.RoleOwner {
t.Fatalf("persisted role = %q, want owner", again.Role)
}
}