51 lines
2.6 KiB
TypeScript
51 lines
2.6 KiB
TypeScript
import { after, test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
|
|
process.env.JWT_SECRET = "local-test-only-secret-32-characters-long";
|
|
process.env.DATUM_ADMIN_PASSWORD = "local-test-only";
|
|
process.env.NOSTR_OWNER_PUBKEYS = "a".repeat(64);
|
|
const { ChatStore } = await import("../src/chat/store.js");
|
|
const dir = mkdtempSync(join(tmpdir(), "gashboard-chat-"));
|
|
after(() => rmSync(dir, { recursive: true, force: true }));
|
|
const owner = "a".repeat(64);
|
|
const viewer = "b".repeat(64);
|
|
const newcomer = "c".repeat(64);
|
|
|
|
test("encrypted history, reactions and key wraps survive restart with private permissions", () => {
|
|
const file = join(dir, "chat.json");
|
|
const store = new ChatStore(file);
|
|
store.shareKey(owner, [{ recipientPubkey: owner, ciphertext: "encrypted-key" }]);
|
|
const message = store.addMessage({ pubkey: owner, content: "encrypted-message" });
|
|
store.addReaction({ pubkey: owner, messageId: message.id, content: "encrypted-reaction" });
|
|
assert.deepEqual(new ChatStore(file).list(), store.list());
|
|
assert.equal(statSync(file).mode & 0o777, 0o600);
|
|
const copy = store.list();
|
|
copy.keyWraps[0]!.ciphertext = "changed";
|
|
assert.equal(store.list().keyWraps[0]!.ciphertext, "encrypted-key");
|
|
writeFileSync(file, "{}");
|
|
assert.throws(() => new ChatStore(file));
|
|
});
|
|
|
|
test("new invitations and simultaneous first visits cannot overwrite the room key", () => {
|
|
const store = new ChatStore(join(dir, "invites.json"));
|
|
store.shareKey(owner, [{ recipientPubkey: owner, ciphertext: "original-key" }]);
|
|
assert.throws(() => store.shareKey(viewer, [{ recipientPubkey: viewer, ciphertext: "different-key" }]), /existing chat member/);
|
|
store.shareKey(owner, [{ recipientPubkey: viewer, ciphertext: "same-key-for-viewer" }]);
|
|
assert.throws(() => store.shareKey(viewer, [{ recipientPubkey: viewer, ciphertext: "replacement-key" }]), /already shared/);
|
|
store.shareKey(viewer, [{ recipientPubkey: newcomer, ciphertext: "same-key-for-newcomer" }]);
|
|
assert.equal(store.list().keyWraps[0]!.ciphertext, "original-key");
|
|
assert.equal(store.list().keyWraps.length, 3);
|
|
});
|
|
|
|
test("failed persistence does not report or retain an unsaved message", () => {
|
|
const parent = join(dir, "blocked");
|
|
const store = new ChatStore(join(parent, "chat.json"));
|
|
writeFileSync(parent, "not a directory");
|
|
assert.throws(() => store.addMessage({ pubkey: owner, content: "ciphertext" }));
|
|
assert.deepEqual(store.list().messages, []);
|
|
assert.equal(readFileSync(parent, "utf8"), "not a directory");
|
|
});
|