117 lines
4.4 KiB
TypeScript
117 lines
4.4 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const script = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "ensure-local-env.sh");
|
|
|
|
const EXAMPLE = `NODE_ENV=development
|
|
BETTER_AUTH_SECRET=replace-with-32-plus-character-secret
|
|
ENCRYPTION_KEY=replace-with-64-random-hex-characters
|
|
SANDBOX_SUPERVISOR_TOKEN=
|
|
SCREEN_PROXY_SECRET=replace-with-32-plus-character-screen-proxy-secret
|
|
COMPUTER_USER_PASSWORD=
|
|
COMPUTER_ALLOW_SUDO=
|
|
# VITE_DEFAULT_UI_LOCALE=en
|
|
`;
|
|
|
|
function readKey(file: string, key: string) {
|
|
let value = "";
|
|
for (const line of readFileSync(file, "utf8").split(/\r?\n/)) {
|
|
if (line.startsWith(`${key}=`)) value = line.slice(key.length + 1);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function run(dir: string, extraEnv: NodeJS.ProcessEnv = {}) {
|
|
const env = { ...process.env };
|
|
for (const key of [
|
|
"BETTER_AUTH_SECRET",
|
|
"ENCRYPTION_KEY",
|
|
"SANDBOX_SUPERVISOR_TOKEN",
|
|
"SCREEN_PROXY_SECRET",
|
|
"COMPUTER_USER_PASSWORD",
|
|
"COMPUTER_ALLOW_SUDO",
|
|
"VITE_DEFAULT_UI_LOCALE",
|
|
"LOCAL_COMPUTER_PASSWORD",
|
|
"LOCAL_COMPUTER_SUDO",
|
|
"LOCAL_UI_LOCALE",
|
|
]) {
|
|
delete env[key];
|
|
}
|
|
return execFileSync("bash", [script], {
|
|
encoding: "utf8",
|
|
env: {
|
|
...env,
|
|
ENV_FILE: path.join(dir, ".env"),
|
|
EXAMPLE_FILE: path.join(dir, ".env.example"),
|
|
...extraEnv,
|
|
},
|
|
});
|
|
}
|
|
|
|
describe("ensure-local-env", () => {
|
|
it("creates .env and injects the local computer baseline plus secrets", () => {
|
|
const dir = mkdtempSync(path.join(tmpdir(), "bangso-env-"));
|
|
writeFileSync(path.join(dir, ".env.example"), EXAMPLE);
|
|
const output = run(dir);
|
|
|
|
const envFile = path.join(dir, ".env");
|
|
expect(output).toContain("created");
|
|
expect(readKey(envFile, "COMPUTER_ALLOW_SUDO")).toBe("1");
|
|
expect(readKey(envFile, "COMPUTER_USER_PASSWORD")).toBe("bangso");
|
|
expect(readKey(envFile, "VITE_DEFAULT_UI_LOCALE")).toBe("zh-TW");
|
|
expect(readKey(envFile, "BETTER_AUTH_SECRET")).toMatch(/^[0-9a-f]{64}$/);
|
|
expect(readKey(envFile, "ENCRYPTION_KEY")).toMatch(/^[0-9a-f]{64}$/);
|
|
expect(readKey(envFile, "SANDBOX_SUPERVISOR_TOKEN")).toMatch(/^[0-9a-f]{64}$/);
|
|
expect(readKey(envFile, "SCREEN_PROXY_SECRET")).toMatch(/^[0-9a-f]{64}$/);
|
|
expect(readKey(envFile, "NODE_ENV")).toBe("development");
|
|
});
|
|
|
|
it("does not clobber values already set in .env", () => {
|
|
const dir = mkdtempSync(path.join(tmpdir(), "bangso-env-"));
|
|
writeFileSync(path.join(dir, ".env.example"), EXAMPLE);
|
|
writeFileSync(
|
|
path.join(dir, ".env"),
|
|
`BETTER_AUTH_SECRET=keep-auth-secret-value-32chars-min
|
|
ENCRYPTION_KEY=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
SANDBOX_SUPERVISOR_TOKEN=keep-supervisor-token-value-32chars
|
|
SCREEN_PROXY_SECRET=keep-screen-proxy-secret-value-32c
|
|
COMPUTER_USER_PASSWORD=already-set
|
|
COMPUTER_ALLOW_SUDO=0
|
|
VITE_DEFAULT_UI_LOCALE=en
|
|
`,
|
|
);
|
|
const output = run(dir);
|
|
const envFile = path.join(dir, ".env");
|
|
expect(output).not.toContain("injected");
|
|
expect(readKey(envFile, "COMPUTER_ALLOW_SUDO")).toBe("0");
|
|
expect(readKey(envFile, "COMPUTER_USER_PASSWORD")).toBe("already-set");
|
|
expect(readKey(envFile, "VITE_DEFAULT_UI_LOCALE")).toBe("en");
|
|
expect(readKey(envFile, "BETTER_AUTH_SECRET")).toBe("keep-auth-secret-value-32chars-min");
|
|
});
|
|
|
|
it("fills only blank computer keys and accepts process-env overrides", () => {
|
|
const dir = mkdtempSync(path.join(tmpdir(), "bangso-env-"));
|
|
writeFileSync(path.join(dir, ".env.example"), EXAMPLE);
|
|
writeFileSync(
|
|
path.join(dir, ".env"),
|
|
`BETTER_AUTH_SECRET=keep-auth-secret-value-32chars-min
|
|
ENCRYPTION_KEY=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
SANDBOX_SUPERVISOR_TOKEN=keep-supervisor-token-value-32chars
|
|
SCREEN_PROXY_SECRET=keep-screen-proxy-secret-value-32c
|
|
COMPUTER_USER_PASSWORD=
|
|
COMPUTER_ALLOW_SUDO=
|
|
`,
|
|
);
|
|
run(dir, { COMPUTER_USER_PASSWORD: "from-make", COMPUTER_ALLOW_SUDO: "1" });
|
|
const envFile = path.join(dir, ".env");
|
|
expect(readKey(envFile, "COMPUTER_USER_PASSWORD")).toBe("from-make");
|
|
expect(readKey(envFile, "COMPUTER_ALLOW_SUDO")).toBe("1");
|
|
expect(readKey(envFile, "VITE_DEFAULT_UI_LOCALE")).toBe("zh-TW");
|
|
expect(readKey(envFile, "BETTER_AUTH_SECRET")).toBe("keep-auth-secret-value-32chars-min");
|
|
});
|
|
});
|