feat: improve API keys and build workflows
This commit is contained in:
@@ -26,7 +26,7 @@ function encode(value: string): string {
|
||||
}
|
||||
|
||||
function secret(
|
||||
recordType: "user" | "session",
|
||||
recordType: "user" | "session" | "api-key",
|
||||
name: string,
|
||||
values: Record<string, string>,
|
||||
): StoredSecret {
|
||||
@@ -111,6 +111,65 @@ function setup(): {
|
||||
}
|
||||
|
||||
describe("KubernetesAuthStore", () => {
|
||||
test("persists absent expiry, reads finite legacy keys, and rejects malformed expiries", async () => {
|
||||
const { fake, store } = setup();
|
||||
await store.putUser({
|
||||
username: "alice",
|
||||
passwordHash: "hash",
|
||||
roles: ["viewer"],
|
||||
});
|
||||
const never = {
|
||||
id: "never-expiring-key-123",
|
||||
tokenHash: hashToken("never"),
|
||||
username: "alice",
|
||||
capabilities: ["kubernetes:read" as const],
|
||||
};
|
||||
await store.createApiKey(never);
|
||||
expect(fake.patches.at(-1)?.stringData).not.toHaveProperty("expiresAt");
|
||||
expect(await store.getApiKey(never.tokenHash)).toMatchObject(never);
|
||||
const finite = {
|
||||
...never,
|
||||
id: "finite-expiry-key-123",
|
||||
tokenHash: hashToken("finite"),
|
||||
expiresAt: "2020-01-01T00:00:00.000Z",
|
||||
};
|
||||
await store.createApiKey(finite);
|
||||
expect(
|
||||
(await store.listApiKeys("alice")).map((key) => key.expiresAt),
|
||||
).toEqual([finite.expiresAt, undefined]);
|
||||
expect(await store.deleteExpiredApiKeys()).toBe(1);
|
||||
expect(await store.getApiKey(never.tokenHash)).toMatchObject(never);
|
||||
const active = {
|
||||
...finite,
|
||||
id: "active-finite-key-123",
|
||||
tokenHash: hashToken("active-finite"),
|
||||
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
||||
};
|
||||
await store.createApiKey(active);
|
||||
expect(await store.getApiKey(active.tokenHash)).toMatchObject(active);
|
||||
const name = objectName("api-key", never.tokenHash);
|
||||
for (const expiry of ["none", "", "2026-09-03"]) {
|
||||
fake.secrets.set(
|
||||
name,
|
||||
secret("api-key", name, {
|
||||
id: never.id,
|
||||
tokenHash: never.tokenHash,
|
||||
username: never.username,
|
||||
capabilities: JSON.stringify(never.capabilities),
|
||||
workspace: "",
|
||||
disabled: "false",
|
||||
expiresAt: expiry,
|
||||
}),
|
||||
);
|
||||
expect(await store.getApiKey(never.tokenHash)).toBeUndefined();
|
||||
}
|
||||
expect(await store.revokeApiKey("bob", finite.id)).toBe(false);
|
||||
await expect(
|
||||
store.createApiKey({ ...never, username: "missing" }),
|
||||
).rejects.toThrow("not active");
|
||||
await store.updateUser("alice", { disabled: true });
|
||||
await expect(store.createApiKey(never)).rejects.toThrow("not active");
|
||||
});
|
||||
test("validates the session and user from the store on every request", async () => {
|
||||
const { fake, store } = setup();
|
||||
const tokenHash = hashToken("fresh");
|
||||
|
||||
Reference in New Issue
Block a user