fix(web): surface a failed OAuth clear instead of floating its rejection (#2144)
Copilot review round 10. Both Clear entry points discarded the promise with `void`, but `clearServerOAuthAndDisconnect` does not own its failures — the store write or the disconnect can reject. That produced an unhandled rejection and left the user with a control that had silently done nothing. A shared `runClear` terminates it with `.catch` and raises a red, non-expiring notification: the tokens may still be on disk and the session may still be up, which is not a notice to let time out. An RFC 7009 failure is not this case — those come back as an outcome and are already reported in the success toast. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
5170cc484b
commit
1661f09d0a
1 changed files with 29 additions and 6 deletions
|
|
@ -1320,19 +1320,42 @@ function App() {
|
|||
// target isn't resolvable.
|
||||
const settingsModalIsStdio = settingsModalServerType === "stdio";
|
||||
|
||||
/**
|
||||
* Run a clear from a key/click handler, which cannot await.
|
||||
*
|
||||
* `clearServerOAuthAndDisconnect` does **not** own its failures — the store
|
||||
* write or the disconnect can reject — so a bare `void` would produce an
|
||||
* unhandled rejection and leave the user with a control that silently did
|
||||
* nothing. (An RFC 7009 failure is not this: those come back as an outcome
|
||||
* and are already reported in the success toast.)
|
||||
*/
|
||||
const runClear = useCallback(
|
||||
(server: Parameters<typeof clearServerOAuthAndDisconnect>[0]) => {
|
||||
clearServerOAuthAndDisconnect(server).catch((err: unknown) => {
|
||||
notifications.show({
|
||||
title: "Could not clear the stored OAuth state",
|
||||
message: err instanceof Error ? err.message : String(err),
|
||||
color: "red",
|
||||
// The tokens may still be on disk and the session may still be up,
|
||||
// so this is not a notice to let time out.
|
||||
autoClose: false,
|
||||
});
|
||||
});
|
||||
},
|
||||
[clearServerOAuthAndDisconnect],
|
||||
);
|
||||
|
||||
const handleClearConnectionOAuth = useCallback(() => {
|
||||
if (!activeServer) return;
|
||||
void clearServerOAuthAndDisconnect(activeServer);
|
||||
}, [activeServer, clearServerOAuthAndDisconnect]);
|
||||
runClear(activeServer);
|
||||
}, [activeServer, runClear]);
|
||||
|
||||
const handleClearStoredOAuthFromSettings = useCallback(() => {
|
||||
if (!settingsModalTarget) return;
|
||||
// Clear from *inside* the settings modal, so the draft is what the user is
|
||||
// looking at rather than what the debounced save has persisted (#2144).
|
||||
void clearServerOAuthAndDisconnect(
|
||||
serverWithDraftSettings(settingsModalTarget, settingsDraft),
|
||||
);
|
||||
}, [settingsModalTarget, settingsDraft, clearServerOAuthAndDisconnect]);
|
||||
runClear(serverWithDraftSettings(settingsModalTarget, settingsDraft));
|
||||
}, [settingsModalTarget, settingsDraft, runClear]);
|
||||
|
||||
const onSettingsModalClose = useCallback(() => {
|
||||
flushSettingsDraft();
|
||||
|
|
|
|||
Loading…
Reference in a new issue