Refactor Authentication Components and Hooks (#7750)

This commit is contained in:
Tommaso Sciortino
2025-09-05 15:35:41 -07:00
committed by GitHub
parent d8dbe6271f
commit 7239c5cd9a
11 changed files with 462 additions and 756 deletions
@@ -21,11 +21,12 @@ import {
} from '@google/gemini-cli-core';
import { useSessionStats } from '../contexts/SessionContext.js';
import { runExitCleanup } from '../../utils/cleanup.js';
import type {
Message,
HistoryItemWithoutId,
HistoryItem,
SlashCommandProcessorResult,
import {
type Message,
type HistoryItemWithoutId,
type HistoryItem,
type SlashCommandProcessorResult,
AuthState,
} from '../types.js';
import { MessageType } from '../types.js';
import type { LoadedSettings } from '../../config/settings.js';
@@ -47,7 +48,7 @@ export const useSlashCommandProcessor = (
refreshStatic: () => void,
onDebugMessage: (message: string) => void,
openThemeDialog: () => void,
openAuthDialog: () => void,
setAuthState: (state: AuthState) => void,
openEditorDialog: () => void,
toggleCorgiMode: () => void,
setQuittingMessages: (message: HistoryItem[]) => void,
@@ -375,7 +376,7 @@ export const useSlashCommandProcessor = (
case 'dialog':
switch (result.dialog) {
case 'auth':
openAuthDialog();
setAuthState(AuthState.Updating);
return { type: 'handled' };
case 'theme':
openThemeDialog();
@@ -554,7 +555,7 @@ export const useSlashCommandProcessor = (
[
config,
addItem,
openAuthDialog,
setAuthState,
commands,
commandContext,
addMessage,
@@ -1,91 +0,0 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { useState, useCallback, useEffect } from 'react';
import type { LoadedSettings, SettingScope } from '../../config/settings.js';
import { AuthType, type Config } from '@google/gemini-cli-core';
import {
clearCachedCredentialFile,
getErrorMessage,
} from '@google/gemini-cli-core';
import { runExitCleanup } from '../../utils/cleanup.js';
export const useAuthCommand = (
settings: LoadedSettings,
setAuthError: (error: string | null) => void,
config: Config,
) => {
const [isAuthDialogOpen, setIsAuthDialogOpen] = useState(
settings.merged.security?.auth?.selectedType === undefined,
);
const openAuthDialog = useCallback(() => {
setIsAuthDialogOpen(true);
}, []);
const [isAuthenticating, setIsAuthenticating] = useState(false);
useEffect(() => {
const authFlow = async () => {
const authType = settings.merged.security?.auth?.selectedType;
if (isAuthDialogOpen || !authType) {
return;
}
try {
setIsAuthenticating(true);
await config.refreshAuth(authType);
console.log(`Authenticated via "${authType}".`);
} catch (e) {
setAuthError(`Failed to login. Message: ${getErrorMessage(e)}`);
openAuthDialog();
} finally {
setIsAuthenticating(false);
}
};
void authFlow();
}, [isAuthDialogOpen, settings, config, setAuthError, openAuthDialog]);
const handleAuthSelect = useCallback(
async (authType: AuthType | undefined, scope: SettingScope) => {
if (authType) {
await clearCachedCredentialFile();
settings.setValue(scope, 'security.auth.selectedType', authType);
if (
authType === AuthType.LOGIN_WITH_GOOGLE &&
config.isBrowserLaunchSuppressed()
) {
runExitCleanup();
console.log(
`
----------------------------------------------------------------
Logging in with Google... Please restart Gemini CLI to continue.
----------------------------------------------------------------
`,
);
process.exit(0);
}
}
setIsAuthDialogOpen(false);
setAuthError(null);
},
[settings, setAuthError, config],
);
const cancelAuthentication = useCallback(() => {
setIsAuthenticating(false);
}, []);
return {
isAuthDialogOpen,
openAuthDialog,
handleAuthSelect,
isAuthenticating,
cancelAuthentication,
};
};
+2 -2
View File
@@ -95,7 +95,7 @@ export const useGeminiStream = (
) => Promise<SlashCommandProcessorResult | false>,
shellModeActive: boolean,
getPreferredEditor: () => EditorType | undefined,
onAuthError: () => void,
onAuthError: (error: string) => void,
performMemoryRefresh: () => Promise<void>,
modelSwitchedFromQuotaError: boolean,
setModelSwitchedFromQuotaError: React.Dispatch<React.SetStateAction<boolean>>,
@@ -751,7 +751,7 @@ export const useGeminiStream = (
}
} catch (error: unknown) {
if (error instanceof UnauthorizedError) {
onAuthError();
onAuthError('Session expired or is unauthorized.');
} else if (!isNodeError(error) || error.name !== 'AbortError') {
addItem(
{