diff --git a/config/config.go b/config/config.go index db2cb20..a784a85 100644 --- a/config/config.go +++ b/config/config.go @@ -2,26 +2,15 @@ package config import ( "encoding/json" - "errors" "fmt" "os" "strconv" "strings" + "super-frpc/global" "github.com/BurntSushi/toml" ) -type Config struct { - ListenAddr string `json:"listenAddr"` - ListenPort string `json:"listenPort"` - FrpcPath string `json:"frpcPath"` - InstancePath string `json:"instancePath"` - Debug bool `json:"debug"` - Watchdog struct { - Port int `json:"port"` - } `json:"watchdog"` -} - type InstanceInfo struct { Name string `json:"name"` ServerAddr string `json:"serverAddr"` @@ -56,60 +45,64 @@ type FrpcConfig struct { Proxies []map[string]interface{} `toml:"proxies"` } -var globalConfig *Config - -func LoadConfig(configPath string, getInitSystem func() string) (*Config, error) { +func LoadConfig(configPath string, getInitSystem func() string) error { data, err := os.ReadFile(configPath) if err != nil { - return nil, fmt.Errorf("failed to read config file: %w", err) + return fmt.Errorf("failed to read config file: %w", err) } - var config Config - if err := json.Unmarshal(data, &config); err != nil { - return nil, fmt.Errorf("failed to parse config file: %w", err) + var fileConfig global.Config + if err := json.Unmarshal(data, &fileConfig); err != nil { + return fmt.Errorf("failed to parse config file: %w", err) } - if config.ListenAddr == "" { - config.ListenAddr = "0.0.0.0" + if fileConfig.ListenAddr != "" { + global.CurrentConfig.ListenAddr = fileConfig.ListenAddr } - if config.ListenPort == "" { - config.ListenPort = "8080" + if fileConfig.ListenPort != "" { + global.CurrentConfig.ListenPort = fileConfig.ListenPort } - if config.FrpcPath == "" { + if fileConfig.FrpcPath != "" { + global.CurrentConfig.FrpcPath = fileConfig.FrpcPath + } else { if getInitSystem() == "windows" { - config.FrpcPath = "frp_client/frpc.exe" + global.CurrentConfig.FrpcPath = "frp_client/frpc.exe" } else { - config.FrpcPath = "/usr/bin/frpc" + global.CurrentConfig.FrpcPath = "/usr/bin/frpc" } } - if config.InstancePath == "" { - config.InstancePath = "./configs" + if fileConfig.InstancePath != "" { + global.CurrentConfig.InstancePath = fileConfig.InstancePath + } else { + global.CurrentConfig.InstancePath = "./configs" } - if config.Watchdog.Port == 0 { - config.Watchdog.Port = 12380 + global.CurrentConfig.Debug = fileConfig.Debug + + if fileConfig.Watchdog.Port != 0 { + global.CurrentConfig.Watchdog.Port = fileConfig.Watchdog.Port + } else { + global.CurrentConfig.Watchdog.Port = 12380 } - if err := os.MkdirAll(config.InstancePath, 0755); err != nil { - return nil, fmt.Errorf("failed to create config directory: %w", err) + global.CurrentConfig.Watchdog.Enabled = fileConfig.Watchdog.Enabled + + if err := os.MkdirAll(global.CurrentConfig.InstancePath, 0755); err != nil { + return fmt.Errorf("failed to create config directory: %w", err) } - globalConfig = &config - return &config, nil + return nil } -func GetConfig() (*Config, error) { - if globalConfig == nil { - return nil, errors.New("config not loaded") - } - return globalConfig, nil +func GetConfig() *global.Config { + return &global.CurrentConfig } -func SaveConfig(configPath string, config *Config) error { - data, err := json.MarshalIndent(config, "", " ") +func SaveConfig(configPath string) error { + data, err := json.MarshalIndent(global.CurrentConfig, "", " ") if err != nil { return fmt.Errorf("failed to marshal config: %w", err) } @@ -118,7 +111,6 @@ func SaveConfig(configPath string, config *Config) error { return fmt.Errorf("failed to write config file: %w", err) } - globalConfig = config return nil } diff --git a/global/global.go b/global/global.go index 77e2ae3..4e8c165 100644 --- a/global/global.go +++ b/global/global.go @@ -13,6 +13,14 @@ type SoftwareInfo struct { BuildType string } +var Software = SoftwareInfo{ + Name: "Super-frpc", + Version: "0.0.1", + Developer: "Madobi Nanami", + BuildVer: 1, + BuildType: "debug", +} + type StatusFlags struct { Debug bool Online bool @@ -25,16 +33,35 @@ var ( LogsDB *sql.DB ) -var Software = SoftwareInfo{ - Name: "Super-frpc", - Version: "0.0.1", - Developer: "Madobi Nanami", - BuildVer: 1, - BuildType: "debug", -} - var Is = StatusFlags{ Debug: false, Online: false, WatchdogConnected: false, } + +type Config struct { + ListenAddr string `json:"listenAddr"` + ListenPort string `json:"listenPort"` + FrpcPath string `json:"frpcPath"` + InstancePath string `json:"instancePath"` + Debug bool `json:"debug"` + Watchdog struct { + Enabled bool `json:"enabled"` + Port int `json:"port"` + } `json:"watchdog"` +} + +var CurrentConfig = Config{ + ListenAddr: "0.0.0.0", + ListenPort: "7000", + FrpcPath: "/usr/bin/frpc", + InstancePath: "/var/lib/frpc", + Debug: false, + Watchdog: struct { + Enabled bool `json:"enabled"` + Port int `json:"port"` + }{ + Enabled: false, + Port: 0, + }, +} diff --git a/instance/instance.go b/handlers/instance.go similarity index 71% rename from instance/instance.go rename to handlers/instance.go index dd5689d..f5a1c37 100644 --- a/instance/instance.go +++ b/handlers/instance.go @@ -1,4 +1,4 @@ -package instance +package handlers import ( "database/sql" @@ -13,15 +13,15 @@ import ( "super-frpc/config" "super-frpc/database" - "super-frpc/handlers" + "super-frpc/utils" "super-frpc/postLog" "super-frpc/service" ) func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[CreateInstanceHandler] Auth failed: %v", err)) return } @@ -29,7 +29,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -37,7 +37,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } @@ -55,7 +55,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { instanceInfoMap, ok := reqMap["instanceInfo"].(map[string]interface{}) if !ok { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceInfo format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceInfo format") return } @@ -80,7 +80,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { if req.InstanceInfo.Name == "" || req.InstanceInfo.ServerAddr == "" || req.InstanceInfo.ServerPort == "" || req.InstanceInfo.AuthMethod == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in instanceInfo") + utils.SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in instanceInfo") return } @@ -92,14 +92,14 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { user, err := database.GetUserByID(userID) if err != nil { postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to get user info: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info") return } configDir, err := service.GetConfigDir() if err != nil { postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to get config directory: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory") return } @@ -112,7 +112,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { if err := config.HandleConfigFileCreate(configPath, req.InstanceInfo, setKeyTextWrapper); err != nil { postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to create config file %s: %v", configPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to create config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to create config file") return } @@ -128,7 +128,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { if err := database.DBAddFrpcInstance(instance); err != nil { os.Remove(configPath) postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to save instance %s to database: %v", req.InstanceInfo.Name, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to save instance to database") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to save instance to database") return } @@ -136,7 +136,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { if err != nil { os.Remove(configPath) postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to query created instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query created instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query created instance") return } @@ -144,19 +144,19 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { database.DBRemoveFrpcInstanceByID(createdInstance.ID) os.Remove(configPath) postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to create boot service for instance %s: %v", req.InstanceInfo.Name, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to create boot service") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to create boot service") return } if req.BootAtStart { if err := service.SetBootAtStart(createdInstance.ID); err != nil { postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to set boot at start for instance %s: %v", req.InstanceInfo.Name, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to set boot at start") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to set boot at start") return } } - handlers.SendSuccessResponse(w, "Instance created successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Instance created successfully", map[string]interface{}{ "name": req.InstanceInfo.Name, "configPath": configPath, "bootAtStart": req.BootAtStart, @@ -165,9 +165,9 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { } func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[DeleteInstanceHandler] Auth failed: %v", err)) return } @@ -175,7 +175,7 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -183,64 +183,64 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceIDStr := getStringFromMap(reqMap, "instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] User %d tried to delete a not existed instance: %d", userID, instanceID)) return } if err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if err := service.RemoveBootService(instanceID); err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to remove boot service for instance %s: %v", instance.Name, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove boot service") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove boot service") return } if _, err := os.Stat(instance.ConfigPath); err == nil { if err := os.Remove(instance.ConfigPath); err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to remove config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove config file") return } } if err := database.DBRemoveFrpcInstanceByID(instanceID); err != nil { postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to delete instance %d from database: %v", instanceID, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to delete instance from database") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to delete instance from database") return } - handlers.SendSuccessResponse(w, "Instance deleted successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Instance deleted successfully", map[string]interface{}{ "id": instanceID, }) postLog.Info(fmt.Sprintf("[DeleteInstanceHandler] Instance %d deleted successfully", instanceID)) } func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ModifyInstanceHandler] Auth failed: %v", err)) return } @@ -248,7 +248,7 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -256,61 +256,61 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceIDStr := getStringFromMap(reqMap, "instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } modifyType := getStringFromMap(reqMap, "type") if modifyType == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "type is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "type is required") return } if modifyType != "configFile" && modifyType != "systemConfig" { - handlers.SendErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("Unknown modify type %s", modifyType)) + utils.SendErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("Unknown modify type %s", modifyType)) return } modifiedData, ok := reqMap["modifiedData"].(map[string]interface{}) if !ok || modifiedData == nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "modifiedData is required and must be an object") + utils.SendErrorResponse(w, http.StatusBadRequest, "modifiedData is required and must be an object") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] User %d tried to modify a not existed instance: %d", userID, instanceID)) - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } if err != nil { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] User %d does not have permission to modify instance %d", userID, instanceID)) - handlers.SendErrorResponse(w, http.StatusForbidden, "Permission denied") + utils.SendErrorResponse(w, http.StatusForbidden, "Permission denied") return } user, err := database.GetUserByID(instance.UserID) if err != nil { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to get user info: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info") return } @@ -355,12 +355,12 @@ func handleConfigFileModify(w http.ResponseWriter, instance database.FrpcInstanc } if err := config.SetKeyText(configPath, configKey, "", configValue, os.ReadFile, os.WriteFile); err != nil { postLog.Error(fmt.Sprintf("[handleConfigFileModify] Failed to set key %s: %v", key, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to set key %s", key)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to set key %s", key)) return } } - handlers.SendSuccessResponse(w, "Config file modified successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Config file modified successfully", map[string]interface{}{ "instanceName": instance.Name, "instanceID": instance.ID, "configPath": configPath, @@ -391,7 +391,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d configDir, err := service.GetConfigDir() if err != nil { postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to get config directory: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory") return } @@ -402,7 +402,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d if _, err := os.Stat(oldConfigPath); err == nil { if err := os.Rename(oldConfigPath, newConfigPath); err != nil { postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to rename config file %s to %s: %v", oldConfigPath, newConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to rename config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to rename config file") return } } @@ -417,7 +417,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d if err := database.DBUpdateFrpcInstance(instance); err != nil { postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to update instance in database: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to update instance in database") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to update instance in database") return } @@ -453,7 +453,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d if bootServiceError != "" { data["bootServiceError"] = bootServiceError } - handlers.SendSuccessResponse(w, "System config modified successfully", data) + utils.SendSuccessResponse(w, "System config modified successfully", data) } func GetUserInstances(userID int) ([]database.FrpcInstance, error) { @@ -497,9 +497,9 @@ func getNumFromMap(m map[string]interface{}, key string) int { } func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodGet) + userID, err := utils.Auth(w, r, http.MethodGet) if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ListInstancesHandler] Auth failed: %v", err)) return } @@ -507,7 +507,7 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { instances, err := GetUserInstances(userID) if err != nil { postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to get user instances: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get instances") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get instances") return } @@ -531,14 +531,14 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { instanceList[i] = instanceData } - handlers.SendSuccessResponse(w, "Instances retrieved successfully", instanceList) + utils.SendSuccessResponse(w, "Instances retrieved successfully", instanceList) postLog.Info(fmt.Sprintf("[ListInstancesHandler] Retrieved %d instances for user %d", len(instances), userID)) } func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[StartInstanceHandler] Auth failed: %v", err)) return } @@ -546,7 +546,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -554,36 +554,36 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceIDStr := getStringFromMap(reqMap, "instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") postLog.Error(fmt.Sprintf("[StartInstanceHandler] User %d tried to start a not existed instance: %d", userID, instanceID)) return } if err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { - handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") + utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found") postLog.Error(fmt.Sprintf("[StartInstanceHandler] User %d tried to start instance %d that does not belong to them", userID, instanceID)) return } @@ -592,7 +592,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { serviceName, err := database.GetServiceNameByInstanceID(instanceID) if err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to get service name: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") return } @@ -600,7 +600,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { case "windows": if err := service.StartWindowsService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to start Windows service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to start Windows service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to start Windows service: %v", err)) return } postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Windows service %s started successfully", serviceName)) @@ -608,7 +608,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { case "systemd": if err := service.StartSystemdService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to start systemd service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to start systemd service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to start systemd service: %v", err)) return } postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Systemd service %s started successfully", serviceName)) @@ -616,17 +616,17 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { case "init.d": if err := service.StartInitDService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to start init.d service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to start init.d service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to start init.d service: %v", err)) return } postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Init.d service %s started successfully", serviceName)) default: - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Unsupported init system: %s", initType)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Unsupported init system: %s", initType)) return } - handlers.SendSuccessResponse(w, "Instance started successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Instance started successfully", map[string]interface{}{ "instanceID": instanceID, "serviceName": serviceName, }) @@ -634,9 +634,9 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { } func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[StopInstanceHandler] Auth failed: %v", err)) return } @@ -644,7 +644,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -652,36 +652,36 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceIDStr := getStringFromMap(reqMap, "instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") postLog.Error(fmt.Sprintf("[StopInstanceHandler] User %d tried to stop a not existed instance: %d", userID, instanceID)) return } if err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { - handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") + utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found") postLog.Error(fmt.Sprintf("[StopInstanceHandler] User %d tried to stop instance %d that does not belong to them", userID, instanceID)) return } @@ -690,7 +690,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { serviceName, err := database.GetServiceNameByInstanceID(instanceID) if err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to get service name: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") return } @@ -698,7 +698,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { case "windows": if err := service.StopWindowsService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to stop Windows service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stop Windows service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stop Windows service: %v", err)) return } postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Windows service %s stopped successfully", serviceName)) @@ -706,7 +706,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { case "systemd": if err := service.StopSystemdService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to stop systemd service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stop systemd service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stop systemd service: %v", err)) return } postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Systemd service %s stopped successfully", serviceName)) @@ -714,17 +714,17 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { case "init.d": if err := service.StopInitDService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to stop init.d service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stop init.d service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stop init.d service: %v", err)) return } postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Init.d service %s stopped successfully", serviceName)) default: - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Unsupported init system: %s", initType)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Unsupported init system: %s", initType)) return } - handlers.SendSuccessResponse(w, "Instance stopped successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Instance stopped successfully", map[string]interface{}{ "instanceID": instanceID, "serviceName": serviceName, }) @@ -732,9 +732,9 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) { } func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[RestartInstanceHandler] Auth failed: %v", err)) return } @@ -742,7 +742,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -750,36 +750,36 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceIDStr := getStringFromMap(reqMap, "instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") postLog.Error(fmt.Sprintf("[RestartInstanceHandler] User %d tried to restart a not existed instance: %d", userID, instanceID)) return } if err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { - handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") + utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found") postLog.Error(fmt.Sprintf("[RestartInstanceHandler] User %d tried to restart instance %d that does not belong to them", userID, instanceID)) return } @@ -788,7 +788,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { serviceName, err := database.GetServiceNameByInstanceID(instanceID) if err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to get service name: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") return } @@ -796,7 +796,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { case "windows": if err := service.RestartWindowsService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to restart Windows service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart Windows service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart Windows service: %v", err)) return } postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Windows service %s restarted successfully", serviceName)) @@ -804,7 +804,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { case "systemd": if err := service.RestartSystemdService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to restart systemd service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart systemd service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart systemd service: %v", err)) return } postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Systemd service %s restarted successfully", serviceName)) @@ -812,17 +812,17 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { case "init.d": if err := service.RestartInitDService(serviceName); err != nil { postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to restart init.d service %s: %v", serviceName, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart init.d service: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart init.d service: %v", err)) return } postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Init.d service %s restarted successfully", serviceName)) default: - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Unsupported init system: %s", initType)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Unsupported init system: %s", initType)) return } - handlers.SendSuccessResponse(w, "Instance restarted successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Instance restarted successfully", map[string]interface{}{ "instanceID": instanceID, "serviceName": serviceName, }) @@ -830,9 +830,9 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) { } func GetInstanceStatusHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodGet) + userID, err := utils.Auth(w, r, http.MethodGet) if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[GetInstanceStatusHandler] Auth failed: %v", err)) return } @@ -840,45 +840,45 @@ func GetInstanceStatusHandler(w http.ResponseWriter, r *http.Request) { queryParams := r.URL.Query() instanceIDStr := queryParams.Get("instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } if err != nil { postLog.Error(fmt.Sprintf("[GetInstanceStatusHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { - handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") + utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found") return } err = service.IsInstanceRunning(instanceID) isRunning := err == nil - handlers.SendSuccessResponse(w, "Instance status retrieved successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Instance status retrieved successfully", map[string]interface{}{ "instanceID": instanceID, "isRunning": isRunning, }) } func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodGet) + userID, err := utils.Auth(w, r, http.MethodGet) if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[GetInstanceInfoHandler] Auth failed: %v", err)) return } @@ -886,57 +886,57 @@ func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) { queryParams := r.URL.Query() instanceIDStr := queryParams.Get("instanceID") if instanceIDStr == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } instanceID, err := strconv.Atoi(instanceIDStr) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") return } instance, err := database.DBQueryFrpcInstanceByID(instanceID) if err == sql.ErrNoRows { - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } if err != nil { postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { - handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") + utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found") return } user, err := database.GetUserByID(userID) if err != nil { postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to get user info: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info") return } serviceName, err := database.GetServiceNameByInstanceID(instanceID) if err != nil { postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to get service name: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to get service name") return } configContent, err := os.ReadFile(instance.ConfigPath) if err != nil { postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to read config file: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") return } frpcConfig, err := config.DecodeFrpcConfig(string(configContent)) if err != nil { postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to decode frpc config: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to decode frpc config") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to decode frpc config") return } @@ -960,5 +960,5 @@ func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) { response["serverPort"] = frpcConfig.Global["serverPort"] } - handlers.SendSuccessResponse(w, "Instance info retrieved successfully", response) + utils.SendSuccessResponse(w, "Instance info retrieved successfully", response) } diff --git a/instance/proxy.go b/handlers/proxy.go similarity index 70% rename from instance/proxy.go rename to handlers/proxy.go index 57fc3c6..d45b703 100644 --- a/instance/proxy.go +++ b/handlers/proxy.go @@ -1,4 +1,4 @@ -package instance +package handlers import ( "encoding/json" @@ -10,16 +10,16 @@ import ( "super-frpc/config" "super-frpc/database" - "super-frpc/handlers" + "super-frpc/utils" "super-frpc/postLog" "github.com/BurntSushi/toml" ) func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[CreateProxyHandler] Auth failed: %v", err)) return } @@ -27,7 +27,7 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -35,21 +35,21 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceID := getStringFromMap(reqMap, "instanceID") if instanceID == "" { postLog.Error("[CreateProxyHandler] instanceID is required") - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{}) if !ok { postLog.Error("[CreateProxyHandler] Invalid proxyInfo format") - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format") return } @@ -64,7 +64,7 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" || proxyInfo.LocalPort == 0 || proxyInfo.RemotePort == 0 { postLog.Error("[CreateProxyHandler] Missing required fields in proxyInfo") - handlers.SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in proxyInfo") + utils.SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in proxyInfo") return } @@ -73,37 +73,37 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) if err != nil { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Instance not found for user %d", userID)) - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } configContent, err := os.ReadFile(instance.ConfigPath) if err != nil { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") return } updatedContent, err := config.AddFrpcProxy(string(configContent), proxyInfo) if err != nil { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to add proxy: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to add proxy") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to add proxy") return } if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil { postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to write config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") return } - handlers.SendSuccessResponse(w, "Proxy created successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Proxy created successfully", map[string]interface{}{ "instanceID": instance.ID, "configPath": instance.ConfigPath, "proxyName": proxyInfo.Name, @@ -112,9 +112,9 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { } func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ModifyProxyHandler] Auth failed: %v", err)) return } @@ -122,7 +122,7 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -130,21 +130,21 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceID := getStringFromMap(reqMap, "instanceID") if instanceID == "" { postLog.Error("[ModifyProxyHandler] instanceID is required") - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{}) if !ok { postLog.Error("[ModifyProxyHandler] Invalid proxyInfo format") - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format") return } @@ -159,7 +159,7 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) { if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" || proxyInfo.LocalPort == 0 || proxyInfo.RemotePort == 0 { postLog.Error("[ModifyProxyHandler] Missing required fields in proxyInfo") - handlers.SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in proxyInfo") + utils.SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in proxyInfo") return } @@ -168,37 +168,37 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) { instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) if err != nil { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Instance not found for user %d", userID)) - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } configContent, err := os.ReadFile(instance.ConfigPath) if err != nil { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") return } updatedContent, err := config.ModifyFrpcProxy(string(configContent), proxyInfo) if err != nil { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to modify proxy: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to modify proxy") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to modify proxy") return } if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil { postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to write config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") return } - handlers.SendSuccessResponse(w, "Proxy modified successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Proxy modified successfully", map[string]interface{}{ "instanceID": instance.ID, "configPath": instance.ConfigPath, "proxyName": proxyInfo.Name, @@ -207,9 +207,9 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) { } func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[DeleteProxyHandler] Auth failed: %v", err)) return } @@ -217,7 +217,7 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to read request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") return } defer r.Body.Close() @@ -225,21 +225,21 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) { var reqMap map[string]interface{} if err := json.Unmarshal(body, &reqMap); err != nil { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to unmarshal request body: %v", err)) - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") return } instanceID := getStringFromMap(reqMap, "instanceID") if instanceID == "" { postLog.Error("[DeleteProxyHandler] instanceID is required") - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } proxyName := getStringFromMap(reqMap, "proxyName") if proxyName == "" { postLog.Error("[DeleteProxyHandler] proxyName is required") - handlers.SendErrorResponse(w, http.StatusBadRequest, "proxyName is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "proxyName is required") return } @@ -248,37 +248,37 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) { instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) if err != nil { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Instance not found for user %d", userID)) - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } configContent, err := os.ReadFile(instance.ConfigPath) if err != nil { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") return } updatedContent, err := config.RemoveFrpcProxy(string(configContent), proxyName) if err != nil { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to remove proxy: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove proxy") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove proxy") return } if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil { postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to write config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") return } - handlers.SendSuccessResponse(w, "Proxy deleted successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Proxy deleted successfully", map[string]interface{}{ "instanceID": instance.ID, "configPath": instance.ConfigPath, "proxyName": proxyName, @@ -287,9 +287,9 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) { } func ListProxiesHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodGet) + userID, err := utils.Auth(w, r, http.MethodGet) if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ListProxiesHandler] Auth failed: %v", err)) return } @@ -298,7 +298,7 @@ func ListProxiesHandler(w http.ResponseWriter, r *http.Request) { instanceID := queryParams.Get("instanceID") if instanceID == "" { postLog.Error("[ListProxiesHandler] instanceID is required") - handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") return } @@ -307,27 +307,27 @@ func ListProxiesHandler(w http.ResponseWriter, r *http.Request) { instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) if err != nil { postLog.Error(fmt.Sprintf("[ListProxiesHandler] Failed to query instance: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance") return } if instance.UserID != userID { postLog.Error(fmt.Sprintf("[ListProxiesHandler] Instance not found for user %d", userID)) - handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") + utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found") return } configContent, err := os.ReadFile(instance.ConfigPath) if err != nil { postLog.Error(fmt.Sprintf("[ListProxiesHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") return } var cfg config.FrpcConfig if _, err := toml.Decode(string(configContent), &cfg); err != nil { postLog.Error(fmt.Sprintf("[ListProxiesHandler] Failed to parse config: %v", err)) - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to parse config file") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to parse config file") return } @@ -343,7 +343,7 @@ func ListProxiesHandler(w http.ResponseWriter, r *http.Request) { proxyList[i] = proxyData } - handlers.SendSuccessResponse(w, "Proxies listed successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "Proxies listed successfully", map[string]interface{}{ "instanceID": instance.ID, "proxyCount": len(proxyList), "proxies": proxyList, diff --git a/handlers/settings.go b/handlers/settings.go new file mode 100644 index 0000000..513450a --- /dev/null +++ b/handlers/settings.go @@ -0,0 +1,18 @@ +package handlers + +import ( + "fmt" + "net/http" + + "super-frpc/postLog" + "super-frpc/utils" +) + +func GetSettingsHandler(w http.ResponseWriter, r *http.Request) { + _, err := utils.Auth(w, r, http.MethodGet, "superuser", "admin") + if err != nil { + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + postLog.Warning(fmt.Sprintf("[GetSettingsHandler] Auth failed: %v", err)) + return + } +} diff --git a/user/user.go b/handlers/user.go similarity index 67% rename from user/user.go rename to handlers/user.go index da05c67..5724039 100644 --- a/user/user.go +++ b/handlers/user.go @@ -1,4 +1,4 @@ -package user +package handlers import ( "encoding/json" @@ -8,7 +8,7 @@ import ( "super-frpc/database" "super-frpc/global" - "super-frpc/handlers" + "super-frpc/utils" "super-frpc/postLog" "super-frpc/session" ) @@ -50,20 +50,20 @@ type RemoveSessionRequest struct { func RegisterHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { - handlers.SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") + utils.SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request method: %s", r.Method)) return } if !session.ValidateTimeStamp(r.Header, global.Is.Debug) { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid or missing X-Timestamp in header: %s", r.Header.Get("X-Timestamp"))) return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[RegisterHandler] Failed to read request body: %v", err)) return } @@ -71,32 +71,32 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) { var req RegisterRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request format: %v", err)) return } if req.Username == "" || req.Passwd == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") + utils.SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") postLog.Warning("[RegisterHandler] New user registration failed: username or password is empty") return } if !isValidInput(req.Username) || !isValidInput(req.Passwd) { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd)) return } if !session.IsValidPassword(req.Passwd) { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Password does not meet complexity requirements (must contain uppercase, lowercase, digit, and special character)") + utils.SendErrorResponse(w, http.StatusBadRequest, "Password does not meet complexity requirements (must contain uppercase, lowercase, digit, and special character)") postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: password \"%s\" does not meet complexity requirements", req.Passwd)) return } userList, err := database.DBListUsers() if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + utils.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to list users: %v", err)) return } @@ -109,19 +109,19 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) { userID, err := database.AddUser(req.Username, req.Passwd, newUserType, session.HashPassword, session.IsValidPassword) if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + utils.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to register user \"%s\": %v", req.Username, err)) return } user, err := database.GetUserByID(userID) if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to retrieve user after registration") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to retrieve user after registration") postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to retrieve user \"%s\" after registration: %v", req.Username, err)) return } - handlers.SendSuccessResponse(w, "user registered successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "user registered successfully", map[string]interface{}{ "userID": user.UserID, "username": user.Username, "type": user.Type, @@ -130,19 +130,19 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) { func LoginHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { - handlers.SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") + utils.SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request method: %s", r.Method)) return } if !session.ValidateTimeStamp(r.Header, global.Is.Debug) { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[LoginHandler] Failed to read request body: %v", err)) return } @@ -150,57 +150,57 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { var req LoginRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request format: %v", err)) return } if req.Username == "" || req.Passwd == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") + utils.SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") postLog.Warning("[LoginHandler] Login failed: username or password is empty") return } if !isValidInput(req.Username) || !isValidInput(req.Passwd) { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") postLog.Debug(fmt.Sprintf("[LoginHandler] Login failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd)) return } user, err := database.GetUserByUsername(req.Username) if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, "User not exist") + utils.SendErrorResponse(w, http.StatusUnauthorized, "User not exist") postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: User not exist \"%s\"", req.Username)) return } if !session.VerifyPassword(req.Passwd, user.Passwd) { - handlers.SendErrorResponse(w, http.StatusUnauthorized, "Invalid password") + utils.SendErrorResponse(w, http.StatusUnauthorized, "Invalid password") postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: invalid password for user \"%s\"", req.Username)) return } existingTokenInfo, err := session.GetTokenInfo(user.UserID) if err == nil && existingTokenInfo != nil { - handlers.SendErrorResponse(w, http.StatusConflict, "User is already logged in") + utils.SendErrorResponse(w, http.StatusConflict, "User is already logged in") postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: user \"%s\" is already logged in", req.Username)) return } token, err := session.GenerateToken(user.UserID) if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to generate token") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to generate token") postLog.Error(fmt.Sprintf("[LoginHandler] Failed to generate token for user \"%s\": %v", req.Username, err)) return } if err := session.JoinSession(user.UserID, user.Username, token); err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to create session") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to create session") postLog.Error(fmt.Sprintf("[LoginHandler] Failed to create session for user \"%s\": %v", req.Username, err)) return } - handlers.SendSuccessResponse(w, "Login successful", map[string]interface{}{ + utils.SendSuccessResponse(w, "Login successful", map[string]interface{}{ "token": token, "userID": user.UserID, "username": user.Username, @@ -210,9 +210,9 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { } func LogoutHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodGet) + userID, err := utils.Auth(w, r, http.MethodGet) if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[LogoutHandler] Auth failed: %v", err)) return } @@ -229,32 +229,32 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request) { sessionTokenMux.RUnlock() if sessionID == "" { - handlers.SendErrorResponse(w, http.StatusNotFound, "Session not found for token") + utils.SendErrorResponse(w, http.StatusNotFound, "Session not found for token") postLog.Warning(fmt.Sprintf("[LogoutHandler] Session not found for token from user [%d]%s", userID, session.GetUsernameByID(userID))) return } if err := session.RemoveSession(sessionID); err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to logout") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to logout") postLog.Error(fmt.Sprintf("[LogoutHandler] Failed to logout user [%d]%s: %v", userID, session.GetUsernameByID(userID), err)) return } - handlers.SendSuccessResponse(w, "Logout successful", nil) + utils.SendSuccessResponse(w, "Logout successful", nil) postLog.Info(fmt.Sprintf("[LogoutHandler] User [%d]%s Logout successful", userID, session.GetUsernameByID(userID))) } func RemoveSessionHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodPost, "superuser") + userID, err := utils.Auth(w, r, http.MethodPost, "superuser") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[RemoveSessionHandler] Auth failed: %v", err)) return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[RemoveSessionHandler] Failed to read request body: %v", err)) return } @@ -262,38 +262,38 @@ func RemoveSessionHandler(w http.ResponseWriter, r *http.Request) { var req RemoveSessionRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[RemoveSessionHandler] Invalid request format: %v", err)) return } if req.SessionID == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "SessionID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "SessionID is required") postLog.Warning("[RemoveSessionHandler] SessionID is empty") return } if err := session.RemoveSession(req.SessionID); err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to remove session: %v", err)) + utils.SendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("Failed to remove session: %v", err)) postLog.Error(fmt.Sprintf("[RemoveSessionHandler] Failed to remove session %s: %v", req.SessionID, err)) return } postLog.Info(fmt.Sprintf("[RemoveSessionHandler] User [%d]%s removed session %s", userID, session.GetUsernameByID(userID), req.SessionID)) - handlers.SendSuccessResponse(w, "Session removed successfully", nil) + utils.SendSuccessResponse(w, "Session removed successfully", nil) } func CreateUserHandler(w http.ResponseWriter, r *http.Request) { - _, err := handlers.Auth(w, r, http.MethodPost, "superuser") + _, err := utils.Auth(w, r, http.MethodPost, "superuser") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[CreateUserHandler] Auth failed: %v", err)) return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[CreateUserHandler] Failed to read request body: %v", err)) return } @@ -301,38 +301,38 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) { var req CreateUserRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[CreateUserHandler] Invalid request format: %v", err)) return } if req.Username == "" || req.Passwd == "" || req.Type == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Username, password, and type are required") + utils.SendErrorResponse(w, http.StatusBadRequest, "Username, password, and type are required") postLog.Warning("[CreateUserHandler] CreateUser failed: username, password, or type is empty") return } if req.Type != "admin" && req.Type != "user" && req.Type != "superuser" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid type: must be 'admin' or 'user' or 'superuser'") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid type: must be 'admin' or 'user' or 'superuser'") postLog.Warning(fmt.Sprintf("[CreateUserHandler] CreateUser failed: invalid type: %s", req.Type)) return } userID, err := database.AddUser(req.Username, req.Passwd, req.Type, session.HashPassword, session.IsValidPassword) if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + utils.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to register user \"%s\": %v", req.Username, err)) return } user, err := database.GetUserByID(userID) if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to retrieve user after creation") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to retrieve user after creation") postLog.Error(fmt.Sprintf("[CreateUserHandler] Failed to retrieve user \"%s\" after creation: %v", req.Username, err)) return } - handlers.SendSuccessResponse(w, "User created successfully", map[string]interface{}{ + utils.SendSuccessResponse(w, "User created successfully", map[string]interface{}{ "userID": user.UserID, "username": user.Username, "type": user.Type, @@ -341,15 +341,15 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) { } func ModifyUserHandler(w http.ResponseWriter, r *http.Request) { - _, err := handlers.Auth(w, r, http.MethodPost, "user", "admin", "superuser") + _, err := utils.Auth(w, r, http.MethodPost, "user", "admin", "superuser") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("Auth failed: %v", err)) + utils.SendErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("Auth failed: %v", err)) return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[ModifyUserHandler] Failed to read request body: %v", err)) return } @@ -358,43 +358,43 @@ func ModifyUserHandler(w http.ResponseWriter, r *http.Request) { var req ModifyUserRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[ModifyUserHandler] Invalid request format: %v", err)) return } if req.UserID == 0 { - handlers.SendErrorResponse(w, http.StatusBadRequest, "UserID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "UserID is required") postLog.Warning("[ModifyUserHandler] ModifyUser failed: UserID is empty") return } if req.Username == "" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Username is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "Username is required") postLog.Warning("[ModifyUserHandler] ModifyUser failed: username is empty") return } if err := database.DBUpdateUser(req.UserID, req.Username, req.Passwd); err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + utils.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) postLog.Error(fmt.Sprintf("[ModifyUserHandler] Failed to update user [%d]: %v", req.UserID, err)) return } - handlers.SendSuccessResponse(w, "User updated successfully", nil) + utils.SendSuccessResponse(w, "User updated successfully", nil) postLog.Info(fmt.Sprintf("[ModifyUserHandler] User [%d]%s updated successfully to: %s", req.UserID, session.GetUsernameByID(req.UserID), req.Username)) } func ModifyUserTypeHandler(w http.ResponseWriter, r *http.Request) { - _, err := handlers.Auth(w, r, http.MethodPost, "superuser") + _, err := utils.Auth(w, r, http.MethodPost, "superuser") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] Auth failed: %v", err)) return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] Failed to read request body: %v", err)) return } @@ -403,40 +403,40 @@ func ModifyUserTypeHandler(w http.ResponseWriter, r *http.Request) { var req ModifyUserTypeRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] Invalid request format: %v", err)) return } if req.UserID == 0 { - handlers.SendErrorResponse(w, http.StatusBadRequest, "UserID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "UserID is required") postLog.Warning("[ModifyUserTypeHandler] ModifyUserType failed: UserID is empty") return } if req.Type != "admin" && req.Type != "visitor" && req.Type != "superuser" { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid type: must be 'admin' or 'visitor' or 'superuser'") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid type: must be 'admin' or 'visitor' or 'superuser'") postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] ModifyUserType failed: invalid type: %s", req.Type)) return } if err := database.DBUpdateUserType(req.UserID, req.Type); err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + utils.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) postLog.Error(fmt.Sprintf("[ModifyUserTypeHandler] Failed to update user type [%d]: %v", req.UserID, err)) return } - handlers.SendSuccessResponse(w, "User type updated successfully", nil) + utils.SendSuccessResponse(w, "User type updated successfully", nil) postLog.Info(fmt.Sprintf("[ModifyUserTypeHandler] User [%d]%s type updated successfully to: %s", req.UserID, session.GetUsernameByID(req.UserID), req.Type)) } func RemoveUserHandler(w http.ResponseWriter, r *http.Request) { - _, err := handlers.Auth(w, r, http.MethodPost, "superuser") + _, err := utils.Auth(w, r, http.MethodPost, "superuser") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[RemoveUserHandler] Auth failed: %v", err)) return } body, err := io.ReadAll(r.Body) if err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") postLog.Warning(fmt.Sprintf("[RemoveUserHandler] Failed to read request body: %v", err)) return } @@ -444,51 +444,51 @@ func RemoveUserHandler(w http.ResponseWriter, r *http.Request) { var req RemoveUserRequest if err := json.Unmarshal(body, &req); err != nil { - handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") postLog.Warning(fmt.Sprintf("[RemoveUserHandler] Invalid request format: %v", err)) return } if req.TargetUserID == 0 { - handlers.SendErrorResponse(w, http.StatusBadRequest, "TargetUserID is required") + utils.SendErrorResponse(w, http.StatusBadRequest, "TargetUserID is required") postLog.Warning("[RemoveUserHandler] RemoveUser failed: TargetUserID is empty") return } if err := database.RemoveUser(req.TargetUserID); err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + utils.SendErrorResponse(w, http.StatusInternalServerError, err.Error()) postLog.Error(fmt.Sprintf("[RemoveUserHandler] Failed to remove user [%d]: %v", req.TargetUserID, err)) return } - handlers.SendSuccessResponse(w, "User removed successfully", nil) + utils.SendSuccessResponse(w, "User removed successfully", nil) } func ListUserHandler(w http.ResponseWriter, r *http.Request) { - _, err := handlers.Auth(w, r, http.MethodGet, "superuser") + _, err := utils.Auth(w, r, http.MethodGet, "superuser") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ListUserHandler] Auth failed: %v", err)) return } userList, err := database.DBListUsers() if err != nil { - handlers.SendErrorResponse(w, http.StatusInternalServerError, "Failed to list users") + utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to list users") postLog.Error(fmt.Sprintf("[ListUserHandler] Failed to list users: %v", err)) return } - handlers.SendSuccessResponse(w, "User list retrieved successfully", userList) + utils.SendSuccessResponse(w, "User list retrieved successfully", userList) } func ListActiveSessionsHandler(w http.ResponseWriter, r *http.Request) { - userID, err := handlers.Auth(w, r, http.MethodGet, "superuser", "admin") + userID, err := utils.Auth(w, r, http.MethodGet, "superuser", "admin") if err != nil { - handlers.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) + utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error()) postLog.Warning(fmt.Sprintf("[ListActiveSessionsHandler] Auth failed: %v", err)) return } sessions := session.ListActiveSessions() postLog.Debug(fmt.Sprintf("[ListActiveSessionsHandler] User [%d]%s listed %d active sessions", userID, session.GetUsernameByID(userID), len(sessions))) - handlers.SendSuccessResponse(w, "Active sessions listed", sessions) + utils.SendSuccessResponse(w, "Active sessions listed", sessions) } func isValidInput(input string) bool { diff --git a/main.go b/main.go index 4cb1ffb..7c8c1d4 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "flag" "fmt" "net/http" @@ -10,10 +11,10 @@ import ( "super-frpc/database" "super-frpc/frpLogger" "super-frpc/global" - "super-frpc/handlers" "super-frpc/postLog" - "super-frpc/session" "super-frpc/service" + "super-frpc/session" + "super-frpc/utils" "super-frpc/watchdog" "syscall" "time" @@ -27,24 +28,23 @@ func main() { flag.Parse() if _, err := os.Stat(*configPath); os.IsNotExist(err) { - defaultConfig := `{ - "listenAddr": "0.0.0.0", - "listenPort": "8080", - "configDir": "./configs" -}` - if err := os.WriteFile(*configPath, []byte(defaultConfig), 0644); err != nil { + // Load the default config + configData, err := json.MarshalIndent(global.CurrentConfig, "", " ") + if err != nil { + postLog.Warning(fmt.Sprintf("Failed to marshal default config: %v", err)) + } else if err := os.WriteFile(*configPath, configData, 0644); err != nil { postLog.Warning(fmt.Sprintf("Failed to create default config file: %v", err)) } postLog.Info(fmt.Sprintf("Created default config file at %s", *configPath)) } - cfg, err := config.LoadConfig(*configPath, service.GetInitSystem) + err := config.LoadConfig(*configPath, service.GetInitSystem) if err != nil { postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err)) } - postLog.SetDebugMode(cfg.Debug) - global.Is.Debug = cfg.Debug + postLog.SetDebugMode(global.CurrentConfig.Debug) + global.Is.Debug = global.CurrentConfig.Debug if err := postLog.InitLogsDatabase(*dbPath_log); err != nil { postLog.Fatal(fmt.Sprintf("Failed to initialize logs database: %v", err)) @@ -61,12 +61,9 @@ func main() { } frpLogger.SetDatabase(global.ConfigDB, global.FrpcDB) - frpLogger.SetDebugMode(cfg.Debug) + frpLogger.SetDebugMode(global.CurrentConfig.Debug) - _, err = config.GetConfig() - if err != nil { - postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err)) - } + config.GetConfig() postLog.InitLogBroadcaster() @@ -76,15 +73,15 @@ func main() { if err != nil { postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err)) } else { - if !watchdog.Connect("127.0.0.1", cfg.Watchdog.Port) { - postLog.Error(fmt.Sprintf("Failed to connect to Watchdog at %s:%d", "127.0.0.1", cfg.Watchdog.Port)) + if !watchdog.Connect("127.0.0.1", global.CurrentConfig.Watchdog.Port) { + postLog.Error(fmt.Sprintf("Failed to connect to Watchdog at %s:%d", "127.0.0.1", global.CurrentConfig.Watchdog.Port)) } else { - postLog.Info(fmt.Sprintf("Connected to Watchdog at %s:%d", "127.0.0.1", cfg.Watchdog.Port)) + postLog.Info(fmt.Sprintf("Connected to Watchdog at %s:%d", "127.0.0.1", global.CurrentConfig.Watchdog.Port)) global.Is.WatchdogConnected = true } } - addr := fmt.Sprintf("%s:%s", cfg.ListenAddr, cfg.ListenPort) + addr := fmt.Sprintf("%s:%s", global.CurrentConfig.ListenAddr, global.CurrentConfig.ListenPort) server := &http.Server{ Addr: addr, ReadTimeout: 15 * time.Second, @@ -139,9 +136,9 @@ func GetStatusHandler(w http.ResponseWriter, r *http.Request) { if global.Is.WatchdogConnected { statusInfo["WatchdogStatus"] = "Online" } - handlers.SendSuccessResponse(w, "getStatus", statusInfo) + utils.SendSuccessResponse(w, "getStatus", statusInfo) } func GetSoftwareInfoHandler(w http.ResponseWriter, r *http.Request) { - handlers.SendSuccessResponse(w, "getSoftwareInfo", global.Software) + utils.SendSuccessResponse(w, "getSoftwareInfo", global.Software) } diff --git a/router.go b/router.go index 1e80b26..81b791a 100644 --- a/router.go +++ b/router.go @@ -4,11 +4,10 @@ import ( "fmt" "net/http" "super-frpc/frpLogger" - "super-frpc/handlers" - "super-frpc/instance" + "super-frpc/utils" "super-frpc/postLog" "super-frpc/session" - "super-frpc/user" + "super-frpc/handlers" ) func setupRoutes() { @@ -17,33 +16,33 @@ func setupRoutes() { systemLogHandler := postLog.NewLogSocketHandler(postLog.GetLogBroadcaster()) http.HandleFunc("/system/getLogs", systemLogHandler.Handle) - http.HandleFunc("/register", user.RegisterHandler) - http.HandleFunc("/login", user.LoginHandler) - http.HandleFunc("/logout", user.LogoutHandler) + http.HandleFunc("/register", handlers.RegisterHandler) + http.HandleFunc("/login", handlers.LoginHandler) + http.HandleFunc("/logout", handlers.LogoutHandler) - http.HandleFunc("/userMgr/create", user.CreateUserHandler) - http.HandleFunc("/userMgr/remove", user.RemoveUserHandler) - http.HandleFunc("/userMgr/list", user.ListUserHandler) - http.HandleFunc("/userMgr/modify", user.ModifyUserHandler) - http.HandleFunc("/userMgr/modifyType", user.ModifyUserTypeHandler) + http.HandleFunc("/userMgr/create", handlers.CreateUserHandler) + http.HandleFunc("/userMgr/remove", handlers.RemoveUserHandler) + http.HandleFunc("/userMgr/list", handlers.ListUserHandler) + http.HandleFunc("/userMgr/modify", handlers.ModifyUserHandler) + http.HandleFunc("/userMgr/modifyType", handlers.ModifyUserTypeHandler) - http.HandleFunc("/sessionMgr/list", user.ListActiveSessionsHandler) - http.HandleFunc("/sessionMgr/remove", user.RemoveSessionHandler) + http.HandleFunc("/sessionMgr/list", handlers.ListActiveSessionsHandler) + http.HandleFunc("/sessionMgr/remove", handlers.RemoveSessionHandler) - http.HandleFunc("/frpcAct/instanceMgr/create", instance.CreateInstanceHandler) - http.HandleFunc("/frpcAct/instanceMgr/delete", instance.DeleteInstanceHandler) - http.HandleFunc("/frpcAct/instanceMgr/modify", instance.ModifyInstanceHandler) - http.HandleFunc("/frpcAct/instanceMgr/list", instance.ListInstancesHandler) - http.HandleFunc("/frpcAct/instanceMgr/start", instance.StartInstanceHandler) - http.HandleFunc("/frpcAct/instanceMgr/stop", instance.StopInstanceHandler) - http.HandleFunc("/frpcAct/instanceMgr/restart", instance.RestartInstanceHandler) - http.HandleFunc("/frpcAct/instanceMgr/status", instance.GetInstanceStatusHandler) - http.HandleFunc("/frpcAct/instanceMgr/getInfo", instance.GetInstanceInfoHandler) + http.HandleFunc("/frpcAct/instanceMgr/create", handlers.CreateInstanceHandler) + http.HandleFunc("/frpcAct/instanceMgr/delete", handlers.DeleteInstanceHandler) + http.HandleFunc("/frpcAct/instanceMgr/modify", handlers.ModifyInstanceHandler) + http.HandleFunc("/frpcAct/instanceMgr/list", handlers.ListInstancesHandler) + http.HandleFunc("/frpcAct/instanceMgr/start", handlers.StartInstanceHandler) + http.HandleFunc("/frpcAct/instanceMgr/stop", handlers.StopInstanceHandler) + http.HandleFunc("/frpcAct/instanceMgr/restart", handlers.RestartInstanceHandler) + http.HandleFunc("/frpcAct/instanceMgr/status", handlers.GetInstanceStatusHandler) + http.HandleFunc("/frpcAct/instanceMgr/getInfo", handlers.GetInstanceInfoHandler) http.HandleFunc("/frpcAct/instanceMgr/logs", frpLogger.NewInstanceLogHandler(session.ValidateTokenFromMap).ServeHTTP) - http.HandleFunc("/frpcAct/proxyMgr/create", instance.CreateProxyHandler) - http.HandleFunc("/frpcAct/proxyMgr/modify", instance.ModifyProxyHandler) - http.HandleFunc("/frpcAct/proxyMgr/delete", instance.DeleteProxyHandler) - http.HandleFunc("/frpcAct/proxyMgr/list", instance.ListProxiesHandler) + http.HandleFunc("/frpcAct/proxyMgr/create", handlers.CreateProxyHandler) + http.HandleFunc("/frpcAct/proxyMgr/modify", handlers.ModifyProxyHandler) + http.HandleFunc("/frpcAct/proxyMgr/delete", handlers.DeleteProxyHandler) + http.HandleFunc("/frpcAct/proxyMgr/list", handlers.ListProxiesHandler) http.HandleFunc("/", NotFoundHandler) @@ -53,5 +52,5 @@ func setupRoutes() { func NotFoundHandler(w http.ResponseWriter, r *http.Request) { postLog.Error(fmt.Sprintf("Route not found: %s %s", r.Method, r.URL.Path)) - handlers.SendErrorResponse(w, http.StatusNotFound, "Invalid request path") + utils.SendErrorResponse(w, http.StatusNotFound, "Invalid request path") } diff --git a/service/service.go b/service/service.go index f53ed67..64cdd67 100644 --- a/service/service.go +++ b/service/service.go @@ -9,27 +9,17 @@ import ( "strconv" "strings" - "super-frpc/config" "super-frpc/database" + "super-frpc/global" "super-frpc/postLog" ) func GetConfigDir() (string, error) { - cfg, err := config.GetConfig() - if err != nil { - postLog.Error(fmt.Sprintf("[GetConfigDir] Failed to get config: %v", err)) - return "", err - } - return cfg.InstancePath, nil + return global.CurrentConfig.InstancePath, nil } func GetFrpcPath() (string, error) { - cfg, err := config.GetConfig() - if err != nil { - postLog.Error(fmt.Sprintf("[GetFrpcPath] Failed to get config: %v", err)) - return "", err - } - return cfg.FrpcPath, nil + return global.CurrentConfig.FrpcPath, nil } func GetInitSystem() string { diff --git a/handlers/handlers.go b/utils/handlers.go similarity index 85% rename from handlers/handlers.go rename to utils/handlers.go index 7a13c7c..e441ad2 100644 --- a/handlers/handlers.go +++ b/utils/handlers.go @@ -1,4 +1,4 @@ -package handlers +package utils import ( "encoding/json" @@ -19,6 +19,8 @@ type Response struct { Data interface{} `json:"data,omitempty"` } +// SendErrorResponse sends an error response with the specified status code and message. +// If data is provided, it is included in the response. func SendErrorResponse(w http.ResponseWriter, statusCode int, message string, data ...interface{}) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) @@ -37,6 +39,8 @@ func SendErrorResponse(w http.ResponseWriter, statusCode int, message string, da w.Write(jsonResp) } +// SendSuccessResponse sends a success response with the specified message and data. +// If data is provided, it is included in the response. func SendSuccessResponse(w http.ResponseWriter, message string, data interface{}) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) @@ -53,6 +57,10 @@ func SendSuccessResponse(w http.ResponseWriter, message string, data interface{} w.Write(jsonResp) } +// Auth authenticates the request. +// It checks the request method, timestamp, and token. +// If any of these checks fail, it returns an error. +// If no error occurs, it returns the user ID. func Auth(w http.ResponseWriter, r *http.Request, targetMethod string, allowedUserLevels ...string) (int, error) { if r.Method != targetMethod { return 0, fmt.Errorf("Method not allowed: %s", targetMethod)