Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tame-apples-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@dormice/cli": patch
---

`dor apikey disable`, `enable` and `revoke` now trim the name argument before matching, the same way key creation trims a name before storing it. Before this, a name typed with the exact leading/trailing whitespace used at creation time (or any other spelling that only differs by whitespace) failed to resolve, so a script or operator could not disable or revoke a credential.
18 changes: 18 additions & 0 deletions packages/cli/src/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,24 @@ describe('apikey commands over real HTTP', () => {
);
});

it('disable and revoke resolve a name by the same trimmed spelling creation stored', async () => {
// Creation trims the name (apiKeyNameSchema), so `ls` and every other
// read shows "incident key". Disable/enable/revoke must resolve by
// that same trimmed spelling, whether the operator retypes it exactly
// or reuses the untrimmed spelling they originally typed at creation.
await apikeyCreate(client, ' incident key ');
expect(await apikeyLs(client)).toMatch(/incident key\s{2,}/);

expect(await apikeyDisable(client, ' incident key ')).toBe(
'Disabled API key " incident key " — it stops working until re-enabled.',
);
expect(await apikeyLs(client)).toMatch(/incident key\s{2,}.*disabled/);

expect(await apikeyRevoke(client, 'incident key')).toBe(
'Revoked API key "incident key" — it stops working immediately.',
);
});

it('--expires mints a TTL key through end-of-day and refuses garbage dates', async () => {
const created = await apikeyCreate(client, 'ttl', '2030-06-15');
expect(created.split('\n')[0]).toMatch(
Expand Down
8 changes: 7 additions & 1 deletion packages/cli/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,14 @@ async function resolveApiKeyId(
client: Dormice,
name: string,
): Promise<string | null> {
// Creation trims the name (apiKeyNameSchema), so the stored spelling
// never has surrounding whitespace — match on the same trimmed spelling
// here so the untrimmed input an operator originally typed still resolves.
const trimmed = name.trim();
const keys = await client.listApiKeys();
return keys.find((k) => k.name === name && k.revokedAt === null)?.id ?? null;
return (
keys.find((k) => k.name === trimmed && k.revokedAt === null)?.id ?? null
);
}

/**
Expand Down