mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-24 23:05:01 +03:00
1df8ab29f8
The first user is now created when the server starts, with a random username and password printed once to its log (docker logs, the journal), instead of a fixed pair seeded by InitDB. CLI calls that initialize the database are often piped away, as the Docker entrypoint's port lookup is, so only the server's own log reliably reaches the operator. `x-ui setting -show` keeps reporting hasDefaultCredential: true until a user exists, so install.sh still sets its own credentials on a fresh install. Existing databases are not changed. Verified on a built binary: fresh setting -show, install.sh-style credential set, first start, login and restart. The PostgreSQL lane was not run locally; the change adds no query.
76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
// Package dbtest opens throwaway panel databases for tests. Migrating a new
|
|
// SQLite file costs ~850ms under -race; copying a migrated template ~130ms.
|
|
package dbtest
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
|
)
|
|
|
|
var migrated struct {
|
|
once sync.Once
|
|
data []byte
|
|
err error
|
|
}
|
|
|
|
// InitDB opens a new, fully migrated panel database at path and closes it when
|
|
// t ends. Reopen an existing file with database.InitDB instead.
|
|
func InitDB(t testing.TB, path string) {
|
|
t.Helper()
|
|
if config.GetDBKind() != "postgres" {
|
|
if _, err := os.Stat(path); err == nil {
|
|
t.Fatalf("dbtest.InitDB would overwrite existing %s; reopen it with database.InitDB", path)
|
|
}
|
|
data, err := migratedTemplate()
|
|
if err != nil {
|
|
t.Fatalf("build template database: %v", err)
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
|
|
t.Fatalf("create database dir: %v", err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o600); err != nil {
|
|
t.Fatalf("copy template database: %v", err)
|
|
}
|
|
}
|
|
if err := database.InitDB(path); err != nil {
|
|
t.Fatalf("InitDB: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = database.CloseDB() })
|
|
// A serving panel always has its first user; a copied template already does.
|
|
if _, _, err := database.EnsureFirstUser(); err != nil {
|
|
t.Fatalf("EnsureFirstUser: %v", err)
|
|
}
|
|
}
|
|
|
|
func migratedTemplate() ([]byte, error) {
|
|
migrated.once.Do(func() {
|
|
dir, err := os.MkdirTemp("", "xui-dbtest-")
|
|
if err != nil {
|
|
migrated.err = err
|
|
return
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
path := filepath.Join(dir, "template.db")
|
|
if err := database.InitDB(path); err != nil {
|
|
migrated.err = err
|
|
return
|
|
}
|
|
if _, _, err := database.EnsureFirstUser(); err != nil {
|
|
migrated.err = err
|
|
return
|
|
}
|
|
// Closing the last connection checkpoints the WAL into the main file.
|
|
if err := database.CloseDB(); err != nil {
|
|
migrated.err = err
|
|
return
|
|
}
|
|
migrated.data, migrated.err = os.ReadFile(path)
|
|
})
|
|
return migrated.data, migrated.err
|
|
}
|