Sync API mutations into shared session state

This commit is contained in:
Joe Julian
2026-04-11 10:26:55 -07:00
parent 852c115b2a
commit 0de682a3af
3 changed files with 185 additions and 15 deletions
+96
View File
@@ -183,6 +183,48 @@ func TestVaultServiceFindsBrowserLoginsForAuthorizedClients(t *testing.T) {
}
}
func TestVaultServiceFindsBrowserLoginsWithinAuthorizedGroupScope(t *testing.T) {
t.Parallel()
client, _, cleanup := newTestClientForModel(t, vault.Model{
Entries: []vault.Entry{
{
ID: "codex-nextcloud",
Title: "Nextcloud (codex)",
Username: "jjulian",
Password: "secret-1",
URL: "https://nextcloud.example.invalid",
Path: []string{"keepass", "Joe", "codex"},
},
{
ID: "joe-nextcloud",
Title: "Nextcloud",
Username: "jjulian",
Password: "secret-2",
URL: "https://nextcloud.example.invalid",
Path: []string{"keepass", "Joe", "Internet"},
},
testAPITokenEntry(t,
apitokens.PolicyRule{Effect: apitokens.EffectAllow, Operation: apitokens.OperationListEntries, Resource: apitokens.Resource{Kind: apitokens.ResourceGroup, Path: []string{"keepass", "Joe", "codex"}}},
),
},
})
defer cleanup()
resp, err := client.FindBrowserLogins(tokenContext(defaultTestTokenSecret), &keepassgov1.FindBrowserLoginsRequest{
PageUrl: "https://nextcloud.example.invalid/login",
})
if err != nil {
t.Fatalf("FindBrowserLogins() error = %v", err)
}
if len(resp.Matches) != 1 {
t.Fatalf("len(FindBrowserLogins().Matches) = %d, want 1", len(resp.Matches))
}
if resp.Matches[0].Id != "codex-nextcloud" {
t.Fatalf("FindBrowserLogins().Matches[0].Id = %q, want codex-nextcloud", resp.Matches[0].Id)
}
}
func TestVaultServiceGetsBrowserCredentialForAuthorizedClients(t *testing.T) {
t.Parallel()
@@ -940,6 +982,60 @@ func TestVaultServiceUpsertsEntriesForAuthorizedClients(t *testing.T) {
}
}
func TestVaultServiceUpsertEntryUpdatesLifecycleModel(t *testing.T) {
t.Parallel()
model := vault.Model{
Entries: []vault.Entry{
testAPITokenEntry(t,
apitokens.PolicyRule{Effect: apitokens.EffectAllow, Operation: apitokens.OperationMutateEntry, Resource: apitokens.Resource{Kind: apitokens.ResourceGroup, Path: []string{"Root"}}},
),
},
}
lifecycle := &stubLifecycle{model: model}
listener := bufconn.Listen(1024 * 1024)
clipboardWriter := &memoryClipboardWriter{}
service := NewServerWithLifecycle(model, passwords.DefaultProfiles(), clipboardWriter, lifecycle)
server := grpc.NewServer()
keepassgov1.RegisterVaultServiceServer(server, service)
go func() { _ = server.Serve(listener) }()
t.Cleanup(func() {
server.Stop()
_ = listener.Close()
})
conn, err := grpc.NewClient("passthrough:///bufnet",
grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) {
return listener.DialContext(ctx)
}),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
t.Fatalf("NewClient() error = %v", err)
}
t.Cleanup(func() { _ = conn.Close() })
client := keepassgov1.NewVaultServiceClient(conn)
_, err = client.UpsertEntry(tokenContext(defaultTestTokenSecret), &keepassgov1.UpsertEntryRequest{
Entry: &keepassgov1.Entry{
Id: "lifecycle-visible",
Title: "Lifecycle Visible",
Path: []string{"Root", "Internet"},
},
})
if err != nil {
t.Fatalf("UpsertEntry() error = %v", err)
}
current, err := lifecycle.Current()
if err != nil {
t.Fatalf("Current() error = %v", err)
}
if _, err := current.EntryByID("lifecycle-visible"); err != nil {
t.Fatalf("Current().EntryByID() error = %v, want persisted lifecycle-visible entry", err)
}
}
func TestVaultServiceDeletesAndRestoresEntriesForAuthorizedClients(t *testing.T) {
t.Parallel()