refactor(global): move config to global package and consolidate handlers

- Move Config struct and related functions to global package
- Consolidate handler utilities into utils package
- Remove deprecated handlers and instance packages
- Add new handlers package with settings and proxy functionality
- Update config.json to include watchdog enabled flag
This commit is contained in:
2026-04-22 19:52:33 +08:00
parent ddf91299e7
commit 489c37e095
10 changed files with 384 additions and 353 deletions
+35 -43
View File
@@ -2,26 +2,15 @@ package config
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"super-frpc/global"
"github.com/BurntSushi/toml" "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 { type InstanceInfo struct {
Name string `json:"name"` Name string `json:"name"`
ServerAddr string `json:"serverAddr"` ServerAddr string `json:"serverAddr"`
@@ -56,60 +45,64 @@ type FrpcConfig struct {
Proxies []map[string]interface{} `toml:"proxies"` Proxies []map[string]interface{} `toml:"proxies"`
} }
var globalConfig *Config func LoadConfig(configPath string, getInitSystem func() string) error {
func LoadConfig(configPath string, getInitSystem func() string) (*Config, error) {
data, err := os.ReadFile(configPath) data, err := os.ReadFile(configPath)
if err != nil { 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 var fileConfig global.Config
if err := json.Unmarshal(data, &config); err != nil { if err := json.Unmarshal(data, &fileConfig); err != nil {
return nil, fmt.Errorf("failed to parse config file: %w", err) return fmt.Errorf("failed to parse config file: %w", err)
} }
if config.ListenAddr == "" { if fileConfig.ListenAddr != "" {
config.ListenAddr = "0.0.0.0" global.CurrentConfig.ListenAddr = fileConfig.ListenAddr
} }
if config.ListenPort == "" { if fileConfig.ListenPort != "" {
config.ListenPort = "8080" global.CurrentConfig.ListenPort = fileConfig.ListenPort
} }
if config.FrpcPath == "" { if fileConfig.FrpcPath != "" {
if getInitSystem() == "windows" { global.CurrentConfig.FrpcPath = fileConfig.FrpcPath
config.FrpcPath = "frp_client/frpc.exe"
} else { } else {
config.FrpcPath = "/usr/bin/frpc" if getInitSystem() == "windows" {
global.CurrentConfig.FrpcPath = "frp_client/frpc.exe"
} else {
global.CurrentConfig.FrpcPath = "/usr/bin/frpc"
} }
} }
if config.InstancePath == "" { if fileConfig.InstancePath != "" {
config.InstancePath = "./configs" global.CurrentConfig.InstancePath = fileConfig.InstancePath
} else {
global.CurrentConfig.InstancePath = "./configs"
} }
if config.Watchdog.Port == 0 { global.CurrentConfig.Debug = fileConfig.Debug
config.Watchdog.Port = 12380
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 { global.CurrentConfig.Watchdog.Enabled = fileConfig.Watchdog.Enabled
return nil, fmt.Errorf("failed to create config directory: %w", err)
if err := os.MkdirAll(global.CurrentConfig.InstancePath, 0755); err != nil {
return fmt.Errorf("failed to create config directory: %w", err)
} }
globalConfig = &config return nil
return &config, nil
} }
func GetConfig() (*Config, error) { func GetConfig() *global.Config {
if globalConfig == nil { return &global.CurrentConfig
return nil, errors.New("config not loaded")
}
return globalConfig, nil
} }
func SaveConfig(configPath string, config *Config) error { func SaveConfig(configPath string) error {
data, err := json.MarshalIndent(config, "", " ") data, err := json.MarshalIndent(global.CurrentConfig, "", " ")
if err != nil { if err != nil {
return fmt.Errorf("failed to marshal config: %w", err) 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) return fmt.Errorf("failed to write config file: %w", err)
} }
globalConfig = config
return nil return nil
} }
+35 -8
View File
@@ -13,6 +13,14 @@ type SoftwareInfo struct {
BuildType string BuildType string
} }
var Software = SoftwareInfo{
Name: "Super-frpc",
Version: "0.0.1",
Developer: "Madobi Nanami",
BuildVer: 1,
BuildType: "debug",
}
type StatusFlags struct { type StatusFlags struct {
Debug bool Debug bool
Online bool Online bool
@@ -25,16 +33,35 @@ var (
LogsDB *sql.DB LogsDB *sql.DB
) )
var Software = SoftwareInfo{
Name: "Super-frpc",
Version: "0.0.1",
Developer: "Madobi Nanami",
BuildVer: 1,
BuildType: "debug",
}
var Is = StatusFlags{ var Is = StatusFlags{
Debug: false, Debug: false,
Online: false, Online: false,
WatchdogConnected: 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,
},
}
+116 -116
View File
@@ -1,4 +1,4 @@
package instance package handlers
import ( import (
"database/sql" "database/sql"
@@ -13,15 +13,15 @@ import (
"super-frpc/config" "super-frpc/config"
"super-frpc/database" "super-frpc/database"
"super-frpc/handlers" "super-frpc/utils"
"super-frpc/postLog" "super-frpc/postLog"
"super-frpc/service" "super-frpc/service"
) )
func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[CreateInstanceHandler] Auth failed: %v", err))
return return
} }
@@ -29,7 +29,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -37,7 +37,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
@@ -55,7 +55,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
instanceInfoMap, ok := reqMap["instanceInfo"].(map[string]interface{}) instanceInfoMap, ok := reqMap["instanceInfo"].(map[string]interface{})
if !ok { if !ok {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceInfo format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceInfo format")
return return
} }
@@ -80,7 +80,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if req.InstanceInfo.Name == "" || req.InstanceInfo.ServerAddr == "" || if req.InstanceInfo.Name == "" || req.InstanceInfo.ServerAddr == "" ||
req.InstanceInfo.ServerPort == "" || req.InstanceInfo.AuthMethod == "" { 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 return
} }
@@ -92,14 +92,14 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
user, err := database.GetUserByID(userID) user, err := database.GetUserByID(userID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to get user info: %v", err)) 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 return
} }
configDir, err := service.GetConfigDir() configDir, err := service.GetConfigDir()
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to get config directory: %v", err)) 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 return
} }
@@ -112,7 +112,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if err := config.HandleConfigFileCreate(configPath, req.InstanceInfo, setKeyTextWrapper); err != nil { if err := config.HandleConfigFileCreate(configPath, req.InstanceInfo, setKeyTextWrapper); err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to create config file %s: %v", configPath, err)) 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 return
} }
@@ -128,7 +128,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if err := database.DBAddFrpcInstance(instance); err != nil { if err := database.DBAddFrpcInstance(instance); err != nil {
os.Remove(configPath) os.Remove(configPath)
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to save instance %s to database: %v", req.InstanceInfo.Name, err)) 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 return
} }
@@ -136,7 +136,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
os.Remove(configPath) os.Remove(configPath)
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to query created instance: %v", err)) 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 return
} }
@@ -144,19 +144,19 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
database.DBRemoveFrpcInstanceByID(createdInstance.ID) database.DBRemoveFrpcInstanceByID(createdInstance.ID)
os.Remove(configPath) os.Remove(configPath)
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to create boot service for instance %s: %v", req.InstanceInfo.Name, err)) 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 return
} }
if req.BootAtStart { if req.BootAtStart {
if err := service.SetBootAtStart(createdInstance.ID); err != nil { 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)) 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 return
} }
} }
handlers.SendSuccessResponse(w, "Instance created successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Instance created successfully", map[string]interface{}{
"name": req.InstanceInfo.Name, "name": req.InstanceInfo.Name,
"configPath": configPath, "configPath": configPath,
"bootAtStart": req.BootAtStart, "bootAtStart": req.BootAtStart,
@@ -165,9 +165,9 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
} }
func DeleteInstanceHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[DeleteInstanceHandler] Auth failed: %v", err))
return return
} }
@@ -175,7 +175,7 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -183,64 +183,64 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceIDStr := getStringFromMap(reqMap, "instanceID") instanceIDStr := getStringFromMap(reqMap, "instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { 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)) postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] User %d tried to delete a not existed instance: %d", userID, instanceID))
return return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to query instance: %v", err)) 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 return
} }
if err := service.RemoveBootService(instanceID); err != nil { if err := service.RemoveBootService(instanceID); err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to remove boot service for instance %s: %v", instance.Name, err)) 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 return
} }
if _, err := os.Stat(instance.ConfigPath); err == nil { if _, err := os.Stat(instance.ConfigPath); err == nil {
if err := os.Remove(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)) 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 return
} }
} }
if err := database.DBRemoveFrpcInstanceByID(instanceID); err != nil { if err := database.DBRemoveFrpcInstanceByID(instanceID); err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to delete instance %d from database: %v", instanceID, err)) 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 return
} }
handlers.SendSuccessResponse(w, "Instance deleted successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Instance deleted successfully", map[string]interface{}{
"id": instanceID, "id": instanceID,
}) })
postLog.Info(fmt.Sprintf("[DeleteInstanceHandler] Instance %d deleted successfully", instanceID)) postLog.Info(fmt.Sprintf("[DeleteInstanceHandler] Instance %d deleted successfully", instanceID))
} }
func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[ModifyInstanceHandler] Auth failed: %v", err))
return return
} }
@@ -248,7 +248,7 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -256,61 +256,61 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceIDStr := getStringFromMap(reqMap, "instanceID") instanceIDStr := getStringFromMap(reqMap, "instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
modifyType := getStringFromMap(reqMap, "type") modifyType := getStringFromMap(reqMap, "type")
if modifyType == "" { if modifyType == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "type is required") utils.SendErrorResponse(w, http.StatusBadRequest, "type is required")
return return
} }
if modifyType != "configFile" && modifyType != "systemConfig" { 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 return
} }
modifiedData, ok := reqMap["modifiedData"].(map[string]interface{}) modifiedData, ok := reqMap["modifiedData"].(map[string]interface{})
if !ok || modifiedData == nil { 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 return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] User %d tried to modify a not existed instance: %d", userID, instanceID)) 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 return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] User %d does not have permission to modify instance %d", userID, instanceID)) 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 return
} }
user, err := database.GetUserByID(instance.UserID) user, err := database.GetUserByID(instance.UserID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to get user info: %v", err)) 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 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 { 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)) 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 return
} }
} }
handlers.SendSuccessResponse(w, "Config file modified successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Config file modified successfully", map[string]interface{}{
"instanceName": instance.Name, "instanceName": instance.Name,
"instanceID": instance.ID, "instanceID": instance.ID,
"configPath": configPath, "configPath": configPath,
@@ -391,7 +391,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d
configDir, err := service.GetConfigDir() configDir, err := service.GetConfigDir()
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to get config directory: %v", err)) 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 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.Stat(oldConfigPath); err == nil {
if err := os.Rename(oldConfigPath, newConfigPath); 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)) 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 return
} }
} }
@@ -417,7 +417,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d
if err := database.DBUpdateFrpcInstance(instance); err != nil { if err := database.DBUpdateFrpcInstance(instance); err != nil {
postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to update instance in database: %v", err)) 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 return
} }
@@ -453,7 +453,7 @@ func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance d
if bootServiceError != "" { if bootServiceError != "" {
data["bootServiceError"] = 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) { 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) { 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 { 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)) postLog.Warning(fmt.Sprintf("[ListInstancesHandler] Auth failed: %v", err))
return return
} }
@@ -507,7 +507,7 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
instances, err := GetUserInstances(userID) instances, err := GetUserInstances(userID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to get user instances: %v", err)) 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 return
} }
@@ -531,14 +531,14 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
instanceList[i] = instanceData 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)) postLog.Info(fmt.Sprintf("[ListInstancesHandler] Retrieved %d instances for user %d", len(instances), userID))
} }
func StartInstanceHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[StartInstanceHandler] Auth failed: %v", err))
return return
} }
@@ -546,7 +546,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -554,36 +554,36 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceIDStr := getStringFromMap(reqMap, "instanceID") instanceIDStr := getStringFromMap(reqMap, "instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { 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)) postLog.Error(fmt.Sprintf("[StartInstanceHandler] User %d tried to start a not existed instance: %d", userID, instanceID))
return return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { 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)) postLog.Error(fmt.Sprintf("[StartInstanceHandler] User %d tried to start instance %d that does not belong to them", userID, instanceID))
return return
} }
@@ -592,7 +592,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) {
serviceName, err := database.GetServiceNameByInstanceID(instanceID) serviceName, err := database.GetServiceNameByInstanceID(instanceID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to get service name: %v", err)) 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 return
} }
@@ -600,7 +600,7 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) {
case "windows": case "windows":
if err := service.StartWindowsService(serviceName); err != nil { if err := service.StartWindowsService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to start Windows service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Windows service %s started successfully", serviceName)) 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": case "systemd":
if err := service.StartSystemdService(serviceName); err != nil { if err := service.StartSystemdService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to start systemd service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Systemd service %s started successfully", serviceName)) 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": case "init.d":
if err := service.StartInitDService(serviceName); err != nil { if err := service.StartInitDService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[StartInstanceHandler] Failed to start init.d service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Init.d service %s started successfully", serviceName)) postLog.Debug(fmt.Sprintf("[StartInstanceHandler] Init.d service %s started successfully", serviceName))
default: 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 return
} }
handlers.SendSuccessResponse(w, "Instance started successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Instance started successfully", map[string]interface{}{
"instanceID": instanceID, "instanceID": instanceID,
"serviceName": serviceName, "serviceName": serviceName,
}) })
@@ -634,9 +634,9 @@ func StartInstanceHandler(w http.ResponseWriter, r *http.Request) {
} }
func StopInstanceHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[StopInstanceHandler] Auth failed: %v", err))
return return
} }
@@ -644,7 +644,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -652,36 +652,36 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceIDStr := getStringFromMap(reqMap, "instanceID") instanceIDStr := getStringFromMap(reqMap, "instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { 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)) postLog.Error(fmt.Sprintf("[StopInstanceHandler] User %d tried to stop a not existed instance: %d", userID, instanceID))
return return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { 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)) postLog.Error(fmt.Sprintf("[StopInstanceHandler] User %d tried to stop instance %d that does not belong to them", userID, instanceID))
return return
} }
@@ -690,7 +690,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) {
serviceName, err := database.GetServiceNameByInstanceID(instanceID) serviceName, err := database.GetServiceNameByInstanceID(instanceID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to get service name: %v", err)) 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 return
} }
@@ -698,7 +698,7 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) {
case "windows": case "windows":
if err := service.StopWindowsService(serviceName); err != nil { if err := service.StopWindowsService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to stop Windows service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Windows service %s stopped successfully", serviceName)) 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": case "systemd":
if err := service.StopSystemdService(serviceName); err != nil { if err := service.StopSystemdService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to stop systemd service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Systemd service %s stopped successfully", serviceName)) 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": case "init.d":
if err := service.StopInitDService(serviceName); err != nil { if err := service.StopInitDService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[StopInstanceHandler] Failed to stop init.d service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Init.d service %s stopped successfully", serviceName)) postLog.Debug(fmt.Sprintf("[StopInstanceHandler] Init.d service %s stopped successfully", serviceName))
default: 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 return
} }
handlers.SendSuccessResponse(w, "Instance stopped successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Instance stopped successfully", map[string]interface{}{
"instanceID": instanceID, "instanceID": instanceID,
"serviceName": serviceName, "serviceName": serviceName,
}) })
@@ -732,9 +732,9 @@ func StopInstanceHandler(w http.ResponseWriter, r *http.Request) {
} }
func RestartInstanceHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[RestartInstanceHandler] Auth failed: %v", err))
return return
} }
@@ -742,7 +742,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -750,36 +750,36 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceIDStr := getStringFromMap(reqMap, "instanceID") instanceIDStr := getStringFromMap(reqMap, "instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { 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)) postLog.Error(fmt.Sprintf("[RestartInstanceHandler] User %d tried to restart a not existed instance: %d", userID, instanceID))
return return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { 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)) postLog.Error(fmt.Sprintf("[RestartInstanceHandler] User %d tried to restart instance %d that does not belong to them", userID, instanceID))
return return
} }
@@ -788,7 +788,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) {
serviceName, err := database.GetServiceNameByInstanceID(instanceID) serviceName, err := database.GetServiceNameByInstanceID(instanceID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to get service name: %v", err)) 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 return
} }
@@ -796,7 +796,7 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) {
case "windows": case "windows":
if err := service.RestartWindowsService(serviceName); err != nil { if err := service.RestartWindowsService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to restart Windows service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Windows service %s restarted successfully", serviceName)) 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": case "systemd":
if err := service.RestartSystemdService(serviceName); err != nil { if err := service.RestartSystemdService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to restart systemd service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Systemd service %s restarted successfully", serviceName)) 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": case "init.d":
if err := service.RestartInitDService(serviceName); err != nil { if err := service.RestartInitDService(serviceName); err != nil {
postLog.Error(fmt.Sprintf("[RestartInstanceHandler] Failed to restart init.d service %s: %v", serviceName, err)) 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 return
} }
postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Init.d service %s restarted successfully", serviceName)) postLog.Debug(fmt.Sprintf("[RestartInstanceHandler] Init.d service %s restarted successfully", serviceName))
default: 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 return
} }
handlers.SendSuccessResponse(w, "Instance restarted successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Instance restarted successfully", map[string]interface{}{
"instanceID": instanceID, "instanceID": instanceID,
"serviceName": serviceName, "serviceName": serviceName,
}) })
@@ -830,9 +830,9 @@ func RestartInstanceHandler(w http.ResponseWriter, r *http.Request) {
} }
func GetInstanceStatusHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[GetInstanceStatusHandler] Auth failed: %v", err))
return return
} }
@@ -840,45 +840,45 @@ func GetInstanceStatusHandler(w http.ResponseWriter, r *http.Request) {
queryParams := r.URL.Query() queryParams := r.URL.Query()
instanceIDStr := queryParams.Get("instanceID") instanceIDStr := queryParams.Get("instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found")
return return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[GetInstanceStatusHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found")
return return
} }
err = service.IsInstanceRunning(instanceID) err = service.IsInstanceRunning(instanceID)
isRunning := err == nil 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, "instanceID": instanceID,
"isRunning": isRunning, "isRunning": isRunning,
}) })
} }
func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[GetInstanceInfoHandler] Auth failed: %v", err))
return return
} }
@@ -886,57 +886,57 @@ func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) {
queryParams := r.URL.Query() queryParams := r.URL.Query()
instanceIDStr := queryParams.Get("instanceID") instanceIDStr := queryParams.Get("instanceID")
if instanceIDStr == "" { if instanceIDStr == "" {
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
instanceID, err := strconv.Atoi(instanceIDStr) instanceID, err := strconv.Atoi(instanceIDStr)
if err != nil { if err != nil {
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceID format")
return return
} }
instance, err := database.DBQueryFrpcInstanceByID(instanceID) instance, err := database.DBQueryFrpcInstanceByID(instanceID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
handlers.SendErrorResponse(w, http.StatusNotFound, "Instance not found") utils.SendErrorResponse(w, http.StatusNotFound, "Instance not found")
return return
} }
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
handlers.SendErrorResponse(w, http.StatusForbidden, "Instance not found") utils.SendErrorResponse(w, http.StatusForbidden, "Instance not found")
return return
} }
user, err := database.GetUserByID(userID) user, err := database.GetUserByID(userID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to get user info: %v", err)) 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 return
} }
serviceName, err := database.GetServiceNameByInstanceID(instanceID) serviceName, err := database.GetServiceNameByInstanceID(instanceID)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to get service name: %v", err)) 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 return
} }
configContent, err := os.ReadFile(instance.ConfigPath) configContent, err := os.ReadFile(instance.ConfigPath)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to read config file: %v", err)) 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 return
} }
frpcConfig, err := config.DecodeFrpcConfig(string(configContent)) frpcConfig, err := config.DecodeFrpcConfig(string(configContent))
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[GetInstanceInfoHandler] Failed to decode frpc config: %v", err)) 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 return
} }
@@ -960,5 +960,5 @@ func GetInstanceInfoHandler(w http.ResponseWriter, r *http.Request) {
response["serverPort"] = frpcConfig.Global["serverPort"] response["serverPort"] = frpcConfig.Global["serverPort"]
} }
handlers.SendSuccessResponse(w, "Instance info retrieved successfully", response) utils.SendSuccessResponse(w, "Instance info retrieved successfully", response)
} }
+48 -48
View File
@@ -1,4 +1,4 @@
package instance package handlers
import ( import (
"encoding/json" "encoding/json"
@@ -10,16 +10,16 @@ import (
"super-frpc/config" "super-frpc/config"
"super-frpc/database" "super-frpc/database"
"super-frpc/handlers" "super-frpc/utils"
"super-frpc/postLog" "super-frpc/postLog"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
) )
func CreateProxyHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[CreateProxyHandler] Auth failed: %v", err))
return return
} }
@@ -27,7 +27,7 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -35,21 +35,21 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceID := getStringFromMap(reqMap, "instanceID") instanceID := getStringFromMap(reqMap, "instanceID")
if instanceID == "" { if instanceID == "" {
postLog.Error("[CreateProxyHandler] instanceID is required") postLog.Error("[CreateProxyHandler] instanceID is required")
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{}) proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{})
if !ok { if !ok {
postLog.Error("[CreateProxyHandler] Invalid proxyInfo format") postLog.Error("[CreateProxyHandler] Invalid proxyInfo format")
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format")
return return
} }
@@ -64,7 +64,7 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) {
if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" || if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" ||
proxyInfo.LocalPort == 0 || proxyInfo.RemotePort == 0 { proxyInfo.LocalPort == 0 || proxyInfo.RemotePort == 0 {
postLog.Error("[CreateProxyHandler] Missing required fields in proxyInfo") 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 return
} }
@@ -73,37 +73,37 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) {
instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Instance not found for user %d", 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 return
} }
configContent, err := os.ReadFile(instance.ConfigPath) configContent, err := os.ReadFile(instance.ConfigPath)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) 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 return
} }
updatedContent, err := config.AddFrpcProxy(string(configContent), proxyInfo) updatedContent, err := config.AddFrpcProxy(string(configContent), proxyInfo)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[CreateProxyHandler] Failed to add proxy: %v", err)) 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 return
} }
if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil { 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)) 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 return
} }
handlers.SendSuccessResponse(w, "Proxy created successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Proxy created successfully", map[string]interface{}{
"instanceID": instance.ID, "instanceID": instance.ID,
"configPath": instance.ConfigPath, "configPath": instance.ConfigPath,
"proxyName": proxyInfo.Name, "proxyName": proxyInfo.Name,
@@ -112,9 +112,9 @@ func CreateProxyHandler(w http.ResponseWriter, r *http.Request) {
} }
func ModifyProxyHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[ModifyProxyHandler] Auth failed: %v", err))
return return
} }
@@ -122,7 +122,7 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -130,21 +130,21 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceID := getStringFromMap(reqMap, "instanceID") instanceID := getStringFromMap(reqMap, "instanceID")
if instanceID == "" { if instanceID == "" {
postLog.Error("[ModifyProxyHandler] instanceID is required") postLog.Error("[ModifyProxyHandler] instanceID is required")
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{}) proxyInfoMap, ok := reqMap["proxyInfo"].(map[string]interface{})
if !ok { if !ok {
postLog.Error("[ModifyProxyHandler] Invalid proxyInfo format") postLog.Error("[ModifyProxyHandler] Invalid proxyInfo format")
handlers.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format") utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid proxyInfo format")
return return
} }
@@ -159,7 +159,7 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) {
if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" || if proxyInfo.Name == "" || proxyInfo.Type == "" || proxyInfo.LocalIP == "" ||
proxyInfo.LocalPort == 0 || proxyInfo.RemotePort == 0 { proxyInfo.LocalPort == 0 || proxyInfo.RemotePort == 0 {
postLog.Error("[ModifyProxyHandler] Missing required fields in proxyInfo") 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 return
} }
@@ -168,37 +168,37 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) {
instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Instance not found for user %d", 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 return
} }
configContent, err := os.ReadFile(instance.ConfigPath) configContent, err := os.ReadFile(instance.ConfigPath)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) 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 return
} }
updatedContent, err := config.ModifyFrpcProxy(string(configContent), proxyInfo) updatedContent, err := config.ModifyFrpcProxy(string(configContent), proxyInfo)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ModifyProxyHandler] Failed to modify proxy: %v", err)) 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 return
} }
if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil { 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)) 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 return
} }
handlers.SendSuccessResponse(w, "Proxy modified successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Proxy modified successfully", map[string]interface{}{
"instanceID": instance.ID, "instanceID": instance.ID,
"configPath": instance.ConfigPath, "configPath": instance.ConfigPath,
"proxyName": proxyInfo.Name, "proxyName": proxyInfo.Name,
@@ -207,9 +207,9 @@ func ModifyProxyHandler(w http.ResponseWriter, r *http.Request) {
} }
func DeleteProxyHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[DeleteProxyHandler] Auth failed: %v", err))
return return
} }
@@ -217,7 +217,7 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to read request body: %v", err)) 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 return
} }
defer r.Body.Close() defer r.Body.Close()
@@ -225,21 +225,21 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) {
var reqMap map[string]interface{} var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil { if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to unmarshal request body: %v", err)) 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 return
} }
instanceID := getStringFromMap(reqMap, "instanceID") instanceID := getStringFromMap(reqMap, "instanceID")
if instanceID == "" { if instanceID == "" {
postLog.Error("[DeleteProxyHandler] instanceID is required") postLog.Error("[DeleteProxyHandler] instanceID is required")
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
proxyName := getStringFromMap(reqMap, "proxyName") proxyName := getStringFromMap(reqMap, "proxyName")
if proxyName == "" { if proxyName == "" {
postLog.Error("[DeleteProxyHandler] proxyName is required") postLog.Error("[DeleteProxyHandler] proxyName is required")
handlers.SendErrorResponse(w, http.StatusBadRequest, "proxyName is required") utils.SendErrorResponse(w, http.StatusBadRequest, "proxyName is required")
return return
} }
@@ -248,37 +248,37 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) {
instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Instance not found for user %d", 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 return
} }
configContent, err := os.ReadFile(instance.ConfigPath) configContent, err := os.ReadFile(instance.ConfigPath)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) 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 return
} }
updatedContent, err := config.RemoveFrpcProxy(string(configContent), proxyName) updatedContent, err := config.RemoveFrpcProxy(string(configContent), proxyName)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[DeleteProxyHandler] Failed to remove proxy: %v", err)) 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 return
} }
if err := os.WriteFile(instance.ConfigPath, []byte(updatedContent), 0644); err != nil { 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)) 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 return
} }
handlers.SendSuccessResponse(w, "Proxy deleted successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Proxy deleted successfully", map[string]interface{}{
"instanceID": instance.ID, "instanceID": instance.ID,
"configPath": instance.ConfigPath, "configPath": instance.ConfigPath,
"proxyName": proxyName, "proxyName": proxyName,
@@ -287,9 +287,9 @@ func DeleteProxyHandler(w http.ResponseWriter, r *http.Request) {
} }
func ListProxiesHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[ListProxiesHandler] Auth failed: %v", err))
return return
} }
@@ -298,7 +298,7 @@ func ListProxiesHandler(w http.ResponseWriter, r *http.Request) {
instanceID := queryParams.Get("instanceID") instanceID := queryParams.Get("instanceID")
if instanceID == "" { if instanceID == "" {
postLog.Error("[ListProxiesHandler] instanceID is required") postLog.Error("[ListProxiesHandler] instanceID is required")
handlers.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") utils.SendErrorResponse(w, http.StatusBadRequest, "instanceID is required")
return return
} }
@@ -307,27 +307,27 @@ func ListProxiesHandler(w http.ResponseWriter, r *http.Request) {
instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt) instance, err = database.DBQueryFrpcInstanceByID(instanceIDInt)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ListProxiesHandler] Failed to query instance: %v", err)) 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 return
} }
if instance.UserID != userID { if instance.UserID != userID {
postLog.Error(fmt.Sprintf("[ListProxiesHandler] Instance not found for user %d", 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 return
} }
configContent, err := os.ReadFile(instance.ConfigPath) configContent, err := os.ReadFile(instance.ConfigPath)
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("[ListProxiesHandler] Failed to read config file %s: %v", instance.ConfigPath, err)) 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 return
} }
var cfg config.FrpcConfig var cfg config.FrpcConfig
if _, err := toml.Decode(string(configContent), &cfg); err != nil { if _, err := toml.Decode(string(configContent), &cfg); err != nil {
postLog.Error(fmt.Sprintf("[ListProxiesHandler] Failed to parse config: %v", err)) 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 return
} }
@@ -343,7 +343,7 @@ func ListProxiesHandler(w http.ResponseWriter, r *http.Request) {
proxyList[i] = proxyData proxyList[i] = proxyData
} }
handlers.SendSuccessResponse(w, "Proxies listed successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "Proxies listed successfully", map[string]interface{}{
"instanceID": instance.ID, "instanceID": instance.ID,
"proxyCount": len(proxyList), "proxyCount": len(proxyList),
"proxies": proxyList, "proxies": proxyList,
+18
View File
@@ -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
}
}
+76 -76
View File
@@ -1,4 +1,4 @@
package user package handlers
import ( import (
"encoding/json" "encoding/json"
@@ -8,7 +8,7 @@ import (
"super-frpc/database" "super-frpc/database"
"super-frpc/global" "super-frpc/global"
"super-frpc/handlers" "super-frpc/utils"
"super-frpc/postLog" "super-frpc/postLog"
"super-frpc/session" "super-frpc/session"
) )
@@ -50,20 +50,20 @@ type RemoveSessionRequest struct {
func RegisterHandler(w http.ResponseWriter, r *http.Request) { func RegisterHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost { 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)) postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request method: %s", r.Method))
return return
} }
if !session.ValidateTimeStamp(r.Header, global.Is.Debug) { 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"))) postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid or missing X-Timestamp in header: %s", r.Header.Get("X-Timestamp")))
return return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[RegisterHandler] Failed to read request body: %v", err))
return return
} }
@@ -71,32 +71,32 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) {
var req RegisterRequest var req RegisterRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request format: %v", err))
return return
} }
if req.Username == "" || req.Passwd == "" { 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") postLog.Warning("[RegisterHandler] New user registration failed: username or password is empty")
return return
} }
if !isValidInput(req.Username) || !isValidInput(req.Passwd) { 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)) postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd))
return return
} }
if !session.IsValidPassword(req.Passwd) { 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)) postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: password \"%s\" does not meet complexity requirements", req.Passwd))
return return
} }
userList, err := database.DBListUsers() userList, err := database.DBListUsers()
if err != nil { 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)) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to list users: %v", err))
return 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) userID, err := database.AddUser(req.Username, req.Passwd, newUserType, session.HashPassword, session.IsValidPassword)
if err != nil { 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)) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to register user \"%s\": %v", req.Username, err))
return return
} }
user, err := database.GetUserByID(userID) user, err := database.GetUserByID(userID)
if err != nil { 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)) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to retrieve user \"%s\" after registration: %v", req.Username, err))
return return
} }
handlers.SendSuccessResponse(w, "user registered successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "user registered successfully", map[string]interface{}{
"userID": user.UserID, "userID": user.UserID,
"username": user.Username, "username": user.Username,
"type": user.Type, "type": user.Type,
@@ -130,19 +130,19 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) {
func LoginHandler(w http.ResponseWriter, r *http.Request) { func LoginHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost { 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)) postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request method: %s", r.Method))
return return
} }
if !session.ValidateTimeStamp(r.Header, global.Is.Debug) { 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 return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[LoginHandler] Failed to read request body: %v", err))
return return
} }
@@ -150,57 +150,57 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
var req LoginRequest var req LoginRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request format: %v", err))
return return
} }
if req.Username == "" || req.Passwd == "" { 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") postLog.Warning("[LoginHandler] Login failed: username or password is empty")
return return
} }
if !isValidInput(req.Username) || !isValidInput(req.Passwd) { 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)) postLog.Debug(fmt.Sprintf("[LoginHandler] Login failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd))
return return
} }
user, err := database.GetUserByUsername(req.Username) user, err := database.GetUserByUsername(req.Username)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: User not exist \"%s\"", req.Username))
return return
} }
if !session.VerifyPassword(req.Passwd, user.Passwd) { 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)) postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: invalid password for user \"%s\"", req.Username))
return return
} }
existingTokenInfo, err := session.GetTokenInfo(user.UserID) existingTokenInfo, err := session.GetTokenInfo(user.UserID)
if err == nil && existingTokenInfo != nil { 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)) postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: user \"%s\" is already logged in", req.Username))
return return
} }
token, err := session.GenerateToken(user.UserID) token, err := session.GenerateToken(user.UserID)
if err != nil { 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)) postLog.Error(fmt.Sprintf("[LoginHandler] Failed to generate token for user \"%s\": %v", req.Username, err))
return return
} }
if err := session.JoinSession(user.UserID, user.Username, token); err != nil { 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)) postLog.Error(fmt.Sprintf("[LoginHandler] Failed to create session for user \"%s\": %v", req.Username, err))
return return
} }
handlers.SendSuccessResponse(w, "Login successful", map[string]interface{}{ utils.SendSuccessResponse(w, "Login successful", map[string]interface{}{
"token": token, "token": token,
"userID": user.UserID, "userID": user.UserID,
"username": user.Username, "username": user.Username,
@@ -210,9 +210,9 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
} }
func LogoutHandler(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 { 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)) postLog.Warning(fmt.Sprintf("[LogoutHandler] Auth failed: %v", err))
return return
} }
@@ -229,32 +229,32 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request) {
sessionTokenMux.RUnlock() sessionTokenMux.RUnlock()
if sessionID == "" { 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))) postLog.Warning(fmt.Sprintf("[LogoutHandler] Session not found for token from user [%d]%s", userID, session.GetUsernameByID(userID)))
return return
} }
if err := session.RemoveSession(sessionID); err != nil { 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)) postLog.Error(fmt.Sprintf("[LogoutHandler] Failed to logout user [%d]%s: %v", userID, session.GetUsernameByID(userID), err))
return 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))) postLog.Info(fmt.Sprintf("[LogoutHandler] User [%d]%s Logout successful", userID, session.GetUsernameByID(userID)))
} }
func RemoveSessionHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[RemoveSessionHandler] Auth failed: %v", err))
return return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[RemoveSessionHandler] Failed to read request body: %v", err))
return return
} }
@@ -262,38 +262,38 @@ func RemoveSessionHandler(w http.ResponseWriter, r *http.Request) {
var req RemoveSessionRequest var req RemoveSessionRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[RemoveSessionHandler] Invalid request format: %v", err))
return return
} }
if req.SessionID == "" { 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") postLog.Warning("[RemoveSessionHandler] SessionID is empty")
return return
} }
if err := session.RemoveSession(req.SessionID); err != nil { 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)) postLog.Error(fmt.Sprintf("[RemoveSessionHandler] Failed to remove session %s: %v", req.SessionID, err))
return return
} }
postLog.Info(fmt.Sprintf("[RemoveSessionHandler] User [%d]%s removed session %s", userID, session.GetUsernameByID(userID), req.SessionID)) 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) { 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 { 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)) postLog.Warning(fmt.Sprintf("[CreateUserHandler] Auth failed: %v", err))
return return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[CreateUserHandler] Failed to read request body: %v", err))
return return
} }
@@ -301,38 +301,38 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest var req CreateUserRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[CreateUserHandler] Invalid request format: %v", err))
return return
} }
if req.Username == "" || req.Passwd == "" || req.Type == "" { 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") postLog.Warning("[CreateUserHandler] CreateUser failed: username, password, or type is empty")
return return
} }
if req.Type != "admin" && req.Type != "user" && req.Type != "superuser" { 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)) postLog.Warning(fmt.Sprintf("[CreateUserHandler] CreateUser failed: invalid type: %s", req.Type))
return return
} }
userID, err := database.AddUser(req.Username, req.Passwd, req.Type, session.HashPassword, session.IsValidPassword) userID, err := database.AddUser(req.Username, req.Passwd, req.Type, session.HashPassword, session.IsValidPassword)
if err != nil { 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)) postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to register user \"%s\": %v", req.Username, err))
return return
} }
user, err := database.GetUserByID(userID) user, err := database.GetUserByID(userID)
if err != nil { 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)) postLog.Error(fmt.Sprintf("[CreateUserHandler] Failed to retrieve user \"%s\" after creation: %v", req.Username, err))
return return
} }
handlers.SendSuccessResponse(w, "User created successfully", map[string]interface{}{ utils.SendSuccessResponse(w, "User created successfully", map[string]interface{}{
"userID": user.UserID, "userID": user.UserID,
"username": user.Username, "username": user.Username,
"type": user.Type, "type": user.Type,
@@ -341,15 +341,15 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
} }
func ModifyUserHandler(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 { 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 return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[ModifyUserHandler] Failed to read request body: %v", err))
return return
} }
@@ -358,43 +358,43 @@ func ModifyUserHandler(w http.ResponseWriter, r *http.Request) {
var req ModifyUserRequest var req ModifyUserRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[ModifyUserHandler] Invalid request format: %v", err))
return return
} }
if req.UserID == 0 { 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") postLog.Warning("[ModifyUserHandler] ModifyUser failed: UserID is empty")
return return
} }
if req.Username == "" { 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") postLog.Warning("[ModifyUserHandler] ModifyUser failed: username is empty")
return return
} }
if err := database.DBUpdateUser(req.UserID, req.Username, req.Passwd); err != nil { 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)) postLog.Error(fmt.Sprintf("[ModifyUserHandler] Failed to update user [%d]: %v", req.UserID, err))
return 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)) 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) { 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 { 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)) postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] Auth failed: %v", err))
return return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] Failed to read request body: %v", err))
return return
} }
@@ -403,40 +403,40 @@ func ModifyUserTypeHandler(w http.ResponseWriter, r *http.Request) {
var req ModifyUserTypeRequest var req ModifyUserTypeRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] Invalid request format: %v", err))
return return
} }
if req.UserID == 0 { 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") postLog.Warning("[ModifyUserTypeHandler] ModifyUserType failed: UserID is empty")
return return
} }
if req.Type != "admin" && req.Type != "visitor" && req.Type != "superuser" { 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)) postLog.Warning(fmt.Sprintf("[ModifyUserTypeHandler] ModifyUserType failed: invalid type: %s", req.Type))
return return
} }
if err := database.DBUpdateUserType(req.UserID, req.Type); err != nil { 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)) postLog.Error(fmt.Sprintf("[ModifyUserTypeHandler] Failed to update user type [%d]: %v", req.UserID, err))
return 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)) 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) { 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 { 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)) postLog.Warning(fmt.Sprintf("[RemoveUserHandler] Auth failed: %v", err))
return return
} }
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
if err != nil { 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)) postLog.Warning(fmt.Sprintf("[RemoveUserHandler] Failed to read request body: %v", err))
return return
} }
@@ -444,51 +444,51 @@ func RemoveUserHandler(w http.ResponseWriter, r *http.Request) {
var req RemoveUserRequest var req RemoveUserRequest
if err := json.Unmarshal(body, &req); err != nil { 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)) postLog.Warning(fmt.Sprintf("[RemoveUserHandler] Invalid request format: %v", err))
return return
} }
if req.TargetUserID == 0 { 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") postLog.Warning("[RemoveUserHandler] RemoveUser failed: TargetUserID is empty")
return return
} }
if err := database.RemoveUser(req.TargetUserID); err != nil { 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)) postLog.Error(fmt.Sprintf("[RemoveUserHandler] Failed to remove user [%d]: %v", req.TargetUserID, err))
return return
} }
handlers.SendSuccessResponse(w, "User removed successfully", nil) utils.SendSuccessResponse(w, "User removed successfully", nil)
} }
func ListUserHandler(w http.ResponseWriter, r *http.Request) { 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 { 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)) postLog.Warning(fmt.Sprintf("[ListUserHandler] Auth failed: %v", err))
return return
} }
userList, err := database.DBListUsers() userList, err := database.DBListUsers()
if err != nil { 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)) postLog.Error(fmt.Sprintf("[ListUserHandler] Failed to list users: %v", err))
return 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) { 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 { 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)) postLog.Warning(fmt.Sprintf("[ListActiveSessionsHandler] Auth failed: %v", err))
return return
} }
sessions := session.ListActiveSessions() sessions := session.ListActiveSessions()
postLog.Debug(fmt.Sprintf("[ListActiveSessionsHandler] User [%d]%s listed %d active sessions", userID, session.GetUsernameByID(userID), len(sessions))) 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 { func isValidInput(input string) bool {
+19 -22
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/json"
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
@@ -10,10 +11,10 @@ import (
"super-frpc/database" "super-frpc/database"
"super-frpc/frpLogger" "super-frpc/frpLogger"
"super-frpc/global" "super-frpc/global"
"super-frpc/handlers"
"super-frpc/postLog" "super-frpc/postLog"
"super-frpc/session"
"super-frpc/service" "super-frpc/service"
"super-frpc/session"
"super-frpc/utils"
"super-frpc/watchdog" "super-frpc/watchdog"
"syscall" "syscall"
"time" "time"
@@ -27,24 +28,23 @@ func main() {
flag.Parse() flag.Parse()
if _, err := os.Stat(*configPath); os.IsNotExist(err) { if _, err := os.Stat(*configPath); os.IsNotExist(err) {
defaultConfig := `{ // Load the default config
"listenAddr": "0.0.0.0", configData, err := json.MarshalIndent(global.CurrentConfig, "", " ")
"listenPort": "8080", if err != nil {
"configDir": "./configs" postLog.Warning(fmt.Sprintf("Failed to marshal default config: %v", err))
}` } else if err := os.WriteFile(*configPath, configData, 0644); err != nil {
if err := os.WriteFile(*configPath, []byte(defaultConfig), 0644); err != nil {
postLog.Warning(fmt.Sprintf("Failed to create default config file: %v", err)) postLog.Warning(fmt.Sprintf("Failed to create default config file: %v", err))
} }
postLog.Info(fmt.Sprintf("Created default config file at %s", *configPath)) 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 { if err != nil {
postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err)) postLog.Fatal(fmt.Sprintf("Failed to load config: %v", err))
} }
postLog.SetDebugMode(cfg.Debug) postLog.SetDebugMode(global.CurrentConfig.Debug)
global.Is.Debug = cfg.Debug global.Is.Debug = global.CurrentConfig.Debug
if err := postLog.InitLogsDatabase(*dbPath_log); err != nil { if err := postLog.InitLogsDatabase(*dbPath_log); err != nil {
postLog.Fatal(fmt.Sprintf("Failed to initialize logs database: %v", err)) postLog.Fatal(fmt.Sprintf("Failed to initialize logs database: %v", err))
@@ -61,12 +61,9 @@ func main() {
} }
frpLogger.SetDatabase(global.ConfigDB, global.FrpcDB) frpLogger.SetDatabase(global.ConfigDB, global.FrpcDB)
frpLogger.SetDebugMode(cfg.Debug) frpLogger.SetDebugMode(global.CurrentConfig.Debug)
_, err = config.GetConfig() config.GetConfig()
if err != nil {
postLog.Fatal(fmt.Sprintf("Failed to get config: %v", err))
}
postLog.InitLogBroadcaster() postLog.InitLogBroadcaster()
@@ -76,15 +73,15 @@ func main() {
if err != nil { if err != nil {
postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err)) postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err))
} else { } else {
if !watchdog.Connect("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", cfg.Watchdog.Port)) postLog.Error(fmt.Sprintf("Failed to connect to Watchdog at %s:%d", "127.0.0.1", global.CurrentConfig.Watchdog.Port))
} else { } 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 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{ server := &http.Server{
Addr: addr, Addr: addr,
ReadTimeout: 15 * time.Second, ReadTimeout: 15 * time.Second,
@@ -139,9 +136,9 @@ func GetStatusHandler(w http.ResponseWriter, r *http.Request) {
if global.Is.WatchdogConnected { if global.Is.WatchdogConnected {
statusInfo["WatchdogStatus"] = "Online" statusInfo["WatchdogStatus"] = "Online"
} }
handlers.SendSuccessResponse(w, "getStatus", statusInfo) utils.SendSuccessResponse(w, "getStatus", statusInfo)
} }
func GetSoftwareInfoHandler(w http.ResponseWriter, r *http.Request) { func GetSoftwareInfoHandler(w http.ResponseWriter, r *http.Request) {
handlers.SendSuccessResponse(w, "getSoftwareInfo", global.Software) utils.SendSuccessResponse(w, "getSoftwareInfo", global.Software)
} }
+26 -27
View File
@@ -4,11 +4,10 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"super-frpc/frpLogger" "super-frpc/frpLogger"
"super-frpc/handlers" "super-frpc/utils"
"super-frpc/instance"
"super-frpc/postLog" "super-frpc/postLog"
"super-frpc/session" "super-frpc/session"
"super-frpc/user" "super-frpc/handlers"
) )
func setupRoutes() { func setupRoutes() {
@@ -17,33 +16,33 @@ func setupRoutes() {
systemLogHandler := postLog.NewLogSocketHandler(postLog.GetLogBroadcaster()) systemLogHandler := postLog.NewLogSocketHandler(postLog.GetLogBroadcaster())
http.HandleFunc("/system/getLogs", systemLogHandler.Handle) http.HandleFunc("/system/getLogs", systemLogHandler.Handle)
http.HandleFunc("/register", user.RegisterHandler) http.HandleFunc("/register", handlers.RegisterHandler)
http.HandleFunc("/login", user.LoginHandler) http.HandleFunc("/login", handlers.LoginHandler)
http.HandleFunc("/logout", user.LogoutHandler) http.HandleFunc("/logout", handlers.LogoutHandler)
http.HandleFunc("/userMgr/create", user.CreateUserHandler) http.HandleFunc("/userMgr/create", handlers.CreateUserHandler)
http.HandleFunc("/userMgr/remove", user.RemoveUserHandler) http.HandleFunc("/userMgr/remove", handlers.RemoveUserHandler)
http.HandleFunc("/userMgr/list", user.ListUserHandler) http.HandleFunc("/userMgr/list", handlers.ListUserHandler)
http.HandleFunc("/userMgr/modify", user.ModifyUserHandler) http.HandleFunc("/userMgr/modify", handlers.ModifyUserHandler)
http.HandleFunc("/userMgr/modifyType", user.ModifyUserTypeHandler) http.HandleFunc("/userMgr/modifyType", handlers.ModifyUserTypeHandler)
http.HandleFunc("/sessionMgr/list", user.ListActiveSessionsHandler) http.HandleFunc("/sessionMgr/list", handlers.ListActiveSessionsHandler)
http.HandleFunc("/sessionMgr/remove", user.RemoveSessionHandler) http.HandleFunc("/sessionMgr/remove", handlers.RemoveSessionHandler)
http.HandleFunc("/frpcAct/instanceMgr/create", instance.CreateInstanceHandler) http.HandleFunc("/frpcAct/instanceMgr/create", handlers.CreateInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/delete", instance.DeleteInstanceHandler) http.HandleFunc("/frpcAct/instanceMgr/delete", handlers.DeleteInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/modify", instance.ModifyInstanceHandler) http.HandleFunc("/frpcAct/instanceMgr/modify", handlers.ModifyInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/list", instance.ListInstancesHandler) http.HandleFunc("/frpcAct/instanceMgr/list", handlers.ListInstancesHandler)
http.HandleFunc("/frpcAct/instanceMgr/start", instance.StartInstanceHandler) http.HandleFunc("/frpcAct/instanceMgr/start", handlers.StartInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/stop", instance.StopInstanceHandler) http.HandleFunc("/frpcAct/instanceMgr/stop", handlers.StopInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/restart", instance.RestartInstanceHandler) http.HandleFunc("/frpcAct/instanceMgr/restart", handlers.RestartInstanceHandler)
http.HandleFunc("/frpcAct/instanceMgr/status", instance.GetInstanceStatusHandler) http.HandleFunc("/frpcAct/instanceMgr/status", handlers.GetInstanceStatusHandler)
http.HandleFunc("/frpcAct/instanceMgr/getInfo", instance.GetInstanceInfoHandler) http.HandleFunc("/frpcAct/instanceMgr/getInfo", handlers.GetInstanceInfoHandler)
http.HandleFunc("/frpcAct/instanceMgr/logs", frpLogger.NewInstanceLogHandler(session.ValidateTokenFromMap).ServeHTTP) http.HandleFunc("/frpcAct/instanceMgr/logs", frpLogger.NewInstanceLogHandler(session.ValidateTokenFromMap).ServeHTTP)
http.HandleFunc("/frpcAct/proxyMgr/create", instance.CreateProxyHandler) http.HandleFunc("/frpcAct/proxyMgr/create", handlers.CreateProxyHandler)
http.HandleFunc("/frpcAct/proxyMgr/modify", instance.ModifyProxyHandler) http.HandleFunc("/frpcAct/proxyMgr/modify", handlers.ModifyProxyHandler)
http.HandleFunc("/frpcAct/proxyMgr/delete", instance.DeleteProxyHandler) http.HandleFunc("/frpcAct/proxyMgr/delete", handlers.DeleteProxyHandler)
http.HandleFunc("/frpcAct/proxyMgr/list", instance.ListProxiesHandler) http.HandleFunc("/frpcAct/proxyMgr/list", handlers.ListProxiesHandler)
http.HandleFunc("/", NotFoundHandler) http.HandleFunc("/", NotFoundHandler)
@@ -53,5 +52,5 @@ func setupRoutes() {
func NotFoundHandler(w http.ResponseWriter, r *http.Request) { func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
postLog.Error(fmt.Sprintf("Route not found: %s %s", r.Method, r.URL.Path)) 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")
} }
+3 -13
View File
@@ -9,27 +9,17 @@ import (
"strconv" "strconv"
"strings" "strings"
"super-frpc/config"
"super-frpc/database" "super-frpc/database"
"super-frpc/global"
"super-frpc/postLog" "super-frpc/postLog"
) )
func GetConfigDir() (string, error) { func GetConfigDir() (string, error) {
cfg, err := config.GetConfig() return global.CurrentConfig.InstancePath, nil
if err != nil {
postLog.Error(fmt.Sprintf("[GetConfigDir] Failed to get config: %v", err))
return "", err
}
return cfg.InstancePath, nil
} }
func GetFrpcPath() (string, error) { func GetFrpcPath() (string, error) {
cfg, err := config.GetConfig() return global.CurrentConfig.FrpcPath, nil
if err != nil {
postLog.Error(fmt.Sprintf("[GetFrpcPath] Failed to get config: %v", err))
return "", err
}
return cfg.FrpcPath, nil
} }
func GetInitSystem() string { func GetInitSystem() string {
+9 -1
View File
@@ -1,4 +1,4 @@
package handlers package utils
import ( import (
"encoding/json" "encoding/json"
@@ -19,6 +19,8 @@ type Response struct {
Data interface{} `json:"data,omitempty"` 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{}) { func SendErrorResponse(w http.ResponseWriter, statusCode int, message string, data ...interface{}) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode) w.WriteHeader(statusCode)
@@ -37,6 +39,8 @@ func SendErrorResponse(w http.ResponseWriter, statusCode int, message string, da
w.Write(jsonResp) 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{}) { func SendSuccessResponse(w http.ResponseWriter, message string, data interface{}) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
@@ -53,6 +57,10 @@ func SendSuccessResponse(w http.ResponseWriter, message string, data interface{}
w.Write(jsonResp) 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) { func Auth(w http.ResponseWriter, r *http.Request, targetMethod string, allowedUserLevels ...string) (int, error) {
if r.Method != targetMethod { if r.Method != targetMethod {
return 0, fmt.Errorf("Method not allowed: %s", targetMethod) return 0, fmt.Errorf("Method not allowed: %s", targetMethod)