Files

181 lines
4.1 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"os"
"sync"
)
// SettingsHandler manages system configuration
type SettingsHandler struct {
mu sync.RWMutex
settings map[string]interface{}
path string
}
func NewSettingsHandler() *SettingsHandler {
h := &SettingsHandler{
settings: make(map[string]interface{}),
path: "/app/config/system.json",
}
h.load()
return h
}
func (h *SettingsHandler) load() {
data, err := os.ReadFile(h.path)
if err != nil {
// Use defaults
h.settings = h.defaultSettings()
return
}
json.Unmarshal(data, &h.settings)
}
func (h *SettingsHandler) save() error {
data, err := json.MarshalIndent(h.settings, "", " ")
if err != nil {
return err
}
return os.WriteFile(h.path, data, 0644)
}
func (h *SettingsHandler) defaultSettings() map[string]interface{} {
return map[string]interface{}{
"appearance": map[string]interface{}{
"theme": "light",
"density": "comfortable",
"sidebar_width": 240,
"animations": true,
},
"dashboard": map[string]interface{}{
"greeting_enabled": true,
"kpi_refresh": 300,
"activity_max": 10,
},
"notifications": map[string]interface{}{
"in_app": true,
"email": false,
"slack": false,
},
"advanced": map[string]interface{}{
"api_rate_limit": 1000,
"cache_ttl": 300,
"log_level": "info",
"export_max_rows": 10000,
},
}
}
// GetSettings returns all settings
func (h *SettingsHandler) GetSettings(w http.ResponseWriter, r *http.Request) {
h.mu.RLock()
defer h.mu.RUnlock()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(h.settings)
}
// UpdateSettings updates settings
func (h *SettingsHandler) UpdateSettings(w http.ResponseWriter, r *http.Request) {
var updates map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&updates); err != nil {
writeError(w, http.StatusBadRequest, "invalid request body")
return
}
h.mu.Lock()
defer h.mu.Unlock()
// Merge updates
for key, value := range updates {
h.settings[key] = value
}
if err := h.save(); err != nil {
writeError(w, http.StatusInternalServerError, "failed to save settings")
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(h.settings)
}
// GetModuleConfig returns module configuration
func (h *SettingsHandler) GetModuleConfig(w http.ResponseWriter, r *http.Request) {
module := r.URL.Query().Get("module")
if module == "" {
writeError(w, http.StatusBadRequest, "module required")
return
}
h.mu.RLock()
defer h.mu.RUnlock()
modules, ok := h.settings["modules"].(map[string]interface{})
if !ok {
writeError(w, http.StatusNotFound, "modules not configured")
return
}
config, ok := modules[module]
if !ok {
writeError(w, http.StatusNotFound, "module not found")
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(config)
}
// ToggleModule enables/disables a module
func (h *SettingsHandler) ToggleModule(w http.ResponseWriter, r *http.Request) {
module := r.URL.Query().Get("module")
if module == "" {
writeError(w, http.StatusBadRequest, "module required")
return
}
h.mu.Lock()
defer h.mu.Unlock()
modules, ok := h.settings["modules"].(map[string]interface{})
if !ok {
modules = make(map[string]interface{})
h.settings["modules"] = modules
}
config, ok := modules[module].(map[string]interface{})
if !ok {
config = map[string]interface{}{"enabled": false}
}
// Toggle enabled state
if enabled, ok := config["enabled"].(bool); ok {
config["enabled"] = !enabled
} else {
config["enabled"] = true
}
modules[module] = config
if err := h.save(); err != nil {
writeError(w, http.StatusInternalServerError, "failed to save")
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(config)
}
func (h *SettingsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
h.GetSettings(w, r)
case http.MethodPut:
h.UpdateSettings(w, r)
default:
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
}
}