test(api): cover assistant settings tools
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { DEFAULT_OPENAI_MODEL, SystemRole } from "@capakraken/shared";
|
||||
|
||||
import { createToolContext, executeTool } from "./assistant-tools-settings-test-helpers.js";
|
||||
|
||||
describe("assistant settings tools runtime settings", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it("returns system settings with runtime secret flags through the real settings router path", async () => {
|
||||
vi.stubEnv("OPENAI_API_KEY", "env-openai-key");
|
||||
vi.stubEnv("SMTP_PASSWORD", "env-smtp-password");
|
||||
vi.stubEnv("GEMINI_API_KEY", "env-gemini-key");
|
||||
|
||||
const ctx = createToolContext({
|
||||
systemSettings: {
|
||||
findUnique: vi.fn().mockResolvedValue({
|
||||
aiProvider: "openai",
|
||||
azureOpenAiApiKey: null,
|
||||
smtpPassword: null,
|
||||
geminiApiKey: null,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const result = await executeTool("get_system_settings", JSON.stringify({}), ctx);
|
||||
const parsed = JSON.parse(result.content) as {
|
||||
hasApiKey: boolean;
|
||||
hasSmtpPassword: boolean;
|
||||
hasGeminiApiKey: boolean;
|
||||
runtimeSecrets: {
|
||||
azureOpenAiApiKey: { activeSource: string };
|
||||
smtpPassword: { activeSource: string };
|
||||
};
|
||||
legacyStoredSecretFields: string[];
|
||||
};
|
||||
|
||||
expect(parsed.hasApiKey).toBe(true);
|
||||
expect(parsed.hasSmtpPassword).toBe(true);
|
||||
expect(parsed.hasGeminiApiKey).toBe(true);
|
||||
expect(parsed.runtimeSecrets.azureOpenAiApiKey.activeSource).toBe("environment");
|
||||
expect(parsed.runtimeSecrets.smtpPassword.activeSource).toBe("environment");
|
||||
expect(parsed.legacyStoredSecretFields).toEqual([]);
|
||||
});
|
||||
|
||||
it("updates system settings without persisting incoming secret fields", async () => {
|
||||
const findUnique = vi.fn().mockResolvedValue(null);
|
||||
const upsert = vi.fn().mockResolvedValue({});
|
||||
const ctx = createToolContext({
|
||||
systemSettings: {
|
||||
findUnique,
|
||||
upsert,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await executeTool(
|
||||
"update_system_settings",
|
||||
JSON.stringify({
|
||||
azureOpenAiApiKey: "sk-should-not-store",
|
||||
smtpPassword: "smtp-should-not-store",
|
||||
geminiApiKey: "gemini-should-not-store",
|
||||
azureDalleApiKey: "dalle-should-not-store",
|
||||
anonymizationSeed: "seed-should-not-store",
|
||||
aiProvider: "openai",
|
||||
azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
|
||||
}),
|
||||
ctx,
|
||||
);
|
||||
|
||||
expect(JSON.parse(result.content)).toEqual({
|
||||
ok: true,
|
||||
ignoredSecretFields: [
|
||||
"azureOpenAiApiKey",
|
||||
"smtpPassword",
|
||||
"anonymizationSeed",
|
||||
"azureDalleApiKey",
|
||||
"geminiApiKey",
|
||||
],
|
||||
secretStorageMode: "environment-only",
|
||||
});
|
||||
expect(findUnique).toHaveBeenCalledWith({ where: { id: "singleton" } });
|
||||
expect(upsert).toHaveBeenCalledWith({
|
||||
where: { id: "singleton" },
|
||||
create: {
|
||||
id: "singleton",
|
||||
aiProvider: "openai",
|
||||
azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
|
||||
},
|
||||
update: {
|
||||
aiProvider: "openai",
|
||||
azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("clears legacy runtime secrets through the real settings router path", async () => {
|
||||
const findUnique = vi.fn().mockResolvedValue({
|
||||
azureOpenAiApiKey: "db-openai",
|
||||
azureDalleApiKey: null,
|
||||
geminiApiKey: "db-gemini",
|
||||
smtpPassword: null,
|
||||
anonymizationSeed: "db-seed",
|
||||
});
|
||||
const update = vi.fn().mockResolvedValue({ id: "singleton" });
|
||||
const auditCreate = vi.fn().mockResolvedValue(undefined);
|
||||
const ctx = createToolContext({
|
||||
systemSettings: {
|
||||
findUnique,
|
||||
update,
|
||||
},
|
||||
auditLog: {
|
||||
create: auditCreate,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await executeTool("clear_stored_runtime_secrets", "{}", ctx);
|
||||
|
||||
expect(JSON.parse(result.content)).toEqual({
|
||||
ok: true,
|
||||
clearedFields: ["azureOpenAiApiKey", "geminiApiKey", "anonymizationSeed"],
|
||||
});
|
||||
expect(update).toHaveBeenCalledWith({
|
||||
where: { id: "singleton" },
|
||||
data: {
|
||||
azureOpenAiApiKey: null,
|
||||
geminiApiKey: null,
|
||||
anonymizationSeed: null,
|
||||
},
|
||||
});
|
||||
expect(auditCreate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects admin-only runtime settings tools for non-admin assistant users", async () => {
|
||||
const ctx = createToolContext(
|
||||
{
|
||||
systemSettings: {
|
||||
findUnique: vi.fn(),
|
||||
upsert: vi.fn(),
|
||||
update: vi.fn(),
|
||||
},
|
||||
},
|
||||
SystemRole.MANAGER,
|
||||
);
|
||||
|
||||
for (const [toolName, payload] of [
|
||||
["get_system_settings", {}],
|
||||
["update_system_settings", { aiProvider: "openai" }],
|
||||
["clear_stored_runtime_secrets", {}],
|
||||
] as const) {
|
||||
const result = await executeTool(toolName, JSON.stringify(payload), ctx);
|
||||
expect(JSON.parse(result.content)).toEqual({
|
||||
error: "You do not have permission to perform this action.",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user