fileSessions
uses node:fs
Sign-ins kept in file: one this user owns, not a link, which only they can read (it's made so if others could),
written whole and new each time, in a directory only they can enter.
import { Refused } from "#codebase/tcmts/atproto"; import type { KeptSessions, SessionStore } from "#codebase/tcmts/atproto"; import { randomBytes } from "node:crypto"; import fs from "node:fs"; import path from "node:path"; export function fileSessions(file: string): SessionStore { const read = (): KeptSessions => { let st: fs.Stats; try { st = fs.lstatSync(file); } catch { return { sessions: {} }; } if (!st.isFile() || (process.getuid !== undefined && st.uid !== process.getuid())) throw new Refused( `${file} isn't a file of yours: sign-ins aren't read from it (remove it to sign in again)`, ); if (process.platform !== "win32" && st.mode & 0o077) fs.chmodSync(file, 0o600); try { return JSON.parse(fs.readFileSync(file, "utf8")) as KeptSessions; } catch { return { sessions: {} }; } }; return { read, keep(did, s) { const kept = read(); if (s) { kept.sessions[did] = s; kept.last = did; } else { delete kept.sessions[did]; if (kept.last === did) delete kept.last; } // (its directory this user's alone, whatever made it; the file written new, never through a link someone left) fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 }); fs.chmodSync(path.dirname(file), 0o700); const tmp = `${file}.${process.pid}.${randomBytes(6).toString("hex")}`; fs.writeFileSync(tmp, `${JSON.stringify(kept, null, 2)}\n`, { mode: 0o600, flag: "wx" }); fs.renameSync(tmp, file); }, }; }