diff options
| author | Ho3ein <ho3ein.sanaei@gmail.com> | 2023-05-06 12:23:41 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-06 12:23:41 +0300 |
| commit | ac31d6d9fb666ba8deec353d0ba783eb6a8b231f (patch) | |
| tree | ea1e1764da0208035a7000f7d884a6c36b55d830 /web/service | |
| parent | 78638a97373bccc761f46cbbef0fda34a8dedd6c (diff) | |
| parent | 83c853ffb6b896c8a6d1eef4e0354ba1201ebf13 (diff) | |
Merge pull request #347 from hamid-gh98/main
[Feature] import/export database in the panel
Diffstat (limited to 'web/service')
| -rw-r--r-- | web/service/inbound.go | 11 | ||||
| -rw-r--r-- | web/service/server.go | 106 |
2 files changed, 115 insertions, 2 deletions
diff --git a/web/service/inbound.go b/web/service/inbound.go index dd633c4b..b14f7b4f 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -595,6 +595,7 @@ func (s *InboundService) DisableInvalidInbounds() (int64, error) { count := result.RowsAffected return count, err } + func (s *InboundService) DisableInvalidClients() (int64, error) { db := database.GetDB() now := time.Now().Unix() * 1000 @@ -605,7 +606,8 @@ func (s *InboundService) DisableInvalidClients() (int64, error) { count := result.RowsAffected return count, err } -func (s *InboundService) RemoveOrphanedTraffics() { + +func (s *InboundService) MigrationRemoveOrphanedTraffics() { db := database.GetDB() db.Exec(` DELETE FROM client_traffics @@ -616,6 +618,7 @@ func (s *InboundService) RemoveOrphanedTraffics() { ) `) } + func (s *InboundService) AddClientStat(inboundId int, client *model.Client) error { db := database.GetDB() @@ -634,6 +637,7 @@ func (s *InboundService) AddClientStat(inboundId int, client *model.Client) erro } return nil } + func (s *InboundService) UpdateClientStat(email string, client *model.Client) error { db := database.GetDB() @@ -1166,3 +1170,8 @@ func (s *InboundService) MigrationRequirements() { // Remove orphaned traffics db.Where("inbound_id = 0").Delete(xray.ClientTraffic{}) } + +func (s *InboundService) MigrateDB() { + s.MigrationRequirements() + s.MigrationRemoveOrphanedTraffics() +} diff --git a/web/service/server.go b/web/service/server.go index 1108926b..d8a2239b 100644 --- a/web/service/server.go +++ b/web/service/server.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "io/fs" + "mime/multipart" "net/http" "os" "os/exec" @@ -14,7 +15,9 @@ import ( "strings" "time" "x-ui/config" + "x-ui/database" "x-ui/logger" + "x-ui/util/common" "x-ui/util/sys" "x-ui/xray" @@ -73,7 +76,8 @@ type Release struct { } type ServerService struct { - xrayService XrayService + xrayService XrayService + inboundService InboundService } func (s *ServerService) GetStatus(lastStatus *Status) *Status { @@ -395,6 +399,106 @@ func (s *ServerService) GetDb() ([]byte, error) { return fileContents, nil } +func (s *ServerService) ImportDB(file multipart.File) error { + // Check if the file is a SQLite database + isValidDb, err := database.IsSQLiteDB(file) + if err != nil { + return common.NewErrorf("Error checking db file format: %v", err) + } + if !isValidDb { + return common.NewError("Invalid db file format") + } + + // Reset the file reader to the beginning + _, err = file.Seek(0, 0) + if err != nil { + return common.NewErrorf("Error resetting file reader: %v", err) + } + + // Save the file as temporary file + tempPath := fmt.Sprintf("%s.temp", config.GetDBPath()) + // Remove the existing fallback file (if any) before creating one + _, err = os.Stat(tempPath) + if err == nil { + errRemove := os.Remove(tempPath) + if errRemove != nil { + return common.NewErrorf("Error removing existing temporary db file: %v", errRemove) + } + } + // Create the temporary file + tempFile, err := os.Create(tempPath) + if err != nil { + return common.NewErrorf("Error creating temporary db file: %v", err) + } + defer tempFile.Close() + + // Remove temp file before returning + defer os.Remove(tempPath) + + // Save uploaded file to temporary file + _, err = io.Copy(tempFile, file) + if err != nil { + return common.NewErrorf("Error saving db: %v", err) + } + + // Check if we can init db or not + err = database.InitDB(tempPath) + if err != nil { + return common.NewErrorf("Error checking db: %v", err) + } + + // Stop Xray + s.StopXrayService() + + // Backup the current database for fallback + fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath()) + // Remove the existing fallback file (if any) + _, err = os.Stat(fallbackPath) + if err == nil { + errRemove := os.Remove(fallbackPath) + if errRemove != nil { + return common.NewErrorf("Error removing existing fallback db file: %v", errRemove) + } + } + // Move the current database to the fallback location + err = os.Rename(config.GetDBPath(), fallbackPath) + if err != nil { + return common.NewErrorf("Error backing up temporary db file: %v", err) + } + + // Remove the temporary file before returning + defer os.Remove(fallbackPath) + + // Move temp to DB path + err = os.Rename(tempPath, config.GetDBPath()) + if err != nil { + errRename := os.Rename(fallbackPath, config.GetDBPath()) + if errRename != nil { + return common.NewErrorf("Error moving db file and restoring fallback: %v", errRename) + } + return common.NewErrorf("Error moving db file: %v", err) + } + + // Migrate DB + err = database.InitDB(config.GetDBPath()) + if err != nil { + errRename := os.Rename(fallbackPath, config.GetDBPath()) + if errRename != nil { + return common.NewErrorf("Error migrating db and restoring fallback: %v", errRename) + } + return common.NewErrorf("Error migrating db: %v", err) + } + s.inboundService.MigrateDB() + + // Start Xray + err = s.RestartXrayService() + if err != nil { + return common.NewErrorf("Imported DB but Failed to start Xray: %v", err) + } + + return nil +} + func (s *ServerService) GetNewX25519Cert() (interface{}, error) { // Run the command cmd := exec.Command(xray.GetBinaryPath(), "x25519") |
