fix: hide the lite server field once config.json sets jmapServerUrl #1087

This commit is contained in:
Linus Rath
2026-09-23 18:19:26 +02:00
parent 2d8de2a817
commit c96814db4c
2 changed files with 25 additions and 4 deletions
+13 -2
View File
@@ -60,6 +60,7 @@ import { runPostbuild } from '../../scripts/lite/postbuild.mjs';
import { verifyExport } from '../../scripts/lite/verify.mjs';
import { stageContainer } from '../../scripts/lite/container.mjs';
import { LITE_PENDING_PATH_KEY as APP_LITE_PENDING_PATH_KEY } from '../lite';
import { applyLiteConfig } from '../lite-config';
/** The scripts take `process.env`-shaped input; tests pass plain objects. */
function env(values: Record<string, string> = {}): NodeJS.ProcessEnv {
@@ -102,18 +103,28 @@ describe('lite build helpers', () => {
it('derives config.json from the LITE_* inputs with safe defaults', () => {
const empty = buildLiteConfig({});
expect(empty.jmapServerUrl).toBe('');
expect(empty.allowCustomJmapEndpoint).toBe(true);
expect(empty).not.toHaveProperty('allowCustomJmapEndpoint');
expect(applyLiteConfig(empty).allowCustomJmapEndpoint).toBe(true);
expect(empty.rememberMeEnabled).toBe(true);
expect(empty.demoMode).toBe(false);
expect(empty.appName).toBe('Bulwark Webmail');
const fixed = buildLiteConfig({ LITE_JMAP_SERVER_URL: 'https://mail.example.com/', LITE_APP_NAME: 'Acme', LITE_DEMO_MODE: 'true', LITE_REMEMBER_ME: 'false' });
expect(fixed.jmapServerUrl).toBe('https://mail.example.com');
expect(fixed.allowCustomJmapEndpoint).toBe(false);
expect(fixed).not.toHaveProperty('allowCustomJmapEndpoint');
expect(applyLiteConfig(fixed).allowCustomJmapEndpoint).toBe(false);
expect(fixed.appName).toBe('Acme');
expect(fixed.demoMode).toBe(true);
expect(fixed.rememberMeEnabled).toBe(false);
expect(buildLitePolicy().features).toEqual({ pluginsEnabled: false, sidebarAppsEnabled: false });
expect(buildLiteConfig({ LITE_ALLOW_CUSTOM_ENDPOINT: 'true' }).allowCustomJmapEndpoint).toBe(true);
expect(buildLiteConfig({ LITE_ALLOW_CUSTOM_ENDPOINT: 'false' }).allowCustomJmapEndpoint).toBe(false);
});
it('hides the server field once a deployer fills in jmapServerUrl of the shipped config.json (#1087)', () => {
const shipped = buildLiteConfig({});
const edited = { ...shipped, jmapServerUrl: 'https://mail.example.com' };
expect(applyLiteConfig(edited).allowCustomJmapEndpoint).toBe(false);
});
it('prefixes manifest and redirect paths with the base path', () => {
+12 -2
View File
@@ -139,17 +139,25 @@ export function normalizeBasePath(raw) {
* config.json contents from the LITE_* build inputs. The Stalwart target is
* served by the mail server itself: an empty server URL means "this origin"
* there, so the server field stays hidden unless a build asks for it.
*
* The static target leaves `allowCustomJmapEndpoint` out unless the build sets
* it: the app then derives it from `jmapServerUrl` at runtime. Writing the
* derived `true` of an empty server URL kept the server field on the login
* page after a deployer filled in `jmapServerUrl` and nothing else (#1087).
*/
export function buildLiteConfig(env = {}, { target = "static" } = {}) {
const jmapServerUrl = (env.LITE_JMAP_SERVER_URL ?? "").trim().replace(/\/+$/, "");
const stalwart = target === "stalwart";
const customEndpointSet = (env.LITE_ALLOW_CUSTOM_ENDPOINT ?? "") !== "";
return {
_comment: stalwart
? "Bulwark Lite for Stalwart. Read-only inside the Application bundle: to change it, build your own zip (see LITE-README.md). An empty jmapServerUrl means the Stalwart server that serves this page."
: "Bulwark Lite runtime configuration. Edit and re-upload; no rebuild needed. See LITE-README.md.",
appName: (env.LITE_APP_NAME ?? "").trim() || "Bulwark Webmail",
jmapServerUrl,
allowCustomJmapEndpoint: parseBool(env.LITE_ALLOW_CUSTOM_ENDPOINT, !stalwart && jmapServerUrl === ""),
...(stalwart || customEndpointSet
? { allowCustomJmapEndpoint: parseBool(env.LITE_ALLOW_CUSTOM_ENDPOINT, false) }
: {}),
rememberMeEnabled: parseBool(env.LITE_REMEMBER_ME, true),
demoMode: parseBool(env.LITE_DEMO_MODE, false),
loginShowTotp: true,
@@ -574,7 +582,9 @@ ${demoMode ? "Demo mode is ON: the login page offers a built-in demo account and
2. Edit \`config.json\`:
- \`jmapServerUrl\`: your mail server, e.g. \`https://mail.example.com\`${jmapServerUrl ? ` (currently \`${jmapServerUrl}\`)` : ""}.
- \`appName\`: the name shown in the tab and on the login page.
- \`allowCustomJmapEndpoint\`: \`true\` shows a server field on the login page.
- \`allowCustomJmapEndpoint\` (optional): \`true\` always shows a server field
on the login page, \`false\` never does. Left out, the field shows only
while \`jmapServerUrl\` is empty.
- \`rememberMeEnabled\`: \`false\` hides "remember me" (sessions then end with the tab).
Optional keys: \`demoMode\`, \`jmapServers\`, \`jmapServerAutoPickByDomain\`, the login logo/company/link keys and \`loginShow*\` toggles (same names as the Docker env vars, camelCased).
3. Allow the browser to talk to the mail server (CORS). In Stalwart: