3x-ui/database/db.go

166 lines
2.8 KiB
Go
Raw Normal View History

2023-02-09 22:18:06 +03:00
package database
import (
2023-05-05 21:21:39 +03:00
"bytes"
"io"
2023-02-09 22:18:06 +03:00
"io/fs"
2024-07-14 02:22:02 +03:00
"log"
2023-02-09 22:18:06 +03:00
"os"
"path"
2023-02-09 22:18:06 +03:00
"x-ui/config"
"x-ui/database/model"
2023-02-16 18:58:20 +03:00
"x-ui/xray"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
2023-02-09 22:18:06 +03:00
)
var db *gorm.DB
2024-07-14 02:22:02 +03:00
const (
defaultUsername = "admin"
defaultPassword = "admin"
defaultSecret = ""
)
func initModels() error {
models := []interface{}{
&model.User{},
&model.Inbound{},
&model.OutboundTraffics{},
&model.Setting{},
&model.InboundClientIps{},
&xray.ClientTraffic{},
}
for _, model := range models {
if err := db.AutoMigrate(model); err != nil {
log.Printf("Error auto migrating model: %v", err)
return err
}
}
return nil
2023-05-23 02:13:15 +03:00
}
2023-02-09 22:18:06 +03:00
func initUser() error {
2024-07-14 02:22:02 +03:00
empty, err := isTableEmpty("users")
2023-02-09 22:18:06 +03:00
if err != nil {
2024-07-14 02:22:02 +03:00
log.Printf("Error checking if users table is empty: %v", err)
2023-02-09 22:18:06 +03:00
return err
}
2024-07-14 02:22:02 +03:00
if empty {
2023-02-09 22:18:06 +03:00
user := &model.User{
2024-07-14 02:22:02 +03:00
Username: defaultUsername,
Password: defaultPassword,
LoginSecret: defaultSecret,
2023-02-09 22:18:06 +03:00
}
return db.Create(user).Error
}
return nil
}
2024-07-14 02:22:02 +03:00
func isTableEmpty(tableName string) (bool, error) {
var count int64
err := db.Table(tableName).Count(&count).Error
return count == 0, err
2023-02-09 22:18:06 +03:00
}
func InitDB(dbPath string) error {
dir := path.Dir(dbPath)
2023-05-23 02:13:15 +03:00
err := os.MkdirAll(dir, fs.ModePerm)
2023-02-09 22:18:06 +03:00
if err != nil {
return err
}
var gormLogger logger.Interface
if config.IsDebug() {
gormLogger = logger.Default
} else {
gormLogger = logger.Discard
}
c := &gorm.Config{
Logger: gormLogger,
SkipDefaultTransaction: true,
PrepareStmt: true,
2023-02-09 22:18:06 +03:00
}
dsn := dbPath + "?cache=shared&_journal_mode=WAL&_synchronous=NORMAL"
db, err = gorm.Open(sqlite.Open(dsn), c)
if err != nil {
return err
}
sqlDB, err := db.DB()
if err != nil {
return err
}
_, err = sqlDB.Exec("PRAGMA cache_size = -64000;")
if err != nil {
return err
}
_, err = sqlDB.Exec("PRAGMA temp_store = MEMORY;")
if err != nil {
return err
}
_, err = sqlDB.Exec("PRAGMA foreign_keys = ON;")
2023-02-09 22:18:06 +03:00
if err != nil {
return err
}
2024-07-14 02:22:02 +03:00
if err := initModels(); err != nil {
return err
}
if err := initUser(); err != nil {
return err
}
return nil
}
func CloseDB() error {
if db != nil {
if err := Checkpoint(); err != nil {
log.Printf("error executing checkpoint: %v", err)
}
2024-07-14 02:22:02 +03:00
sqlDB, err := db.DB()
if err != nil {
2023-05-23 02:13:15 +03:00
return err
}
2024-07-14 02:22:02 +03:00
return sqlDB.Close()
2023-02-09 22:18:06 +03:00
}
return nil
}
func GetDB() *gorm.DB {
return db
}
func IsNotFound(err error) bool {
return err == gorm.ErrRecordNotFound
}
2023-05-05 21:21:39 +03:00
2023-05-23 02:13:15 +03:00
func IsSQLiteDB(file io.ReaderAt) (bool, error) {
2023-05-05 21:21:39 +03:00
signature := []byte("SQLite format 3\x00")
buf := make([]byte, len(signature))
2023-05-23 02:13:15 +03:00
_, err := file.ReadAt(buf, 0)
2023-05-05 21:21:39 +03:00
if err != nil {
return false, err
}
return bytes.Equal(buf, signature), nil
}
2023-12-08 22:35:10 +03:00
func Checkpoint() error {
// Update WAL
err := db.Exec("PRAGMA wal_checkpoint;").Error
if err != nil {
return err
}
return nil
}