sshkeeper/internal/config/config.go

107 lines
2.1 KiB
Go

package config
import (
"os"
"path/filepath"
"github.com/BurntSushi/toml"
)
type Config struct {
SSH SSHConfig `toml:"ssh"`
Vault VaultConfig `toml:"vault"`
UI UIConfig `toml:"ui"`
// resolved paths
ConfigDir string `toml:"-"`
DataDir string `toml:"-"`
}
type SSHConfig struct {
Binary string `toml:"binary"`
ConnectTimeoutSec int `toml:"connect_timeout_seconds"`
TestCommand string `toml:"test_command"`
}
type VaultConfig struct {
AutoLockMinutes int `toml:"auto_lock_minutes"`
}
type UIConfig struct {
ShowSecurityHints bool `toml:"show_security_hints"`
}
func defaultConfig() *Config {
return &Config{
SSH: SSHConfig{
Binary: "/usr/bin/ssh",
ConnectTimeoutSec: 10,
TestCommand: "echo SSHKEEPER_OK",
},
Vault: VaultConfig{
AutoLockMinutes: 15,
},
UI: UIConfig{
ShowSecurityHints: false,
},
}
}
func Load() (*Config, error) {
cfg := defaultConfig()
// XDG paths
configDir := os.Getenv("XDG_CONFIG_HOME")
if configDir == "" {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
configDir = filepath.Join(home, ".config", "sshkeeper")
}
cfg.ConfigDir = configDir
dataDir := os.Getenv("XDG_DATA_HOME")
if dataDir == "" {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
dataDir = filepath.Join(home, ".local", "share", "sshkeeper")
}
cfg.DataDir = dataDir
// Ensure dirs exist
if err := os.MkdirAll(configDir, 0700); err != nil {
return nil, err
}
if err := os.MkdirAll(dataDir, 0700); err != nil {
return nil, err
}
configFile := filepath.Join(configDir, "config.toml")
// Write default config if not exists
if _, err := os.Stat(configFile); os.IsNotExist(err) {
f, err := os.OpenFile(configFile, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return nil, err
}
defer f.Close()
if err := toml.NewEncoder(f).Encode(cfg); err != nil {
return nil, err
}
}
// Parse existing config
if _, err := toml.DecodeFile(configFile, cfg); err != nil {
return nil, err
}
// Re-apply paths since toml decode might overwrite
cfg.ConfigDir = configDir
cfg.DataDir = dataDir
return cfg, nil
}