From 13a401dafe7d02847eb3b4c5e5a6aad29f9a5413 Mon Sep 17 00:00:00 2001 From: NanamiAdmin Date: Mon, 2 Mar 2026 13:32:58 +0800 Subject: [PATCH] refactor(frpc, database): move all database actions to database.go --- database.go | 62 ++++++++++++++++++++++++++++- frpc.go | 112 +++++++++++++++++++++++++++------------------------- 2 files changed, 119 insertions(+), 55 deletions(-) diff --git a/database.go b/database.go index e3340db..e7a619e 100644 --- a/database.go +++ b/database.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "strings" + "time" _ "modernc.org/sqlite" ) @@ -283,4 +284,63 @@ func InitUserDatabase(dbPath string) error { } return nil - } \ No newline at end of file + } + +func DBAddFrpcInstance(instance FrpcInstance) error { + _, err := frpcDB.Exec("INSERT INTO frpcInstances (userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + instance.UserID, instance.Name, instance.ServerAddr, instance.ServerPort, instance.AuthMethod, instance.BootAtStart, instance.RunUser, instance.ConfigPath, time.Now().Format(time.RFC3339)) + if err != nil { + return fmt.Errorf("failed to insert frpc instance: %w", err) + } + return nil +} + +func DBQueryFrpcInstance(userID int, instanceName string) (FrpcInstance, error) { + var instance FrpcInstance + err := frpcDB.QueryRow("SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt FROM frpcInstances WHERE userID = ? AND name = ?", userID, instanceName).Scan( + &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt) + if err != nil { + return instance, fmt.Errorf("failed to query frpc instance: %w", err) + } + return instance, nil +} + +func DBRemoveFrpcInstance(userID int, instanceName string) error { + _, err := frpcDB.Exec("DELETE FROM frpcInstances WHERE userID = ? AND name = ?", userID, instanceName) + if err != nil { + return fmt.Errorf("failed to delete frpc instance: %w", err) + } + return nil +} + +func DBUpdateFrpcInstance(instance FrpcInstance) error { + _, err := frpcDB.Exec("UPDATE frpcInstances SET serverAddr = ?, serverPort = ?, auth_method = ?, bootAtStart = ?, runUser = ?, configPath = ? WHERE id = ?", + instance.ServerAddr, instance.ServerPort, instance.AuthMethod, instance.BootAtStart, instance.RunUser, instance.ConfigPath, instance.ID) + if err != nil { + return fmt.Errorf("failed to update frpc instance: %w", err) + } + return nil +} + +func DBListFrpcInstances(userID int) ([]FrpcInstance, error) { + rows, err := frpcDB.Query("SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt FROM frpcInstances WHERE userID = ?", userID) + if err != nil { + return nil, fmt.Errorf("failed to query frpc instances: %w", err) + } + defer rows.Close() + + var instances []FrpcInstance + for rows.Next() { + var instance FrpcInstance + if err := rows.Scan(&instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt); err != nil { + return nil, fmt.Errorf("failed to scan frpc instance: %w", err) + } + instances = append(instances, instance) + } + + if err = rows.Err(); err != nil { + return nil, fmt.Errorf("rows error: %w", err) + } + + return instances, nil +} \ No newline at end of file diff --git a/frpc.go b/frpc.go index c6caefb..8c4c3c9 100644 --- a/frpc.go +++ b/frpc.go @@ -165,6 +165,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { return } + // Add frpc instance configFileName := fmt.Sprintf("superfrpc_%s_%s.toml", user.Username, req.InstanceInfo.Name) configPath := filepath.Join(configDir, configFileName) @@ -175,13 +176,18 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { return } - _, err = frpcDB.Exec(` - INSERT INTO frpcInstances (userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) - `, userID, req.InstanceInfo.Name, req.InstanceInfo.ServerAddr, req.InstanceInfo.ServerPort, - req.InstanceInfo.AuthMethod, req.BootAtStart, runUser, configPath, time.Now().Format(time.RFC3339)) + instance := FrpcInstance{ + UserID: userID, + Name: req.InstanceInfo.Name, + ServerAddr: req.InstanceInfo.ServerAddr, + ServerPort: req.InstanceInfo.ServerPort, + AuthMethod: req.InstanceInfo.AuthMethod, + BootAtStart: req.BootAtStart, + RunUser: runUser, + ConfigPath: configPath, + } - if err != nil { + if err := DBAddFrpcInstance(instance); err != nil { os.Remove(configPath) postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to save instance %s to database: %v", req.InstanceInfo.Name, err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to save instance to database") @@ -197,6 +203,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { return } } + // Finish add frpc instance SendSuccessResponse(w, "Instance created successfully", map[string]interface{}{ "name": req.InstanceInfo.Name, @@ -233,7 +240,6 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { return } - // 从Header中验证token和timeStamp userID, _, err := ValidateRequestWithHeader(w, r) if err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to validate request header: %v", err)) @@ -255,15 +261,16 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { } var instance FrpcInstance - err = frpcDB.QueryRow(` - SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt - FROM frpcInstances WHERE userID = ? AND name = ? - `, userID, instanceName).Scan( - &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, - &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt) - + // err = frpcDB.QueryRow(` + // SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt + // FROM frpcInstances WHERE userID = ? AND name = ? + // `, userID, instanceName).Scan( + // &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, + // &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt) + instance, err = DBQueryFrpcInstance(userID, instanceName) if err == sql.ErrNoRows { - SendErrorResponse(w, http.StatusNotFound, "instance not found") + SendErrorResponse(w, http.StatusNotFound, "Instance not found") + postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] User %d tried to delete a not existed instance: %s", userID, instanceName)) return } if err != nil { @@ -288,8 +295,7 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { } } - _, err = frpcDB.Exec("DELETE FROM frpcInstances WHERE id = ?", instance.ID) - if err != nil { + if err := DBRemoveFrpcInstance(userID, instanceName); err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to delete instance %s from database: %v", instanceName, err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to delete instance from database") return @@ -351,15 +357,16 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) } var instance FrpcInstance - err = frpcDB.QueryRow(` - SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt - FROM frpcInstances WHERE userID = ? AND name = ? - `, userID, instanceName).Scan( - &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, - &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt) - + // err = frpcDB.QueryRow(` + // SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt + // FROM frpcInstances WHERE userID = ? AND name = ? + // `, userID, instanceName).Scan( + // &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, + // &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt) + instance, err = DBQueryFrpcInstance(userID, instanceName) if err == sql.ErrNoRows { - SendErrorResponse(w, http.StatusNotFound, "instance not found") + postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] User %d tried to modify a not existed instance: %s", userID, instanceName)) + SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } if err != nil { @@ -435,12 +442,20 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) return } - _, err = frpcDB.Exec(` - UPDATE frpcInstances - SET name = ?, serverAddr = ?, serverPort = ?, auth_method = ?, bootAtStart = ?, runUser = ?, configPath = ? - WHERE id = ? - `, newName, newServerAddr, newServerPort, newAuthMethod, newBootAtStart, newRunUser, newConfigPath, instance.ID) + // _, err = frpcDB.Exec(` + // UPDATE frpcInstances + // SET name = ?, serverAddr = ?, serverPort = ?, auth_method = ?, bootAtStart = ?, runUser = ?, configPath = ? + // WHERE id = ? + // `, newName, newServerAddr, newServerPort, newAuthMethod, newBootAtStart, newRunUser, newConfigPath, instance.ID) + instance.Name = newName + instance.ServerAddr = newServerAddr + instance.ServerPort = newServerPort + instance.AuthMethod = newAuthMethod + instance.BootAtStart = newBootAtStart + instance.RunUser = newRunUser + instance.ConfigPath = newConfigPath + err = DBUpdateFrpcInstance(instance) if err != nil { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to update instance in database: %v", err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to update instance in database") @@ -483,30 +498,19 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { return } - rows, err := frpcDB.Query(` - SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt - FROM frpcInstances WHERE userID = ? - `, userID) + // rows, err := frpcDB.Query(` + // SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt + // FROM frpcInstances WHERE userID = ? + // `, userID) + instanceList, err := DBListFrpcInstances(userID) if err != nil { postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to query instances: %v", err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instances") return } - defer rows.Close() - - var instances []map[string]interface{} - for rows.Next() { - var instance FrpcInstance - var createdAtStr string - if err := rows.Scan( - &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, - &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &createdAtStr, - ); err != nil { - postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to scan instance: %v", err)) - SendErrorResponse(w, http.StatusInternalServerError, "Failed to scan instance") - return - } + var responseInstances []map[string]interface{} + for _, instance := range instanceList { instanceData := map[string]interface{}{ "name": instance.Name, "serverAddr": instance.ServerAddr, @@ -515,7 +519,7 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { "bootAtStart": instance.BootAtStart, "runUser": instance.RunUser, "configPath": instance.ConfigPath, - "createdAt": createdAtStr, + "createdAt": instance.CreatedAt, } if userType == "visitor" { @@ -524,14 +528,14 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { delete(instanceData, "auth_method") } - instances = append(instances, instanceData) + responseInstances = append(responseInstances, instanceData) } - if instances == nil { - instances = []map[string]interface{}{} + if responseInstances == nil { + responseInstances = []map[string]interface{}{} } - SendSuccessResponse(w, "Instances retrieved successfully", instances) + SendSuccessResponse(w, "Instances retrieved successfully", responseInstances) } func generateFrpcConfig(info InstanceInfo) string { @@ -550,7 +554,7 @@ func generateFrpcConfig(info InstanceInfo) string { func addFrpcProxy(info FrpcProxyInfo) string { var sb strings.Builder - sb.WriteString("[[proxies]]") + sb.WriteString("[[proxies]]\n") sb.WriteString(fmt.Sprintf("name = %s\n", info.Name)) sb.WriteString(fmt.Sprintf("type = %s\n", info.Type)) sb.WriteString(fmt.Sprintf("local_ip = %s\n", info.LocalIP))