import vscode = require ( 'vscode' ) ; import { getFromWorkspaceState , updateWorkspaceState } from './stateUtils' ; const WORKSPACE_IS_TRUSTED_KEY = 'WORKSPACE_IS_TRUSTED_KEY' ; const SECURITY_SENSITIVE_CONFIG = [ 'sphinxBuildPath' , 'linter.executablePath' ] ; export async function initConfig ( ctx ) { const isTrusted = getFromWorkspaceState ( WORKSPACE_IS_TRUSTED_KEY , false ) ; if ( isTrusted !== defaultConfig . workspaceIsTrusted ( ) ) { defaultConfig . toggleWorkspaceIsTrusted ( ) ; } ctx . subscriptions . push ( vscode . commands . registerCommand ( 'restructuredtext.workspace.isTrusted.toggle' , toggleWorkspaceIsTrusted ) ) ; if ( isTrusted ) { return ; } const ignored = ignoredWorkspaceConfig ( vscode . workspace . getConfiguration ( 'restructuredtext' ) , SECURITY_SENSITIVE_CONFIG ) ; if ( ignored . length === 0 ) { return ; } const ignoredSettings = ignored . map ( ( x ) => `"restructuredtext.${ x }"` ) . join ( ',' ) ; const val = await vscode . window . showWarningMessage ( `Some workspace/folder-level settings (${ ignoredSettings }) from the untrusted workspace are disabled ` + 'by default. If this workspace is trusted, explicitly enable the workspace/folder-level settings ' + 'by running the "reStructuredText: Toggle Workspace Trust Flag" command.' , 'OK' , 'Trust This Workspace' , 'More Info' ) ; switch ( val ) { case 'Trust This Workspace' : await toggleWorkspaceIsTrusted ( ) ; break ; case 'More Info' : vscode . env . openExternal ( vscode . Uri . parse ( 'https://docs.restructuredtext.net/articles/configuration.html#security' ) ) ; break ; default : break ; } } function ignoredWorkspaceConfig ( cfg , keys ) { return keys . filter ( ( key ) => { const inspect = cfg . inspect ( key ) ; return inspect . workspaceValue !== undefined || inspect . workspaceFolderValue !== undefined ; } ) ; } async function toggleWorkspaceIsTrusted ( ) { const v = defaultConfig . toggleWorkspaceIsTrusted ( ) ; await updateWorkspaceState ( WORKSPACE_IS_TRUSTED_KEY , v ) ; } export class Configuration { constructor ( private _workspaceIsTrusted = false , private getConfiguration = vscode . workspace . getConfiguration ) { } public toggleWorkspaceIsTrusted ( ) { this . _workspaceIsTrusted = ! this . _workspaceIsTrusted ; return this . _workspaceIsTrusted ; } public get ( section , uri ? ) { const cfg = this . getConfiguration ( section , uri ) ; if ( section !== 'restructuredtext' || this . _workspaceIsTrusted ) { return cfg ; } return new WrappedConfiguration ( cfg ) ; } public workspaceIsTrusted ( ) { return this . _workspaceIsTrusted ; } } const defaultConfig = new Configuration ( ) ; export function DefaultConfig ( ) { return defaultConfig ; } class WrappedConfiguration implements vscode . WorkspaceConfiguration { constructor ( private readonly _wrapped ) { const desc = Object . getOwnPropertyDescriptors ( _wrapped ) ; for ( const prop in desc ) { if ( typeof prop === 'string' && ! [ 'get' , 'has' , 'inspect' , 'update' , '_wrapped' ] . includes ( prop ) ) { const d = desc [ prop ] ; if ( SECURITY_SENSITIVE_CONFIG . includes ( prop ) ) { const inspect = this . _wrapped . inspect ( prop ) ; d . value = inspect . globalValue ?? inspect . defaultValue ; } Object . defineProperty ( this , prop , desc [ prop ] ) ; } } } public get ( section , defaultValue ? ) { if ( SECURITY_SENSITIVE_CONFIG . includes ( section ) ) { const inspect = this . _wrapped . inspect ( section ) ; return inspect . globalValue ?? defaultValue ?? inspect . defaultValue ; } return this . _wrapped . get ( section , defaultValue ) ; } public has ( section ) { return this . _wrapped . has ( section ) ; } public inspect < T > ( section ) { return this . _wrapped . inspect < T > ( section ) ; } public update ( section , value , configurationTarget ? , overrideInLanguage ? ) { return this . _wrapped . update ( section , value , configurationTarget , overrideInLanguage ) ; } } export function getConfig ( section , uri ? ) { if ( ! uri ) { if ( vscode . window . activeTextEditor ) { uri = vscode . window . activeTextEditor . document . uri ; } else { uri = null ; } } return defaultConfig . get ( section , uri ) ; } export const IsInCloudIDE = process . env . CLOUD_SHELL === 'true' || process . env . CODESPACES === 'true' ;