mirror of
https://github.com/tale/headplane.git
synced 2026-08-17 16:47:51 +00:00
list all preauth keys without user filter
headscale 0.28 added GET /v1/preauthkey without a user param which returns all keys including tag-only ones. this change adds getAllPreAuthKeys() and uses it when available, falling back to per-user fetching on older versions. the UI now handles keys where user is null, showing them as Tag Only in the filter dropdown. closes #432 Amp-Thread-ID: https://ampcode.com/threads/T-019c9861-2d45-73ef-ab94-5fce62f63670 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { getBootstrapClient, getRuntimeClient, HS_VERSIONS } from "./setup/env";
|
||||
import { getBootstrapClient, getIsAtLeast, getRuntimeClient, HS_VERSIONS } from "./setup/env";
|
||||
|
||||
describe.sequential.for(HS_VERSIONS)("Headscale %s: Pre-auth Keys", (version) => {
|
||||
test("pre-auth keys can be created", async () => {
|
||||
@@ -13,7 +13,7 @@ describe.sequential.for(HS_VERSIONS)("Headscale %s: Pre-auth Keys", (version) =>
|
||||
const preAuthKey = await client.createPreAuthKey(preAuthKeyUser.id, false, false, expiry, null);
|
||||
|
||||
expect(preAuthKey).toBeDefined();
|
||||
expect(preAuthKey.user.id).toBe(preAuthKeyUser.id);
|
||||
expect(preAuthKey.user?.id).toBe(preAuthKeyUser.id);
|
||||
expect(preAuthKey.ephemeral).toBe(false);
|
||||
expect(preAuthKey.reusable).toBe(false);
|
||||
expect(preAuthKey.aclTags).toEqual([]);
|
||||
@@ -30,7 +30,7 @@ describe.sequential.for(HS_VERSIONS)("Headscale %s: Pre-auth Keys", (version) =>
|
||||
const preAuthKey = await client.createPreAuthKey(preAuthKeyUser.id, true, true, null, aclTags);
|
||||
|
||||
expect(preAuthKey).toBeDefined();
|
||||
expect(preAuthKey.user.id).toBe(preAuthKeyUser.id);
|
||||
expect(preAuthKey.user?.id).toBe(preAuthKeyUser.id);
|
||||
expect(preAuthKey.ephemeral).toBe(true);
|
||||
expect(preAuthKey.reusable).toBe(true);
|
||||
expect(preAuthKey.aclTags.sort()).toEqual(aclTags.sort());
|
||||
@@ -64,6 +64,47 @@ describe.sequential.for(HS_VERSIONS)("Headscale %s: Pre-auth Keys", (version) =>
|
||||
expect(preAuthKeys.length).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
|
||||
test("all pre-auth keys can be listed without user filter (0.28+)", async (context) => {
|
||||
const isAtLeast = await getIsAtLeast(version);
|
||||
if (!isAtLeast("0.28.0")) {
|
||||
context.skip();
|
||||
}
|
||||
|
||||
const client = await getRuntimeClient(version);
|
||||
const [preAuthKeyUser] = await client.getUsers(undefined, "preauthkeyuser@");
|
||||
expect(preAuthKeyUser).toBeDefined();
|
||||
|
||||
const allKeys = await client.getAllPreAuthKeys();
|
||||
expect(Array.isArray(allKeys)).toBe(true);
|
||||
expect(allKeys.length).toBeGreaterThanOrEqual(2);
|
||||
|
||||
const userSpecificKeys = await client.getPreAuthKeys(preAuthKeyUser.id);
|
||||
for (const userKey of userSpecificKeys) {
|
||||
const found = allKeys.find((k) => k.key === userKey.key);
|
||||
expect(found).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test("getAllPreAuthKeys returns keys with correct structure (0.28+)", async (context) => {
|
||||
const isAtLeast = await getIsAtLeast(version);
|
||||
if (!isAtLeast("0.28.0")) {
|
||||
context.skip();
|
||||
}
|
||||
|
||||
const client = await getRuntimeClient(version);
|
||||
const allKeys = await client.getAllPreAuthKeys();
|
||||
|
||||
for (const key of allKeys) {
|
||||
expect(key.id).toBeDefined();
|
||||
expect(key.key).toBeDefined();
|
||||
expect(typeof key.reusable).toBe("boolean");
|
||||
expect(typeof key.ephemeral).toBe("boolean");
|
||||
expect(typeof key.used).toBe("boolean");
|
||||
expect(key.expiration).toBeDefined();
|
||||
expect(key.createdAt).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test("pre-auth keys can be expired", async () => {
|
||||
const client = await getRuntimeClient(version);
|
||||
const [preAuthKeyUser] = await client.getUsers(undefined, "preauthkeyuser@");
|
||||
|
||||
Reference in New Issue
Block a user