s3d is driven entirely by a CLI and a two-route admin API, which keeps Sia storage out of reach for anyone who does not live in a terminal. Pithos wraps it: install the pinned s3d release (checksum verified), start/stop and logs, indexer login, users and access keys, a bucket and object browser with share links and public-read policies, and the upload pipeline stats. One control server (core/) serves one UI (ui/), and three hosts run it: a web console, an Electron desktop window and a Theseus add-on, so a feature lands everywhere at once. The server binds loopback, rejects foreign Host headers, and signs views in with a one-time secret that becomes a SameSite=Strict cookie. s3d login reads the recovery phrase with term.ReadPassword, so it is driven through a pty, with a console window fallback where the pty module is not shipped.
34 lines
1.2 KiB
JavaScript
34 lines
1.2 KiB
JavaScript
// s3d's admin API (Basic auth, empty user): upload stats, flush, snapshots.
|
|
|
|
function authHeader(password) {
|
|
return 'Basic ' + Buffer.from(':' + password).toString('base64');
|
|
}
|
|
|
|
async function adminFetch(cfg, method, route, { timeout = 10_000 } = {}) {
|
|
if (!cfg.adminAddress || !cfg.adminPassword) throw new Error('adminAddress and adminPassword must be set in s3d.yml');
|
|
const ctl = new AbortController();
|
|
const timer = timeout ? setTimeout(() => ctl.abort(), timeout) : null;
|
|
try {
|
|
const res = await fetch(`http://${cfg.adminAddress}${route}`, {
|
|
method, headers: { authorization: authHeader(cfg.adminPassword) }, signal: ctl.signal,
|
|
});
|
|
const text = await res.text();
|
|
if (!res.ok) throw new Error(`admin API ${route}: ${res.status} ${text.trim()}`);
|
|
return text;
|
|
} finally {
|
|
if (timer) clearTimeout(timer);
|
|
}
|
|
}
|
|
|
|
export async function uploadStats(cfg) {
|
|
return JSON.parse(await adminFetch(cfg, 'GET', '/stats/uploads'));
|
|
}
|
|
|
|
// Blocks until every pending object is on Sia, so no timeout.
|
|
export async function flush(cfg) {
|
|
await adminFetch(cfg, 'POST', '/objects/flush', { timeout: 0 });
|
|
}
|
|
|
|
export async function snapshot(cfg) {
|
|
return adminFetch(cfg, 'POST', '/snapshots', { timeout: 0 });
|
|
}
|