@@ -209,7 +209,7 @@ export let checkingConnection = false;
209209export let serverManagerApi : serverManager . ServerManagerAPI ;
210210
211211/** Map of the intersystems.server connection specs we have resolved via the API to that extension */
212- const resolvedConnSpecs = new Map < string , serverManager . IServerSpec > ( ) ;
212+ const resolvedConnSpecs = new Map < string , serverManager . IServerSpec & { accessToken ?: string } > ( ) ;
213213
214214/**
215215 * If servermanager extension is available, fetch the connection spec unless already cached.
@@ -255,8 +255,7 @@ export async function resolveConnectionSpec(
255255 superServer : {
256256 port : serverForUri . superserverPort ,
257257 } ,
258- username : serverForUri . username ,
259- password : serverForUri . password ? serverForUri . password : undefined ,
258+ authorization : serverManagerApi . makeAuthorization ( serverForUri . username , serverForUri . password ) ,
260259 description : `Server for workspace folder '${ serverName } '` ,
261260 } ;
262261 }
@@ -269,14 +268,12 @@ export async function resolveConnectionSpec(
269268 }
270269}
271270
272- async function resolvePassword ( serverSpec , ignoreUnauthenticated = false ) : Promise < void > {
273- if (
274- // Connection isn't unauthenticated
275- ( ! isUnauthenticated ( serverSpec . username ) || ignoreUnauthenticated ) &&
276- // A password is missing
277- typeof serverSpec . password == "undefined"
278- ) {
279- const scopes = [ serverSpec . name , serverSpec . username || "" ] ;
271+ async function resolvePassword (
272+ serverSpec : Pick < serverManager . IServerSpec , "name" | "authorization" > ,
273+ ignoreUnauthenticated = false
274+ ) : Promise < string | undefined > {
275+ if ( ! ( serverSpec . authorization . resolved ( ) || ignoreUnauthenticated ) ) {
276+ const scopes = [ serverSpec . name , serverSpec . authorization . username || "" ] ;
280277
281278 // Handle Server Manager extension version < 3.8.0
282279 const account = serverManagerApi . getAccount ? serverManagerApi . getAccount ( serverSpec ) : undefined ;
@@ -293,25 +290,28 @@ async function resolvePassword(serverSpec, ignoreUnauthenticated = false): Promi
293290 }
294291 if ( session ) {
295292 // If original spec lacked username use the one obtained from the user by the authprovider (exact case)
296- serverSpec . username = serverSpec . username || session . scopes [ 1 ] ;
297- serverSpec . password = session . accessToken ;
293+ serverSpec . authorization . resolve ( session . accessToken , session . scopes [ 1 ] ) ;
294+ return session . accessToken ;
298295 }
299296 }
300297}
301298
302299/** Resolve credentials for `serverName` and returned the complete connection spec if successful */
303- export async function resolveUsernameAndPassword ( serverName : string , oldSpec : any ) : Promise < any > {
304- const newSpec : { name : string ; username ?: string ; password ?: string } = {
305- name : serverName ,
306- username : oldSpec ?. username ,
307- } ;
308- await resolvePassword ( newSpec , true ) ;
309- if ( newSpec . password ) {
300+ export async function resolveUsernameAndPassword (
301+ serverName : string ,
302+ oldSpec : serverManager . IServerSpec
303+ ) : Promise < ( serverManager . IServerSpec & { accessToken ?: string } ) | undefined > {
304+ const { authorization : _authorization , ...newSpec } = oldSpec ;
305+ newSpec . name = serverName ;
306+ const authorization = _authorization . clone ( ) ;
307+
308+ const accessToken = await resolvePassword ( { ...newSpec , authorization } , true ) ;
309+ if ( authorization . resolved ( ) ) {
310310 // Update the connection spec
311311 resolvedConnSpecs . set ( serverName , {
312312 ...oldSpec ,
313- username : newSpec . username ,
314- password : newSpec . password ,
313+ authorization ,
314+ accessToken ,
315315 } ) ;
316316 return resolvedConnSpecs . get ( serverName ) ;
317317 }
@@ -364,7 +364,8 @@ export async function checkConnection(
364364 _onDidChangeConnection . fire ( ) ;
365365 }
366366 let api = new AtelierAPI ( apiTarget , false ) ;
367- const { active, host = "" , port = 0 , superserverPort = 0 , ns = "" , username } = api . config ;
367+ const { active, host = "" , port = 0 , superserverPort = 0 , ns = "" , authorization } = api . config ;
368+ const username = authorization . resolved ( ) ? authorization . username : "" ;
368369 vscode . commands . executeCommand ( "setContext" , "vscode-objectscript.connectActive" , active ) ;
369370 if ( ! panel . text ) {
370371 panel . text = `${ PANEL_LABEL } ` ;
@@ -470,8 +471,7 @@ export async function checkConnection(
470471 let success = false ;
471472 message = "Not Authorized." ;
472473 errorMessage = `Authorization error: Check your credentials in Settings, and that you have sufficient privileges on the /api/atelier web application on ${ connInfo } ` ;
473- const username = api . config . username ;
474- if ( isUnauthenticated ( username ) ) {
474+ if ( isUnauthenticated ( api . config . authorization . username ) ) {
475475 vscode . window . showErrorMessage (
476476 `Unauthenticated access rejected by '${ api . serverId } '.${
477477 ! api . config . serverName ? " Connection has been disabled." : ""
@@ -487,7 +487,7 @@ export async function checkConnection(
487487 const newSpec = await resolveUsernameAndPassword ( api . config . serverName , oldSpec ) ;
488488 if ( newSpec ) {
489489 // We were able to resolve credentials, so try again
490- await workspaceState . update ( wsKey + ":password" , newSpec . password ) ;
490+ await workspaceState . update ( wsKey + ":password" , newSpec . accessToken ) ;
491491 api = new AtelierAPI ( apiTarget , false ) ;
492492 await api
493493 . serverInfo ( true , serverInfoTimeout )
@@ -515,7 +515,7 @@ export async function checkConnection(
515515 vscode . window
516516 . showInputBox ( {
517517 password : true ,
518- title : `Not Authorized. Enter password to connect as user '${ username } ' to ${ connInfo } ` ,
518+ title : `Not Authorized. Enter password to connect as user '${ api . config . authorization . username } ' to ${ connInfo } ` ,
519519 prompt : ! api . externalServer ? "If no password is entered the connection will be disabled." : "" ,
520520 ignoreFocusOut : true ,
521521 } )
@@ -1965,11 +1965,10 @@ export interface GeneralServerForUri {
19651965 namespace : string ;
19661966 apiVersion : number ;
19671967 serverVersion : string ;
1968+ authorization : serverManager . Authorization ;
19681969}
19691970
1970- export type ServerForUri = GeneralServerForUri &
1971- HttpsAndScheme &
1972- Required < Pick < serverManager . Authorization , "authMethod" | "username" | "password" > > ;
1971+ export type ServerForUri = GeneralServerForUri & HttpsAndScheme ;
19731972
19741973// This function is exported as one of our API functions but is also used internally
19751974// for example to implement the async variant capable of resolving docker port number.
@@ -1989,13 +1988,28 @@ function serverForUri(uri: vscode.Uri): ServerForUri {
19891988 port,
19901989 superserverPort,
19911990 pathPrefix,
1992- authMethod,
1993- username,
1994- password,
1991+ authorization,
19951992 ns,
19961993 apiVersion,
19971994 serverVersion,
19981995 } = api . config ;
1996+ if ( serverName !== "" ) {
1997+ const password = vscode . workspace
1998+ . getConfiguration (
1999+ `intersystems.servers.${ serverName . toLowerCase ( ) } ` ,
2000+ // objectscript(xml):// URIs are not in any workspace folder,
2001+ // so make sure we resolve the server definition with the proper
2002+ // granularity. This is needed to prevent other extensions like
2003+ // Language Server prompting for a passwoord when it's not needed.
2004+ [ OBJECTSCRIPT_FILE_SCHEMA , OBJECTSCRIPTXML_FILE_SCHEMA ] . includes ( uri . scheme )
2005+ ? vscode . workspace . workspaceFolders ?. find ( ( f ) => f . name . toLowerCase ( ) == configNameLower ) ?. uri
2006+ : uri
2007+ )
2008+ . get ( "password" ) as string | undefined ;
2009+ if ( password !== undefined ) {
2010+ authorization . resolve ( password ) ;
2011+ }
2012+ }
19992013 return {
20002014 serverName,
20012015 active,
@@ -2004,23 +2018,7 @@ function serverForUri(uri: vscode.Uri): ServerForUri {
20042018 port,
20052019 superserverPort,
20062020 pathPrefix,
2007- authMethod,
2008- username,
2009- password :
2010- serverName === ""
2011- ? password
2012- : vscode . workspace
2013- . getConfiguration (
2014- `intersystems.servers.${ serverName . toLowerCase ( ) } ` ,
2015- // objectscript(xml):// URIs are not in any workspace folder,
2016- // so make sure we resolve the server definition with the proper
2017- // granularity. This is needed to prevent other extensions like
2018- // Language Server prompting for a passwoord when it's not needed.
2019- [ OBJECTSCRIPT_FILE_SCHEMA , OBJECTSCRIPTXML_FILE_SCHEMA ] . includes ( uri . scheme )
2020- ? vscode . workspace . workspaceFolders ?. find ( ( f ) => f . name . toLowerCase ( ) == configNameLower ) ?. uri
2021- : uri
2022- )
2023- . get ( "password" ) ,
2021+ authorization,
20242022 namespace : ns ,
20252023 apiVersion : active ? apiVersion : undefined ,
20262024 serverVersion : active ? serverVersion : undefined ,
0 commit comments