mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-14 20:10:36 -07:00
fix: Add a message about permissions command on startup in untrusted … (#10755)
This commit is contained in:
@@ -796,7 +796,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
|
|||||||
const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
|
const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
|
||||||
|
|
||||||
const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } =
|
const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } =
|
||||||
useFolderTrust(settings, setIsTrustedFolder);
|
useFolderTrust(settings, setIsTrustedFolder, historyManager.addItem);
|
||||||
const {
|
const {
|
||||||
needsRestart: ideNeedsRestart,
|
needsRestart: ideNeedsRestart,
|
||||||
restartReason: ideTrustRestartReason,
|
restartReason: ideTrustRestartReason,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ describe('useFolderTrust', () => {
|
|||||||
let loadTrustedFoldersSpy: vi.SpyInstance;
|
let loadTrustedFoldersSpy: vi.SpyInstance;
|
||||||
let isWorkspaceTrustedSpy: vi.SpyInstance;
|
let isWorkspaceTrustedSpy: vi.SpyInstance;
|
||||||
let onTrustChange: (isTrusted: boolean | undefined) => void;
|
let onTrustChange: (isTrusted: boolean | undefined) => void;
|
||||||
|
let addItem: vi.Mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockSettings = {
|
mockSettings = {
|
||||||
@@ -54,6 +55,7 @@ describe('useFolderTrust', () => {
|
|||||||
isWorkspaceTrustedSpy = vi.spyOn(trustedFolders, 'isWorkspaceTrusted');
|
isWorkspaceTrustedSpy = vi.spyOn(trustedFolders, 'isWorkspaceTrusted');
|
||||||
mockedCwd.mockReturnValue('/test/path');
|
mockedCwd.mockReturnValue('/test/path');
|
||||||
onTrustChange = vi.fn();
|
onTrustChange = vi.fn();
|
||||||
|
addItem = vi.fn();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -63,7 +65,7 @@ describe('useFolderTrust', () => {
|
|||||||
it('should not open dialog when folder is already trusted', () => {
|
it('should not open dialog when folder is already trusted', () => {
|
||||||
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: true, source: 'file' });
|
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: true, source: 'file' });
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
expect(result.current.isFolderTrustDialogOpen).toBe(false);
|
expect(result.current.isFolderTrustDialogOpen).toBe(false);
|
||||||
expect(onTrustChange).toHaveBeenCalledWith(true);
|
expect(onTrustChange).toHaveBeenCalledWith(true);
|
||||||
@@ -72,7 +74,7 @@ describe('useFolderTrust', () => {
|
|||||||
it('should not open dialog when folder is already untrusted', () => {
|
it('should not open dialog when folder is already untrusted', () => {
|
||||||
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' });
|
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' });
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
expect(result.current.isFolderTrustDialogOpen).toBe(false);
|
expect(result.current.isFolderTrustDialogOpen).toBe(false);
|
||||||
expect(onTrustChange).toHaveBeenCalledWith(false);
|
expect(onTrustChange).toHaveBeenCalledWith(false);
|
||||||
@@ -84,19 +86,37 @@ describe('useFolderTrust', () => {
|
|||||||
source: undefined,
|
source: undefined,
|
||||||
});
|
});
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
expect(result.current.isFolderTrustDialogOpen).toBe(true);
|
expect(result.current.isFolderTrustDialogOpen).toBe(true);
|
||||||
expect(onTrustChange).toHaveBeenCalledWith(undefined);
|
expect(onTrustChange).toHaveBeenCalledWith(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should send a message if the folder is untrusted', () => {
|
||||||
|
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' });
|
||||||
|
renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
|
||||||
|
expect(addItem).toHaveBeenCalledWith(
|
||||||
|
{
|
||||||
|
text: 'This folder is not trusted. Some features may be disabled. Use the `/permissions` command to change the trust level.',
|
||||||
|
type: 'info',
|
||||||
|
},
|
||||||
|
expect.any(Number),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not send a message if the folder is trusted', () => {
|
||||||
|
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: true, source: 'file' });
|
||||||
|
renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
|
||||||
|
expect(addItem).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle TRUST_FOLDER choice', () => {
|
it('should handle TRUST_FOLDER choice', () => {
|
||||||
isWorkspaceTrustedSpy.mockReturnValue({
|
isWorkspaceTrustedSpy.mockReturnValue({
|
||||||
isTrusted: undefined,
|
isTrusted: undefined,
|
||||||
source: undefined,
|
source: undefined,
|
||||||
});
|
});
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -118,7 +138,7 @@ describe('useFolderTrust', () => {
|
|||||||
source: undefined,
|
source: undefined,
|
||||||
});
|
});
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -139,7 +159,7 @@ describe('useFolderTrust', () => {
|
|||||||
source: undefined,
|
source: undefined,
|
||||||
});
|
});
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -161,7 +181,7 @@ describe('useFolderTrust', () => {
|
|||||||
source: undefined,
|
source: undefined,
|
||||||
});
|
});
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -179,7 +199,7 @@ describe('useFolderTrust', () => {
|
|||||||
it('should set isRestarting to true when trust status changes from false to true', () => {
|
it('should set isRestarting to true when trust status changes from false to true', () => {
|
||||||
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' }); // Initially untrusted
|
isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' }); // Initially untrusted
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -196,7 +216,7 @@ describe('useFolderTrust', () => {
|
|||||||
source: undefined,
|
source: undefined,
|
||||||
});
|
});
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useFolderTrust(mockSettings, onTrustChange),
|
useFolderTrust(mockSettings, onTrustChange, addItem),
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
||||||
import type { LoadedSettings } from '../../config/settings.js';
|
import type { LoadedSettings } from '../../config/settings.js';
|
||||||
import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
|
import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
|
||||||
import {
|
import {
|
||||||
@@ -13,14 +13,17 @@ import {
|
|||||||
isWorkspaceTrusted,
|
isWorkspaceTrusted,
|
||||||
} from '../../config/trustedFolders.js';
|
} from '../../config/trustedFolders.js';
|
||||||
import * as process from 'node:process';
|
import * as process from 'node:process';
|
||||||
|
import { type HistoryItemWithoutId, MessageType } from '../types.js';
|
||||||
|
|
||||||
export const useFolderTrust = (
|
export const useFolderTrust = (
|
||||||
settings: LoadedSettings,
|
settings: LoadedSettings,
|
||||||
onTrustChange: (isTrusted: boolean | undefined) => void,
|
onTrustChange: (isTrusted: boolean | undefined) => void,
|
||||||
|
addItem: (item: HistoryItemWithoutId, timestamp: number) => number,
|
||||||
) => {
|
) => {
|
||||||
const [isTrusted, setIsTrusted] = useState<boolean | undefined>(undefined);
|
const [isTrusted, setIsTrusted] = useState<boolean | undefined>(undefined);
|
||||||
const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState(false);
|
const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState(false);
|
||||||
const [isRestarting, setIsRestarting] = useState(false);
|
const [isRestarting, setIsRestarting] = useState(false);
|
||||||
|
const startupMessageSent = useRef(false);
|
||||||
|
|
||||||
const folderTrust = settings.merged.security?.folderTrust?.enabled;
|
const folderTrust = settings.merged.security?.folderTrust?.enabled;
|
||||||
|
|
||||||
@@ -29,7 +32,18 @@ export const useFolderTrust = (
|
|||||||
setIsTrusted(trusted);
|
setIsTrusted(trusted);
|
||||||
setIsFolderTrustDialogOpen(trusted === undefined);
|
setIsFolderTrustDialogOpen(trusted === undefined);
|
||||||
onTrustChange(trusted);
|
onTrustChange(trusted);
|
||||||
}, [folderTrust, onTrustChange, settings.merged]);
|
|
||||||
|
if (trusted === false && !startupMessageSent.current) {
|
||||||
|
addItem(
|
||||||
|
{
|
||||||
|
type: MessageType.INFO,
|
||||||
|
text: 'This folder is not trusted. Some features may be disabled. Use the `/permissions` command to change the trust level.',
|
||||||
|
},
|
||||||
|
Date.now(),
|
||||||
|
);
|
||||||
|
startupMessageSent.current = true;
|
||||||
|
}
|
||||||
|
}, [folderTrust, onTrustChange, settings.merged, addItem]);
|
||||||
|
|
||||||
const handleFolderTrustSelect = useCallback(
|
const handleFolderTrustSelect = useCallback(
|
||||||
(choice: FolderTrustChoice) => {
|
(choice: FolderTrustChoice) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user