mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
fix: update the tracking usage filter for the usage page
This commit is contained in:
@@ -30,6 +30,21 @@ describe("usage access scope SQL predicates", () => {
|
||||
expect(params).toEqual(["connection-a", "connection-b", "key-a"]);
|
||||
});
|
||||
|
||||
it("uses persisted actor attribution when a user id is available", () => {
|
||||
const conditions = [];
|
||||
const params = [];
|
||||
|
||||
appendUsageAccessClause(conditions, params, {
|
||||
isAdmin: false,
|
||||
userId: "user-a",
|
||||
connectionIds: ["connection-a"],
|
||||
apiKeys: ["key-a"],
|
||||
});
|
||||
|
||||
expect(conditions).toEqual(["userId = ?"]);
|
||||
expect(params).toEqual(["user-a"]);
|
||||
});
|
||||
|
||||
it("denies users with no attributable resources", () => {
|
||||
const conditions = [];
|
||||
const params = [];
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const originalDataDir = process.env.DATA_DIR;
|
||||
let tempDir;
|
||||
let db;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "9router-usage-roles-"));
|
||||
process.env.DATA_DIR = tempDir;
|
||||
vi.resetModules();
|
||||
db = await import("@/lib/db/index.js");
|
||||
await db.initDb();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
if (tempDir) fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
if (originalDataDir === undefined) delete process.env.DATA_DIR;
|
||||
else process.env.DATA_DIR = originalDataDir;
|
||||
});
|
||||
|
||||
describe("usage role breakdowns", () => {
|
||||
it("attributes requests to the API key owner and exposes breakdowns by role", async () => {
|
||||
const keyOwner = await db.createUser({ username: "usage-key-owner", password: "password", role: "user" });
|
||||
const connectionOwner = await db.createUser({ username: "usage-connection-owner", password: "password", role: "user" });
|
||||
const admin = await db.createUser({ username: "usage-admin", password: "password", role: "admin" });
|
||||
const apiKey = await db.createApiKey("usage-owned-key", "usage-machine", keyOwner.id);
|
||||
const connection = await db.createProviderConnection({
|
||||
provider: "usage-test",
|
||||
authType: "apikey",
|
||||
name: "usage connection",
|
||||
apiKey: "upstream-key",
|
||||
ownerId: connectionOwner.id,
|
||||
});
|
||||
|
||||
await db.saveRequestUsage({
|
||||
timestamp: new Date().toISOString(),
|
||||
provider: "usage-test",
|
||||
model: "test-model",
|
||||
connectionId: connection.id,
|
||||
apiKey: apiKey.key,
|
||||
endpoint: "/v1/chat/completions",
|
||||
tokens: { prompt_tokens: 10, completion_tokens: 5 },
|
||||
});
|
||||
|
||||
const keyOwnerStats = await db.getUsageStats("24h", keyOwner);
|
||||
expect(keyOwnerStats.totalRequests).toBe(1);
|
||||
expect(keyOwnerStats.availableTableViews).toEqual(["model", "endpoint"]);
|
||||
expect(keyOwnerStats).not.toHaveProperty("byUser");
|
||||
expect(keyOwnerStats).not.toHaveProperty("byApiKey");
|
||||
expect(keyOwnerStats).not.toHaveProperty("byAccount");
|
||||
|
||||
const connectionOwnerStats = await db.getUsageStats("24h", connectionOwner);
|
||||
expect(connectionOwnerStats.totalRequests).toBe(0);
|
||||
|
||||
const adminStats = await db.getUsageStats("24h", admin);
|
||||
expect(adminStats.availableTableViews).toEqual(["model", "user", "apiKey", "endpoint"]);
|
||||
expect(Object.values(adminStats.byUser)).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({ username: keyOwner.username, requests: 1 }),
|
||||
]));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user