chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
55
third_party/pi/packages/coding-agent/test/mcp-oauth-store.test.ts
vendored
Normal file
55
third_party/pi/packages/coding-agent/test/mcp-oauth-store.test.ts
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { InMemoryAuthStorageBackend } from "../src/core/auth-storage.ts";
|
||||
import { McpOAuthCredentialStore } from "../src/extensions/mcp/oauth.ts";
|
||||
|
||||
const SERVER_URL = "https://mcp.example.com/mcp";
|
||||
|
||||
function state(accessToken: string) {
|
||||
return { serverUrl: SERVER_URL, tokens: { access_token: accessToken, token_type: "Bearer" } };
|
||||
}
|
||||
|
||||
function storedKeys(backend: InMemoryAuthStorageBackend): string[] {
|
||||
return Object.keys(JSON.parse(backend.withLock((current) => ({ result: current ?? "{}" }))));
|
||||
}
|
||||
|
||||
describe("MCP OAuth credential store", () => {
|
||||
// https://github.com/earendil-works/pi/issues/10252
|
||||
it("keeps separate credentials for servers sharing a SERVER_URL", async () => {
|
||||
const store = new McpOAuthCredentialStore(new InMemoryAuthStorageBackend());
|
||||
await store.forServer("work", SERVER_URL).save(state("work-token"));
|
||||
await store.forServer("personal", SERVER_URL).save(state("personal-token"));
|
||||
|
||||
expect((await store.forServer("work", SERVER_URL).load())?.tokens?.access_token).toBe("work-token");
|
||||
expect((await store.forServer("personal", SERVER_URL).load())?.tokens?.access_token).toBe("personal-token");
|
||||
|
||||
expect(store.remove("work", SERVER_URL)).toBe(true);
|
||||
expect(await store.forServer("work", SERVER_URL).load()).toBeUndefined();
|
||||
expect(store.tokens("personal", SERVER_URL)?.access_token).toBe("personal-token");
|
||||
});
|
||||
|
||||
it("moves credentials stored by SERVER_URL to the first server that loads them", async () => {
|
||||
const backend = new InMemoryAuthStorageBackend();
|
||||
backend.withLock(() => ({ result: undefined, next: JSON.stringify({ [SERVER_URL]: state("legacy-token") }) }));
|
||||
const store = new McpOAuthCredentialStore(backend);
|
||||
|
||||
// Reading tokens does not take the legacy state over.
|
||||
expect(store.tokens("work", SERVER_URL)?.access_token).toBe("legacy-token");
|
||||
expect(storedKeys(backend)).toEqual([SERVER_URL]);
|
||||
|
||||
expect((await store.forServer("my_work", SERVER_URL).load())?.tokens?.access_token).toBe("legacy-token");
|
||||
// Names differing only in `-` and `_` are the same server.
|
||||
expect(store.tokens("my-work", SERVER_URL)?.access_token).toBe("legacy-token");
|
||||
expect(await store.forServer("personal", SERVER_URL).load()).toBeUndefined();
|
||||
expect(storedKeys(backend)).toEqual([`mcp__my_work|${SERVER_URL}`]);
|
||||
});
|
||||
|
||||
it("signs out of credentials stored by SERVER_URL", () => {
|
||||
const backend = new InMemoryAuthStorageBackend();
|
||||
backend.withLock(() => ({ result: undefined, next: JSON.stringify({ [SERVER_URL]: state("legacy-token") }) }));
|
||||
const store = new McpOAuthCredentialStore(backend);
|
||||
|
||||
expect(store.remove("work", SERVER_URL)).toBe(true);
|
||||
expect(storedKeys(backend)).toEqual([]);
|
||||
expect(store.remove("work", SERVER_URL)).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user