mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-01-13 01:02:46 +00:00
156 lines
3.7 KiB
Go
156 lines
3.7 KiB
Go
// Package config provides node configuration management, including API key persistence.
|
|
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
)
|
|
|
|
// NodeConfig represents the node's configuration stored on disk.
|
|
type NodeConfig struct {
|
|
ApiKey string `json:"apiKey"` // API key for authentication with panel
|
|
PanelURL string `json:"panelUrl"` // Panel URL (optional, can be set via env var)
|
|
NodeAddress string `json:"nodeAddress"` // Node's own address (optional)
|
|
}
|
|
|
|
var (
|
|
config *NodeConfig
|
|
configMu sync.RWMutex
|
|
configPath string
|
|
)
|
|
|
|
// InitConfig initializes the configuration system and loads existing config if available.
|
|
// configDir is the directory where config file will be stored (e.g., "bin", "/app/bin").
|
|
func InitConfig(configDir string) error {
|
|
configMu.Lock()
|
|
defer configMu.Unlock()
|
|
|
|
// Determine config file path
|
|
if configDir == "" {
|
|
// Try common paths
|
|
possibleDirs := []string{"bin", "config", ".", "/app/bin", "/app/config"}
|
|
for _, dir := range possibleDirs {
|
|
if _, err := os.Stat(dir); err == nil {
|
|
configDir = dir
|
|
break
|
|
}
|
|
}
|
|
if configDir == "" {
|
|
configDir = "." // Fallback to current directory
|
|
}
|
|
}
|
|
|
|
configPath = filepath.Join(configDir, "node-config.json")
|
|
|
|
// Try to load existing config
|
|
if data, err := os.ReadFile(configPath); err == nil {
|
|
var loadedConfig NodeConfig
|
|
if err := json.Unmarshal(data, &loadedConfig); err == nil {
|
|
config = &loadedConfig
|
|
return nil
|
|
}
|
|
// If file exists but is invalid, we'll create a new one
|
|
}
|
|
|
|
// Create empty config if file doesn't exist
|
|
config = &NodeConfig{}
|
|
return nil
|
|
}
|
|
|
|
// GetConfig returns the current node configuration.
|
|
func GetConfig() *NodeConfig {
|
|
configMu.RLock()
|
|
defer configMu.RUnlock()
|
|
|
|
if config == nil {
|
|
return &NodeConfig{}
|
|
}
|
|
|
|
// Return a copy to prevent external modifications
|
|
return &NodeConfig{
|
|
ApiKey: config.ApiKey,
|
|
PanelURL: config.PanelURL,
|
|
NodeAddress: config.NodeAddress,
|
|
}
|
|
}
|
|
|
|
// SetApiKey sets the API key and saves it to disk.
|
|
// If an API key already exists, it will not be overwritten unless force is true.
|
|
func SetApiKey(apiKey string, force bool) error {
|
|
configMu.Lock()
|
|
defer configMu.Unlock()
|
|
|
|
if config == nil {
|
|
config = &NodeConfig{}
|
|
}
|
|
|
|
// Check if API key already exists
|
|
if config.ApiKey != "" && !force {
|
|
return fmt.Errorf("API key already exists. Use force=true to overwrite")
|
|
}
|
|
|
|
config.ApiKey = apiKey
|
|
return saveConfig()
|
|
}
|
|
|
|
// SetPanelURL sets the panel URL and saves it to disk.
|
|
func SetPanelURL(url string) error {
|
|
configMu.Lock()
|
|
defer configMu.Unlock()
|
|
|
|
if config == nil {
|
|
config = &NodeConfig{}
|
|
}
|
|
|
|
config.PanelURL = url
|
|
return saveConfig()
|
|
}
|
|
|
|
// SetNodeAddress sets the node address and saves it to disk.
|
|
func SetNodeAddress(address string) error {
|
|
configMu.Lock()
|
|
defer configMu.Unlock()
|
|
|
|
if config == nil {
|
|
config = &NodeConfig{}
|
|
}
|
|
|
|
config.NodeAddress = address
|
|
return saveConfig()
|
|
}
|
|
|
|
// saveConfig saves the current configuration to disk.
|
|
func saveConfig() error {
|
|
if configPath == "" {
|
|
return fmt.Errorf("config path not initialized, call InitConfig first")
|
|
}
|
|
|
|
// Ensure directory exists
|
|
dir := filepath.Dir(configPath)
|
|
if err := os.MkdirAll(dir, 0750); err != nil {
|
|
return fmt.Errorf("failed to create config directory: %w", err)
|
|
}
|
|
|
|
// Marshal config to JSON
|
|
data, err := json.MarshalIndent(config, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal config: %w", err)
|
|
}
|
|
|
|
// Write to file with proper permissions (readable/writable by owner only)
|
|
if err := os.WriteFile(configPath, data, 0600); err != nil {
|
|
return fmt.Errorf("failed to write config file: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetConfigPath returns the path to the config file.
|
|
func GetConfigPath() string {
|
|
configMu.RLock()
|
|
defer configMu.RUnlock()
|
|
return configPath
|
|
}
|