Path: blob/main/src/vs/workbench/contrib/authentication/browser/authentication.contribution.ts
5245 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 { Disposable } from '../../../../base/common/lifecycle.js';6import { localize } from '../../../../nls.js';7import { registerAction2 } from '../../../../platform/actions/common/actions.js';8import { CommandsRegistry } from '../../../../platform/commands/common/commands.js';9import { IExtensionManifest } from '../../../../platform/extensions/common/extensions.js';10import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';11import { Registry } from '../../../../platform/registry/common/platform.js';12import { IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from '../../../common/contributions.js';13import { SignOutOfAccountAction } from './actions/signOutOfAccountAction.js';14import { IBrowserWorkbenchEnvironmentService } from '../../../services/environment/browser/environmentService.js';15import { Extensions, IExtensionFeatureTableRenderer, IExtensionFeaturesRegistry, IRenderedData, IRowData, ITableData } from '../../../services/extensionManagement/common/extensionFeatures.js';16import { ManageTrustedExtensionsForAccountAction } from './actions/manageTrustedExtensionsForAccountAction.js';17import { ManageAccountPreferencesForExtensionAction } from './actions/manageAccountPreferencesForExtensionAction.js';18import { IAuthenticationUsageService } from '../../../services/authentication/browser/authenticationUsageService.js';19import { ManageAccountPreferencesForMcpServerAction } from './actions/manageAccountPreferencesForMcpServerAction.js';20import { ManageTrustedMcpServersForAccountAction } from './actions/manageTrustedMcpServersForAccountAction.js';21import { RemoveDynamicAuthenticationProvidersAction } from './actions/manageDynamicAuthenticationProvidersAction.js';22import { ManageAccountsAction } from './actions/manageAccountsAction.js';2324const codeExchangeProxyCommand = CommandsRegistry.registerCommand('workbench.getCodeExchangeProxyEndpoints', function (accessor, _) {25const environmentService = accessor.get(IBrowserWorkbenchEnvironmentService);26return environmentService.options?.codeExchangeProxyEndpoints;27});2829class AuthenticationDataRenderer extends Disposable implements IExtensionFeatureTableRenderer {3031readonly type = 'table';3233shouldRender(manifest: IExtensionManifest): boolean {34return !!manifest.contributes?.authentication;35}3637render(manifest: IExtensionManifest): IRenderedData<ITableData> {38const authentication = manifest.contributes?.authentication || [];39if (!authentication.length) {40return { data: { headers: [], rows: [] }, dispose: () => { } };41}4243const headers = [44localize('authenticationlabel', "Label"),45localize('authenticationid', "ID"),46localize('authenticationMcpAuthorizationServers', "MCP Authorization Servers")47];4849const rows: IRowData[][] = authentication50.sort((a, b) => a.label.localeCompare(b.label))51.map(auth => {52return [53auth.label,54auth.id,55(auth.authorizationServerGlobs ?? []).join(',\n')56];57});5859return {60data: {61headers,62rows63},64dispose: () => { }65};66}67}6869const extensionFeature = Registry.as<IExtensionFeaturesRegistry>(Extensions.ExtensionFeaturesRegistry).registerExtensionFeature({70id: 'authentication',71label: localize('authentication', "Authentication"),72access: {73canToggle: false74},75renderer: new SyncDescriptor(AuthenticationDataRenderer),76});7778class AuthenticationContribution extends Disposable implements IWorkbenchContribution {79static ID = 'workbench.contrib.authentication';8081constructor() {82super();83this._register(codeExchangeProxyCommand);84this._register(extensionFeature);8586this._registerActions();87}8889private _registerActions(): void {90this._register(registerAction2(ManageAccountsAction));91this._register(registerAction2(SignOutOfAccountAction));92this._register(registerAction2(ManageTrustedExtensionsForAccountAction));93this._register(registerAction2(ManageAccountPreferencesForExtensionAction));94this._register(registerAction2(ManageTrustedMcpServersForAccountAction));95this._register(registerAction2(ManageAccountPreferencesForMcpServerAction));96this._register(registerAction2(RemoveDynamicAuthenticationProvidersAction));97}98}99100class AuthenticationUsageContribution implements IWorkbenchContribution {101static ID = 'workbench.contrib.authenticationUsage';102103constructor(104@IAuthenticationUsageService private readonly _authenticationUsageService: IAuthenticationUsageService,105) {106this._initializeExtensionUsageCache();107}108109private async _initializeExtensionUsageCache() {110await this._authenticationUsageService.initializeExtensionUsageCache();111}112}113114// class AuthenticationExtensionsContribution extends Disposable implements IWorkbenchContribution {115// static ID = 'workbench.contrib.authenticationExtensions';116117// constructor(118// @IExtensionService private readonly _extensionService: IExtensionService,119// @IAuthenticationQueryService private readonly _authenticationQueryService: IAuthenticationQueryService,120// @IAuthenticationService private readonly _authenticationService: IAuthenticationService121// ) {122// super();123// void this.run();124// this._register(this._extensionService.onDidChangeExtensions(this._onDidChangeExtensions, this));125// this._register(126// Event.any(127// this._authenticationService.onDidChangeDeclaredProviders,128// this._authenticationService.onDidRegisterAuthenticationProvider129// )(() => this._cleanupRemovedExtensions())130// );131// }132133// async run(): Promise<void> {134// await this._extensionService.whenInstalledExtensionsRegistered();135// this._cleanupRemovedExtensions();136// }137138// private _onDidChangeExtensions(delta: { readonly added: readonly IExtensionDescription[]; readonly removed: readonly IExtensionDescription[] }): void {139// if (delta.removed.length > 0) {140// this._cleanupRemovedExtensions(delta.removed);141// }142// }143144// private _cleanupRemovedExtensions(removedExtensions?: readonly IExtensionDescription[]): void {145// const extensionIdsToRemove = removedExtensions146// ? new Set(removedExtensions.map(e => e.identifier.value))147// : new Set(this._extensionService.extensions.map(e => e.identifier.value));148149// // If we are cleaning up specific removed extensions, we only remove those.150// const isTargetedCleanup = !!removedExtensions;151152// const providerIds = this._authenticationQueryService.getProviderIds();153// for (const providerId of providerIds) {154// this._authenticationQueryService.provider(providerId).forEachAccount(account => {155// account.extensions().forEach(extension => {156// const shouldRemove = isTargetedCleanup157// ? extensionIdsToRemove.has(extension.extensionId)158// : !extensionIdsToRemove.has(extension.extensionId);159160// if (shouldRemove) {161// extension.removeUsage();162// extension.setAccessAllowed(false);163// }164// });165// });166// }167// }168// }169170// class AuthenticationMcpContribution extends Disposable implements IWorkbenchContribution {171// static ID = 'workbench.contrib.authenticationMcp';172173// constructor(174// @IMcpRegistry private readonly _mcpRegistry: IMcpRegistry,175// @IAuthenticationQueryService private readonly _authenticationQueryService: IAuthenticationQueryService,176// @IAuthenticationService private readonly _authenticationService: IAuthenticationService177// ) {178// super();179// this._cleanupRemovedMcpServers();180181// // Listen for MCP collections changes using autorun with observables182// this._register(autorun(reader => {183// // Read the collections observable to register dependency184// this._mcpRegistry.collections.read(reader);185// // Schedule cleanup for next tick to avoid running during observable updates186// queueMicrotask(() => this._cleanupRemovedMcpServers());187// }));188// this._register(189// Event.any(190// this._authenticationService.onDidChangeDeclaredProviders,191// this._authenticationService.onDidRegisterAuthenticationProvider192// )(() => this._cleanupRemovedMcpServers())193// );194// }195196// private _cleanupRemovedMcpServers(): void {197// const currentServerIds = new Set(this._mcpRegistry.collections.get().flatMap(c => c.serverDefinitions.get()).map(s => s.id));198// const providerIds = this._authenticationQueryService.getProviderIds();199// for (const providerId of providerIds) {200// this._authenticationQueryService.provider(providerId).forEachAccount(account => {201// account.mcpServers().forEach(server => {202// if (!currentServerIds.has(server.mcpServerId)) {203// server.removeUsage();204// server.setAccessAllowed(false);205// }206// });207// });208// }209// }210// }211212registerWorkbenchContribution2(AuthenticationContribution.ID, AuthenticationContribution, WorkbenchPhase.AfterRestored);213registerWorkbenchContribution2(AuthenticationUsageContribution.ID, AuthenticationUsageContribution, WorkbenchPhase.Eventually);214// registerWorkbenchContribution2(AuthenticationExtensionsContribution.ID, AuthenticationExtensionsContribution, WorkbenchPhase.Eventually);215// registerWorkbenchContribution2(AuthenticationMcpContribution.ID, AuthenticationMcpContribution, WorkbenchPhase.Eventually);216217218