Smail/test/backend/setup_super_admin_test.go
smail 3795c34218
Some checks are pending
Security Checks / security (push) Waiting to run
限制系统邮件记录仅超管可见并校验唯一超级管理员
2026-09-15 21:00:31 +08:00

133 lines
4.1 KiB
Go

package setup
import (
"errors"
"path/filepath"
"sync"
"testing"
"git.pcux.cn/xuans/Smail/config"
"git.pcux.cn/xuans/Smail/db"
"git.pcux.cn/xuans/Smail/models"
appcontext "git.pcux.cn/xuans/Smail/utils/context"
)
func prepareUniqueAdminDatabase(t *testing.T) {
t.Helper()
oldConfig, oldSnapshot := config.Instance, config.CurrentConfig()
oldManager, oldDB := config.CurrentManager(), db.Instance
config.Instance = &config.Config{DbType: config.DBTypeSQLite, DbDSN: filepath.Join(t.TempDir(), "setup.db")}
config.PublishConfigSnapshot(config.Instance)
config.SetRuntimeManager(nil)
db.Instance = nil
t.Setenv("SMAIL_ENABLE_LEGACY_SYNC2", "0")
t.Cleanup(func() {
if db.Instance != nil && db.Instance != oldDB {
_ = db.Instance.Close()
}
db.Instance = oldDB
config.Instance = oldConfig
config.PublishConfigSnapshot(oldSnapshot)
config.SetRuntimeManager(oldManager)
})
if err := db.Init(""); err != nil {
t.Fatal(err)
}
}
func TestConcurrentAdministratorInitialization(t *testing.T) {
prepareUniqueAdminDatabase(t)
var group sync.WaitGroup
results := make(chan error, 4)
for _, account := range []string{"first", "second", "third", "fourth"} {
group.Add(1)
go func(account string) {
defer group.Done()
results <- SetAdminPassword(&appcontext.Context{}, account, "StrongP12")
}(account)
}
group.Wait()
close(results)
successes := 0
for err := range results {
if err == nil {
successes++
}
}
if successes != 1 {
t.Fatalf("初始化成功次数:%d", successes)
}
if err := db.ValidateSuperAdmin(db.Instance); err != nil {
t.Fatal(err)
}
}
func TestSetupRejectsMissingMigrationLock(t *testing.T) {
prepareUniqueAdminDatabase(t)
// 仅破坏本测试的临时迁移记录,不读取或清空运行数据库。
if _, err := db.Instance.Exec("DELETE FROM schema_migration WHERE version = 1"); err != nil {
t.Fatal(err)
}
if err := SetAdminPassword(&appcontext.Context{}, "root", "StrongP12"); err == nil {
t.Fatal("缺少锁记录仍创建了账号")
}
count, err := db.Instance.Count(new(models.User))
if err != nil || count != 0 {
t.Fatalf("失败初始化写入了账号:%d %v", count, err)
}
}
func TestSetupDoesNotPromoteSoleOrdinaryAccount(t *testing.T) {
prepareUniqueAdminDatabase(t)
user := models.User{Account: "ordinary", Name: "ordinary", Password: "unused", Role: "user"}
if _, err := db.Instance.Insert(&user); err != nil {
t.Fatal(err)
}
if err := db.Instance.Close(); err != nil {
t.Fatal(err)
}
db.Instance = nil
if err := db.Init(""); err != nil {
t.Fatal(err)
}
account, err := GetAdminPassword(&appcontext.Context{})
if err != nil || account != "" {
t.Fatalf("把普通用户当作超级管理员:%q %v", account, err)
}
if err := db.ValidateSuperAdmin(db.Instance); !errors.Is(err, db.ErrSuperAdminInvariant) {
t.Fatal("普通用户被自动提权")
}
if err := SetAdminPassword(&appcontext.Context{}, "root", "StrongP12"); err == nil {
t.Fatal("非空库重新初始化")
}
for _, account := range []string{"root", "duplicate"} {
if _, err := db.Instance.Insert(&models.User{Account: account, Name: account, Password: "unused", Role: "super_admin"}); err != nil {
t.Fatal(err)
}
got, err := GetAdminPassword(&appcontext.Context{})
if account == "root" && (err != nil || got != "root") {
t.Fatalf("超级管理员查询错误:%q %v", got, err)
}
if account == "duplicate" && !errors.Is(err, db.ErrSuperAdminInvariant) {
t.Fatal("重复超级管理员没有被拒绝")
}
}
}
func TestFinishRejectsDuplicateSuperAdminBeforeWritingConfiguration(t *testing.T) {
prepareFinishConfigTest(t)
if err := config.WriteConfig(&config.Config{SetupState: config.SetupStateBootstrap}); err != nil {
t.Fatal(err)
}
if _, err := db.Instance.Insert(&models.User{Account: "duplicate", Name: "test", Password: "unused", Role: "super_admin"}); err != nil {
t.Fatal(err)
}
if err := Finish(); !errors.Is(err, db.ErrSuperAdminInvariant) {
t.Fatal("初始化完成时未验证唯一超级管理员")
}
cfg, err := config.ReadConfig()
if err != nil || cfg.IsInit || cfg.SetupState != config.SetupStateBootstrap {
t.Fatal("非法账号状态仍完成了初始化")
}
}