From a094c423de682b44c71dca50c7e4835ee781ce4d Mon Sep 17 00:00:00 2001 From: Andy Oknen Date: Sat, 16 Aug 2025 05:34:20 +0800 Subject: [PATCH] Refactor configuration handling by removing writable flag from ConfigInfo and related UI components. Simplify config response structure in WebUIServer and update frontend to reflect these changes. Clean up unused CSS styles for improved layout. --- src/config/config.go | 92 ++++++++------------------------------ src/webui/server.go | 2 - src/webui/static/config.js | 21 +++------ src/webui/static/style.css | 29 ------------ 4 files changed, 26 insertions(+), 118 deletions(-) diff --git a/src/config/config.go b/src/config/config.go index 283427ea..0849a235 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -286,10 +286,9 @@ func (k *KeyBytes) UnmarshalJSON(b []byte) error { // ConfigInfo contains information about the configuration file type ConfigInfo struct { - Path string `json:"path"` - Format string `json:"format"` - Data interface{} `json:"data"` - Writable bool `json:"writable"` + Path string `json:"path"` + Format string `json:"format"` + Data interface{} `json:"data"` } // Global variables to track the current configuration state @@ -338,20 +337,6 @@ func validateConfigPath(path string) (string, error) { } } - // Basic sanity check on file extension for config files - ext := strings.ToLower(filepath.Ext(absPath)) - allowedExts := []string{".json", ".hjson", ".conf", ".config", ".yml", ".yaml", ""} - validExt := false - for _, allowed := range allowedExts { - if ext == allowed { - validExt = true - break - } - } - if !validExt { - return "", fmt.Errorf("invalid file extension: %s", ext) - } - // Additional check: ensure the path doesn't escape intended directories if strings.Count(absPath, "/") > 10 { return "", fmt.Errorf("path too deep: potential security risk") @@ -381,7 +366,6 @@ func GetCurrentConfig() (*ConfigInfo, error) { var configPath string var configData *NodeConfig var format string = "hjson" - var writable bool = false // Use current config if available, otherwise try to read from default location if currentConfigPath != "" && currentConfigData != nil { @@ -402,72 +386,33 @@ func GetCurrentConfig() (*ConfigInfo, error) { if err != nil { return nil, fmt.Errorf("invalid default config path: %v", err) } - configPath = validatedDefaultPath - // Try to read existing config file - if _, err := os.Stat(configPath); err == nil { // Path already validated above - data, err := os.ReadFile(configPath) // Path already validated above - if err == nil { - cfg := GenerateConfig() - if err := hjson.Unmarshal(data, cfg); err == nil { - configData = cfg - // Detect format - var jsonTest interface{} - if json.Unmarshal(data, &jsonTest) == nil { - format = "json" - } - } else { - return nil, fmt.Errorf("failed to parse config file: %v", err) - } - } - } else { - // No config file exists, use default - configData = GenerateConfig() - } + configPath = validatedDefaultPath + configData = GenerateConfig() } - // Detect format from file if path is known - if configPath != "" { - // Config path is already validated at this point - if _, err := os.Stat(configPath); err == nil { // Path already validated above - data, err := os.ReadFile(configPath) // Path already validated above - if err == nil { + // Try to read existing config file + if _, err := os.Stat(configPath); err == nil { // Path already validated above + data, err := os.ReadFile(configPath) // Path already validated above + if err == nil { + cfg := GenerateConfig() + if err := hjson.Unmarshal(data, cfg); err == nil { + configData = cfg + // Detect format var jsonTest interface{} if json.Unmarshal(data, &jsonTest) == nil { format = "json" } - } - } - } - - // Check if writable - if configPath != "" { - // Config path is already validated at this point - if _, err := os.Stat(configPath); err == nil { // Path already validated above - // File exists, check if writable - if file, err := os.OpenFile(configPath, os.O_WRONLY, 0); err == nil { // Path already validated above - writable = true - file.Close() - } - } else { - // File doesn't exist, check if directory is writable - dir := filepath.Clean(filepath.Dir(configPath)) - if stat, err := os.Stat(dir); err == nil && stat.IsDir() { - testFile := filepath.Join(dir, ".yggdrasil_write_test") - if file, err := os.Create(testFile); err == nil { - file.Close() - os.Remove(testFile) - writable = true - } + } else { + return nil, fmt.Errorf("failed to parse config file: %v", err) } } } return &ConfigInfo{ - Path: configPath, - Format: format, - Data: configData, - Writable: writable, + Path: configPath, + Format: format, + Data: configData, }, nil } @@ -516,6 +461,7 @@ func SaveConfig(configData interface{}, configPath, format string) error { } } } + if targetFormat == "" { targetFormat = "hjson" } diff --git a/src/webui/server.go b/src/webui/server.go index 6457ec10..7a5d1a7a 100644 --- a/src/webui/server.go +++ b/src/webui/server.go @@ -388,7 +388,6 @@ type ConfigResponse struct { ConfigPath string `json:"config_path"` ConfigFormat string `json:"config_format"` ConfigJSON string `json:"config_json"` - IsWritable bool `json:"is_writable"` } type ConfigSetRequest struct { @@ -432,7 +431,6 @@ func (w *WebUIServer) getConfigHandler(rw http.ResponseWriter, r *http.Request) ConfigPath: configInfo.Path, ConfigFormat: configInfo.Format, ConfigJSON: string(configBytes), - IsWritable: configInfo.Writable, } rw.Header().Set("Content-Type", "application/json") diff --git a/src/webui/static/config.js b/src/webui/static/config.js index 9183037d..9540ceff 100644 --- a/src/webui/static/config.js +++ b/src/webui/static/config.js @@ -30,8 +30,7 @@ async function loadConfiguration() { currentConfigJSON = data.config_json; configMeta = { path: data.config_path, - format: data.config_format, - isWritable: data.is_writable + format: data.config_format }; renderConfigEditor(); @@ -54,9 +53,6 @@ function renderConfigEditor() {
${configMeta.path} ${configMeta.format.toUpperCase()} - - ${configMeta.isWritable ? '✏️ Редактируемый' : '🔒 Только чтение'} -
@@ -76,14 +72,12 @@ function renderConfigEditor() {
Проверить
- ${configMeta.isWritable ? ` -
- Сохранить -
-
- Сохранить и перезапустить -
- ` : ''} +
+ Сохранить +
+
+ Сохранить и перезапустить +
@@ -93,7 +87,6 @@ function renderConfigEditor() { id="config-json-textarea" class="json-editor" spellcheck="false" - ${configMeta.isWritable ? '' : 'readonly'} placeholder="Загрузка конфигурации..." oninput="onConfigChange()" onscroll="syncLineNumbers()" diff --git a/src/webui/static/style.css b/src/webui/static/style.css index 001d6bd1..5db33daa 100644 --- a/src/webui/static/style.css +++ b/src/webui/static/style.css @@ -1542,9 +1542,6 @@ button[onclick="copyNodeKey()"]:hover { } .config-header { - display: flex; - justify-content: space-between; - align-items: flex-start; margin-bottom: 30px; padding: 20px; background: var(--bg-info-card); @@ -1564,13 +1561,6 @@ button[onclick="copyNodeKey()"]:hover { font-size: 1.5em; } -.config-meta { - display: flex; - gap: 15px; - flex-wrap: wrap; - align-items: center; -} - .config-path { font-family: 'Courier New', monospace; background: var(--bg-nav-item); @@ -1602,25 +1592,6 @@ button[onclick="copyNodeKey()"]:hover { color: #7b1fa2; } -.config-status { - padding: 4px 8px; - border-radius: 4px; - font-size: 0.8em; - font-weight: bold; -} - -.config-status.writable { - background: var(--bg-success); - color: var(--text-success); -} - -.config-status.readonly { - background: var(--bg-warning); - color: var(--text-warning); -} - - - /* Configuration Groups */ .config-groups { display: flex;