Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@
"command": "intersystems-community.servermanager.viewWebApp",
"title": "View Files in Web Application",
"icon": "$(eye)"
},
{
"command": "intersystems-community.servermanager.signOut",
"category": "InterSystems Server Manager",
"title": "Sign Out of Accounts..."
}
],
"submenus": [
Expand Down
41 changes: 39 additions & 2 deletions src/authenticationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
const enteredPassword = inputBox.value;
if (secretStorage && enteredPassword) {
await secretStorage.store(credentialKey, enteredPassword);
console.log(`Stored password at ${credentialKey}`);
}
// Resolve the promise and tidy up
resolve(enteredPassword);
Expand Down Expand Up @@ -270,7 +269,6 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
if (deletePassword) {
// Delete from secret storage
await this.secretStorage.delete(credentialKey);
console.log(`${AUTHENTICATION_PROVIDER_LABEL}: Deleted password at ${credentialKey}`);
}
if (index > -1) {
// Remove session here so we don't store it
Expand All @@ -280,6 +278,45 @@ export class ServerManagerAuthenticationProvider implements AuthenticationProvid
this._onDidChangeSessions.fire({ added: [], removed: [session], changed: [] });
}

public async removeSessions(sessionIds: string[]): Promise<void> {
const storedPasswordCredKeys: string[] = [];
const removed: AuthenticationSession[] = [];
await Promise.allSettled(sessionIds.map(async (sessionId) => {
const index = this._sessions.findIndex((item) => item.id === sessionId);
const session = this._sessions[index];
const credentialKey = ServerManagerAuthenticationProvider.credentialKey(sessionId);
if (await this.secretStorage.get(credentialKey) !== undefined) {
storedPasswordCredKeys.push(credentialKey);
}
if (index > -1) {
this._sessions.splice(index, 1);
}
removed.push(session);
}));
if (storedPasswordCredKeys.length) {
const passwordOption = workspace.getConfiguration("intersystemsServerManager.credentialsProvider")
.get<string>("deletePasswordOnSignout", "ask");
let deletePasswords = (passwordOption === "always");
if (passwordOption === "ask") {
const choice = await window.showWarningMessage(
`Do you want to keep the stored passwords or delete them?`,
{
detail: `${storedPasswordCredKeys.length == sessionIds.length ? "All" : "Some"
} of the ${AUTHENTICATION_PROVIDER_LABEL} accounts you signed out are currently storing their passwords securely on your workstation.`, modal: true
},
{ title: "Keep", isCloseAffordance: true },
{ title: "Delete", isCloseAffordance: false },
);
deletePasswords = (choice?.title === "Delete");
}
if (deletePasswords) {
await Promise.allSettled(storedPasswordCredKeys.map((e) => this.secretStorage.delete(e)));
}
}
await this._storeStrippedSessions();
this._onDidChangeSessions.fire({ added: [], removed, changed: [] });
}

private async _ensureInitialized(): Promise<void> {
if (this._initializedDisposable === undefined) {

Expand Down
15 changes: 13 additions & 2 deletions src/commonActivate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ export function commonActivate(context: vscode.ExtensionContext, view: ServerMan
}
};

const authProvider = new ServerManagerAuthenticationProvider(context.secrets);
context.subscriptions.push(
// Register our authentication provider. NOTE: this will register the provider globally which means that
// any other extension can request to use use this provider via the `vscode.authentication.getSession` API.
vscode.authentication.registerAuthenticationProvider(
ServerManagerAuthenticationProvider.id,
ServerManagerAuthenticationProvider.label,
new ServerManagerAuthenticationProvider(context.secrets),
authProvider,
{ supportsMultipleAccounts: true },
),
// Ensure cookies do not survive an account sign-out
Expand Down Expand Up @@ -136,7 +137,7 @@ export function commonActivate(context: vscode.ExtensionContext, view: ServerMan
}
const choice = await vscode.window.showQuickPick(options, {
ignoreFocusOut: true,
title: "Pick a settngs scope in which to add the server definition"
title: "Pick a settings scope in which to add the server definition"
});
if (!choice) return;
scope = choice.scope;
Expand Down Expand Up @@ -330,6 +331,16 @@ export function commonActivate(context: vscode.ExtensionContext, view: ServerMan
await addWorkspaceFolderAsync(true, true, <NamespaceTreeItem>webAppTreeItem?.parent?.parent, undefined, webAppTreeItem?.name);
}),
vscode.workspace.onDidChangeWorkspaceFolders(() => view.refreshTree()),
vscode.commands.registerCommand(`${extensionId}.signOut`, async () => {
const sessions = await authProvider.getSessions(undefined, {}).catch(() => { });
if (!sessions?.length) {
vscode.window.showInformationMessage("There are no stored accounts to sign out of.", "Dismiss");
return;
}
const picks = await vscode.window.showQuickPick(sessions.map((s) => s.account), { canPickMany: true, title: "Pick the accounts to sign out of" });
if (!picks?.length) return;
return authProvider.removeSessions(picks.map((p) => p.id));
}),
// Listen for relevant configuration changes
vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration("intersystems.servers") || e.affectsConfiguration("objectscript.conn")) {
Expand Down