Files
picoclaw/web/backend/api/launcher_config.go
T
wenjie 7f7b4c430b feat(web): persist dashboard token in launcher config (#2304)
- add `launcher_token` to launcher config API/schema and save/load flow
- update dashboard token resolution order: env var -> launcher config -> random
- expose token source in startup logs and auth help metadata (including config path)
- add launcher token input to the config page and wire frontend form/API updates
- update login help/i18n copy and extend backend tests for new token-source behavior
2026-04-03 14:54:27 +08:00

91 lines
2.6 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"github.com/sipeed/picoclaw/web/backend/launcherconfig"
)
type launcherConfigPayload struct {
Port int `json:"port"`
Public bool `json:"public"`
AllowedCIDRs []string `json:"allowed_cidrs"`
LauncherToken string `json:"launcher_token"`
}
func (h *Handler) registerLauncherConfigRoutes(mux *http.ServeMux) {
mux.HandleFunc("GET /api/system/launcher-config", h.handleGetLauncherConfig)
mux.HandleFunc("PUT /api/system/launcher-config", h.handleUpdateLauncherConfig)
}
func (h *Handler) launcherConfigPath() string {
return launcherconfig.PathForAppConfig(h.configPath)
}
func (h *Handler) launcherFallbackConfig() launcherconfig.Config {
port := h.serverPort
if port <= 0 {
port = launcherconfig.DefaultPort
}
return launcherconfig.Config{
Port: port,
Public: h.serverPublic,
AllowedCIDRs: append([]string(nil), h.serverCIDRs...),
}
}
func (h *Handler) loadLauncherConfig() (launcherconfig.Config, error) {
return launcherconfig.Load(h.launcherConfigPath(), h.launcherFallbackConfig())
}
func (h *Handler) handleGetLauncherConfig(w http.ResponseWriter, r *http.Request) {
cfg, err := h.loadLauncherConfig()
if err != nil {
http.Error(w, fmt.Sprintf("Failed to load launcher config: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(launcherConfigPayload{
Port: cfg.Port,
Public: cfg.Public,
AllowedCIDRs: append([]string(nil), cfg.AllowedCIDRs...),
LauncherToken: cfg.LauncherToken,
})
}
func (h *Handler) handleUpdateLauncherConfig(w http.ResponseWriter, r *http.Request) {
var payload launcherConfigPayload
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
return
}
cfg := launcherconfig.Config{
Port: payload.Port,
Public: payload.Public,
AllowedCIDRs: append([]string(nil), payload.AllowedCIDRs...),
LauncherToken: strings.TrimSpace(payload.LauncherToken),
}
if err := launcherconfig.Validate(cfg); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := launcherconfig.Save(h.launcherConfigPath(), cfg); err != nil {
http.Error(w, fmt.Sprintf("Failed to save launcher config: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(launcherConfigPayload{
Port: cfg.Port,
Public: cfg.Public,
AllowedCIDRs: append([]string(nil), cfg.AllowedCIDRs...),
LauncherToken: cfg.LauncherToken,
})
}