mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
fix(web): confirm before clearing the saved Composio API key (#877)
The Clear button on Settings → Connectors removed the daemon-stored Composio key in a single click with no recovery — a stray click wiped a credential the user had to fetch back from app.composio.dev. Wrap the existing onClick in window.confirm() matching the same pattern the codebase already uses for destructive actions (conversation delete, design delete, FileWorkspace file delete, and the Media providers Clear button shipped alongside this in issue #737). The prompt copy stays in English to match the rest of the Composio section, which is hardcoded English today. Updated the existing 'clears a saved Composio key' test to auto-accept the prompt, plus added a sibling test asserting that dismissing the prompt leaves the daemon-stored key intact in the saved payload. Co-authored-by: Nagendhra <nagendhra405@gmail.com>
This commit is contained in:
parent
751b2357f1
commit
661d11e60b
2 changed files with 60 additions and 1 deletions
|
|
@ -1856,7 +1856,19 @@ function ComposioSection({
|
|||
type="button"
|
||||
className="ghost"
|
||||
disabled={!apiKeyConfigured}
|
||||
onClick={() => updateComposio({ apiKey: '', apiKeyConfigured: false, apiKeyTail: '' })}
|
||||
onClick={() => {
|
||||
// Match the existing window.confirm guard the rest of the
|
||||
// app uses for destructive actions (conversation delete,
|
||||
// design delete, file delete in FileWorkspace, and the
|
||||
// Media providers Clear button). Without this a stray
|
||||
// click wipes the daemon-stored Composio key and the
|
||||
// user has to paste it back from their secrets manager.
|
||||
// Issue #734.
|
||||
if (!confirm('Clear the saved Composio API key? You\'ll need to paste it again to use Composio-backed connectors.')) {
|
||||
return;
|
||||
}
|
||||
updateComposio({ apiKey: '', apiKeyConfigured: false, apiKeyTail: '' });
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -890,8 +890,15 @@ describe('SettingsDialog connectors interactions', () => {
|
|||
{ initialSection: 'composio' },
|
||||
);
|
||||
|
||||
// Issue #734 added a window.confirm guard on the Clear button so a
|
||||
// stray click cannot wipe a daemon-stored Composio key. Auto-accept
|
||||
// the prompt here so the test still exercises the cleared-payload
|
||||
// path.
|
||||
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Clear' }));
|
||||
|
||||
expect(confirmSpy).toHaveBeenCalledTimes(1);
|
||||
expect((screen.getByPlaceholderText('Paste Composio API key') as HTMLInputElement).value).toBe('');
|
||||
expect(screen.getByText(/Keys are stored locally in the daemon/i)).toBeTruthy();
|
||||
|
||||
|
|
@ -906,6 +913,46 @@ describe('SettingsDialog connectors interactions', () => {
|
|||
}),
|
||||
false,
|
||||
);
|
||||
|
||||
confirmSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('cancels Clear when the Composio confirmation is dismissed (issue #734)', () => {
|
||||
const { onSave } = renderSettingsDialog(
|
||||
{
|
||||
mode: 'daemon',
|
||||
agentId: 'codex',
|
||||
composio: {
|
||||
apiKey: '',
|
||||
apiKeyConfigured: true,
|
||||
apiKeyTail: 'uQEg',
|
||||
},
|
||||
},
|
||||
{ initialSection: 'composio' },
|
||||
);
|
||||
|
||||
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(false);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Clear' }));
|
||||
|
||||
expect(confirmSpy).toHaveBeenCalledTimes(1);
|
||||
// Saved badge survives because apiKeyConfigured is still true.
|
||||
expect(screen.getByText(/Saved · ••••uQEg/)).toBeTruthy();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save' }));
|
||||
// Without a confirmation, the saved key must remain in the payload
|
||||
// so the user does not silently lose their daemon-stored credential.
|
||||
expect(onSave).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
composio: expect.objectContaining({
|
||||
apiKeyConfigured: true,
|
||||
apiKeyTail: 'uQEg',
|
||||
}),
|
||||
}),
|
||||
false,
|
||||
);
|
||||
|
||||
confirmSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('does not save Composio edits when cancel is used or the backdrop is clicked', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue