111 lines
4.2 KiB
JavaScript
111 lines
4.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import {spawn} from "node:child_process";
|
|
import {randomBytes} from "node:crypto";
|
|
import {mkdtempSync, rmSync, writeFileSync} from "node:fs";
|
|
import http from "node:http";
|
|
import {tmpdir} from "node:os";
|
|
import {join} from "node:path";
|
|
|
|
const directory = mkdtempSync(join(tmpdir(), "xiteng-key-vault-api-test-"));
|
|
writeFileSync(join(directory, "master-key"), randomBytes(32).toString("base64"));
|
|
writeFileSync(join(directory, "service-token"), "integration-service-token");
|
|
|
|
const portProbe = http.createServer();
|
|
await new Promise((resolve) => portProbe.listen(0, "127.0.0.1", resolve));
|
|
const port = portProbe.address().port;
|
|
await new Promise((resolve) => portProbe.close(resolve));
|
|
|
|
const service = spawn(process.execPath, ["server.mjs"], {
|
|
cwd: new URL(".", import.meta.url),
|
|
env: {
|
|
...process.env,
|
|
PORT: String(port),
|
|
DATABASE_PATH: join(directory, "vault.db"),
|
|
MASTER_KEY_FILE: join(directory, "master-key"),
|
|
SERVICE_TOKEN_FILE: join(directory, "service-token"),
|
|
PROVIDER_CATALOG_FILE: new URL("providers.json", import.meta.url).pathname
|
|
},
|
|
stdio: ["ignore", "pipe", "pipe"]
|
|
});
|
|
let logs = "";
|
|
service.stdout.on("data", (chunk) => { logs += chunk; });
|
|
service.stderr.on("data", (chunk) => { logs += chunk; });
|
|
|
|
function request(pathname, {method = "GET", body} = {}) {
|
|
return fetch(`http://127.0.0.1:${port}${pathname}`, {
|
|
method,
|
|
headers: {
|
|
"Authorization": "Bearer integration-service-token",
|
|
"Accept": "application/json",
|
|
...(body ? {"Content-Type": "application/json"} : {}),
|
|
"X-Key-Vault-Actor-Issuer": "https://auth.xiteng.site",
|
|
"X-Key-Vault-Actor-Sub": "integration-user",
|
|
"X-Key-Vault-Actor-Username": "integration"
|
|
},
|
|
body: body ? JSON.stringify(body) : undefined
|
|
});
|
|
}
|
|
|
|
try {
|
|
let ready = false;
|
|
for (let attempt = 0; attempt < 50; attempt += 1) {
|
|
try {
|
|
if ((await fetch(`http://127.0.0.1:${port}/healthz`)).ok) {
|
|
ready = true;
|
|
break;
|
|
}
|
|
} catch {}
|
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
}
|
|
assert.equal(ready, true, logs || "Key Vault did not start");
|
|
|
|
const providersResponse = await request("/v1/providers");
|
|
assert.equal(providersResponse.status, 200);
|
|
const providers = await providersResponse.json();
|
|
assert.ok(providers.providers.some((provider) => provider.id === "openai"));
|
|
assert.ok(providers.providers.some((provider) => provider.id === "ollama" && provider.credentialState === "local"));
|
|
|
|
const customResponse = await request("/v1/providers", {
|
|
method: "POST",
|
|
body: {
|
|
id: "integration-provider",
|
|
name: "Integration Provider",
|
|
api: "openai-completions",
|
|
connection: {type: "backend", baseUrl: "https://example.com/v1", proxy: null},
|
|
auth: {type: "bearer"},
|
|
defaultModel: "test-model",
|
|
discovery: {type: "openai-models-list", url: "https://example.com/v1/models"}
|
|
}
|
|
});
|
|
assert.equal(customResponse.status, 200);
|
|
const savedCustom = await customResponse.json();
|
|
assert.equal(savedCustom.provider.discovery.url, "https://example.com/v1/models");
|
|
assert.equal("models" in savedCustom.provider, false);
|
|
|
|
const createdResponse = await request("/v1/credentials", {
|
|
method: "POST",
|
|
body: {providerId: "integration-provider", name: "default", secret: {provider: {apiKey: "provider-secret"}}}
|
|
});
|
|
assert.equal(createdResponse.status, 201);
|
|
|
|
const resolvedResponse = await request("/v1/resolve", {
|
|
method: "POST",
|
|
body: {providerId: "integration-provider", credentialName: "default"}
|
|
});
|
|
assert.equal(resolvedResponse.status, 200);
|
|
const resolved = await resolvedResponse.json();
|
|
assert.equal(resolved.provider.connection.baseUrl, "https://example.com/v1");
|
|
assert.equal(resolved.credential.secret.provider.apiKey, "provider-secret");
|
|
|
|
const frontendCredential = await request("/v1/credentials", {
|
|
method: "POST",
|
|
body: {providerId: "ollama", name: "default", secret: "browser-only"}
|
|
});
|
|
assert.equal(frontendCredential.status, 409);
|
|
console.log("Key Vault API tests passed");
|
|
} finally {
|
|
service.kill("SIGTERM");
|
|
await new Promise((resolve) => service.once("exit", resolve));
|
|
rmSync(directory, {recursive: true, force: true});
|
|
}
|