chore(config): merge userConfig with defaultConfig and add a lock (#164)

* chore(config): merge userConfig with defaultConfig and add a lock

* chore(config): remove lock for LoadConfig
This commit is contained in:
Aveline 2025-02-17 20:12:34 +01:00 committed by GitHub
parent cd333c4ebc
commit 69461140e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 11 additions and 34 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"sync"
) )
type WakeOnLanDevice struct { type WakeOnLanDevice struct {
@ -40,25 +41,28 @@ var defaultConfig = &Config{
DisplayOffAfterSec: 1800, // 30 minutes DisplayOffAfterSec: 1800, // 30 minutes
} }
var config *Config var (
config *Config
configLock = &sync.Mutex{}
)
func LoadConfig() { func LoadConfig() {
if config != nil { if config != nil {
logger.Info("config already loaded, skipping")
return return
} }
file, err := os.Open(configPath) file, err := os.Open(configPath)
if err != nil { if err != nil {
logger.Debug("default config file doesn't exist, using default") logger.Debug("default config file doesn't exist, using default")
config = defaultConfig
return return
} }
defer file.Close() defer file.Close()
var loadedConfig Config // load and merge the default config with the user config
loadedConfig := *defaultConfig
if err := json.NewDecoder(file).Decode(&loadedConfig); err != nil { if err := json.NewDecoder(file).Decode(&loadedConfig); err != nil {
logger.Errorf("config file JSON parsing failed, %v", err) logger.Errorf("config file JSON parsing failed, %v", err)
config = defaultConfig
return return
} }
@ -66,6 +70,9 @@ func LoadConfig() {
} }
func SaveConfig() error { func SaveConfig() error {
configLock.Lock()
defer configLock.Unlock()
file, err := os.Create(configPath) file, err := os.Create(configPath)
if err != nil { if err != nil {
return fmt.Errorf("failed to create config file: %w", err) return fmt.Errorf("failed to create config file: %w", err)

View File

@ -209,7 +209,6 @@ func watchTsEvents() {
// if they're not already set. This is done separately to the init routine as the "never dim" // if they're not already set. This is done separately to the init routine as the "never dim"
// option has the value set to zero, but time.NewTicker only accept positive values. // option has the value set to zero, but time.NewTicker only accept positive values.
func startBacklightTickers() { func startBacklightTickers() {
LoadConfig()
// Don't start the tickers if the display is switched off. // Don't start the tickers if the display is switched off.
// Set the display to off if that's the case. // Set the display to off if that's the case.
if config.DisplayMaxBrightness == 0 { if config.DisplayMaxBrightness == 0 {

View File

@ -194,7 +194,6 @@ func rpcSetEDID(edid string) error {
} }
// Save EDID to config, allowing it to be restored on reboot. // Save EDID to config, allowing it to be restored on reboot.
LoadConfig()
config.EdidString = edid config.EdidString = edid
SaveConfig() SaveConfig()
@ -235,8 +234,6 @@ func rpcTryUpdate() error {
} }
func rpcSetBacklightSettings(params BacklightSettings) error { func rpcSetBacklightSettings(params BacklightSettings) error {
LoadConfig()
blConfig := params blConfig := params
// NOTE: by default, the frontend limits the brightness to 64, as that's what the device originally shipped with. // NOTE: by default, the frontend limits the brightness to 64, as that's what the device originally shipped with.
@ -275,8 +272,6 @@ func rpcSetBacklightSettings(params BacklightSettings) error {
} }
func rpcGetBacklightSettings() (*BacklightSettings, error) { func rpcGetBacklightSettings() (*BacklightSettings, error) {
LoadConfig()
return &BacklightSettings{ return &BacklightSettings{
MaxBrightness: config.DisplayMaxBrightness, MaxBrightness: config.DisplayMaxBrightness,
DimAfter: int(config.DisplayDimAfterSec), DimAfter: int(config.DisplayDimAfterSec),
@ -544,7 +539,6 @@ func rpcSetUsbEmulationState(enabled bool) error {
} }
func rpcGetWakeOnLanDevices() ([]WakeOnLanDevice, error) { func rpcGetWakeOnLanDevices() ([]WakeOnLanDevice, error) {
LoadConfig()
if config.WakeOnLanDevices == nil { if config.WakeOnLanDevices == nil {
return []WakeOnLanDevice{}, nil return []WakeOnLanDevice{}, nil
} }
@ -556,13 +550,11 @@ type SetWakeOnLanDevicesParams struct {
} }
func rpcSetWakeOnLanDevices(params SetWakeOnLanDevicesParams) error { func rpcSetWakeOnLanDevices(params SetWakeOnLanDevicesParams) error {
LoadConfig()
config.WakeOnLanDevices = params.Devices config.WakeOnLanDevices = params.Devices
return SaveConfig() return SaveConfig()
} }
func rpcResetConfig() error { func rpcResetConfig() error {
LoadConfig()
config = defaultConfig config = defaultConfig
if err := SaveConfig(); err != nil { if err := SaveConfig(); err != nil {
return fmt.Errorf("failed to reset config: %w", err) return fmt.Errorf("failed to reset config: %w", err)

View File

@ -311,7 +311,6 @@ func ensureBinaryUpdated(destPath string) error {
// Restore the HDMI EDID value from the config. // Restore the HDMI EDID value from the config.
// Called after successful connection to jetkvm_native. // Called after successful connection to jetkvm_native.
func restoreHdmiEdid() { func restoreHdmiEdid() {
LoadConfig()
if config.EdidString != "" { if config.EdidString != "" {
logger.Infof("Restoring HDMI EDID to %v", config.EdidString) logger.Infof("Restoring HDMI EDID to %v", config.EdidString)
_, err := CallCtrlAction("set_edid", map[string]interface{}{"edid": config.EdidString}) _, err := CallCtrlAction("set_edid", map[string]interface{}{"edid": config.EdidString})

20
web.go
View File

@ -147,8 +147,6 @@ func handleWebRTCSession(c *gin.Context) {
} }
func handleLogin(c *gin.Context) { func handleLogin(c *gin.Context) {
LoadConfig()
if config.LocalAuthMode == "noPassword" { if config.LocalAuthMode == "noPassword" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Login is disabled in noPassword mode"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Login is disabled in noPassword mode"})
return return
@ -161,7 +159,6 @@ func handleLogin(c *gin.Context) {
return return
} }
LoadConfig()
err := bcrypt.CompareHashAndPassword([]byte(config.HashedPassword), []byte(req.Password)) err := bcrypt.CompareHashAndPassword([]byte(config.HashedPassword), []byte(req.Password))
if err != nil { if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid password"}) c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid password"})
@ -177,7 +174,6 @@ func handleLogin(c *gin.Context) {
} }
func handleLogout(c *gin.Context) { func handleLogout(c *gin.Context) {
LoadConfig()
config.LocalAuthToken = "" config.LocalAuthToken = ""
if err := SaveConfig(); err != nil { if err := SaveConfig(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save configuration"}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save configuration"})
@ -191,8 +187,6 @@ func handleLogout(c *gin.Context) {
func protectedMiddleware() gin.HandlerFunc { func protectedMiddleware() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
LoadConfig()
if config.LocalAuthMode == "noPassword" { if config.LocalAuthMode == "noPassword" {
c.Next() c.Next()
return return
@ -221,8 +215,6 @@ func RunWebServer() {
} }
func handleDevice(c *gin.Context) { func handleDevice(c *gin.Context) {
LoadConfig()
response := LocalDevice{ response := LocalDevice{
AuthMode: &config.LocalAuthMode, AuthMode: &config.LocalAuthMode,
DeviceID: GetDeviceID(), DeviceID: GetDeviceID(),
@ -232,8 +224,6 @@ func handleDevice(c *gin.Context) {
} }
func handleCreatePassword(c *gin.Context) { func handleCreatePassword(c *gin.Context) {
LoadConfig()
if config.HashedPassword != "" { if config.HashedPassword != "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Password already set"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Password already set"})
return return
@ -274,8 +264,6 @@ func handleCreatePassword(c *gin.Context) {
} }
func handleUpdatePassword(c *gin.Context) { func handleUpdatePassword(c *gin.Context) {
LoadConfig()
if config.HashedPassword == "" { if config.HashedPassword == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Password is not set"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Password is not set"})
return return
@ -319,8 +307,6 @@ func handleUpdatePassword(c *gin.Context) {
} }
func handleDeletePassword(c *gin.Context) { func handleDeletePassword(c *gin.Context) {
LoadConfig()
if config.HashedPassword == "" { if config.HashedPassword == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Password is not set"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Password is not set"})
return return
@ -357,8 +343,6 @@ func handleDeletePassword(c *gin.Context) {
} }
func handleDeviceStatus(c *gin.Context) { func handleDeviceStatus(c *gin.Context) {
LoadConfig()
response := DeviceStatus{ response := DeviceStatus{
IsSetup: config.LocalAuthMode != "", IsSetup: config.LocalAuthMode != "",
} }
@ -367,8 +351,6 @@ func handleDeviceStatus(c *gin.Context) {
} }
func handleDeviceUIConfig(c *gin.Context) { func handleDeviceUIConfig(c *gin.Context) {
LoadConfig()
config, _ := json.Marshal(gin.H{ config, _ := json.Marshal(gin.H{
"CLOUD_API": config.CloudURL, "CLOUD_API": config.CloudURL,
"DEVICE_VERSION": builtAppVersion, "DEVICE_VERSION": builtAppVersion,
@ -384,8 +366,6 @@ func handleDeviceUIConfig(c *gin.Context) {
} }
func handleSetup(c *gin.Context) { func handleSetup(c *gin.Context) {
LoadConfig()
// Check if the device is already set up // Check if the device is already set up
if config.LocalAuthMode != "" || config.HashedPassword != "" { if config.LocalAuthMode != "" || config.HashedPassword != "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Device is already set up"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Device is already set up"})