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.

This commit is contained in:
Andy Oknen 2025-08-16 05:34:20 +08:00
parent 8e44b57879
commit a094c423de
4 changed files with 26 additions and 118 deletions

View file

@ -289,7 +289,6 @@ type ConfigInfo struct {
Path string `json:"path"`
Format string `json:"format"`
Data interface{} `json:"data"`
Writable bool `json:"writable"`
}
// 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,7 +386,10 @@ func GetCurrentConfig() (*ConfigInfo, error) {
if err != nil {
return nil, fmt.Errorf("invalid default config path: %v", err)
}
configPath = validatedDefaultPath
configData = GenerateConfig()
}
// Try to read existing config file
if _, err := os.Stat(configPath); err == nil { // Path already validated above
@ -420,54 +407,12 @@ func GetCurrentConfig() (*ConfigInfo, error) {
return nil, fmt.Errorf("failed to parse config file: %v", err)
}
}
} else {
// No config file exists, use default
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 {
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
}
}
}
}
return &ConfigInfo{
Path: configPath,
Format: format,
Data: configData,
Writable: writable,
}, nil
}
@ -516,6 +461,7 @@ func SaveConfig(configData interface{}, configPath, format string) error {
}
}
}
if targetFormat == "" {
targetFormat = "hjson"
}

View file

@ -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")

View file

@ -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() {
<div class="config-meta">
<span class="config-path" title="${configMeta.path}">${configMeta.path}</span>
<span class="config-format ${configMeta.format}">${configMeta.format.toUpperCase()}</span>
<span class="config-status ${configMeta.isWritable ? 'writable' : 'readonly'}">
${configMeta.isWritable ? '✏️ <span data-key="editable">Редактируемый</span>' : '🔒 <span data-key="readonly">Только чтение</span>'}
</span>
</div>
</div>
</div>
@ -76,14 +72,12 @@ function renderConfigEditor() {
<div onclick="validateJSON()" class="action-btn">
<span data-key="validate">Проверить</span>
</div>
${configMeta.isWritable ? `
<div onclick="saveConfiguration()" class="action-btn">
<span data-key="save_config">Сохранить</span>
</div>
<div onclick="saveAndRestartConfiguration()" class="action-btn">
<span data-key="save_and_restart">Сохранить и перезапустить</span>
</div>
` : ''}
</div>
</div>
</div>
@ -93,7 +87,6 @@ function renderConfigEditor() {
id="config-json-textarea"
class="json-editor"
spellcheck="false"
${configMeta.isWritable ? '' : 'readonly'}
placeholder="Загрузка конфигурации..."
oninput="onConfigChange()"
onscroll="syncLineNumbers()"

View file

@ -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;