Move username to top of copy menu; send user to copy menu after creating/editing an entry; allow copying old password from copy menu

This commit is contained in:
2025-11-23 13:40:41 -05:00
parent 23c6d2e354
commit b26c2ce17c
8 changed files with 41 additions and 30 deletions
+2 -2
View File
@@ -44,9 +44,9 @@ func AddEntry(realPath string, hideSecrets bool, entryType uint8) {
// write and preview the new entry
if password != "" {
writeEntryCLI(realPath, decryptedEntry, hideSecrets, true)
writeEntryCLI(realPath, decryptedEntry, hideSecrets, true, "")
} else {
writeEntryCLI(realPath, decryptedEntry, hideSecrets, false)
writeEntryCLI(realPath, decryptedEntry, hideSecrets, false, "")
}
}
+25 -17
View File
@@ -16,25 +16,27 @@ import (
// CopyMenu decrypts an entry and allows the user to
// interactively copy fields without having to re-decrypt each time.
func CopyMenu(realPath string) {
// decrypt entry
decSlice, err := crypt.DecryptFileToSlice(realPath)
if err != nil {
other.PrintError("Failed to decrypt entry: "+err.Error(), global.ErrorDecryption)
// Only one of realPath or decSlice should be provided.
func CopyMenu(realPath string, decSlice []string, oldPassword string) {
var err error
if decSlice == nil {
// decrypt entry
decSlice, err = crypt.DecryptFileToSlice(realPath)
if err != nil {
other.PrintError("Failed to decrypt entry: "+err.Error(), global.ErrorDecryption)
}
}
// determine populated fields in entry
fieldIndexToString := map[int]string{
0: "Password",
1: "Username",
2: "TOTP Code",
3: "URL",
4: "Note (first line)",
}
var fieldStrings = []string{"Username", "Password", "TOTP Code", "URL", "Note (first line)"}
var indices = []int{1, 0, 2, 3, 4}
var fields []string
for i, _ := range decSlice[:min(5, len(decSlice))] {
if decSlice[i] != "" {
fields = append(fields, fieldIndexToString[i])
for i := range indices {
if len(decSlice) > indices[i] && decSlice[indices[i]] != "" {
fields = append(fields, fieldStrings[i])
if indices[i] == 0 && oldPassword != "" {
fields = append(fields, "Old Password")
}
}
}
@@ -52,10 +54,16 @@ func CopyMenu(realPath string) {
fmt.Println()
choice := front.InputMenuGen("Field to copy:", fields)
switch fields[choice-1] {
case "Password":
choice = 0
case "Username":
choice = 1
case "Password":
choice = 0
case "Old Password":
err := clip.CopyString(false, oldPassword)
if err != nil {
other.PrintError("Failed to copy old password to clipboard: "+err.Error(), global.ErrorClipboard)
}
continue
case "TOTP Code":
choice = 2
case "URL":
+6 -3
View File
@@ -35,8 +35,10 @@ func EditEntryField(realPath string, hideSecrets bool, field int) {
}
// edit the field
var oldPassword string
switch field {
case 0:
oldPassword = decryptedEntry[field]
decryptedEntry[field] = string(front.InputHidden("Password:"))
case 1:
decryptedEntry[field] = front.Input("Username:")
@@ -59,9 +61,9 @@ func EditEntryField(realPath string, hideSecrets bool, field int) {
// write and preview the modified entry
if field == 0 {
writeEntryCLI(realPath, decryptedEntry, hideSecrets, true)
writeEntryCLI(realPath, decryptedEntry, hideSecrets, true, oldPassword)
} else {
writeEntryCLI(realPath, decryptedEntry, hideSecrets, false)
writeEntryCLI(realPath, decryptedEntry, hideSecrets, false, oldPassword)
}
}
@@ -74,10 +76,11 @@ func GenUpdate(realPath string, hideSecrets bool) {
}
// generate a new password
oldPassword := decryptedEntry[0]
decryptedEntry[0] = inputPasswordGen()
// write and preview the modified entry
writeEntryCLI(realPath, decryptedEntry, hideSecrets, true)
writeEntryCLI(realPath, decryptedEntry, hideSecrets, true, oldPassword)
}
// editNote uses the user-specified text editor to edit an existing note (or create a new one if baseNote is empty).
-3
View File
@@ -2,7 +2,6 @@ package cli
import (
"fmt"
"os"
"strings"
"github.com/charmbracelet/glamour"
@@ -78,8 +77,6 @@ fieldLoop:
other.PrintError("Failed to sync entries: "+err.Error(), global.ErrorSyncProcess)
}
}
os.Exit(0)
}
// EntryReaderDecrypt is a wrapper for EntryReader that first decrypts an RCW-wrapped file before sending it to EntryReader.
+4 -1
View File
@@ -2,6 +2,7 @@ package cli
import (
"fmt"
"os"
"github.com/rwinkhart/go-boilerplate/back"
"github.com/rwinkhart/go-boilerplate/front"
@@ -28,7 +29,7 @@ func inputPasswordGen() string {
}
// writeEntryCLI writes an entry to realPath and previews it (errors if no data is supplied).
func writeEntryCLI(realPath string, decSlice []string, hideSecrets bool, passwordIsNew bool) {
func writeEntryCLI(realPath string, decSlice []string, hideSecrets bool, passwordIsNew bool, oldPassword string) {
if core.EntryIsNotEmpty(decSlice) {
err := core.WriteEntry(realPath, decSlice, passwordIsNew)
if err != nil {
@@ -37,6 +38,8 @@ func writeEntryCLI(realPath string, decSlice []string, hideSecrets bool, passwor
// preview the entry
fmt.Println(back.AnsiBold + "\nEntry Preview:" + back.AnsiReset)
EntryReader(decSlice, hideSecrets, true)
CopyMenu("", decSlice, oldPassword)
os.Exit(0)
} else {
other.PrintError("No data supplied for entry", back.ErrorTargetNotFound)
}