Path: blob/main/src/vs/workbench/contrib/authentication/browser/actions/manageAccountsAction.ts
4780 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Lazy } from '../../../../../base/common/lazy.js';6import { DisposableStore } from '../../../../../base/common/lifecycle.js';7import { localize, localize2 } from '../../../../../nls.js';8import { Action2 } from '../../../../../platform/actions/common/actions.js';9import { ICommandService } from '../../../../../platform/commands/common/commands.js';10import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';11import { IProductService } from '../../../../../platform/product/common/productService.js';12import { IQuickInputService, IQuickPickItem } from '../../../../../platform/quickinput/common/quickInput.js';13import { ISecretStorageService } from '../../../../../platform/secrets/common/secrets.js';14import { AuthenticationSessionInfo, getCurrentAuthenticationSessionInfo } from '../../../../services/authentication/browser/authenticationService.js';15import { IAuthenticationProvider, IAuthenticationService } from '../../../../services/authentication/common/authentication.js';1617export class ManageAccountsAction extends Action2 {18constructor() {19super({20id: 'workbench.action.manageAccounts',21title: localize2('manageAccounts', "Manage Accounts"),22category: localize2('accounts', "Accounts"),23f1: true24});25}2627public override run(accessor: ServicesAccessor): Promise<void> {28const instantiationService = accessor.get(IInstantiationService);29return instantiationService.createInstance(ManageAccountsActionImpl).run();30}31}3233interface AccountQuickPickItem extends IQuickPickItem {34providerId: string;35canUseMcp: boolean;36canSignOut: () => Promise<boolean>;37}3839interface AccountActionQuickPickItem extends IQuickPickItem {40action: () => void;41}4243class ManageAccountsActionImpl {44constructor(45@IQuickInputService private readonly quickInputService: IQuickInputService,46@IAuthenticationService private readonly authenticationService: IAuthenticationService,47@ICommandService private readonly commandService: ICommandService,48@ISecretStorageService private readonly secretStorageService: ISecretStorageService,49@IProductService private readonly productService: IProductService,50) { }5152public async run() {53const placeHolder = localize('pickAccount', "Select an account to manage");5455const accounts = await this.listAccounts();56if (!accounts.length) {57await this.quickInputService.pick([{ label: localize('noActiveAccounts', "There are no active accounts.") }], { placeHolder });58return;59}6061const account = await this.quickInputService.pick(accounts, { placeHolder, matchOnDescription: true });62if (!account) {63return;64}6566await this.showAccountActions(account);67}6869private async listAccounts(): Promise<AccountQuickPickItem[]> {70const activeSession = new Lazy(() => getCurrentAuthenticationSessionInfo(this.secretStorageService, this.productService));71const accounts: AccountQuickPickItem[] = [];72for (const providerId of this.authenticationService.getProviderIds()) {73const provider = this.authenticationService.getProvider(providerId);74for (const { label, id } of await this.authenticationService.getAccounts(providerId)) {75accounts.push({76label,77description: provider.label,78providerId,79canUseMcp: !!provider.authorizationServers?.length,80canSignOut: async () => this.canSignOut(provider, id, await activeSession.value)81});82}83}84return accounts;85}8687private async canSignOut(provider: IAuthenticationProvider, accountId: string, session?: AuthenticationSessionInfo): Promise<boolean> {88if (session && !session.canSignOut && session.providerId === provider.id) {89const sessions = await this.authenticationService.getSessions(provider.id);90return !sessions.some(o => o.id === session.id && o.account.id === accountId);91}92return true;93}9495private async showAccountActions(account: AccountQuickPickItem): Promise<void> {96const { providerId, label: accountLabel, canUseMcp, canSignOut } = account;9798const store = new DisposableStore();99const quickPick = store.add(this.quickInputService.createQuickPick<AccountActionQuickPickItem>());100101quickPick.title = localize('manageAccount', "Manage '{0}'", accountLabel);102quickPick.placeholder = localize('selectAction', "Select an action");103quickPick.buttons = [this.quickInputService.backButton];104105const items: AccountActionQuickPickItem[] = [{106label: localize('manageTrustedExtensions', "Manage Trusted Extensions"),107action: () => this.commandService.executeCommand('_manageTrustedExtensionsForAccount', { providerId, accountLabel })108}];109110if (canUseMcp) {111items.push({112label: localize('manageTrustedMCPServers', "Manage Trusted MCP Servers"),113action: () => this.commandService.executeCommand('_manageTrustedMCPServersForAccount', { providerId, accountLabel })114});115}116117if (await canSignOut()) {118items.push({119label: localize('signOut', "Sign Out"),120action: () => this.commandService.executeCommand('_signOutOfAccount', { providerId, accountLabel })121});122}123124quickPick.items = items;125126store.add(quickPick.onDidAccept(() => {127const selected = quickPick.selectedItems[0];128if (selected) {129quickPick.hide();130selected.action();131}132}));133134store.add(quickPick.onDidTriggerButton((button) => {135if (button === this.quickInputService.backButton) {136void this.run();137}138}));139140store.add(quickPick.onDidHide(() => store.dispose()));141142quickPick.show();143}144}145146147