Skip to content

Commit f76d0be

Browse files
committed
Preserve generated API key token on create failure
1 parent 0e4984d commit f76d0be

2 files changed

Lines changed: 38 additions & 3 deletions

File tree

frontend/src/pages/Profile.apiKeys.test.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,41 @@ describe("Profile API keys", () => {
205205
expect(screen.getByRole("button", { name: /create api key/i })).toBeDisabled();
206206
expect(api.createApiKey).not.toHaveBeenCalled();
207207
});
208+
209+
it("keeps a one-time token visible if creating another API key fails", async () => {
210+
vi.mocked(api.createApiKey)
211+
.mockResolvedValueOnce({
212+
apiKey: {
213+
...existingApiKey,
214+
id: "key-2",
215+
name: "First Token",
216+
prefix: "exd_key_first",
217+
},
218+
token: "exd_key_first.secret-token-value",
219+
})
220+
.mockRejectedValueOnce(new Error("Network error"));
221+
222+
render(
223+
<MemoryRouter>
224+
<Profile />
225+
</MemoryRouter>
226+
);
227+
228+
await screen.findByText("Existing Key");
229+
230+
fireEvent.change(screen.getByLabelText(/api key name/i), {
231+
target: { value: "First Token" },
232+
});
233+
fireEvent.click(screen.getByRole("button", { name: /create api key/i }));
234+
235+
expect(await screen.findByDisplayValue("exd_key_first.secret-token-value")).toBeInTheDocument();
236+
237+
fireEvent.change(screen.getByLabelText(/api key name/i), {
238+
target: { value: "Second Token" },
239+
});
240+
fireEvent.click(screen.getByRole("button", { name: /create api key/i }));
241+
242+
expect(await screen.findByText(/failed to create api key/i)).toBeInTheDocument();
243+
expect(screen.getByDisplayValue("exd_key_first.secret-token-value")).toBeInTheDocument();
244+
});
208245
});

frontend/src/pages/Profile.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,6 @@ export const Profile: React.FC = () => {
289289
setApiKeyActionLoading(true);
290290
setApiKeyError('');
291291
setSuccess('');
292-
setGeneratedToken('');
293-
setGeneratedTokenName('');
294-
setCopiedToken(false);
295292

296293
try {
297294
const response = await api.createApiKey(trimmedName, selectedApiKeyScopes);
@@ -300,6 +297,7 @@ export const Profile: React.FC = () => {
300297
setSelectedApiKeyScopes([...api.API_KEY_SCOPES]);
301298
setGeneratedToken(response.token);
302299
setGeneratedTokenName(response.apiKey.name);
300+
setCopiedToken(false);
303301
setSuccess('API key created. Copy the token now; it will not be shown again.');
304302
} catch (err: unknown) {
305303
setApiKeyError(getApiErrorMessage(err, 'Failed to create API key'));

0 commit comments

Comments
 (0)