- 设置 → 管理员:仅 id=1 的账户在“其他人”那一行看到「编辑」入口,自己那行不显示
- 新增编辑页 /settings/users/{id}/edit:可改用户名、显示名称,密码留空则不修改
- 重置密码后立即清除该账户的所有登录会话,强制对方用新密码重新登录;只改昵称/用户名不影响会话
- 服务端三重校验:非 id=1 拒绝、不能编辑自己、用户名 3-32 字符且唯一、密码 ≥6 位且两次一致
- 所有修改写入操作日志(旧用户名/昵称 → 新值,是否重置密码)
- 设置页根据当前账户显示不同提示:超管看到可编辑说明,其他人只看到“只有初始管理员可以修改”
数据库:无需变更(复用 users 表与 sessions 表)
测试:
- 新增单测 TestUpdateUserByAdmin:昵称更新、会话保留、改密后旧会话失效、新密码可登录旧密码失效、重名返回 ErrDuplicate、空用户名拒绝
- 功能验证 20 项:入口显示/隐藏、普通管理员与自我编辑被拒、改密踢下线、新旧密码、长度/一致性/重名校验、留空密码、日志记录
- 原有 119 项验收回归全绿;go vet / go test ./... 通过;版本号 1.4.0
This commit is contained in:
@@ -2,6 +2,7 @@ package store
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -957,3 +958,64 @@ func TestUserColorAndAssignee(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUserByAdmin(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
|
||||
admin, err := db.CreateUser("admin", "老板", "daili123")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
u, err := db.CreateUser("dashou", "阿强", "dashou123")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 建一个会话,稍后用密码重置把它踢掉
|
||||
token := "tok-" + domain.Date(domain.Today())
|
||||
if err := db.CreateSession(token, u.ID, time.Hour, "127.0.0.1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.SessionUser(token); err != nil {
|
||||
t.Fatalf("会话应有效: %v", err)
|
||||
}
|
||||
|
||||
// 只改昵称:会话保留
|
||||
if err := db.UpdateUserByAdmin(u.ID, "dashou", "强哥", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, _ := db.UserByID(u.ID)
|
||||
if got.DisplayName != "强哥" || got.Username != "dashou" {
|
||||
t.Fatalf("昵称未更新: %+v", got)
|
||||
}
|
||||
if _, err := db.SessionUser(token); err != nil {
|
||||
t.Fatalf("未改密码不应踢下线: %v", err)
|
||||
}
|
||||
|
||||
// 改用户名 + 重置密码:会话失效,新密码可登录
|
||||
if err := db.UpdateUserByAdmin(u.ID, "laoban", "强哥", "newpass123"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.SessionUser(token); err == nil {
|
||||
t.Fatal("改密后旧会话应失效")
|
||||
}
|
||||
if _, err := db.Authenticate("laoban", "newpass123"); err != nil {
|
||||
t.Fatalf("新密码应可登录: %v", err)
|
||||
}
|
||||
if _, err := db.Authenticate("laoban", "dashou123"); err == nil {
|
||||
t.Fatal("旧密码不应还能登录")
|
||||
}
|
||||
|
||||
// 用户名冲突
|
||||
if err := db.UpdateUserByAdmin(u.ID, "admin", "", ""); !errors.Is(err, ErrDuplicate) {
|
||||
t.Fatalf("重名应返回 ErrDuplicate, got %v", err)
|
||||
}
|
||||
// 空用户名
|
||||
if err := db.UpdateUserByAdmin(u.ID, " ", "", ""); err == nil {
|
||||
t.Fatal("空用户名应报错")
|
||||
}
|
||||
// 超管自己也在表里,但接口层才限制“只能改别人”
|
||||
if admin.ID != 1 {
|
||||
t.Fatalf("首个账户 id 应为 1,实际 %d", admin.ID)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user