feat: harden plugin api for separate repos, signed updates and generic external login

This commit is contained in:
LukeGus committed 2026-09-29 18:11:59 -05:00
1 parent fb9c168b6b
commit 80944301dd
310 files changed
+6577 -4927

No files matched your search

@@ -0,0 +1,103 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
const api = vi.hoisted(() => ({
getSharedWithMe: vi.fn(async () => [] as unknown[]),
}));
const sdk = vi.hoisted(() => ({
invokeAction: vi.fn(async () => undefined),
allowed: true,
}));
vi.mock("../../src/frontend/api", () => api);
vi.mock("@termix/plugin-sdk/frontend", async (importActual) => ({
...(await importActual<typeof import("@termix/plugin-sdk/frontend")>()),
invokeAction: sdk.invokeAction,
usePermission: () => sdk.allowed,
useHosts: () => ({ hosts: [], loaded: true }),
useTranslation: () => ({
t: (key: string, options?: Record<string, unknown>) =>
options ? `${key}:${JSON.stringify(options)}` : key,
language: "en",
}),
}));
import { SharedWithMeSection } from "../../src/frontend/SharedWithMeSection";
function shared(overrides: Record<string, unknown> = {}) {
return {
sessionId: "sess-1",
hostId: 5,
hostName: "prod-db",
isConnected: true,
sharedByUsername: "alice",
permissionLevel: "read-only",
shareId: "share-1",
...overrides,
};
}
beforeEach(() => {
api.getSharedWithMe.mockReset();
sdk.invokeAction.mockClear();
sdk.allowed = true;
});
afterEach(() => cleanup());
describe("shared with me section", () => {
it("lists sessions shared with the user", async () => {
api.getSharedWithMe.mockResolvedValue([shared()]);
render(<SharedWithMeSection />);
expect(await screen.findByText("prod-db")).toBeTruthy();
expect(
screen.getByText('connections.sharedBy:{"username":"alice"}'),
).toBeTruthy();
expect(
screen.getByText("sessionSharing.permissionLevel.readOnly"),
).toBeTruthy();
});
it("hides a session the user already joined in a tab", async () => {
api.getSharedWithMe.mockResolvedValue([shared()]);
render(
<SharedWithMeSection openTabData={[{ joinSharedSessionId: "sess-1" }]} />,
);
await vi.waitFor(() => expect(api.getSharedWithMe).toHaveBeenCalled());
expect(screen.queryByText("prod-db")).toBeNull();
});
it("filters by the connections search", async () => {
api.getSharedWithMe.mockResolvedValue([
shared(),
shared({ sessionId: "sess-2", hostName: "web", sharedByUsername: "bob" }),
]);
render(<SharedWithMeSection search="bob" />);
expect(await screen.findByText("web")).toBeTruthy();
expect(screen.queryByText("prod-db")).toBeNull();
});
it("joins through the terminal's open action", async () => {
api.getSharedWithMe.mockResolvedValue([shared()]);
render(<SharedWithMeSection />);
fireEvent.click(await screen.findByText("connections.join"));
expect(sdk.invokeAction).toHaveBeenCalledWith(
"terminal.open",
expect.objectContaining({ id: "5", name: "prod-db" }),
expect.objectContaining({
joinSharedSessionId: "sess-1",
joinShareId: "share-1",
}),
);
});
it("renders nothing for a user without the use permission", async () => {
sdk.allowed = false;
api.getSharedWithMe.mockResolvedValue([shared()]);
const { container } = render(<SharedWithMeSection />);
expect(container.textContent).toBe("");
expect(api.getSharedWithMe).not.toHaveBeenCalled();
});
});
@@ -69,7 +69,9 @@ describe("session-sharing activate", () => {
expect(rendered.registered.slot("shell.overlay")).toHaveLength(2);
expect(rendered.registered.actions().sort()).toEqual([
"session-sharing.share",
"sessions.sharedWithMe",
]);
expect(rendered.registered.slot("connections.sections")).toEqual([
"session-sharing.sharedWithMe",
]);
});
@@ -167,20 +169,6 @@ describe("session-sharing activate", () => {
);
});
it("answers sessions shared with the user through the api", async () => {
const shared = [{ sessionId: "s", isOwnSession: false }];
rendered = await renderWithApp(plugin, {
manifest,
locales,
api: stubApi({
get: vi.fn(async () => ({ data: shared })) as never,
}),
});
await expect(invokeAction("sessions.sharedWithMe")).resolves.toEqual(
shared,
);
});
it("removes everything it registered on deactivate", async () => {
const app = await renderWithApp(plugin, {
manifest,