mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-30 16:16:19 +00:00
The startup banner printed `/setup?token=...`, so the one-hour bootstrap token that grants the setup wizard landed in reverse-proxy access logs, Referer headers and browser history. The link now carries the token in the fragment, which never leaves the browser, and the wizard removes it from the address bar as soon as it reads it. Old `?token=` links still work and are cleaned up the same way.
65 lines
2.7 KiB
TypeScript
65 lines
2.7 KiB
TypeScript
import { readFileSync } from "fs";
|
|
import { configManager } from "./lib/admin/config-manager";
|
|
import { initAdminPassword } from "./lib/admin/password";
|
|
import { migrateLegacyAdminLayout, migratePolicyUnifiedMailbox } from "./lib/admin/migrate";
|
|
import { detectSetupState } from "./lib/setup/state";
|
|
import { ensureSetupToken } from "./lib/setup/token";
|
|
|
|
const pkg = JSON.parse(
|
|
readFileSync(`${process.cwd()}/package.json`, "utf-8")
|
|
);
|
|
const current: string = pkg.version ?? "0.0.0";
|
|
console.info(`Bulwark Webmail v${current}`);
|
|
|
|
// Initialize admin config and password bootstrap. Migration runs first so
|
|
// existing v1 layouts are split before anything reads admin.json.
|
|
migrateLegacyAdminLayout()
|
|
.then(() => migratePolicyUnifiedMailbox())
|
|
.then(() => configManager.load())
|
|
.then(() => initAdminPassword())
|
|
.then(async () => {
|
|
console.info("Admin dashboard initialized");
|
|
// If we're in bootstrap state (no JMAP_SERVER_URL env and no
|
|
// setupComplete in config.json), generate/refresh the setup token and
|
|
// print it to the logs so the operator can complete the web wizard
|
|
// without execing into the container.
|
|
if (detectSetupState() === "bootstrap") {
|
|
try {
|
|
const token = await ensureSetupToken();
|
|
const port = process.env.PORT || "3000";
|
|
console.info("");
|
|
console.info("==============================================================");
|
|
console.info(" SETUP REQUIRED");
|
|
console.info(` Token: ${token}`);
|
|
// In the fragment, so the token stays out of access logs and Referer.
|
|
console.info(` Open: http://<host>:${port}/setup#token=${token}`);
|
|
console.info(" Token expires in 1 hour. Restart the container to reissue.");
|
|
console.info("==============================================================");
|
|
console.info("");
|
|
} catch (err) {
|
|
console.warn(
|
|
"Failed to issue setup token:",
|
|
err instanceof Error ? err.message : err,
|
|
);
|
|
}
|
|
}
|
|
})
|
|
.then(async () => {
|
|
// Anonymous telemetry - on by default. Admins can disable via the
|
|
// admin UI, the BULWARK_TELEMETRY env var, or by clearing the endpoint.
|
|
// See https://bulwarkmail.org/docs/legal/privacy/telemetry
|
|
const { startScheduler, markProcessStart } = await import("./lib/telemetry");
|
|
markProcessStart();
|
|
await startScheduler();
|
|
})
|
|
.then(async () => {
|
|
// Hourly check against version.telemetry.bulwarkmail.org. Disable with
|
|
// BULWARK_UPDATE_CHECK=off or override the endpoint with
|
|
// BULWARK_UPDATE_CHECK_URL.
|
|
const { startScheduler } = await import("./lib/version-check");
|
|
await startScheduler();
|
|
})
|
|
.catch((err) => {
|
|
console.warn("Admin dashboard init skipped:", err instanceof Error ? err.message : err);
|
|
});
|