@@ -77,7 +77,6 @@ import {
7777 terminalWithDocker ,
7878 notNull ,
7979 currentFile ,
80- InputBoxManager ,
8180 isImportableLocalFile ,
8281 workspaceFolderOfUri ,
8382 uriOfWorkspaceFolder ,
@@ -212,7 +211,8 @@ export async function resolvePassword(serverSpec): Promise<void> {
212211 session = await vscode . authentication . getSession ( AUTHENTICATION_PROVIDER , scopes , { createIfNone : true } ) ;
213212 }
214213 if ( session ) {
215- serverSpec . username = session . scopes [ 1 ] ;
214+ // If original spec lacked username use the one obtained by the authprovider
215+ serverSpec . username = serverSpec . username || session . scopes [ 1 ] ;
216216 serverSpec . password = session . accessToken ;
217217 }
218218 }
@@ -240,11 +240,11 @@ export async function checkConnection(clearCookies = false, uri?: vscode.Uri): P
240240 const { apiTarget, configName } = connectionTarget ( uri ) ;
241241 if ( clearCookies ) {
242242 /// clean-up cached values
243- workspaceState . update ( configName + ":host" , undefined ) ;
244- workspaceState . update ( configName + ":port" , undefined ) ;
245- workspaceState . update ( configName + ":password" , undefined ) ;
246- workspaceState . update ( configName + ":apiVersion" , undefined ) ;
247- workspaceState . update ( configName + ":docker" , undefined ) ;
243+ await workspaceState . update ( configName + ":host" , undefined ) ;
244+ await workspaceState . update ( configName + ":port" , undefined ) ;
245+ await workspaceState . update ( configName + ":password" , undefined ) ;
246+ await workspaceState . update ( configName + ":apiVersion" , undefined ) ;
247+ await workspaceState . update ( configName + ":docker" , undefined ) ;
248248 _onDidChangeConnection . fire ( ) ;
249249 }
250250 let api = new AtelierAPI ( apiTarget , false ) ;
@@ -303,75 +303,111 @@ export async function checkConnection(clearCookies = false, uri?: vscode.Uri): P
303303 api . clearCookies ( ) ;
304304 }
305305
306- // Why must this be recreated here?
306+ // Why must this be recreated here? Maybe in case something has updated connection details since we last fetched them.
307307 api = new AtelierAPI ( apiTarget , false ) ;
308308
309309 if ( ! api . config . host || ! api . config . port || ! api . config . ns ) {
310310 const message = "'host', 'port' and 'ns' must be specified." ;
311311 outputChannel . appendError ( message ) ;
312312 panel . text = `${ PANEL_LABEL } $(error)` ;
313313 panel . tooltip = `ERROR - ${ message } ` ;
314- disableConnection ( configName ) ;
314+ if ( ! api . externalServer ) {
315+ await setConnectionState ( configName , false ) ;
316+ }
315317 return ;
316318 }
317319 checkingConnection = true ;
320+
321+ // What we do when api.serverInfo call succeeds
322+ const gotServerInfo = async ( info ) => {
323+ panel . text = api . connInfo ;
324+ panel . tooltip = `Connected${ pathPrefix ? " to " + pathPrefix : "" } as ${ username } ` ;
325+ const hasHS = info . result . content . features . find ( ( el ) => el . name === "HEALTHSHARE" && el . enabled ) !== undefined ;
326+ reporter &&
327+ reporter . sendTelemetryEvent ( "connected" , {
328+ serverVersion : info . result . content . version ,
329+ healthshare : hasHS ? "yes" : "no" ,
330+ } ) ;
331+
332+ // Update CSP web app cache if required
333+ const key = (
334+ api . config . serverName && api . config . serverName != ""
335+ ? `${ api . config . serverName } :${ api . config . ns } `
336+ : `${ api . config . host } :${ api . config . port } ${ api . config . pathPrefix } :${ api . config . ns } `
337+ ) . toLowerCase ( ) ;
338+ if ( ! cspApps . has ( key ) ) {
339+ cspApps . set ( key , await api . getCSPApps ( ) . then ( ( data ) => data . result . content || [ ] ) ) ;
340+ }
341+ if ( ! api . externalServer ) {
342+ await setConnectionState ( configName , true ) ;
343+ }
344+ return ;
345+ } ;
346+
347+ // Do the check
318348 return api
319349 . serverInfo ( )
320- . then ( async ( info ) => {
321- panel . text = api . connInfo ;
322- panel . tooltip = `Connected${ pathPrefix ? " to " + pathPrefix : "" } as ${ username } ` ;
323- const hasHS = info . result . content . features . find ( ( el ) => el . name === "HEALTHSHARE" && el . enabled ) !== undefined ;
324- reporter &&
325- reporter . sendTelemetryEvent ( "connected" , {
326- serverVersion : info . result . content . version ,
327- healthshare : hasHS ? "yes" : "no" ,
328- } ) ;
329- // Update CSP web app cache if required
330- const key = (
331- api . config . serverName && api . config . serverName != ""
332- ? `${ api . config . serverName } :${ api . config . ns } `
333- : `${ api . config . host } :${ api . config . port } ${ api . config . pathPrefix } :${ api . config . ns } `
334- ) . toLowerCase ( ) ;
335- if ( ! cspApps . has ( key ) ) {
336- cspApps . set ( key , await api . getCSPApps ( ) . then ( ( data ) => data . result . content || [ ] ) ) ;
337- }
338- return ;
339- } )
340- . catch ( ( error ) => {
350+ . then ( gotServerInfo )
351+ . catch ( async ( error ) => {
341352 let message = error . message ;
342353 let errorMessage ;
343354 if ( error . statusCode === 401 ) {
344- setTimeout ( ( ) => {
345- const username = api . config . username ;
346- if ( username === "" ) {
347- vscode . window . showErrorMessage ( `Anonymous access rejected by ${ connInfo } .` ) ;
348- if ( ! api . externalServer ) {
349- vscode . window . showErrorMessage ( "Connection has been disabled." ) ;
350- disableConnection ( configName ) ;
351- }
352- } else {
353- InputBoxManager . showInputBox (
354- {
355+ let success = false ;
356+ message = "Not Authorized." ;
357+ errorMessage = `Authorization error: Check your credentials in Settings, and that you have sufficient privileges on the /api/atelier web application on ${ connInfo } ` ;
358+ const username = api . config . username ;
359+ if ( username === "" ) {
360+ vscode . window . showErrorMessage ( `Anonymous access rejected by ${ connInfo } .` ) ;
361+ if ( ! api . externalServer ) {
362+ vscode . window . showErrorMessage ( "Connection has been disabled." ) ;
363+ await setConnectionState ( configName , false ) ;
364+ }
365+ } else {
366+ success = await new Promise < boolean > ( ( resolve ) => {
367+ vscode . window
368+ . showInputBox ( {
355369 password : true ,
356370 placeHolder : `Not Authorized. Enter password to connect as user '${ username } ' to ${ connInfo } ` ,
357371 prompt : ! api . externalServer ? "If no password is entered the connection will be disabled." : "" ,
358372 ignoreFocusOut : true ,
359- } ,
360- async ( password ) => {
361- if ( password ) {
362- workspaceState . update ( configName + ":password" , password ) ;
363- _onDidChangeConnection . fire ( ) ;
364- await checkConnection ( false , uri ) ;
365- } else if ( ! api . externalServer ) {
366- disableConnection ( configName ) ;
373+ } )
374+ . then (
375+ async ( password ) => {
376+ if ( password ) {
377+ await workspaceState . update ( configName + ":password" , password ) ;
378+ resolve (
379+ api
380+ . serverInfo ( )
381+ . then ( async ( info ) : Promise < boolean > => {
382+ await gotServerInfo ( info ) ;
383+ _onDidChangeConnection . fire ( ) ;
384+ return true ;
385+ } )
386+ . catch ( async ( error ) => {
387+ console . log ( `Second connect failed: ${ error } ` ) ;
388+ await setConnectionState ( configName , false ) ;
389+ await workspaceState . update ( configName + ":password" , undefined ) ;
390+ return false ;
391+ } )
392+ . finally ( ( ) => {
393+ checkingConnection = false ;
394+ } )
395+ ) ;
396+ } else if ( ! api . externalServer ) {
397+ await setConnectionState ( configName , false ) ;
398+ }
399+ console . log ( `Finished prompting for password` ) ;
400+ resolve ( false ) ;
401+ } ,
402+ ( reason ) => {
403+ console . log ( `showInputBox for password dismissed: ${ reason } ` ) ;
367404 }
368- } ,
369- connInfo
370- ) ;
405+ ) ;
406+ } ) ;
407+ if ( success ) {
408+ return ;
371409 }
372- } , 1000 ) ;
373- message = "Not Authorized." ;
374- errorMessage = `Authorization error: Check your credentials in Settings, and that you have sufficient privileges on the /api/atelier web application on ${ connInfo } ` ;
410+ }
375411 } else {
376412 errorMessage = `${ message } \nCheck your server details in Settings (${ connInfo } ).` ;
377413 }
@@ -395,16 +431,16 @@ export async function checkConnection(clearCookies = false, uri?: vscode.Uri): P
395431 } ) ;
396432}
397433
398- // Set objectscript.conn.active = false at WorkspaceFolder level if objectscript.conn is defined there,
399- // else set it false at Workspace level
400- function disableConnection ( configName : string ) {
434+ // Set objectscript.conn.active at WorkspaceFolder level if objectscript.conn is defined there,
435+ // else set it at Workspace level
436+ function setConnectionState ( configName : string , active : boolean ) {
401437 const connConfig : vscode . WorkspaceConfiguration = config ( "" , configName ) ;
402438 const target : vscode . ConfigurationTarget = connConfig . inspect ( "conn" ) . workspaceFolderValue
403439 ? vscode . ConfigurationTarget . WorkspaceFolder
404440 : vscode . ConfigurationTarget . Workspace ;
405441 const targetConfig : any =
406442 connConfig . inspect ( "conn" ) . workspaceFolderValue || connConfig . inspect ( "conn" ) . workspaceValue ;
407- return connConfig . update ( "conn" , { ...targetConfig , active : false } , target ) ;
443+ return connConfig . update ( "conn" , { ...targetConfig , active } , target ) ;
408444}
409445
410446// Promise to return the API of the servermanager
@@ -521,7 +557,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
521557 serverManagerApi = await serverManager ( ) ;
522558
523559 documentContentProvider = new DocumentContentProvider ( ) ;
524- xmlContentProvider = new XmlContentProvider ( ) ;
525560 fileSystemProvider = new FileSystemProvider ( ) ;
526561
527562 explorerProvider = new ObjectScriptExplorerProvider ( ) ;
@@ -555,17 +590,27 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
555590 vscode . workspace . workspaceFolders ?. map ( ( workspaceFolder ) => {
556591 const uri = workspaceFolder . uri ;
557592 const { configName } = connectionTarget ( uri ) ;
558- toCheck . set ( configName , uri ) ;
593+ const serverName = uri . scheme === "file" ? config ( "conn" , configName ) . server : configName ;
594+ toCheck . set ( serverName , uri ) ;
559595 } ) ;
560596 for await ( const oneToCheck of toCheck ) {
561- const configName = oneToCheck [ 0 ] ;
597+ const serverName = oneToCheck [ 0 ] ;
562598 const uri = oneToCheck [ 1 ] ;
563- const serverName = uri . scheme === "file" ? config ( "conn" , configName ) . server : configName ;
564- await resolveConnectionSpec ( serverName ) ;
565- // Ignore any failure
566- checkConnection ( true , uri ) . finally ( ) ;
599+ try {
600+ try {
601+ await resolveConnectionSpec ( serverName ) ;
602+ } finally {
603+ await checkConnection ( true , uri ) ;
604+ }
605+ } catch ( _ ) {
606+ // Ignore any failure
607+ continue ;
608+ }
567609 }
568610
611+ // This constructor instantiates an AtelierAPI object, so needs to happen after resolving and checking connections above
612+ xmlContentProvider = new XmlContentProvider ( ) ;
613+
569614 const documentSelector = ( ...list ) =>
570615 [ "file" , ...schemas ] . reduce ( ( acc , scheme ) => acc . concat ( list . map ( ( language ) => ( { scheme, language } ) ) ) , [ ] ) ;
571616
0 commit comments