Files
backend/handlers/settings.go
NanamiAdmin ac51641e93 feat(settings): add settings management API endpoints
- Add GET /settings/get and POST /settings/set endpoints for managing system settings
- Implement config file persistence for settings changes
- Update config schema to include notification and webhook settings
- Add API documentation for new endpoints
- Move config path variables to global package for consistency
2026-04-23 12:43:11 +08:00

132 lines
4.2 KiB
Go

package handlers
import (
"encoding/json"
"fmt"
"io"
"net/http"
"super-frpc/config"
"super-frpc/global"
"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
}
key := r.URL.Query().Get("key")
if key != "" {
var value interface{}
switch key {
case "ListenAddr":
value = global.CurrentConfig.ListenAddr
case "ListenPort":
value = global.CurrentConfig.ListenPort
case "FrpcPath":
value = global.CurrentConfig.FrpcPath
case "InstancePath":
value = global.CurrentConfig.InstancePath
case "Debug":
value = global.CurrentConfig.Debug
case "Watchdog.Enabled":
value = global.CurrentConfig.Watchdog.Enabled
case "Watchdog.Port":
value = global.CurrentConfig.Watchdog.Port
case "Notification.Enabled":
value = global.CurrentConfig.Notification.Enabled
case "Notification.Method":
value = global.CurrentConfig.Notification.Method
case "Webhook.Method":
value = global.CurrentConfig.Webhook.Method
case "Webhook.URL":
value = global.CurrentConfig.Webhook.URL
case "Webhook.Headers":
value = global.CurrentConfig.Webhook.Headers
case "Webhook.Body":
value = global.CurrentConfig.Webhook.Body
default:
utils.SendErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("Unknown setting key: %s", key))
return
}
utils.SendSuccessResponse(w, "Setting retrieved successfully", map[string]interface{}{
"key": key,
"value": value,
})
} else {
settings := map[string]interface{}{
"ListenAddr": global.CurrentConfig.ListenAddr,
"ListenPort": global.CurrentConfig.ListenPort,
"FrpcPath": global.CurrentConfig.FrpcPath,
"InstancePath": global.CurrentConfig.InstancePath,
"Debug": global.CurrentConfig.Debug,
"Watchdog.Enabled": global.CurrentConfig.Watchdog.Enabled,
"Watchdog.Port": global.CurrentConfig.Watchdog.Port,
"Notification.Enabled": global.CurrentConfig.Notification.Enabled,
"Notification.Method": global.CurrentConfig.Notification.Method,
"Webhook.Method": global.CurrentConfig.Webhook.Method,
"Webhook.URL": global.CurrentConfig.Webhook.URL,
"Webhook.Headers": global.CurrentConfig.Webhook.Headers,
"Webhook.Body": global.CurrentConfig.Webhook.Body,
}
utils.SendSuccessResponse(w, "Settings retrieved successfully", settings)
}
}
func SetSettingsHandler(w http.ResponseWriter, r *http.Request) {
_, err := utils.Auth(w, r, http.MethodPost, "superuser", "admin")
if err != nil {
utils.SendErrorResponse(w, http.StatusUnauthorized, err.Error())
postLog.Warning(fmt.Sprintf("[SetSettingsHandler] Auth failed: %v", err))
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
postLog.Error(fmt.Sprintf("[SetSettingsHandler] Failed to read request body: %v", err))
utils.SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body")
return
}
defer r.Body.Close()
var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil {
postLog.Error(fmt.Sprintf("[SetSettingsHandler] Failed to unmarshal request body: %v", err))
utils.SendErrorResponse(w, http.StatusBadRequest, "Invalid request format")
return
}
for key, value := range reqMap {
postLog.Debug(fmt.Sprintf("[SetSettingsHandler] Modify setting: %s = %v", key, value))
switch key {
case "ListenAddr":
if v, ok := value.(string); ok {
global.CurrentConfig.ListenAddr = v
}
case "ListenPort":
if v, ok := value.(float64); ok {
global.CurrentConfig.ListenPort = fmt.Sprintf("%d", int(v))
}
default:
postLog.Warning(fmt.Sprintf("[SetSettingsHandler] Unknown setting key: %s", key))
}
}
err = config.SaveConfig()
if err != nil {
postLog.Error(fmt.Sprintf("[SetSettingsHandler] Failed to save config: %v", err))
utils.SendErrorResponse(w, http.StatusInternalServerError, "Failed to save config")
return
}
postLog.Debug("[SetSettingsHandler] Config saved successfully")
utils.SendSuccessResponse(w, "Config saved successfully", nil)
}