migrate database
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
package migration
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"s-ui/database/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InboundData struct {
|
||||
Id uint
|
||||
Tag string
|
||||
Addrs json.RawMessage
|
||||
OutJson json.RawMessage
|
||||
}
|
||||
|
||||
func moveJsonToDb(db *gorm.DB) error {
|
||||
binFolderPath := os.Getenv("SUI_BIN_FOLDER")
|
||||
if binFolderPath == "" {
|
||||
binFolderPath = "bin"
|
||||
}
|
||||
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
configPath := dir + "/" + binFolderPath + "/config.json"
|
||||
if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var oldConfig map[string]interface{}
|
||||
err = json.Unmarshal(data, &oldConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldInbounds := oldConfig["inbounds"].([]interface{})
|
||||
db.Migrator().DropTable(&model.Inbound{})
|
||||
db.AutoMigrate(&model.Inbound{})
|
||||
for _, inbound := range oldInbounds {
|
||||
inbObj, _ := inbound.(map[string]interface{})
|
||||
tag, _ := inbObj["tag"].(string)
|
||||
if tlsObj, ok := inbObj["tls"]; ok {
|
||||
var tls_id uint
|
||||
err = db.Raw("SELECT id FROM tls WHERE inbounds like ?", `%"`+tag+`"%`).Find(&tls_id).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Bind or Create tls_id
|
||||
if tls_id > 0 {
|
||||
inbObj["tls_id"] = tls_id
|
||||
} else {
|
||||
tls_server, _ := json.MarshalIndent(tlsObj, "", " ")
|
||||
if len(tls_server) > 5 {
|
||||
newTls := &model.Tls{
|
||||
Name: tag,
|
||||
Server: tls_server,
|
||||
}
|
||||
err = db.Create(newTls).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inbObj["tls_id"] = newTls.Id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inbData InboundData
|
||||
db.Raw("select id,addrs,out_json from inbound_data where tag = ?", tag).Find(&inbData)
|
||||
if inbData.Id > 0 {
|
||||
inbObj["outJson"] = inbData.OutJson
|
||||
inbObj["addrs"] = inbData.Addrs
|
||||
} else {
|
||||
inbObj["outJson"] = json.RawMessage("{}")
|
||||
inbObj["addrs"] = json.RawMessage("[]")
|
||||
}
|
||||
inbJson, _ := json.Marshal(inbObj)
|
||||
|
||||
var newInbound model.Inbound
|
||||
err = newInbound.UnmarshalJSON(inbJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Create(&newInbound).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
delete(oldConfig, "inbounds")
|
||||
|
||||
oldOutbounds := oldConfig["outbounds"].([]interface{})
|
||||
db.Migrator().DropTable(&model.Outbound{}, &model.Endpoint{})
|
||||
db.AutoMigrate(&model.Outbound{}, &model.Endpoint{})
|
||||
for _, outbound := range oldOutbounds {
|
||||
outType, _ := outbound.(map[string]interface{})["type"].(string)
|
||||
outboundRaw, _ := json.MarshalIndent(outbound, "", " ")
|
||||
if outType == "wireguard" { // Check if it is Entrypoint
|
||||
var newEntrypoint model.Endpoint
|
||||
err = newEntrypoint.UnmarshalJSON(outboundRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Create(&newEntrypoint).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else { // It is Outbound
|
||||
var newOutbound model.Outbound
|
||||
err = newOutbound.UnmarshalJSON(outboundRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Create(&newOutbound).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
delete(oldConfig, "outbounds")
|
||||
|
||||
// Remove v2rayapi and clashapi from experimental config
|
||||
experimental := oldConfig["experimental"].(map[string]interface{})
|
||||
delete(experimental, "v2ray_api")
|
||||
delete(experimental, "clash_api")
|
||||
oldConfig["experimental"] = experimental
|
||||
|
||||
// Save the other configs
|
||||
var otherConfigs json.RawMessage
|
||||
otherConfigs, err = json.MarshalIndent(oldConfig, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.Save(&model.Setting{
|
||||
Key: "config",
|
||||
Value: string(otherConfigs),
|
||||
}).Error
|
||||
}
|
||||
|
||||
func migrateTls(db *gorm.DB) error {
|
||||
if !db.Migrator().HasColumn(&model.Tls{}, "inbounds") {
|
||||
return nil
|
||||
}
|
||||
return db.Migrator().DropColumn(&model.Tls{}, "inbounds")
|
||||
}
|
||||
|
||||
func dropInboundData(db *gorm.DB) error {
|
||||
if !db.Migrator().HasTable(&InboundData{}) {
|
||||
return nil
|
||||
}
|
||||
return db.Migrator().DropTable(&InboundData{})
|
||||
}
|
||||
|
||||
func migrateClients(db *gorm.DB) error {
|
||||
var oldClients []model.Client
|
||||
err := db.Model(model.Client{}).Scan(&oldClients).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for index, oldClient := range oldClients {
|
||||
var old_inbounds []string
|
||||
err = json.Unmarshal(oldClient.Inbounds, &old_inbounds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var inbound_ids []uint
|
||||
err = db.Raw("SELECT id FROM inbounds WHERE tag in ?", old_inbounds).Find(&inbound_ids).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldClients[index].Inbounds, _ = json.Marshal(inbound_ids)
|
||||
}
|
||||
return db.Save(oldClients).Error
|
||||
}
|
||||
|
||||
func to1_2(db *gorm.DB) error {
|
||||
err := moveJsonToDb(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = migrateTls(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dropInboundData(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return migrateClients(db)
|
||||
}
|
||||
Reference in New Issue
Block a user