mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
feat: add models page for the web application
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const getDisabledModels = vi.fn();
|
||||
|
||||
vi.mock("@/lib/disabledModelsDb", () => ({ getDisabledModels }));
|
||||
vi.mock("@/shared/constants/providers", () => ({
|
||||
getProviderAlias: (provider) => ({ openai: "oa", claude: "claude" })[provider] || provider,
|
||||
}));
|
||||
|
||||
const { getDisabledModelResponse } = await import("../../src/sse/services/disabledModels.js");
|
||||
|
||||
describe("getDisabledModelResponse", () => {
|
||||
beforeEach(() => {
|
||||
getDisabledModels.mockReset();
|
||||
});
|
||||
|
||||
it("allows an enabled model", async () => {
|
||||
getDisabledModels.mockResolvedValue({ oa: ["gpt-disabled"] });
|
||||
|
||||
await expect(getDisabledModelResponse("openai", "gpt-enabled")).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it("blocks a model disabled under the provider alias", async () => {
|
||||
getDisabledModels.mockResolvedValue({ oa: ["gpt-disabled"] });
|
||||
|
||||
const response = await getDisabledModelResponse("openai", "gpt-disabled");
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
await expect(response.json()).resolves.toMatchObject({
|
||||
error: {
|
||||
code: "model_not_found",
|
||||
message: "Model openai/gpt-disabled is disabled by an administrator",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("blocks a model disabled under the provider ID", async () => {
|
||||
getDisabledModels.mockResolvedValue({ openai: ["gpt-disabled"] });
|
||||
|
||||
const response = await getDisabledModelResponse("openai", "gpt-disabled");
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
});
|
||||
|
||||
it("fails closed when disabled-model storage cannot be read", async () => {
|
||||
getDisabledModels.mockRejectedValue(new Error("database unavailable"));
|
||||
|
||||
const response = await getDisabledModelResponse("openai", "gpt-enabled");
|
||||
|
||||
expect(response.status).toBe(500);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const getDisabledModels = vi.fn();
|
||||
const disableModels = vi.fn();
|
||||
const enableModels = vi.fn();
|
||||
const requireAdminUser = vi.fn();
|
||||
|
||||
vi.mock("@/lib/disabledModelsDb", () => ({
|
||||
getDisabledModels,
|
||||
disableModels,
|
||||
enableModels,
|
||||
}));
|
||||
vi.mock("@/lib/auth/currentUser", () => ({ requireAdminUser }));
|
||||
|
||||
const { GET, POST, DELETE } = await import("../../src/app/api/models/disabled/route.js");
|
||||
|
||||
describe("/api/models/disabled", () => {
|
||||
beforeEach(() => {
|
||||
getDisabledModels.mockReset();
|
||||
disableModels.mockReset();
|
||||
enableModels.mockReset();
|
||||
requireAdminUser.mockReset();
|
||||
});
|
||||
|
||||
it("keeps disabled model reads available for model selectors", async () => {
|
||||
getDisabledModels.mockResolvedValue({ claude: ["claude-disabled"] });
|
||||
|
||||
const response = await GET(new Request("http://localhost/api/models/disabled?providerAlias=claude"));
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
await expect(response.json()).resolves.toEqual({ ids: ["claude-disabled"] });
|
||||
expect(requireAdminUser).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects a non-admin disable request", async () => {
|
||||
requireAdminUser.mockRejectedValue(new Error("Forbidden"));
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/models/disabled", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ providerAlias: "claude", ids: ["claude-disabled"] }),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(403);
|
||||
expect(disableModels).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows an admin to disable models", async () => {
|
||||
requireAdminUser.mockResolvedValue({ role: "admin" });
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/models/disabled", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ providerAlias: "claude", ids: ["claude-disabled"] }),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(disableModels).toHaveBeenCalledWith("claude", ["claude-disabled"]);
|
||||
});
|
||||
|
||||
it("rejects a non-admin enable request", async () => {
|
||||
requireAdminUser.mockRejectedValue(new Error("Forbidden"));
|
||||
|
||||
const response = await DELETE(new Request("http://localhost/api/models/disabled?providerAlias=claude&id=claude-disabled", {
|
||||
method: "DELETE",
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(403);
|
||||
expect(enableModels).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user