Support KeePassGO state dir via flag and env
This commit is contained in:
@@ -71,6 +71,11 @@ type attachmentItem struct {
|
||||
Size int
|
||||
}
|
||||
|
||||
type statePaths struct {
|
||||
DefaultSaveAsPath string
|
||||
RecentVaultsPath string
|
||||
}
|
||||
|
||||
type ui struct {
|
||||
mode string
|
||||
theme *material.Theme
|
||||
@@ -184,19 +189,23 @@ const (
|
||||
errSaveAsPathRequired = "save-as path is required"
|
||||
)
|
||||
|
||||
func newUI(mode string) *ui {
|
||||
return newUIWithSession(mode, &session.Manager{})
|
||||
func newUI(mode string, paths statePaths) *ui {
|
||||
return newUIWithSession(mode, &session.Manager{}, paths)
|
||||
}
|
||||
|
||||
func newUIWithModel(mode string, model vault.Model) *ui {
|
||||
return newUIWithState(mode, &uiSession{model: model})
|
||||
return newUIWithState(mode, &uiSession{model: model}, defaultStatePaths(""))
|
||||
}
|
||||
|
||||
func newUIWithSession(mode string, sess appstate.CurrentSession) *ui {
|
||||
return newUIWithState(mode, sess)
|
||||
func newUIWithSession(mode string, sess appstate.CurrentSession, paths ...statePaths) *ui {
|
||||
selected := defaultStatePaths("")
|
||||
if len(paths) > 0 {
|
||||
selected = paths[0]
|
||||
}
|
||||
return newUIWithState(mode, sess, selected)
|
||||
}
|
||||
|
||||
func newUIWithState(mode string, sess appstate.CurrentSession) *ui {
|
||||
func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths) *ui {
|
||||
th := material.NewTheme()
|
||||
th.Palette.Bg = bgColor
|
||||
th.Palette.Fg = color.NRGBA{R: 31, G: 29, B: 27, A: 255}
|
||||
@@ -242,8 +251,8 @@ func newUIWithState(mode string, sess appstate.CurrentSession) *ui {
|
||||
state: appstate.State{},
|
||||
selectedHistoryIndex: -1,
|
||||
lifecycleMode: "local",
|
||||
defaultSaveAsPath: defaultSaveAsPath(),
|
||||
recentVaultsPath: defaultRecentVaultsPath(),
|
||||
defaultSaveAsPath: paths.DefaultSaveAsPath,
|
||||
recentVaultsPath: paths.RecentVaultsPath,
|
||||
}
|
||||
u.state.Session = sess
|
||||
u.phoneSplit.Value = 0.46
|
||||
@@ -270,20 +279,29 @@ func (u *ui) filter() {
|
||||
}
|
||||
}
|
||||
|
||||
func defaultSaveAsPath() string {
|
||||
cacheDir, err := os.UserCacheDir()
|
||||
if err != nil || strings.TrimSpace(cacheDir) == "" {
|
||||
cacheDir = os.TempDir()
|
||||
func defaultStatePaths(stateDir string) statePaths {
|
||||
baseDir := strings.TrimSpace(stateDir)
|
||||
if baseDir == "" {
|
||||
configDir, err := os.UserConfigDir()
|
||||
if err != nil || strings.TrimSpace(configDir) == "" {
|
||||
configDir = os.TempDir()
|
||||
}
|
||||
baseDir = filepath.Join(configDir, "keepassgo")
|
||||
}
|
||||
return statePaths{
|
||||
DefaultSaveAsPath: filepath.Join(baseDir, "vault.kdbx"),
|
||||
RecentVaultsPath: filepath.Join(baseDir, "recent-vaults.json"),
|
||||
}
|
||||
return filepath.Join(cacheDir, "keepassgo", "vault.kdbx")
|
||||
}
|
||||
|
||||
func defaultRecentVaultsPath() string {
|
||||
configDir, err := os.UserConfigDir()
|
||||
if err != nil || strings.TrimSpace(configDir) == "" {
|
||||
configDir = os.TempDir()
|
||||
func resolveFlagOrEnv(flagValue, envName, fallback string) string {
|
||||
if value := strings.TrimSpace(flagValue); value != "" {
|
||||
return value
|
||||
}
|
||||
return filepath.Join(configDir, "keepassgo", "recent-vaults.json")
|
||||
if value := strings.TrimSpace(os.Getenv(envName)); value != "" {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func (u *ui) selectedAttachmentItems() []attachmentItem {
|
||||
@@ -1858,12 +1876,16 @@ func fill(c color.NRGBA) layout.Widget {
|
||||
}
|
||||
|
||||
func main() {
|
||||
mode := flag.String("mode", "desktop", "window mode: desktop or phone")
|
||||
mode := flag.String("mode", "", "window mode: desktop or phone")
|
||||
stateDir := flag.String("state-dir", "", "directory for KeePassGO state such as recent-vault history and default save targets")
|
||||
flag.Parse()
|
||||
|
||||
resolvedMode := resolveFlagOrEnv(*mode, "KEEPASSGO_MODE", "desktop")
|
||||
resolvedStateDir := resolveFlagOrEnv(*stateDir, "KEEPASSGO_STATE_DIR", "")
|
||||
|
||||
width := unit.Dp(1180)
|
||||
height := unit.Dp(760)
|
||||
if strings.EqualFold(*mode, "phone") {
|
||||
if strings.EqualFold(resolvedMode, "phone") {
|
||||
// Pixel 10 uses a 20:9 display; use a 412x915 dp viewport as a desktop-friendly preview.
|
||||
width = unit.Dp(412)
|
||||
height = unit.Dp(915)
|
||||
@@ -1875,7 +1897,7 @@ func main() {
|
||||
app.Title(productName),
|
||||
app.Size(width, height),
|
||||
)
|
||||
if err := run(w, strings.ToLower(*mode)); err != nil {
|
||||
if err := run(w, strings.ToLower(resolvedMode), defaultStatePaths(resolvedStateDir)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
os.Exit(0)
|
||||
@@ -1883,9 +1905,9 @@ func main() {
|
||||
app.Main()
|
||||
}
|
||||
|
||||
func run(w *app.Window, mode string) error {
|
||||
func run(w *app.Window, mode string, paths statePaths) error {
|
||||
var ops op.Ops
|
||||
ui := newUI(mode)
|
||||
ui := newUI(mode, paths)
|
||||
for {
|
||||
e := w.Event()
|
||||
switch e := e.(type) {
|
||||
|
||||
@@ -1798,6 +1798,34 @@ func TestUILoadsRecentVaultsFromPersistedConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultStatePathsUsesProvidedStateDir(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
base := filepath.Join(t.TempDir(), "keepassgo-state")
|
||||
paths := defaultStatePaths(base)
|
||||
|
||||
if got := paths.DefaultSaveAsPath; got != filepath.Join(base, "vault.kdbx") {
|
||||
t.Fatalf("DefaultSaveAsPath = %q, want %q", got, filepath.Join(base, "vault.kdbx"))
|
||||
}
|
||||
if got := paths.RecentVaultsPath; got != filepath.Join(base, "recent-vaults.json") {
|
||||
t.Fatalf("RecentVaultsPath = %q, want %q", got, filepath.Join(base, "recent-vaults.json"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveFlagOrEnvPrefersFlagThenEnvThenFallback(t *testing.T) {
|
||||
t.Setenv("KEEPASSGO_TEST_VALUE", "from-env")
|
||||
|
||||
if got := resolveFlagOrEnv("from-flag", "KEEPASSGO_TEST_VALUE", "fallback"); got != "from-flag" {
|
||||
t.Fatalf("resolveFlagOrEnv(flag) = %q, want %q", got, "from-flag")
|
||||
}
|
||||
if got := resolveFlagOrEnv("", "KEEPASSGO_TEST_VALUE", "fallback"); got != "from-env" {
|
||||
t.Fatalf("resolveFlagOrEnv(env) = %q, want %q", got, "from-env")
|
||||
}
|
||||
if got := resolveFlagOrEnv("", "KEEPASSGO_TEST_MISSING", "fallback"); got != "fallback" {
|
||||
t.Fatalf("resolveFlagOrEnv(fallback) = %q, want %q", got, "fallback")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnterOnLocalLifecycleScreenDefaultsToOpenVault(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user