Reset password peek across view changes

This commit is contained in:
Joe Julian
2026-03-29 17:27:19 -07:00
parent 4a3e52ec1c
commit 3066442c1b
4 changed files with 75 additions and 5 deletions
+12 -1
View File
@@ -386,20 +386,27 @@ func (u *ui) selectedAttachmentNames() []string {
}
func (u *ui) showEntriesSection() {
u.resetPasswordPeek()
u.state.ShowSection(appstate.SectionEntries)
u.filter()
}
func (u *ui) showTemplatesSection() {
u.resetPasswordPeek()
u.state.ShowSection(appstate.SectionTemplates)
u.filter()
}
func (u *ui) showRecycleBinSection() {
u.resetPasswordPeek()
u.state.ShowSection(appstate.SectionRecycleBin)
u.filter()
}
func (u *ui) resetPasswordPeek() {
u.showPassword = false
}
func (u *ui) childGroups() []string {
u.state.SetSearchQuery(u.search.Text())
groups, err := u.state.ChildGroups()
@@ -506,6 +513,7 @@ func (u *ui) createVaultAction() error {
u.vaultPath.SetText(u.saveAsTargetPath())
u.noteRecentVault(u.saveAsTargetPath())
}
u.resetPasswordPeek()
u.currentPath = append([]string(nil), u.state.CurrentPath...)
u.editingEntry = false
u.filter()
@@ -526,6 +534,7 @@ func (u *ui) openVaultAction() error {
return err
}
u.noteRecentVault(path)
u.resetPasswordPeek()
u.currentPath = append([]string(nil), u.state.CurrentPath...)
u.restoreRecentVaultGroup(path)
u.editingEntry = false
@@ -573,6 +582,7 @@ func (u *ui) openRemoteAction() error {
u.remotePassword.Text(),
u.rememberRemoteAuth.Value,
)
u.resetPasswordPeek()
u.enterHiddenVaultRoot()
u.editingEntry = false
u.filter()
@@ -585,7 +595,7 @@ func (u *ui) lockAction() error {
return err
}
u.currentPath = append([]string(nil), u.state.CurrentPath...)
u.showPassword = false
u.resetPasswordPeek()
u.editingEntry = false
u.filter()
return nil
@@ -600,6 +610,7 @@ func (u *ui) unlockAction() error {
if err := u.state.Unlock(key); err != nil {
return err
}
u.resetPasswordPeek()
u.currentPath = append([]string(nil), u.state.CurrentPath...)
u.editingEntry = false
u.filter()
+54
View File
@@ -2097,6 +2097,60 @@ func TestEnterOnRemoteLifecycleScreenDefaultsToOpenRemoteVault(t *testing.T) {
}
}
func TestMasterPasswordPeekResetsAfterOpeningVault(t *testing.T) {
t.Parallel()
path := filepath.Join(t.TempDir(), "vault.kdbx")
var encoded bytes.Buffer
if err := vault.SaveKDBX(&encoded, vault.Model{
Entries: []vault.Entry{
{ID: "vault-console", Title: "Vault Console", Password: "token-1", Path: []string{"Root", "Internet"}},
},
}, "correct horse battery staple"); err != nil {
t.Fatalf("SaveKDBX() error = %v", err)
}
if err := os.WriteFile(path, encoded.Bytes(), 0o600); err != nil {
t.Fatalf("WriteFile(vault.kdbx) error = %v", err)
}
u := newUIWithSession("desktop", &session.Manager{})
u.masterPassword.SetText("correct horse battery staple")
u.vaultPath.SetText(path)
u.showPassword = true
if err := u.openVaultAction(); err != nil {
t.Fatalf("openVaultAction() error = %v", err)
}
if u.showPassword {
t.Fatal("showPassword = true after openVaultAction(), want false")
}
}
func TestPasswordPeekResetsWhenChangingSelectedEntry(t *testing.T) {
t.Parallel()
u := newUIWithModel("desktop", vault.Model{
Entries: []vault.Entry{
{ID: "vault-console", Title: "Vault Console", Password: "token-1", Path: []string{"Root", "Internet"}},
{ID: "bellagio", Title: "Bellagio", Password: "token-2", Path: []string{"Root", "Internet"}},
},
})
u.showEntriesSection()
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "vault-console"
u.loadSelectedEntryIntoEditor()
u.showPassword = true
u.state.SelectedEntryID = "bellagio"
u.loadSelectedEntryIntoEditor()
if u.showPassword {
t.Fatal("showPassword = true after selecting a different entry, want false")
}
}
func TestEnterOnLockedScreenDefaultsToUnlockVault(t *testing.T) {
t.Parallel()
+1
View File
@@ -40,6 +40,7 @@ func (u *ui) attachmentInput() (string, []byte, error) {
}
func (u *ui) loadSelectedEntryIntoEditor() {
u.resetPasswordPeek()
u.selectedHistoryIndex = -1
u.historyIndex.SetText("")
+8 -4
View File
@@ -26,7 +26,9 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
layout.Rigid(labeledEditorHelp(u.theme, "Master Password", "Leave blank if this vault is protected by key file only.", &u.masterPassword, true)),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return u.masterPasswordField(gtx, "Leave blank if this vault is protected by key file only.")
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
layout.Rigid(selectorEditorHelp(u.theme, "Key File", "Optional path to a KeePass-compatible key file.", &u.keyFilePath, &u.pickKeyFile, "Choose File", false)),
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
@@ -490,7 +492,9 @@ func selectorEditorHelp(th *material.Theme, label, help string, editor *widget.E
func (u *ui) unlockPanel(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(u.unlockPasswordField),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return u.masterPasswordField(gtx, "Used alone or together with a key file to unlock the vault.")
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
layout.Rigid(selectorEditorHelp(u.theme, "Key File", "Optional path to a KeePass-compatible key file.", &u.keyFilePath, &u.pickKeyFile, "Choose File", false)),
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
@@ -500,7 +504,7 @@ func (u *ui) unlockPanel(gtx layout.Context) layout.Dimensions {
)
}
func (u *ui) unlockPasswordField(gtx layout.Context) layout.Dimensions {
func (u *ui) masterPasswordField(gtx layout.Context, help string) layout.Dimensions {
icon := u.eyeIcon
desc := "Show master password"
mask := rune('•')
@@ -542,7 +546,7 @@ func (u *ui) unlockPasswordField(gtx layout.Context) layout.Dimensions {
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(11), "Used alone or together with a key file to unlock the vault.")
lbl := material.Label(u.theme, unit.Sp(11), help)
lbl.Color = mutedColor
return lbl.Layout(gtx)
}),