@@ -32,6 +32,23 @@ const BUILT_IN_AUTH_DEPENDENTS: AuthDependent[] = [
3232 }
3333] ;
3434
35+ interface AllowedExtension {
36+ id : string ;
37+ name : string ;
38+ }
39+
40+ function readAllowedExtensions ( storageService : IStorageService , providerId : string , accountName : string ) : AllowedExtension [ ] {
41+ let trustedExtensions : AllowedExtension [ ] = [ ] ;
42+ try {
43+ const trustedExtensionSrc = storageService . get ( `${ providerId } -${ accountName } ` , StorageScope . GLOBAL ) ;
44+ if ( trustedExtensionSrc ) {
45+ trustedExtensions = JSON . parse ( trustedExtensionSrc ) ;
46+ }
47+ } catch ( err ) { }
48+
49+ return trustedExtensions ;
50+ }
51+
3552export class MainThreadAuthenticationProvider extends Disposable {
3653 private _sessionMenuItems = new Map < string , IDisposable [ ] > ( ) ;
3754 private _accounts = new Map < string , string [ ] > ( ) ; // Map account name to session ids
@@ -48,30 +65,25 @@ export class MainThreadAuthenticationProvider extends Disposable {
4865 this . registerCommandsAndContextMenuItems ( ) ;
4966 }
5067
51- private setPermissionsForAccount ( quickInputService : IQuickInputService , doLogin ?: boolean ) {
52- const quickPick = quickInputService . createQuickPick ( ) ;
68+ private manageTrustedExtensions ( quickInputService : IQuickInputService , storageService : IStorageService , accountName : string ) {
69+ const quickPick = quickInputService . createQuickPick < { label : string , extension : AllowedExtension } > ( ) ;
5370 quickPick . canSelectMany = true ;
54- const items = this . dependents . map ( dependent => {
71+ const allowedExtensions = readAllowedExtensions ( storageService , this . id , accountName ) ;
72+ const items = allowedExtensions . map ( extension => {
5573 return {
56- label : dependent . label ,
57- description : dependent . scopeDescriptions ,
58- picked : true ,
59- scopes : dependent . scopes
74+ label : extension . name ,
75+ extension
6076 } ;
6177 } ) ;
6278
6379 quickPick . items = items ;
64- // TODO read from storage and filter is not doLogin
6580 quickPick . selectedItems = items ;
66- quickPick . title = nls . localize ( 'signInTo ' , "Sign in to {0}" , this . displayName ) ;
67- quickPick . placeholder = nls . localize ( 'accountPermissions ' , "Choose what features and extensions to authorize to use this account" ) ;
81+ quickPick . title = nls . localize ( 'manageTrustedExtensions ' , "Manage Trusted Extensions" ) ;
82+ quickPick . placeholder = nls . localize ( 'manageExensions ' , "Choose which extensions can access this account" ) ;
6883
6984 quickPick . onDidAccept ( ( ) => {
70- const scopes = quickPick . selectedItems . reduce ( ( previous , current ) => previous . concat ( ( current as any ) . scopes ) , [ ] ) ;
71- if ( scopes . length && doLogin ) {
72- this . login ( scopes ) ;
73- }
74-
85+ const updatedAllowedList = quickPick . selectedItems . map ( item => item . extension ) ;
86+ storageService . store ( `${ this . id } -${ accountName } ` , JSON . stringify ( updatedAllowedList ) , StorageScope . GLOBAL ) ;
7587 quickPick . dispose ( ) ;
7688 } ) ;
7789
@@ -87,7 +99,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
8799 this . _register ( CommandsRegistry . registerCommand ( {
88100 id : `signIn${ this . id } ` ,
89101 handler : ( accessor , args ) => {
90- this . setPermissionsForAccount ( accessor . get ( IQuickInputService ) , true ) ;
102+ this . login ( this . dependents . reduce ( ( previous : string [ ] , current ) => previous . concat ( current . scopes ) , [ ] ) ) ;
91103 } ,
92104 } ) ) ;
93105
@@ -130,19 +142,26 @@ export class MainThreadAuthenticationProvider extends Disposable {
130142 id : `configureSessions${ session . id } ` ,
131143 handler : ( accessor , args ) => {
132144 const quickInputService = accessor . get ( IQuickInputService ) ;
145+ const storageService = accessor . get ( IStorageService ) ;
133146
134147 const quickPick = quickInputService . createQuickPick ( ) ;
135- const items = [ { label : 'Sign Out' } ] ;
148+ const manage = nls . localize ( 'manageTrustedExtensions' , "Manage Trusted Extensions" ) ;
149+ const signOut = nls . localize ( 'signOut' , "Sign Out" ) ;
150+ const items = ( [ { label : manage } , { label : signOut } ] ) ;
136151
137152 quickPick . items = items ;
138153
139154 quickPick . onDidAccept ( e => {
140155 const selected = quickPick . selectedItems [ 0 ] ;
141- if ( selected . label === 'Sign Out' ) {
156+ if ( selected . label === signOut ) {
142157 const sessionsForAccount = this . _accounts . get ( session . accountName ) ;
143158 sessionsForAccount ?. forEach ( sessionId => this . logout ( sessionId ) ) ;
144159 }
145160
161+ if ( selected . label === manage ) {
162+ this . manageTrustedExtensions ( quickInputService , storageService , session . accountName ) ;
163+ }
164+
146165 quickPick . dispose ( ) ;
147166 } ) ;
148167
@@ -185,6 +204,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
185204 disposeables . forEach ( disposeable => disposeable . dispose ( ) ) ;
186205 this . _sessionMenuItems . delete ( accountName ) ;
187206 }
207+ this . _accounts . delete ( accountName ) ;
188208 }
189209 }
190210 } ) ;
@@ -242,55 +262,45 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
242262 this . authenticationService . sessionsUpdate ( id , event ) ;
243263 }
244264
245- async $getSessionsPrompt ( providerId : string , providerName : string , extensionId : string , extensionName : string ) : Promise < boolean > {
246- const alwaysAllow = this . storageService . get ( ` ${ extensionId } - ${ providerId } ` , StorageScope . GLOBAL ) ;
247- if ( alwaysAllow ) {
248- return alwaysAllow === ' true' ;
265+ async $getSessionsPrompt ( providerId : string , accountName : string , providerName : string , extensionId : string , extensionName : string ) : Promise < boolean > {
266+ let allowList = readAllowedExtensions ( this . storageService , providerId , accountName ) ;
267+ if ( allowList . some ( extension => extension . id === extensionId ) ) {
268+ return true ;
249269 }
250270
251- const { choice, checkboxChecked } = await this . dialogService . show (
271+ const { choice } = await this . dialogService . show (
252272 Severity . Info ,
253- nls . localize ( 'confirmAuthenticationAccess' , "The extension '{0}' is trying to access authentication information from {1}." , extensionName , providerName ) ,
273+ nls . localize ( 'confirmAuthenticationAccess' , "The extension '{0}' is trying to access authentication information for the {1} account '{2}' ." , extensionName , providerName , accountName ) ,
254274 [ nls . localize ( 'cancel' , "Cancel" ) , nls . localize ( 'allow' , "Allow" ) ] ,
255275 {
256- cancelId : 0 ,
257- checkbox : {
258- label : nls . localize ( 'neverAgain' , "Don't Show Again" )
259- }
276+ cancelId : 0
260277 }
261278 ) ;
262279
263280 const allow = choice === 1 ;
264- if ( checkboxChecked ) {
265- this . storageService . store ( `${ extensionId } -${ providerId } ` , allow ? 'true' : 'false' , StorageScope . GLOBAL ) ;
281+ if ( allow ) {
282+ allowList = allowList . concat ( { id : extensionId , name : extensionName } ) ;
283+ this . storageService . store ( `${ providerId } -${ accountName } ` , JSON . stringify ( allowList ) , StorageScope . GLOBAL ) ;
266284 }
267285
268286 return allow ;
269287 }
270288
271- async $loginPrompt ( providerId : string , providerName : string , extensionId : string , extensionName : string ) : Promise < boolean > {
272- const alwaysAllow = this . storageService . get ( `${ extensionId } -${ providerId } ` , StorageScope . GLOBAL ) ;
273- if ( alwaysAllow ) {
274- return alwaysAllow === 'true' ;
275- }
276-
277- const { choice, checkboxChecked } = await this . dialogService . show (
289+ async $loginPrompt ( providerName : string , extensionName : string ) : Promise < boolean > {
290+ const { choice } = await this . dialogService . show (
278291 Severity . Info ,
279292 nls . localize ( 'confirmLogin' , "The extension '{0}' wants to sign in using {1}." , extensionName , providerName ) ,
280- [ nls . localize ( 'cancel' , "Cancel" ) , nls . localize ( 'continue ' , "Continue " ) ] ,
293+ [ nls . localize ( 'cancel' , "Cancel" ) , nls . localize ( 'allow ' , "Allow " ) ] ,
281294 {
282- cancelId : 0 ,
283- checkbox : {
284- label : nls . localize ( 'neverAgain' , "Don't Show Again" )
285- }
295+ cancelId : 0
286296 }
287297 ) ;
288298
289- const allow = choice === 1 ;
290- if ( checkboxChecked ) {
291- this . storageService . store ( `${ extensionId } -${ providerId } ` , allow ? 'true' : 'false' , StorageScope . GLOBAL ) ;
292- }
299+ return choice === 1 ;
300+ }
293301
294- return allow ;
302+ async $setTrustedExtension ( providerId : string , accountName : string , extensionId : string , extensionName : string ) : Promise < void > {
303+ const allowList = readAllowedExtensions ( this . storageService , providerId , accountName ) . concat ( { id : extensionId , name : extensionName } ) ;
304+ this . storageService . store ( `${ providerId } -${ accountName } ` , JSON . stringify ( allowList ) , StorageScope . GLOBAL ) ;
295305 }
296306}
0 commit comments