Harden window state path configuration
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

This commit is contained in:
Snider 2026-04-18 08:49:04 +01:00
parent 1705e6ef57
commit db535805a1
3 changed files with 31 additions and 2 deletions

View file

@ -0,0 +1 @@
- @bug pkg/window/layout.go:29 — layout persistence has the same hard-coded config-dir assumption and needs an explicit file-path override for restricted runtimes.

View file

@ -10,6 +10,8 @@ import (
coreio "dappco.re/go/core/io"
)
const windowStateFileEnv = "WINDOW_STATE_FILE"
// WindowState holds the persisted position/size of a window.
// JSON tags match existing window_state.json format for backward compat.
type WindowState struct {
@ -23,7 +25,7 @@ type WindowState struct {
UpdatedAt int64 `json:"updatedAt,omitempty"`
}
// StateManager persists window positions to ~/.config/Core/window_state.json.
// StateManager persists window positions to the configured window state file.
type StateManager struct {
configDir string
statePath string
@ -32,8 +34,12 @@ type StateManager struct {
saveTimer *time.Timer
}
// NewStateManager creates a StateManager loading from the default config directory.
// NewStateManager creates a StateManager loading from the configured default path.
// WINDOW_STATE_FILE overrides the directory-based default when present.
func NewStateManager() *StateManager {
if stateFile := core.Env(windowStateFileEnv); stateFile != "" {
return NewStateManagerWithPath(stateFile)
}
sm := &StateManager{
states: make(map[string]WindowState),
}
@ -55,6 +61,17 @@ func NewStateManagerWithDir(configDir string) *StateManager {
return sm
}
// NewStateManagerWithPath creates a StateManager loading from a custom state file.
// Useful for tests or restricted runtimes that need an explicit writable target.
func NewStateManagerWithPath(path string) *StateManager {
sm := &StateManager{
statePath: path,
states: make(map[string]WindowState),
}
sm.load()
return sm
}
func (sm *StateManager) filePath() string {
if sm.statePath != "" {
return sm.statePath

View file

@ -20,6 +20,17 @@ func TestStateManagerState_NewStateManagerWithDir_Good(t *testing.T) {
assert.Empty(t, sm.ListStates())
}
func TestStateManagerState_NewStateManagerWithPathEnv_Good(t *testing.T) {
path := filepath.Join(t.TempDir(), "custom", "window_state.json")
t.Setenv(windowStateFileEnv, path)
sm := NewStateManager()
require.NotNil(t, sm)
assert.Equal(t, path, sm.filePath())
assert.Equal(t, filepath.Dir(path), sm.dataDir())
}
func TestStateManagerState_NewStateManagerWithDir_Bad(t *testing.T) {
sm := NewStateManagerWithDir("")