~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-fedproxy

fedproxy and ingress modules for atlibs: SSH public keys on your PDS, did:key ingress; pages and web tiles

0
0
main
118 lines · 5.0 KB Raw History
// node --test web/fedproxy-ssh-public-keys/fedproxy-cubit.test.mjs  (after `cargo wasm`)
// The cubit with the real fedproxy module and runModule; only OAuth and the PDS are stubbed.
import assert from "node:assert/strict";
import { registerHooks } from "node:module";
import { test } from "node:test";

import { load } from "../../../atlibs/rust/src/harness.mjs";

// The page resolves atlibs/ through its import map; Node gets the same mapping here.
registerHooks({
	resolve(specifier, context, next) {
		const lib = specifier.startsWith("atlibs/") && new URL(`../../../atlibs/javascript/src/${specifier.slice("atlibs/".length)}`, import.meta.url).href;
		return next(lib || specifier, context);
	},
});
const { FedproxyCubit } = await import("./fedproxy-cubit.js");
const { run } = await load(new URL("../../target/wasm32-unknown-unknown/release/fedproxy.wasm", import.meta.url));

const did = "did:plc:lpfuqerea3deuoyrn7ojser4";
const handle = "alice.bsky.social";
const key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG9BVPpCtKTckpQVk4etPSsC65Vo91Ie0kpjJH6PSdow laptop";

// A PDS holding com.fedproxy.sshPublicKey records, answering the calls the module plans.
function pds(records = []) {
	const calls = [];
	const agent = {
		did,
		com: { atproto: { server: { getSession: async () => ({ success: true, data: { handle } }) } } },
		async call(nsid, params, input) {
			calls.push(nsid);
			if (nsid === "com.atproto.repo.listRecords") return { data: { records } };
			if (nsid === "com.atproto.repo.createRecord") {
				const uri = `at://${did}/com.fedproxy.sshPublicKey/${records.length}`;
				records.push({ uri, value: input.record });
				return { data: { uri, cid: "bafy" } };
			}
			throw new Error(`unexpected ${nsid}`);
		},
	};
	return { agent, calls, records };
}

function cubitWith({ session = { sub: did }, agent } = {}) {
	const revoked = [];
	const client = Promise.resolve({
		init: async () => (session ? { session } : undefined),
		signIn: async () => { throw new Error("popup blocked"); },
		revoke: async (sub) => revoked.push(sub),
	});
	const cubit = new FedproxyCubit({
		client,
		makeAgent: () => agent,
		module: Promise.resolve({ module: new Uint8Array(), calls: ["com.atproto.repo.listRecords", "com.atproto.repo.createRecord"] }),
		ctx: { wasm: { run: async ({ entry, input }) => run(entry, input) } },
	});
	const states = [];
	cubit.subscribe((state) => states.push(state));
	return { cubit, states, revoked };
}

const summary = (s) => `${s.session} keys:${s.keys.status} create:${s.create.status}`;

test("init without a session shows sign-in", async () => {
	const { cubit, states } = cubitWith({ session: null });
	await cubit.init();
	assert.deepEqual(states.map(summary), ["loading keys:idle create:idle", "signed-out keys:idle create:idle"]);
});

test("init restores the session and lists keys grouped by service", async () => {
	const { agent } = pds([{ uri: `at://${did}/com.fedproxy.sshPublicKey/1`, value: { service: "app", name: "laptop", key } }]);
	const { cubit, states } = cubitWith({ agent });
	await cubit.init();
	assert.deepEqual(states.map(summary), [
		"loading keys:idle create:idle",
		"signed-in keys:idle create:idle",
		"signed-in keys:loading create:idle",
		"signed-in keys:loaded create:idle",
	]);
	assert.equal(cubit.state.handle, handle);
	const [service] = cubit.state.keys.services;
	assert.equal(service.host, "app--alice-bsky-social.fedproxy.com");
	assert.match(service.command, /-R app:80:127\.0\.0\.1:8080/);
});

test("a rejected key reports the module's message and writes nothing", async () => {
	const { agent, calls } = pds();
	const { cubit, states } = cubitWith({ agent });
	await cubit.init();
	states.length = 0;
	await cubit.createKey({ name: "laptop", service: "app", key: "not a key" });
	assert.deepEqual(states.map((s) => s.create.status), ["busy", "error"]);
	assert.match(cubit.state.create.error, /^key must be an OpenSSH public key/);
	assert.ok(!calls.includes("com.atproto.repo.createRecord"));
});

test("creating a key writes it, relists, then reports done with its uri", async () => {
	const { agent, records } = pds();
	const { cubit, states } = cubitWith({ agent });
	await cubit.init();
	states.length = 0;
	await cubit.createKey({ name: "laptop", service: "*.app", key });
	assert.deepEqual(states.map((s) => `${s.keys.status}/${s.create.status}`), ["loaded/busy", "loading/busy", "loaded/busy", "loaded/done"]);
	assert.equal(records.length, 1);
	assert.equal(records[0].value.service, "*.app");
	assert.equal(cubit.state.create.uri, `at://${did}/com.fedproxy.sshPublicKey/0`);
	assert.equal(cubit.state.keys.services[0].host, "*.app--alice-bsky-social.fedproxy.com");
});

test("login failure is shown; logout revokes and resets", async () => {
	const { agent } = pds();
	const { cubit, revoked } = cubitWith({ agent });
	await cubit.init();
	await cubit.login("alice.bsky.social");
	assert.deepEqual(cubit.state.login, { busy: false, error: "Login error: popup blocked" });
	await cubit.logout();
	assert.deepEqual(revoked, [did]);
	assert.equal(summary(cubit.state), "signed-out keys:idle create:idle");
});