mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-17 05:43:36 +00:00
refactor(tests): move backend tests into src/backend/tests mirror tree
Backend *.test.ts files (and the test-support harness) no longer sit next to source files; they live under src/backend/tests/ mirroring the source layout. Imports rewritten accordingly; CLAUDE.md convention updated.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import crypto from "crypto";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { FieldEncryptionBoundary } from "../../../database/repositories/field-encryption-boundary.js";
|
||||
|
||||
describe("FieldEncryptionBoundary", () => {
|
||||
const userDataKey = crypto.randomBytes(32);
|
||||
|
||||
it("encrypts sensitive host fields while leaving queryable metadata plaintext", () => {
|
||||
const host = {
|
||||
id: 42,
|
||||
userId: "user-1",
|
||||
name: "prod-db",
|
||||
ip: "10.0.0.5",
|
||||
username: "root",
|
||||
password: "secret",
|
||||
rdpPassword: "rdp-secret",
|
||||
};
|
||||
|
||||
const encrypted = FieldEncryptionBoundary.encryptRecord(
|
||||
"ssh_data",
|
||||
host,
|
||||
userDataKey,
|
||||
);
|
||||
|
||||
expect(encrypted.password).not.toBe("secret");
|
||||
expect(encrypted.rdpPassword).not.toBe("rdp-secret");
|
||||
expect(encrypted.ip).toBe("10.0.0.5");
|
||||
expect(encrypted.name).toBe("prod-db");
|
||||
|
||||
const decrypted = FieldEncryptionBoundary.decryptRecord(
|
||||
"ssh_data",
|
||||
encrypted,
|
||||
userDataKey,
|
||||
);
|
||||
expect(decrypted).toMatchObject(host);
|
||||
});
|
||||
|
||||
it("encrypts credential secret fields and keeps metadata plaintext", () => {
|
||||
const credential = {
|
||||
id: 7,
|
||||
userId: "user-1",
|
||||
name: "primary credential",
|
||||
authType: "key",
|
||||
key: "private-key-material",
|
||||
keyPassword: "key-password",
|
||||
};
|
||||
|
||||
const encrypted = FieldEncryptionBoundary.encryptRecord(
|
||||
"ssh_credentials",
|
||||
credential,
|
||||
userDataKey,
|
||||
);
|
||||
|
||||
expect(encrypted.key).not.toBe("private-key-material");
|
||||
expect(encrypted.keyPassword).not.toBe("key-password");
|
||||
expect(encrypted.name).toBe("primary credential");
|
||||
|
||||
expect(
|
||||
FieldEncryptionBoundary.decryptRecord(
|
||||
"ssh_credentials",
|
||||
encrypted,
|
||||
userDataKey,
|
||||
),
|
||||
).toMatchObject(credential);
|
||||
});
|
||||
|
||||
it("keeps empty and non-string sensitive values unchanged", () => {
|
||||
const encrypted = FieldEncryptionBoundary.encryptRecord(
|
||||
"ssh_data",
|
||||
{
|
||||
id: 1,
|
||||
password: "",
|
||||
key: null,
|
||||
},
|
||||
userDataKey,
|
||||
);
|
||||
|
||||
expect(encrypted.password).toBe("");
|
||||
expect(encrypted.key).toBeNull();
|
||||
});
|
||||
|
||||
it("requires a stable record id instead of inventing a temporary encryption context", () => {
|
||||
expect(() =>
|
||||
FieldEncryptionBoundary.encryptRecord(
|
||||
"ssh_data",
|
||||
{ password: "secret" },
|
||||
userDataKey,
|
||||
),
|
||||
).toThrow(/stable record id/);
|
||||
});
|
||||
|
||||
it("classifies sensitive, plaintext, and unknown fields", () => {
|
||||
expect(FieldEncryptionBoundary.classifyField("ssh_data", "password")).toBe(
|
||||
"sensitive",
|
||||
);
|
||||
expect(FieldEncryptionBoundary.classifyField("ssh_data", "ip")).toBe(
|
||||
"plaintext",
|
||||
);
|
||||
expect(FieldEncryptionBoundary.classifyField("ssh_data", "newField")).toBe(
|
||||
"unknown",
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user