@@ -14,6 +14,8 @@ import {
14
14
} from "vscode" ;
15
15
import { ServerManagerAuthenticationSession } from "./authenticationSession" ;
16
16
import { globalState } from "./extension" ;
17
+ import { getServerSpec } from "./api/getServerSpec" ;
18
+ import { makeRESTRequest } from "./makeRESTRequest" ;
17
19
18
20
export const AUTHENTICATION_PROVIDER = "intersystems-server-credentials" ;
19
21
const AUTHENTICATION_PROVIDER_LABEL = "InterSystems Server Credentials" ;
@@ -35,6 +37,7 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
35
37
private readonly _secretStorage ;
36
38
37
39
private _sessions : ServerManagerAuthenticationSession [ ] = [ ] ;
40
+ private _checkedSessions : ServerManagerAuthenticationSession [ ] = [ ] ;
38
41
39
42
private _serverManagerExtension = extensions . getExtension ( "intersystems-community.servermanager" ) ;
40
43
@@ -52,7 +55,7 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
52
55
this . _initializedDisposable ?. dispose ( ) ;
53
56
}
54
57
55
- // This function is called first when `vscode.authentication.getSessions ` is called.
58
+ // This function is called first when `vscode.authentication.getSession ` is called.
56
59
public async getSessions ( scopes : string [ ] = [ ] ) : Promise < readonly AuthenticationSession [ ] > {
57
60
await this . _ensureInitialized ( ) ;
58
61
let sessions = this . _sessions ;
@@ -61,7 +64,11 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
61
64
for ( let index = 0 ; index < scopes . length ; index ++ ) {
62
65
sessions = sessions . filter ( ( session ) => session . scopes [ index ] === scopes [ index ] . toLowerCase ( ) ) ;
63
66
}
64
- return sessions ;
67
+
68
+ if ( sessions . length === 1 ) {
69
+ sessions = sessions . filter ( async ( session ) => await this . _isStillValid ( session ) ) ;
70
+ }
71
+ return sessions || [ ] ;
65
72
}
66
73
67
74
// This function is called after `this.getSessions` is called, and only when:
@@ -104,9 +111,17 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
104
111
105
112
// Return existing session if found
106
113
const sessionId = ServerManagerAuthenticationProvider . sessionId ( serverName , userName ) ;
107
- const existingSession = this . _sessions . find ( ( s ) => s . id === sessionId ) ;
114
+ let existingSession = this . _sessions . find ( ( s ) => s . id === sessionId ) ;
108
115
if ( existingSession ) {
109
- return existingSession ;
116
+ if ( this . _checkedSessions . find ( ( s ) => s . id === sessionId ) ) {
117
+ return existingSession ;
118
+ }
119
+
120
+ // Check if the session is still valid
121
+ if ( await this . _isStillValid ( existingSession ) ) {
122
+ this . _checkedSessions . push ( existingSession ) ;
123
+ return existingSession ;
124
+ }
110
125
}
111
126
112
127
let password : string | undefined = "" ;
@@ -190,25 +205,52 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
190
205
return session ;
191
206
}
192
207
208
+ private async _isStillValid ( session : ServerManagerAuthenticationSession ) : Promise < boolean > {
209
+ if ( this . _checkedSessions . find ( ( s ) => s . id === session . id ) ) {
210
+ return true ;
211
+ }
212
+ const serverSpec = await getServerSpec ( session . serverName ) ;
213
+ if ( serverSpec ) {
214
+ serverSpec . username = session . userName ;
215
+ serverSpec . password = session . accessToken ;
216
+ const response = await makeRESTRequest ( "HEAD" , serverSpec ) ;
217
+ if ( response ?. status !== 200 ) {
218
+ this . _removeSession ( session . id , true ) ;
219
+ return false ;
220
+ }
221
+ }
222
+ this . _checkedSessions . push ( session ) ;
223
+ return true ;
224
+ }
225
+
193
226
// This function is called when the end user signs out of the account.
194
227
public async removeSession ( sessionId : string ) : Promise < void > {
228
+ this . _removeSession ( sessionId ) ;
229
+ }
230
+
231
+ private async _removeSession ( sessionId : string , alwaysDeletePassword = false ) : Promise < void > {
195
232
const index = this . _sessions . findIndex ( ( item ) => item . id === sessionId ) ;
196
233
const session = this . _sessions [ index ] ;
197
234
198
- let deletePassword = false ;
199
235
const credentialKey = ServerManagerAuthenticationProvider . credentialKey ( sessionId ) ;
200
- if ( await this . secretStorage . get ( credentialKey ) ) {
201
- const passwordOption = workspace . getConfiguration ( "intersystemsServerManager.credentialsProvider" )
202
- . get < string > ( "deletePasswordOnSignout" , "ask" ) ;
203
- deletePassword = ( passwordOption === "always" ) ;
204
- if ( passwordOption === "ask" ) {
205
- const choice = await window . showWarningMessage (
206
- `Do you want to keep the password or delete it?` ,
207
- { detail : `The ${ AUTHENTICATION_PROVIDER_LABEL } account you signed out (${ session . account . label } ) is currently storing its password securely on your workstation.` , modal : true } ,
208
- { title : "Keep" , isCloseAffordance : true } ,
209
- { title : "Delete" , isCloseAffordance : false } ,
210
- ) ;
211
- deletePassword = ( choice ?. title === "Delete" ) ;
236
+ let deletePassword = false ;
237
+ const hasStoredPassword = await this . secretStorage . get ( credentialKey ) !== undefined ;
238
+ if ( alwaysDeletePassword ) {
239
+ deletePassword = hasStoredPassword ;
240
+ } else {
241
+ if ( hasStoredPassword ) {
242
+ const passwordOption = workspace . getConfiguration ( "intersystemsServerManager.credentialsProvider" )
243
+ . get < string > ( "deletePasswordOnSignout" , "ask" ) ;
244
+ deletePassword = ( passwordOption === "always" ) ;
245
+ if ( passwordOption === "ask" ) {
246
+ const choice = await window . showWarningMessage (
247
+ `Do you want to keep the password or delete it?` ,
248
+ { detail : `The ${ AUTHENTICATION_PROVIDER_LABEL } account you signed out (${ session . account . label } ) is currently storing its password securely on your workstation.` , modal : true } ,
249
+ { title : "Keep" , isCloseAffordance : true } ,
250
+ { title : "Delete" , isCloseAffordance : false } ,
251
+ ) ;
252
+ deletePassword = ( choice ?. title === "Delete" ) ;
253
+ }
212
254
}
213
255
}
214
256
if ( deletePassword ) {
0 commit comments