mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-16 21:10:40 -07:00
fix: Make trustedFolders file path configurable (#8306)
Co-authored-by: cornmander <shikhman@google.com>
This commit is contained in:
@@ -21,7 +21,7 @@ import stripJsonComments from 'strip-json-comments';
|
|||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
import {
|
import {
|
||||||
loadTrustedFolders,
|
loadTrustedFolders,
|
||||||
USER_TRUSTED_FOLDERS_PATH,
|
getTrustedFoldersPath,
|
||||||
TrustLevel,
|
TrustLevel,
|
||||||
isWorkspaceTrusted,
|
isWorkspaceTrusted,
|
||||||
} from './trustedFolders.js';
|
} from './trustedFolders.js';
|
||||||
@@ -80,10 +80,10 @@ describe('Trusted Folders Loading', () => {
|
|||||||
describe('isPathTrusted', () => {
|
describe('isPathTrusted', () => {
|
||||||
function setup({ config = {} as Record<string, TrustLevel> } = {}) {
|
function setup({ config = {} as Record<string, TrustLevel> } = {}) {
|
||||||
(mockFsExistsSync as Mock).mockImplementation(
|
(mockFsExistsSync as Mock).mockImplementation(
|
||||||
(p) => p === USER_TRUSTED_FOLDERS_PATH,
|
(p) => p === getTrustedFoldersPath(),
|
||||||
);
|
);
|
||||||
(fs.readFileSync as Mock).mockImplementation((p) => {
|
(fs.readFileSync as Mock).mockImplementation((p) => {
|
||||||
if (p === USER_TRUSTED_FOLDERS_PATH) return JSON.stringify(config);
|
if (p === getTrustedFoldersPath()) return JSON.stringify(config);
|
||||||
return '{}';
|
return '{}';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ describe('Trusted Folders Loading', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should load user rules if only user file exists', () => {
|
it('should load user rules if only user file exists', () => {
|
||||||
const userPath = USER_TRUSTED_FOLDERS_PATH;
|
const userPath = getTrustedFoldersPath();
|
||||||
(mockFsExistsSync as Mock).mockImplementation((p) => p === userPath);
|
(mockFsExistsSync as Mock).mockImplementation((p) => p === userPath);
|
||||||
const userContent = {
|
const userContent = {
|
||||||
'/user/folder': TrustLevel.TRUST_FOLDER,
|
'/user/folder': TrustLevel.TRUST_FOLDER,
|
||||||
@@ -142,7 +142,7 @@ describe('Trusted Folders Loading', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle JSON parsing errors gracefully', () => {
|
it('should handle JSON parsing errors gracefully', () => {
|
||||||
const userPath = USER_TRUSTED_FOLDERS_PATH;
|
const userPath = getTrustedFoldersPath();
|
||||||
(mockFsExistsSync as Mock).mockImplementation((p) => p === userPath);
|
(mockFsExistsSync as Mock).mockImplementation((p) => p === userPath);
|
||||||
(fs.readFileSync as Mock).mockImplementation((p) => {
|
(fs.readFileSync as Mock).mockImplementation((p) => {
|
||||||
if (p === userPath) return 'invalid json';
|
if (p === userPath) return 'invalid json';
|
||||||
@@ -156,6 +156,31 @@ describe('Trusted Folders Loading', () => {
|
|||||||
expect(errors[0].message).toContain('Unexpected token');
|
expect(errors[0].message).toContain('Unexpected token');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should use GEMINI_CLI_TRUSTED_FOLDERS_PATH env var if set', () => {
|
||||||
|
const customPath = '/custom/path/to/trusted_folders.json';
|
||||||
|
process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'] = customPath;
|
||||||
|
|
||||||
|
(mockFsExistsSync as Mock).mockImplementation((p) => p === customPath);
|
||||||
|
const userContent = {
|
||||||
|
'/user/folder/from/env': TrustLevel.TRUST_FOLDER,
|
||||||
|
};
|
||||||
|
(fs.readFileSync as Mock).mockImplementation((p) => {
|
||||||
|
if (p === customPath) return JSON.stringify(userContent);
|
||||||
|
return '{}';
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rules, errors } = loadTrustedFolders();
|
||||||
|
expect(rules).toEqual([
|
||||||
|
{
|
||||||
|
path: '/user/folder/from/env',
|
||||||
|
trustLevel: TrustLevel.TRUST_FOLDER,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(errors).toEqual([]);
|
||||||
|
|
||||||
|
delete process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
|
||||||
|
});
|
||||||
|
|
||||||
it('setValue should update the user config and save it', () => {
|
it('setValue should update the user config and save it', () => {
|
||||||
const loadedFolders = loadTrustedFolders();
|
const loadedFolders = loadTrustedFolders();
|
||||||
loadedFolders.setValue('/new/path', TrustLevel.TRUST_FOLDER);
|
loadedFolders.setValue('/new/path', TrustLevel.TRUST_FOLDER);
|
||||||
@@ -164,7 +189,7 @@ describe('Trusted Folders Loading', () => {
|
|||||||
TrustLevel.TRUST_FOLDER,
|
TrustLevel.TRUST_FOLDER,
|
||||||
);
|
);
|
||||||
expect(mockFsWriteFileSync).toHaveBeenCalledWith(
|
expect(mockFsWriteFileSync).toHaveBeenCalledWith(
|
||||||
USER_TRUSTED_FOLDERS_PATH,
|
getTrustedFoldersPath(),
|
||||||
JSON.stringify({ '/new/path': TrustLevel.TRUST_FOLDER }, null, 2),
|
JSON.stringify({ '/new/path': TrustLevel.TRUST_FOLDER }, null, 2),
|
||||||
{ encoding: 'utf-8', mode: 0o600 },
|
{ encoding: 'utf-8', mode: 0o600 },
|
||||||
);
|
);
|
||||||
@@ -185,13 +210,13 @@ describe('isWorkspaceTrusted', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.spyOn(process, 'cwd').mockImplementation(() => mockCwd);
|
vi.spyOn(process, 'cwd').mockImplementation(() => mockCwd);
|
||||||
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
|
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
|
||||||
if (p === USER_TRUSTED_FOLDERS_PATH) {
|
if (p === getTrustedFoldersPath()) {
|
||||||
return JSON.stringify(mockRules);
|
return JSON.stringify(mockRules);
|
||||||
}
|
}
|
||||||
return '{}';
|
return '{}';
|
||||||
});
|
});
|
||||||
vi.spyOn(fs, 'existsSync').mockImplementation(
|
vi.spyOn(fs, 'existsSync').mockImplementation(
|
||||||
(p) => p === USER_TRUSTED_FOLDERS_PATH,
|
(p) => p === getTrustedFoldersPath(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ import stripJsonComments from 'strip-json-comments';
|
|||||||
export const TRUSTED_FOLDERS_FILENAME = 'trustedFolders.json';
|
export const TRUSTED_FOLDERS_FILENAME = 'trustedFolders.json';
|
||||||
export const SETTINGS_DIRECTORY_NAME = '.gemini';
|
export const SETTINGS_DIRECTORY_NAME = '.gemini';
|
||||||
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
|
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
|
||||||
export const USER_TRUSTED_FOLDERS_PATH = path.join(
|
|
||||||
USER_SETTINGS_DIR,
|
export function getTrustedFoldersPath(): string {
|
||||||
TRUSTED_FOLDERS_FILENAME,
|
if (process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH']) {
|
||||||
);
|
return process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
|
||||||
|
}
|
||||||
|
return path.join(USER_SETTINGS_DIR, TRUSTED_FOLDERS_FILENAME);
|
||||||
|
}
|
||||||
|
|
||||||
export enum TrustLevel {
|
export enum TrustLevel {
|
||||||
TRUST_FOLDER = 'TRUST_FOLDER',
|
TRUST_FOLDER = 'TRUST_FOLDER',
|
||||||
@@ -110,7 +113,7 @@ export function loadTrustedFolders(): LoadedTrustedFolders {
|
|||||||
const errors: TrustedFoldersError[] = [];
|
const errors: TrustedFoldersError[] = [];
|
||||||
const userConfig: Record<string, TrustLevel> = {};
|
const userConfig: Record<string, TrustLevel> = {};
|
||||||
|
|
||||||
const userPath = USER_TRUSTED_FOLDERS_PATH;
|
const userPath = getTrustedFoldersPath();
|
||||||
|
|
||||||
// Load user trusted folders
|
// Load user trusted folders
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user