feat: improve API keys and build workflows
This commit is contained in:
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
MemoryAuthStore,
|
||||
hashToken,
|
||||
normalizeApiKey,
|
||||
tokenHashesEqual,
|
||||
} from "../../server/auth";
|
||||
import {
|
||||
@@ -23,6 +24,54 @@ describe("authorization", () => {
|
||||
});
|
||||
|
||||
describe("memory auth store", () => {
|
||||
test("keeps non-expiring keys active and preserves finite expiry validation", async () => {
|
||||
const store = new MemoryAuthStore();
|
||||
await store.putUser({
|
||||
username: "alice",
|
||||
passwordHash: "hash",
|
||||
roles: ["viewer"],
|
||||
});
|
||||
const key = {
|
||||
id: "never-expiring-key-123",
|
||||
tokenHash: hashToken("never"),
|
||||
username: "alice",
|
||||
capabilities: ["kubernetes:read" as const],
|
||||
};
|
||||
await store.createApiKey(key);
|
||||
expect(await store.getApiKey(key.tokenHash)).toMatchObject(key);
|
||||
expect((await store.listApiKeys("alice"))[0]?.expiresAt).toBeUndefined();
|
||||
await store.createApiKey({
|
||||
...key,
|
||||
id: "finite-expiry-key-123",
|
||||
tokenHash: hashToken("finite"),
|
||||
expiresAt: "2020-01-01T00:00:00.000Z",
|
||||
});
|
||||
expect(await store.deleteExpiredApiKeys()).toBe(1);
|
||||
expect(await store.getApiKey(key.tokenHash)).toMatchObject(key);
|
||||
expect(
|
||||
normalizeApiKey({ ...key, expiresAt: undefined }).expiresAt,
|
||||
).toBeUndefined();
|
||||
for (const expiresAt of ["none", "not-a-date", "2026-09-03", ""]) {
|
||||
expect(() => normalizeApiKey({ ...key, expiresAt })).toThrow(
|
||||
"ISO timestamp",
|
||||
);
|
||||
}
|
||||
await expect(
|
||||
store.createApiKey({
|
||||
...key,
|
||||
id: "duplicate-key-id-123",
|
||||
tokenHash: hashToken("duplicate"),
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
expect(await store.revokeApiKey("bob", key.id)).toBe(false);
|
||||
expect(await store.revokeApiKey("alice", key.id)).toBe(true);
|
||||
expect(await store.getApiKey(key.tokenHash)).toBeUndefined();
|
||||
await expect(
|
||||
store.createApiKey({ ...key, username: "missing" }),
|
||||
).rejects.toThrow("not active");
|
||||
await store.updateUser("alice", { disabled: true });
|
||||
await expect(store.createApiKey({ ...key })).rejects.toThrow("not active");
|
||||
});
|
||||
test("maintains the API-key hash index across key mutations", async () => {
|
||||
const store = new MemoryAuthStore();
|
||||
await store.putUser({
|
||||
|
||||
Reference in New Issue
Block a user