custom branding

This commit is contained in:
KingKDot
2026-07-08 21:47:57 -05:00
parent faac5b6029
commit b29d5b4291
13 changed files with 735 additions and 31 deletions
+104 -2
View File
@@ -1,6 +1,9 @@
import { describe, expect, test } from "bun:test";
import { extractTokenFromCookie, extractTokenFromHeader } from "./auth";
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { extractTokenFromCookie, extractTokenFromHeader, generateToken } from "./auth";
import { getConfig, updateAppearanceConfig, type Config } from "./config";
import { generateTotpCode } from "./mfa";
import * as fs from "fs/promises";
import path from "path";
import {
createUser,
deleteUser,
@@ -9,11 +12,25 @@ import {
setUserMfaSecret,
} from "./users";
import { handleAuthRoutes } from "./server/routes/auth-routes";
import { handleMiscRoutes } from "./server/routes/misc-routes";
const PASSWORD = "Aa1!AuthMfaTest_2026";
const mockServer = {
requestIP: () => ({ address: "127.0.0.1" }),
};
let originalAppearance: Config["appearance"];
const uploadPublicRoot = path.resolve(".test-data", "branding-upload-public");
beforeAll(() => {
originalAppearance = JSON.parse(JSON.stringify(getConfig().appearance));
});
afterAll(async () => {
if (originalAppearance) {
await updateAppearanceConfig(originalAppearance.customCSS, originalAppearance.loginBranding);
}
await fs.rm(uploadPublicRoot, { recursive: true, force: true });
});
describe("auth token extraction", () => {
test("extractTokenFromHeader returns bearer token", () => {
@@ -39,8 +56,93 @@ describe("login branding", () => {
const body = (await res!.json()) as any;
expect(body.productName).toBe("Overlord");
expect(body.navName).toBe("Overlord");
expect(body.title).toBe("Welcome back");
expect(body.logoUrl).toBe("");
expect(body.navLogoUrl).toBe("");
expect(body.heroImageUrl).toBe("");
expect(body.accentColor).toBe("#7a5bff");
});
test("returns sanitized enterprise branding fields", async () => {
await updateAppearanceConfig("", {
productName: "Acme SOC",
navName: "Acme Console",
title: "Welcome to Acme",
subtitle: "Use your Acme identity",
iconClass: "fa-solid fa-shield-halved<script>",
logoUrl: "javascript:alert(1)",
navLogoUrl: "/assets/acme-nav.png",
heroImageUrl: "https://cdn.example.test/login.jpg",
accentColor: "#14B8A6",
footerText: "Authorized access only",
supportText: "Need help?",
supportUrl: "https://help.example.test",
});
const url = new URL("https://localhost/api/login/branding");
const res = await handleAuthRoutes(new Request(url), url, mockServer);
expect(res?.status).toBe(200);
const body = (await res!.json()) as any;
expect(body.productName).toBe("Acme SOC");
expect(body.navName).toBe("Acme Console");
expect(body.iconClass).toBe("fa-solid fa-shield-halvedscript");
expect(body.logoUrl).toBe("");
expect(body.navLogoUrl).toBe("/assets/acme-nav.png");
expect(body.heroImageUrl).toBe("https://cdn.example.test/login.jpg");
expect(body.accentColor).toBe("#14b8a6");
expect(body.footerText).toBe("Authorized access only");
expect(body.supportUrl).toBe("https://help.example.test/");
});
});
describe("branding uploads", () => {
test("accepts admin image upload and returns a branding asset URL", async () => {
const username = `branding_upload_${Date.now().toString(36)}`;
const created = await createUser(username, PASSWORD, "admin", "test");
expect(created.success).toBe(true);
try {
await fs.mkdir(uploadPublicRoot, { recursive: true });
const user = getUserById(created.userId!);
expect(user).toBeTruthy();
const token = await generateToken(user!);
const pngBytes = new Uint8Array([
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
0x00, 0x00, 0x00, 0x0d,
]);
const form = new FormData();
form.append("kind", "nav-logo");
form.append("file", new File([pngBytes], "logo.png", { type: "image/png" }));
const url = new URL("https://localhost/api/settings/appearance/image");
const res = await handleMiscRoutes(
new Request(url, {
method: "POST",
headers: { Cookie: `overlord_token=${token}` },
body: form,
}),
url,
{
CORS_HEADERS: {},
SERVER_VERSION: "test",
PUBLIC_ROOT: uploadPublicRoot,
requestIP: () => ({ address: "127.0.0.1" }),
getConsoleSessionCount: () => 0,
getRdSessionCount: () => 0,
getFileBrowserSessionCount: () => 0,
getProcessSessionCount: () => 0,
},
);
expect(res?.status).toBe(200);
const body = (await res!.json()) as any;
expect(body.url).toMatch(/^\/assets\/branding\/nav-logo-[a-z0-9]+-[0-9a-f-]+\.png$/);
expect(await Bun.file(path.join(uploadPublicRoot, body.url.replace("/assets/", "assets/"))).exists()).toBe(true);
} finally {
deleteUser(created.userId!);
}
});
});