refactor: trim v2 hardening scaffolding

This commit is contained in:
ajnart committed 2026-07-30 15:19:17 +02:00
1 parent ecfb9d59e0
commit 2eb0baf17e
75 files changed
+334 -2067

No files matched your search

@@ -4,16 +4,13 @@ import { beforeEach, describe, expect, test, vi } from "vitest";
const mocks = vi.hoisted(() => ({
auth: vi.fn(),
env: { CUSTOM_WIDGETS_ENABLED: true },
}));
vi.mock("@homarr/auth/next", () => ({ auth: mocks.auth }));
vi.mock("~/env", () => ({ env: mocks.env }));
import { requireCustomWidgetAdmin } from "./admin";
beforeEach(() => {
mocks.env.CUSTOM_WIDGETS_ENABLED = true;
mocks.auth.mockResolvedValue({ user: { permissions: ["admin"] } });
});
@@ -30,11 +27,4 @@ describe("Custom Widget HTTP resource access", () => {
const response = await requireCustomWidgetAdmin();
expect(response?.status).toBe(403);
});
test("returns an unavailable response when the emergency switch is off", async () => {
mocks.env.CUSTOM_WIDGETS_ENABLED = false;
const response = await requireCustomWidgetAdmin();
expect(response?.status).toBe(503);
await expect(response?.json()).resolves.toMatchObject({ error: expect.stringContaining("temporarily disabled") });
});
});
@@ -2,18 +2,10 @@ import { NextResponse } from "next/server";
import { auth } from "@homarr/auth/next";
import { env } from "~/env";
export const requireCustomWidgetAdmin = async (): Promise<NextResponse | null> => {
const session = await auth();
if (!session?.user.permissions.includes("admin")) {
return NextResponse.json({ error: "Administrator access is required." }, { status: 403 });
}
if (env.CUSTOM_WIDGETS_ENABLED === false) {
return NextResponse.json(
{ error: "Custom Widgets are temporarily disabled by the server administrator." },
{ status: 503 },
);
}
return null;
};
@@ -7,7 +7,6 @@ const mocks = vi.hoisted(() => ({
rateLimitAddress: vi.fn(() => "127.0.0.1"),
toolProcedure: vi.fn(),
loggerWarn: vi.fn(),
env: { CUSTOM_WIDGETS_ENABLED: true, WORKSHOP_ENABLED: true },
buildPrompt: vi.fn((request?: string, documentationUrl?: string) =>
[`Request: ${request ?? ""}`, `Documentation: ${documentationUrl ?? ""}`].join("\n"),
),
@@ -39,7 +38,6 @@ vi.mock("@homarr/custom-widgets/core", () => ({
getCustomWidgetJsonSchema: () => ({ type: "object", title: "Custom Widget" }),
}));
vi.mock("@homarr/db", () => ({ db: {} }));
vi.mock("~/env", () => ({ env: mocks.env }));
vi.mock("~/versions/package-reader", () => ({ getPackageVersion: () => "test-version" }));
vi.mock("../_extract-tools", () => ({
extractMcpTools: () => [
@@ -75,8 +73,6 @@ interface JsonRpcResponse {
beforeEach(() => {
mocks.authenticate.mockResolvedValue({ user: { id: "user-1", permissions: ["admin"] } });
mocks.env.CUSTOM_WIDGETS_ENABLED = true;
mocks.env.WORKSHOP_ENABLED = true;
mocks.buildPrompt.mockClear();
mocks.getComponent.mockClear();
mocks.rateLimitAddress.mockClear();
@@ -242,27 +238,6 @@ describe("non-admin MCP discovery", () => {
});
});
describe("MCP emergency switches", () => {
test("removes Custom Widget authoring discovery when Custom Widgets are disabled", async () => {
mocks.env.CUSTOM_WIDGETS_ENABLED = false;
expect((await callMcp("prompts/list")).body.result).toEqual({ prompts: [] });
expect((await callMcp("resources/list")).body.result).toEqual({ resources: [] });
const tools = await callMcp("tools/list");
expect(((tools.body.result?.tools ?? []) as Array<{ name: string }>).map(({ name }) => name)).toEqual([
"board_getAllBoards",
]);
});
test("removes only Workshop tools when Workshop is disabled", async () => {
mocks.env.WORKSHOP_ENABLED = false;
const tools = await callMcp("tools/list");
expect(((tools.body.result?.tools ?? []) as Array<{ name: string }>).map(({ name }) => name)).toEqual([
"board_getAllBoards",
"customWidget_list",
]);
});
});
describe("MCP protocol errors", () => {
test.each([
["prompts/get", { name: "unknown" }],
@@ -27,7 +27,6 @@ import {
import { customJsxExamples, getCustomWidgetJsonSchema } from "@homarr/custom-widgets/core";
import { db } from "@homarr/db";
import { env } from "~/env";
import { getPackageVersion } from "~/versions/package-reader";
import { extractMcpTools } from "../_extract-tools";
@@ -124,17 +123,14 @@ function getVisibleTools() {
if (!isCustomWidgetMcpEnabled()) {
return tools.filter((tool) => !tool.name.startsWith("customWidget_"));
}
return env.WORKSHOP_ENABLED === false
? tools.filter((tool) => !tool.name.startsWith("customWidget_workshop"))
: tools;
return tools;
}
function requireCustomWidgetMcpAdmin() {
if (!isCustomWidgetMcpEnabled()) throw new Error("Resource not found");
}
const isCustomWidgetMcpEnabled = () =>
Boolean(callerStorage.getStore()?.isAdmin) && env.CUSTOM_WIDGETS_ENABLED !== false;
const isCustomWidgetMcpEnabled = () => Boolean(callerStorage.getStore()?.isAdmin);
const SAFE_ERROR_MESSAGES: Record<string, string> = {
UNAUTHORIZED: "You do not have permission to perform this action",