~ 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
54 lines · 2.4 KB Raw History
import { templated } from 'atlibs/component/index.js'

const Base = await templated(new URL('./ssh-public-keys-list.html', import.meta.url));

function keyItem(k) {
	const li = Base.templates.key.content.cloneNode(true);
	li.querySelector(".name").textContent = k.name;
	if (k.createdAt) li.querySelector(".created").textContent = ` (Created: ${new Date(k.createdAt).toLocaleDateString()})`;
	li.querySelector(".key").textContent = k.key;
	return li;
}

// host and command come from the fedproxy module: host is null for "*", a *.pattern for wildcard subdomains.
function serviceArticle({ host, command, keys }) {
	const article = Base.templates.service.content.cloneNode(true);
	const header = article.querySelector(".host");
	if (host === null) {
		// Auth wildcard: key valid for every service, not a host itself.
		header.textContent = "* (key valid for all your services)";
	} else if (host.startsWith("*.")) {
		// Explicit wildcard subdomain: matches any sub-host, so not a single clickable link.
		header.textContent = host;
	} else {
		header.append(Object.assign(document.createElement("a"), { target: "_blank", href: `https://${host}`, textContent: host }));
	}
	article.querySelector(".command").textContent = command;
	article.querySelector("ul").append(...keys.map(keyItem));
	return article;
}

// All text goes in through textContent, so record values cannot inject markup.
// What it shows comes only from render(state), the page cubit's state.
// Classes, not ids, inside: the page may hold more than one.
customElements.define('ssh-public-keys-list', class extends Base {
	render(state, previous) {
		this.querySelector(".panel").style.display = state.session === "signed-in" ? "inherit" : "none";
		if (previous && previous.keys === state.keys) return;
		const list = this.querySelector(".keys");
		const { status, services, error } = state.keys;
		if (status === "loading" || status === "idle") {
			list.setAttribute("aria-busy", "true");
			list.replaceChildren();
			return;
		}
		list.removeAttribute("aria-busy");
		if (status === "error") {
			list.replaceChildren(Object.assign(document.createElement("p"), { style: "color: #E37474;", textContent: `Error loading keys: ${error}` }));
		} else if (services.length === 0) {
			list.innerHTML = "<p><em>No SSH keys found. Create one above!</em></p>";
		} else {
			list.replaceChildren(...services.map((service) => serviceArticle(service)));
		}
	}
});