/** * @file session-account.test.js * @description A session no workspace owns is billed to the user of the Linux * account it ran as (server/lib/session-account.js): a member's account to * that member, the host's to the admin marked as its owner (or the only * admin). A workspace's ownership always wins, a pushed session never gets an * account, and the hook peer is stamped once. * @author Nguyễn Ngọc Trí Vĩ */ const { describe, it, before, after } = require("node:test"); const assert = require("node:assert/strict"); const path = require("node:path"); const fs = require("node:fs"); const os = require("node:os"); const TMP = fs.mkdtempSync(path.join(os.tmpdir(), "session-account-test-")); process.env.DASHBOARD_DB_PATH = path.join(TMP, "dashboard.db"); const { db } = require("../db"); const sa = require("../lib/session-account"); const scope = require("../lib/scope"); const { OWNED_SESSIONS } = require("../routes/users"); const own = (id) => { const w = scope.ownSessionWhere({ user: { id } }); return db .prepare(`SELECT id FROM sessions WHERE ${w.where} ORDER BY id`) .all(...w.params) .map((r) => r.id); }; before(() => { const user = db.prepare( "INSERT INTO users (id, username, role, password_hash) VALUES (?, ?, ?, 'x')" ); user.run(1, "boss", "admin"); user.run(2, "dev", "developer"); db.prepare("INSERT INTO lanes (id, cwd, tool, owner_id) VALUES (1, '/w/dev', 'claude', 2)").run(); const s = db.prepare( "INSERT INTO sessions (id, name, status, cwd, lane_id, account, source) VALUES (?, ?, 'active', '/w', ?, ?, ?)" ); s.run("host-free", "eval", null, "", "local"); s.run("dev-free", "eval", null, "dev", "local"); s.run("host-in-dev-lane", "lane", 1, "", "local"); s.run("unknown", "old", null, null, "local"); s.run("gone-member", "x", null, "ghost", "local"); }); after(() => fs.rmSync(TMP, { recursive: true, force: true })); describe("session-account", () => { it("bills a member's account to that member and the host's to the only admin", () => { assert.equal(sa.hostOwner(), 1); assert.deepEqual(own(1), ["host-free"]); assert.deepEqual(own(2), ["dev-free", "host-in-dev-lane"]); }); it("lets the workspace's owner win over the account", () => { assert.ok(!own(1).includes("host-in-dev-lane")); }); it("bills nobody for the host when two admins and none is marked, then the marked one", () => { db.prepare( "INSERT INTO users (id, username, role, password_hash) VALUES (3, 'boss2', 'admin', 'x')" ).run(); assert.equal(sa.hostOwner(), null); assert.deepEqual(own(1), []); sa.setHostOwner(3); assert.equal(sa.hostOwner(), 3); assert.deepEqual(own(3), ["host-free"]); sa.setHostOwner(1); assert.deepEqual(own(3), []); assert.deepEqual(own(1), ["host-free"]); }); it("lists account-billed sessions in OWNED_SESSIONS (Users page, spend quota)", () => { const rows = db.prepare(OWNED_SESSIONS).all(); const by = Object.fromEntries(rows.map((r) => [r.session_id, r.uid])); assert.equal(by["host-free"], 1); assert.equal(by["dev-free"], 2); assert.equal(by["host-in-dev-lane"], 2); assert.equal(by.unknown, undefined); assert.equal(by["gone-member"], undefined); }); it("stamps the hook peer once and never a pushed session", () => { db.prepare("INSERT INTO sessions (id, name, status, cwd) VALUES ('fresh', 'f', 'active', '/w')").run(); db.prepare("INSERT INTO sessions (id, name, status, cwd) VALUES ('pushed', 'p', 'active', '/w')").run(); sa.stampFromPeer("fresh", { kind: "member", name: "dev", home: "/srv/u/dev" }); sa.stampFromPeer("fresh", { kind: "host" }); sa.stampFromPeer("pushed", { kind: "host" }, "push:laptop"); sa.stampFromPeer("pushed", { kind: "refused" }); const acct = (id) => db.prepare("SELECT account FROM sessions WHERE id = ?").get(id).account; assert.equal(acct("fresh"), "dev"); assert.equal(acct("pushed"), null); }); it("gives a folder's account to sessions no hook stamped, skipping pushed ones", () => { db.prepare( "INSERT INTO sessions (id, name, status, cwd, source) VALUES ('remote', 'r', 'active', '/w', 'push:laptop')" ).run(); sa.stampFromFolders(); const acct = (id) => db.prepare("SELECT account FROM sessions WHERE id = ?").get(id).account; // Outside S3 every folder is the host's. assert.equal(acct("unknown"), ""); assert.equal(acct("pushed"), ""); assert.equal(acct("remote"), null); }); });