fix(tsc): ensure appSecret is set in type system
This commit is contained in:
parent
0e56ce395a
commit
cf19881d4f
2 changed files with 8 additions and 93 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||||
import os from "node:os";
|
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { parseConfig } from "../config";
|
import { parseConfig } from "../config";
|
||||||
|
|
||||||
|
|
@ -8,45 +7,6 @@ const fileAppSecret = "b".repeat(32);
|
||||||
const appSecretFixturePath = fileURLToPath(new URL("./fixtures/app-secret.txt", import.meta.url));
|
const appSecretFixturePath = fileURLToPath(new URL("./fixtures/app-secret.txt", import.meta.url));
|
||||||
const shortAppSecretFixturePath = fileURLToPath(new URL("./fixtures/short-app-secret.txt", import.meta.url));
|
const shortAppSecretFixturePath = fileURLToPath(new URL("./fixtures/short-app-secret.txt", import.meta.url));
|
||||||
|
|
||||||
const loadParseConfigWithSystemMocks = async ({
|
|
||||||
mountinfo,
|
|
||||||
hostname,
|
|
||||||
}: {
|
|
||||||
mountinfo: string | Error;
|
|
||||||
hostname?: string;
|
|
||||||
}) => {
|
|
||||||
vi.resetModules();
|
|
||||||
vi.doMock("node:fs", async () => {
|
|
||||||
const actual = await vi.importActual<typeof import("node:fs")>("node:fs");
|
|
||||||
|
|
||||||
return {
|
|
||||||
...actual,
|
|
||||||
readFileSync: vi.fn(() => {
|
|
||||||
if (mountinfo instanceof Error) {
|
|
||||||
throw mountinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mountinfo;
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
vi.doMock("node:os", async () => {
|
|
||||||
const actual = await vi.importActual<typeof import("node:os")>("node:os");
|
|
||||||
const hostnameMock = vi.fn(() => hostname ?? actual.hostname());
|
|
||||||
|
|
||||||
return {
|
|
||||||
...actual,
|
|
||||||
default: {
|
|
||||||
...actual,
|
|
||||||
hostname: hostnameMock,
|
|
||||||
},
|
|
||||||
hostname: hostnameMock,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return (await import("../config")).parseConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createEnv = (overrides: Record<string, string | undefined> = {}) => {
|
const createEnv = (overrides: Record<string, string | undefined> = {}) => {
|
||||||
const env = {
|
const env = {
|
||||||
APP_SECRET: validAppSecret,
|
APP_SECRET: validAppSecret,
|
||||||
|
|
@ -72,9 +32,6 @@ const expectParseConfigToExit = (env: Record<string, string | undefined>, messag
|
||||||
describe("parseConfig", () => {
|
describe("parseConfig", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
vi.doUnmock("node:fs");
|
|
||||||
vi.doUnmock("node:os");
|
|
||||||
vi.resetModules();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("parses quoted origins and derives runtime flags", () => {
|
test("parses quoted origins and derives runtime flags", () => {
|
||||||
|
|
@ -117,8 +74,6 @@ describe("parseConfig", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses the configured RESTIC_HOSTNAME when present", () => {
|
test("uses the configured RESTIC_HOSTNAME when present", () => {
|
||||||
const hostnameSpy = vi.spyOn(os, "hostname");
|
|
||||||
|
|
||||||
const config = parseConfig(
|
const config = parseConfig(
|
||||||
createEnv({
|
createEnv({
|
||||||
RESTIC_HOSTNAME: "manual-restic-host",
|
RESTIC_HOSTNAME: "manual-restic-host",
|
||||||
|
|
@ -126,53 +81,6 @@ describe("parseConfig", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(config.resticHostname).toBe("manual-restic-host");
|
expect(config.resticHostname).toBe("manual-restic-host");
|
||||||
expect(hostnameSpy).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("falls back to zerobyte when the mountinfo hostname lookup fails", async () => {
|
|
||||||
const mockedParseConfig = await loadParseConfigWithSystemMocks({
|
|
||||||
mountinfo: new Error("mountinfo unavailable"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const config = mockedParseConfig(
|
|
||||||
createEnv({
|
|
||||||
RESTIC_HOSTNAME: undefined,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(config.resticHostname).toBe("zerobyte");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses the OS hostname when mountinfo resolves to a different container id", async () => {
|
|
||||||
const mockedParseConfig = await loadParseConfigWithSystemMocks({
|
|
||||||
mountinfo:
|
|
||||||
"36 25 0:32 /hostname /etc/hostname rw,relatime - ext4 /dev/root rw 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n",
|
|
||||||
hostname: "hostbox",
|
|
||||||
});
|
|
||||||
|
|
||||||
const config = mockedParseConfig(
|
|
||||||
createEnv({
|
|
||||||
RESTIC_HOSTNAME: undefined,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(config.resticHostname).toBe("hostbox");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("collapses container-derived hostnames back to zerobyte", async () => {
|
|
||||||
const containerHostname = "abc123";
|
|
||||||
const mockedParseConfig = await loadParseConfigWithSystemMocks({
|
|
||||||
mountinfo: `36 25 0:32 /hostname /etc/hostname rw,relatime - ext4 /dev/root rw ${containerHostname}${"0".repeat(58)}\n`,
|
|
||||||
hostname: containerHostname,
|
|
||||||
});
|
|
||||||
|
|
||||||
const config = mockedParseConfig(
|
|
||||||
createEnv({
|
|
||||||
RESTIC_HOSTNAME: undefined,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(config.resticHostname).toBe("zerobyte");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("reads APP_SECRET from APP_SECRET_FILE", () => {
|
test("reads APP_SECRET from APP_SECRET_FILE", () => {
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ const envSchema = z
|
||||||
trustedOrigins: trustedOrigins,
|
trustedOrigins: trustedOrigins,
|
||||||
trustProxy: s.TRUST_PROXY === "true",
|
trustProxy: s.TRUST_PROXY === "true",
|
||||||
disableRateLimiting: s.DISABLE_RATE_LIMITING === "true" || s.NODE_ENV === "test",
|
disableRateLimiting: s.DISABLE_RATE_LIMITING === "true" || s.NODE_ENV === "test",
|
||||||
appSecret,
|
appSecret: appSecret ?? "",
|
||||||
baseUrl,
|
baseUrl,
|
||||||
isSecure: baseUrl.startsWith("https://"),
|
isSecure: baseUrl.startsWith("https://"),
|
||||||
enableDevPanel: s.ENABLE_DEV_PANEL === "true",
|
enableDevPanel: s.ENABLE_DEV_PANEL === "true",
|
||||||
|
|
@ -143,6 +143,13 @@ export const parseConfig = (env: unknown) => {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!result.data.appSecret) {
|
||||||
|
console.error(
|
||||||
|
"APP_SECRET is required but was not provided. Please set the APP_SECRET environment variable or provide a file with APP_SECRET_FILE.",
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue