Skip to content

Commit 518946e

Browse files
committed
Test connection with retrieved password, and sign out if this fails
1 parent d18e158 commit 518946e

File tree

1 file changed

+59
-17
lines changed

1 file changed

+59
-17
lines changed

src/authenticationProvider.ts

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
} from "vscode";
1515
import { ServerManagerAuthenticationSession } from "./authenticationSession";
1616
import { globalState } from "./extension";
17+
import { getServerSpec } from "./api/getServerSpec";
18+
import { makeRESTRequest } from "./makeRESTRequest";
1719

1820
export const AUTHENTICATION_PROVIDER = "intersystems-server-credentials";
1921
const AUTHENTICATION_PROVIDER_LABEL = "InterSystems Server Credentials";
@@ -35,6 +37,7 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
3537
private readonly _secretStorage;
3638

3739
private _sessions: ServerManagerAuthenticationSession[] = [];
40+
private _checkedSessions: ServerManagerAuthenticationSession[] = [];
3841

3942
private _serverManagerExtension = extensions.getExtension("intersystems-community.servermanager");
4043

@@ -52,7 +55,7 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
5255
this._initializedDisposable?.dispose();
5356
}
5457

55-
// This function is called first when `vscode.authentication.getSessions` is called.
58+
// This function is called first when `vscode.authentication.getSession` is called.
5659
public async getSessions(scopes: string[] = []): Promise<readonly AuthenticationSession[]> {
5760
await this._ensureInitialized();
5861
let sessions = this._sessions;
@@ -61,7 +64,11 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
6164
for (let index = 0; index < scopes.length; index++) {
6265
sessions = sessions.filter((session) => session.scopes[index] === scopes[index].toLowerCase());
6366
}
64-
return sessions;
67+
68+
if (sessions.length === 1) {
69+
sessions = sessions.filter(async (session) => await this._isStillValid(session));
70+
}
71+
return sessions || [];
6572
}
6673

6774
// This function is called after `this.getSessions` is called, and only when:
@@ -104,9 +111,17 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
104111

105112
// Return existing session if found
106113
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);
108115
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+
}
110125
}
111126

112127
let password: string | undefined = "";
@@ -190,25 +205,52 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
190205
return session;
191206
}
192207

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+
193226
// This function is called when the end user signs out of the account.
194227
public async removeSession(sessionId: string): Promise<void> {
228+
this._removeSession(sessionId);
229+
}
230+
231+
private async _removeSession(sessionId: string, alwaysDeletePassword = false): Promise<void> {
195232
const index = this._sessions.findIndex((item) => item.id === sessionId);
196233
const session = this._sessions[index];
197234

198-
let deletePassword = false;
199235
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+
}
212254
}
213255
}
214256
if (deletePassword) {

0 commit comments

Comments
 (0)