251 lines
7.5 KiB
Go
251 lines
7.5 KiB
Go
package appstate
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.julianfamily.org/keepassgo/internal/vault"
|
|
)
|
|
|
|
func TestRemoteBindingResolveUsesVaultProfileAndCredentialEntry(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
model := vault.Model{
|
|
Entries: []vault.Entry{
|
|
{
|
|
ID: "linuscaldwell-webdav",
|
|
Title: "Bellagio WebDAV Sign-In",
|
|
Username: "linuscaldwell",
|
|
Password: "bellagio-pass-1",
|
|
Path: []string{"Crew", "Internet"},
|
|
},
|
|
},
|
|
RemoteProfiles: []vault.RemoteProfile{
|
|
{
|
|
ID: "bellagio-webdav",
|
|
Name: "Bellagio Vault",
|
|
Backend: vault.RemoteBackendWebDAV,
|
|
BaseURL: "https://dav.example.invalid/remote.php/dav",
|
|
Path: "files/bellagio/keepass.kdbx",
|
|
},
|
|
},
|
|
}
|
|
|
|
binding := RemoteBinding{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
CredentialEntryID: "linuscaldwell-webdav",
|
|
SyncMode: SyncModeAutomaticOnOpenSave,
|
|
}
|
|
|
|
resolved, err := binding.Resolve(model)
|
|
if err != nil {
|
|
t.Fatalf("Resolve() error = %v", err)
|
|
}
|
|
if got := resolved.Profile.BaseURL; got != "https://dav.example.invalid/remote.php/dav" {
|
|
t.Fatalf("resolved profile base URL = %q, want remote.php/dav URL", got)
|
|
}
|
|
if got := resolved.Profile.Path; got != "files/bellagio/keepass.kdbx" {
|
|
t.Fatalf("resolved profile path = %q, want files/bellagio/keepass.kdbx", got)
|
|
}
|
|
if got := resolved.Credentials.Username; got != "linuscaldwell" {
|
|
t.Fatalf("resolved credentials username = %q, want linuscaldwell", got)
|
|
}
|
|
if got := resolved.Credentials.Password; got != "bellagio-pass-1" {
|
|
t.Fatalf("resolved credentials password = %q, want bellagio-pass-1", got)
|
|
}
|
|
}
|
|
|
|
func TestRemoteBindingResolveFailsWhenVaultReferenceIsMissing(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
model := vault.Model{
|
|
Entries: []vault.Entry{
|
|
{ID: "linuscaldwell-webdav", Title: "Bellagio WebDAV Sign-In"},
|
|
},
|
|
}
|
|
|
|
_, err := (RemoteBinding{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
CredentialEntryID: "missing-creds",
|
|
}).Resolve(model)
|
|
if !errors.Is(err, vault.ErrRemoteProfileNotFound) {
|
|
t.Fatalf("Resolve() error = %v, want ErrRemoteProfileNotFound first", err)
|
|
}
|
|
|
|
model.RemoteProfiles = []vault.RemoteProfile{{
|
|
ID: "bellagio-webdav",
|
|
Name: "Bellagio Vault",
|
|
Backend: vault.RemoteBackendWebDAV,
|
|
BaseURL: "https://dav.example.invalid/remote.php/dav",
|
|
Path: "files/bellagio/keepass.kdbx",
|
|
}}
|
|
|
|
_, err = (RemoteBinding{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
CredentialEntryID: "missing-creds",
|
|
}).Resolve(model)
|
|
if !errors.Is(err, vault.ErrEntryNotFound) {
|
|
t.Fatalf("Resolve() error = %v, want ErrEntryNotFound", err)
|
|
}
|
|
}
|
|
|
|
func TestRemoteBindingJSONStoresOnlyNonSecretReferences(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
content, err := json.Marshal(RemoteBinding{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
CredentialEntryID: "remote-creds-1",
|
|
SyncMode: SyncModeAutomaticOnOpenSave,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal(RemoteBinding) error = %v", err)
|
|
}
|
|
|
|
text := string(content)
|
|
for _, disallowed := range []string{"bellagio-pass-1", "password", "username", "baseUrl"} {
|
|
if strings.Contains(text, disallowed) {
|
|
t.Fatalf("binding JSON %q unexpectedly contains %q", text, disallowed)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigureRemoteBindingStoresProfileAndCredentialsInVault(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var model vault.Model
|
|
|
|
binding, err := ConfigureRemoteBinding(&model, RemoteBindingInput{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
RemoteProfileName: "Bellagio Vault",
|
|
BaseURL: "https://dav.example.invalid/remote.php/dav",
|
|
RemotePath: "files/bellagio/keepass.kdbx",
|
|
CredentialEntryID: "remote-creds-1",
|
|
CredentialTitle: "Bellagio WebDAV Sign-In",
|
|
Username: "linuscaldwell",
|
|
Password: "bellagio-pass-1",
|
|
CredentialPath: []string{"Crew", "Internet"},
|
|
SyncMode: SyncModeAutomaticOnOpenSave,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ConfigureRemoteBinding() error = %v", err)
|
|
}
|
|
|
|
if len(model.RemoteProfiles) != 1 {
|
|
t.Fatalf("len(RemoteProfiles) = %d, want 1", len(model.RemoteProfiles))
|
|
}
|
|
if got := model.RemoteProfiles[0].BaseURL; got != "https://dav.example.invalid/remote.php/dav" {
|
|
t.Fatalf("stored remote profile base URL = %q, want remote.php/dav URL", got)
|
|
}
|
|
|
|
credentials, err := model.EntryByID("remote-creds-1")
|
|
if err != nil {
|
|
t.Fatalf("EntryByID(remote-creds-1) error = %v", err)
|
|
}
|
|
if credentials.Username != "linuscaldwell" || credentials.Password != "bellagio-pass-1" {
|
|
t.Fatalf("stored credential entry = %#v, want linuscaldwell/bellagio-pass-1", credentials)
|
|
}
|
|
if credentials.URL != "https://dav.example.invalid/remote.php/dav" {
|
|
t.Fatalf("stored credential entry URL = %q, want remote.php/dav URL", credentials.URL)
|
|
}
|
|
|
|
if binding.LocalVaultPath != "/tmp/bellagio.kdbx" {
|
|
t.Fatalf("binding LocalVaultPath = %q, want /tmp/bellagio.kdbx", binding.LocalVaultPath)
|
|
}
|
|
if binding.RemoteProfileID != "bellagio-webdav" || binding.CredentialEntryID != "remote-creds-1" {
|
|
t.Fatalf("binding = %#v, want only vault references", binding)
|
|
}
|
|
}
|
|
|
|
func TestConfigureRemoteBindingRejectsIncompleteInput(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
input RemoteBindingInput
|
|
}{
|
|
{
|
|
name: "missing_local_vault_path",
|
|
input: RemoteBindingInput{
|
|
RemoteProfileID: "bellagio-webdav",
|
|
BaseURL: "https://dav.example.invalid/remote.php/dav",
|
|
RemotePath: "files/bellagio/keepass.kdbx",
|
|
CredentialEntryID: "remote-creds-1",
|
|
Password: "bellagio-pass-1",
|
|
},
|
|
},
|
|
{
|
|
name: "missing_remote_base_url",
|
|
input: RemoteBindingInput{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
RemotePath: "files/bellagio/keepass.kdbx",
|
|
CredentialEntryID: "remote-creds-1",
|
|
Password: "bellagio-pass-1",
|
|
},
|
|
},
|
|
{
|
|
name: "missing_credential_entry_id",
|
|
input: RemoteBindingInput{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
BaseURL: "https://dav.example.invalid/remote.php/dav",
|
|
RemotePath: "files/bellagio/keepass.kdbx",
|
|
Password: "bellagio-pass-1",
|
|
},
|
|
},
|
|
} {
|
|
tc := tc
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var model vault.Model
|
|
if _, err := ConfigureRemoteBinding(&model, tc.input); err == nil {
|
|
t.Fatalf("ConfigureRemoteBinding(%#v) error = nil, want validation error", tc.input)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRemoveRemoteBindingRemovesProfileAndCredentialsFromVault(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
model := vault.Model{
|
|
Entries: []vault.Entry{{
|
|
ID: "remote-creds-1",
|
|
Title: "Bellagio WebDAV Sign-In",
|
|
Username: "linuscaldwell",
|
|
Password: "bellagio-pass-1",
|
|
}},
|
|
RemoteProfiles: []vault.RemoteProfile{{
|
|
ID: "bellagio-webdav",
|
|
Name: "Bellagio Vault",
|
|
Backend: vault.RemoteBackendWebDAV,
|
|
BaseURL: "https://dav.example.invalid/remote.php/dav",
|
|
Path: "files/bellagio/keepass.kdbx",
|
|
}},
|
|
}
|
|
|
|
err := RemoveRemoteBinding(&model, RemoteBinding{
|
|
LocalVaultPath: "/tmp/bellagio.kdbx",
|
|
RemoteProfileID: "bellagio-webdav",
|
|
CredentialEntryID: "remote-creds-1",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("RemoveRemoteBinding() error = %v", err)
|
|
}
|
|
|
|
if got := len(model.RemoteProfiles); got != 0 {
|
|
t.Fatalf("len(RemoteProfiles) = %d, want 0", got)
|
|
}
|
|
if _, err := model.EntryByID("remote-creds-1"); !errors.Is(err, vault.ErrEntryNotFound) {
|
|
t.Fatalf("EntryByID(remote-creds-1) error = %v, want ErrEntryNotFound", err)
|
|
}
|
|
}
|