refactor(frpc, database): move all database actions to database.go

This commit is contained in:
2026-03-02 13:32:58 +08:00
parent 9be737ae56
commit 13a401dafe
2 changed files with 119 additions and 55 deletions
+60
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"strings"
"time"
_ "modernc.org/sqlite"
)
@@ -284,3 +285,62 @@ func InitUserDatabase(dbPath string) error {
return nil
}
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
}
+58 -54
View File
@@ -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))