Preserve single-root KDBX group trees
This commit is contained in:
@@ -175,6 +175,80 @@ func TestSavePersistsEditsBackToCurrentPath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveReparentsMixedPathsUnderSingleVaultRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
key := vault.MasterKey{Password: "correct horse battery staple"}
|
||||
path := filepath.Join(t.TempDir(), "hidden-root.kdbx")
|
||||
|
||||
var initial bytes.Buffer
|
||||
if err := vault.SaveKDBX(&initial, vault.Model{
|
||||
Entries: []vault.Entry{
|
||||
{
|
||||
ID: "entry-1",
|
||||
Title: "Vault Console",
|
||||
Username: "dannyocean",
|
||||
Password: "token-1",
|
||||
URL: "https://vault.crew.example.invalid",
|
||||
Path: []string{"keepass", "Crew", "Internet"},
|
||||
},
|
||||
{
|
||||
ID: "entry-2",
|
||||
Title: "Mail",
|
||||
Username: "dannyocean",
|
||||
Password: "token-2",
|
||||
URL: "https://dispatch.crew.example.invalid",
|
||||
Path: []string{"keepass", "Crew", "eMail"},
|
||||
},
|
||||
},
|
||||
}, key.Password); err != nil {
|
||||
t.Fatalf("SaveKDBX() error = %v", err)
|
||||
}
|
||||
if err := os.WriteFile(path, initial.Bytes(), 0o600); err != nil {
|
||||
t.Fatalf("WriteFile(hidden-root.kdbx) error = %v", err)
|
||||
}
|
||||
|
||||
var sess Manager
|
||||
if err := sess.Open(path, key); err != nil {
|
||||
t.Fatalf("Open() error = %v", err)
|
||||
}
|
||||
|
||||
current, err := sess.Current()
|
||||
if err != nil {
|
||||
t.Fatalf("Current() error = %v", err)
|
||||
}
|
||||
current.Entries[0].Path = []string{"Crew", "Internet"}
|
||||
current.Groups = append(current.Groups, []string{"Crew"}, []string{"Crew", "Internet"}, []string{"Crew", "eMail"})
|
||||
sess.Replace(current)
|
||||
|
||||
if err := sess.Save(); err != nil {
|
||||
t.Fatalf("Save() error = %v", err)
|
||||
}
|
||||
|
||||
reopened, err := os.Open(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Open(saved path) error = %v", err)
|
||||
}
|
||||
defer reopened.Close()
|
||||
|
||||
db := gokeepasslib.NewDatabase()
|
||||
db.Credentials = gokeepasslib.NewPasswordCredentials(key.Password)
|
||||
if err := gokeepasslib.NewDecoder(reopened).Decode(db); err != nil {
|
||||
t.Fatalf("Decode(saved path) error = %v", err)
|
||||
}
|
||||
if err := db.UnlockProtectedEntries(); err != nil {
|
||||
t.Fatalf("UnlockProtectedEntries() error = %v", err)
|
||||
}
|
||||
|
||||
if len(db.Content.Root.Groups) != 1 || db.Content.Root.Groups[0].Name != "keepass" {
|
||||
t.Fatalf("top-level groups = %#v, want single keepass root", db.Content.Root.Groups)
|
||||
}
|
||||
rootGroups := db.Content.Root.Groups[0].Groups
|
||||
if len(rootGroups) != 1 || rootGroups[0].Name != "Crew" {
|
||||
t.Fatalf("keepass child groups = %#v, want single Crew group", rootGroups)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveWithoutPathFails(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user