@codingame/monaco-vscode-authentication-service-override 18.4.0 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +5 -1
- package/package.json +5 -4
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageAccountPreferencesForExtensionAction.d.ts +6 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageAccountPreferencesForExtensionAction.js +171 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageAccountPreferencesForMcpServerAction.d.ts +6 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageAccountPreferencesForMcpServerAction.js +171 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageDynamicAuthenticationProvidersAction.d.ts +7 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageDynamicAuthenticationProvidersAction.js +76 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageTrustedExtensionsForAccountAction.d.ts +9 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageTrustedExtensionsForAccountAction.js +177 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageTrustedMcpServersForAccountAction.d.ts +9 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/manageTrustedMcpServersForAccountAction.js +171 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/signOutOfAccountAction.d.ts +9 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/actions/signOutOfAccountAction.js +52 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/authentication.contribution.d.ts +1 -0
- package/vscode/src/vs/workbench/contrib/authentication/browser/authentication.contribution.js +140 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationAccessService.js +39 -6
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.js +9 -9
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationQueryService.d.ts +39 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationQueryService.js +613 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationUsageService.d.ts +1 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationUsageService.js +7 -2
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
|
|
2
|
+
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
|
|
4
|
+
import { fromNow } from '@codingame/monaco-vscode-api/vscode/vs/base/common/date';
|
|
5
|
+
import { DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
6
|
+
import { ThemeIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/themables';
|
|
7
|
+
import { localize2, localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
8
|
+
import { Action2 } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
|
|
9
|
+
import { ICommandService } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service';
|
|
10
|
+
import { IDialogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service';
|
|
11
|
+
import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
|
|
12
|
+
import { IQuickInputService } from '@codingame/monaco-vscode-api/vscode/vs/platform/quickinput/common/quickInput.service';
|
|
13
|
+
import { IAuthenticationService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authentication.service';
|
|
14
|
+
import { IAuthenticationQueryService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authenticationQuery.service';
|
|
15
|
+
import { IExtensionService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensions.service';
|
|
16
|
+
|
|
17
|
+
class ManageTrustedExtensionsForAccountAction extends Action2 {
|
|
18
|
+
constructor() {
|
|
19
|
+
super({
|
|
20
|
+
id: '_manageTrustedExtensionsForAccount',
|
|
21
|
+
title: ( localize2(4310, "Manage Trusted Extensions For Account")),
|
|
22
|
+
category: ( localize2(4311, "Accounts")),
|
|
23
|
+
f1: true
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
run(accessor, options) {
|
|
27
|
+
const instantiationService = accessor.get(IInstantiationService);
|
|
28
|
+
return instantiationService.createInstance(ManageTrustedExtensionsForAccountActionImpl).run(options);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let ManageTrustedExtensionsForAccountActionImpl = class ManageTrustedExtensionsForAccountActionImpl {
|
|
32
|
+
constructor(_extensionService, _dialogService, _quickInputService, _authenticationService, _authenticationQueryService, _commandService) {
|
|
33
|
+
this._extensionService = _extensionService;
|
|
34
|
+
this._dialogService = _dialogService;
|
|
35
|
+
this._quickInputService = _quickInputService;
|
|
36
|
+
this._authenticationService = _authenticationService;
|
|
37
|
+
this._authenticationQueryService = _authenticationQueryService;
|
|
38
|
+
this._commandService = _commandService;
|
|
39
|
+
}
|
|
40
|
+
async run(options) {
|
|
41
|
+
const accountQuery = await this._resolveAccountQuery(options?.providerId, options?.accountLabel);
|
|
42
|
+
if (!accountQuery) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const items = await this._getItems(accountQuery);
|
|
46
|
+
if (!items.length) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const picker = this._createQuickPick(accountQuery);
|
|
50
|
+
picker.items = items;
|
|
51
|
+
picker.selectedItems = items.filter((i) => i.type !== 'separator' && !!i.picked);
|
|
52
|
+
picker.show();
|
|
53
|
+
}
|
|
54
|
+
async _resolveAccountQuery(providerId, accountLabel) {
|
|
55
|
+
if (providerId && accountLabel) {
|
|
56
|
+
return this._authenticationQueryService.provider(providerId).account(accountLabel);
|
|
57
|
+
}
|
|
58
|
+
const accounts = await this._getAllAvailableAccounts();
|
|
59
|
+
const pick = await this._quickInputService.pick(accounts, {
|
|
60
|
+
placeHolder: ( localize(4312, "Pick an account to manage trusted extensions for")),
|
|
61
|
+
matchOnDescription: true,
|
|
62
|
+
});
|
|
63
|
+
return pick ? this._authenticationQueryService.provider(pick.providerId).account(pick.label) : undefined;
|
|
64
|
+
}
|
|
65
|
+
async _getAllAvailableAccounts() {
|
|
66
|
+
const accounts = [];
|
|
67
|
+
for (const providerId of this._authenticationService.getProviderIds()) {
|
|
68
|
+
const provider = this._authenticationService.getProvider(providerId);
|
|
69
|
+
const sessions = await this._authenticationService.getSessions(providerId);
|
|
70
|
+
const uniqueLabels = ( new Set());
|
|
71
|
+
for (const session of sessions) {
|
|
72
|
+
if (!( uniqueLabels.has(session.account.label))) {
|
|
73
|
+
uniqueLabels.add(session.account.label);
|
|
74
|
+
accounts.push({
|
|
75
|
+
providerId,
|
|
76
|
+
label: session.account.label,
|
|
77
|
+
description: provider.label
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return accounts;
|
|
83
|
+
}
|
|
84
|
+
async _getItems(accountQuery) {
|
|
85
|
+
const allowedExtensions = accountQuery.extensions().getAllowedExtensions();
|
|
86
|
+
const extensionIdToDisplayName = ( new Map());
|
|
87
|
+
const resolvedExtensions = await Promise.all(( allowedExtensions.map(ext => this._extensionService.getExtension(ext.id))));
|
|
88
|
+
resolvedExtensions.forEach((resolved, i) => {
|
|
89
|
+
if (resolved) {
|
|
90
|
+
extensionIdToDisplayName.set(allowedExtensions[i].id, resolved.displayName || resolved.name);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const filteredExtensions = ( allowedExtensions
|
|
94
|
+
.filter(ext => ( extensionIdToDisplayName.has(ext.id)))
|
|
95
|
+
.map(ext => {
|
|
96
|
+
const usage = accountQuery.extension(ext.id).getUsage();
|
|
97
|
+
return {
|
|
98
|
+
...ext,
|
|
99
|
+
name: extensionIdToDisplayName.get(ext.id),
|
|
100
|
+
lastUsed: usage.length > 0 ? Math.max(...( usage.map(u => u.lastUsed))) : ext.lastUsed
|
|
101
|
+
};
|
|
102
|
+
}));
|
|
103
|
+
if (!filteredExtensions.length) {
|
|
104
|
+
this._dialogService.info(( localize(4313, "This account has not been used by any extensions.")));
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
const trustedExtensions = filteredExtensions.filter(e => e.trusted);
|
|
108
|
+
const otherExtensions = filteredExtensions.filter(e => !e.trusted);
|
|
109
|
+
const sortByLastUsed = (a, b) => (b.lastUsed || 0) - (a.lastUsed || 0);
|
|
110
|
+
return [
|
|
111
|
+
...( otherExtensions.sort(sortByLastUsed).map(this._toQuickPickItem)),
|
|
112
|
+
{ type: 'separator', label: ( localize(4314, "Trusted by Microsoft")) },
|
|
113
|
+
...( trustedExtensions.sort(sortByLastUsed).map(this._toQuickPickItem))
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
_toQuickPickItem(extension) {
|
|
117
|
+
const lastUsed = extension.lastUsed;
|
|
118
|
+
const description = lastUsed
|
|
119
|
+
? ( localize(4315, "Last used this account {0}", fromNow(lastUsed, true)))
|
|
120
|
+
: ( localize(4316, "Has not used this account"));
|
|
121
|
+
let tooltip;
|
|
122
|
+
let disabled;
|
|
123
|
+
if (extension.trusted) {
|
|
124
|
+
tooltip = ( localize(
|
|
125
|
+
4317,
|
|
126
|
+
"This extension is trusted by Microsoft and\nalways has access to this account"
|
|
127
|
+
));
|
|
128
|
+
disabled = true;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
label: extension.name,
|
|
132
|
+
extension,
|
|
133
|
+
description,
|
|
134
|
+
tooltip,
|
|
135
|
+
disabled,
|
|
136
|
+
buttons: [{
|
|
137
|
+
tooltip: ( localize(4318, "Manage account preferences for this extension")),
|
|
138
|
+
iconClass: ThemeIcon.asClassName(Codicon.settingsGear),
|
|
139
|
+
}],
|
|
140
|
+
picked: extension.allowed === undefined || extension.allowed
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
_createQuickPick(accountQuery) {
|
|
144
|
+
const disposableStore = ( new DisposableStore());
|
|
145
|
+
const quickPick = disposableStore.add(this._quickInputService.createQuickPick({ useSeparators: true }));
|
|
146
|
+
quickPick.canSelectMany = true;
|
|
147
|
+
quickPick.customButton = true;
|
|
148
|
+
quickPick.customLabel = ( localize(4319, 'Cancel'));
|
|
149
|
+
quickPick.title = ( localize(4320, "Manage Trusted Extensions"));
|
|
150
|
+
quickPick.placeholder = ( localize(4321, "Choose which extensions can access this account"));
|
|
151
|
+
disposableStore.add(quickPick.onDidAccept(() => {
|
|
152
|
+
const updatedAllowedList = ( quickPick.items
|
|
153
|
+
.filter((item) => item.type !== 'separator')
|
|
154
|
+
.map(i => i.extension));
|
|
155
|
+
const allowedExtensionsSet = ( new Set(( quickPick.selectedItems.map(i => i.extension))));
|
|
156
|
+
for (const extension of updatedAllowedList) {
|
|
157
|
+
const allowed = ( allowedExtensionsSet.has(extension));
|
|
158
|
+
accountQuery.extension(extension.id).setAccessAllowed(allowed, extension.name);
|
|
159
|
+
}
|
|
160
|
+
quickPick.hide();
|
|
161
|
+
}));
|
|
162
|
+
disposableStore.add(quickPick.onDidHide(() => disposableStore.dispose()));
|
|
163
|
+
disposableStore.add(quickPick.onDidCustom(() => quickPick.hide()));
|
|
164
|
+
disposableStore.add(quickPick.onDidTriggerItemButton(e => this._commandService.executeCommand('_manageAccountPreferencesForExtension', e.item.extension.id, accountQuery.providerId)));
|
|
165
|
+
return quickPick;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
ManageTrustedExtensionsForAccountActionImpl = ( __decorate([
|
|
169
|
+
( __param(0, IExtensionService)),
|
|
170
|
+
( __param(1, IDialogService)),
|
|
171
|
+
( __param(2, IQuickInputService)),
|
|
172
|
+
( __param(3, IAuthenticationService)),
|
|
173
|
+
( __param(4, IAuthenticationQueryService)),
|
|
174
|
+
( __param(5, ICommandService))
|
|
175
|
+
], ManageTrustedExtensionsForAccountActionImpl));
|
|
176
|
+
|
|
177
|
+
export { ManageTrustedExtensionsForAccountAction };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Action2 } from "@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions";
|
|
2
|
+
import { ServicesAccessor } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
|
|
3
|
+
export declare class ManageTrustedMcpServersForAccountAction extends Action2 {
|
|
4
|
+
constructor();
|
|
5
|
+
run(accessor: ServicesAccessor, options?: {
|
|
6
|
+
providerId: string;
|
|
7
|
+
accountLabel: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
|
|
2
|
+
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
|
|
4
|
+
import { fromNow } from '@codingame/monaco-vscode-api/vscode/vs/base/common/date';
|
|
5
|
+
import { DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
6
|
+
import { ThemeIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/themables';
|
|
7
|
+
import { localize2, localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
8
|
+
import { Action2 } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
|
|
9
|
+
import { ICommandService } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service';
|
|
10
|
+
import { IDialogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service';
|
|
11
|
+
import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
|
|
12
|
+
import { IQuickInputService } from '@codingame/monaco-vscode-api/vscode/vs/platform/quickinput/common/quickInput.service';
|
|
13
|
+
import { IAuthenticationService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authentication.service';
|
|
14
|
+
import { IAuthenticationQueryService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authenticationQuery.service';
|
|
15
|
+
import { IMcpService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service';
|
|
16
|
+
|
|
17
|
+
class ManageTrustedMcpServersForAccountAction extends Action2 {
|
|
18
|
+
constructor() {
|
|
19
|
+
super({
|
|
20
|
+
id: '_manageTrustedMCPServersForAccount',
|
|
21
|
+
title: ( localize2(4322, "Manage Trusted MCP Servers For Account")),
|
|
22
|
+
category: ( localize2(4323, "Accounts")),
|
|
23
|
+
f1: true
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
run(accessor, options) {
|
|
27
|
+
const instantiationService = accessor.get(IInstantiationService);
|
|
28
|
+
return instantiationService.createInstance(ManageTrustedMcpServersForAccountActionImpl).run(options);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let ManageTrustedMcpServersForAccountActionImpl = class ManageTrustedMcpServersForAccountActionImpl {
|
|
32
|
+
constructor(_mcpServerService, _dialogService, _quickInputService, _mcpServerAuthenticationService, _authenticationQueryService, _commandService) {
|
|
33
|
+
this._mcpServerService = _mcpServerService;
|
|
34
|
+
this._dialogService = _dialogService;
|
|
35
|
+
this._quickInputService = _quickInputService;
|
|
36
|
+
this._mcpServerAuthenticationService = _mcpServerAuthenticationService;
|
|
37
|
+
this._authenticationQueryService = _authenticationQueryService;
|
|
38
|
+
this._commandService = _commandService;
|
|
39
|
+
}
|
|
40
|
+
async run(options) {
|
|
41
|
+
const accountQuery = await this._resolveAccountQuery(options?.providerId, options?.accountLabel);
|
|
42
|
+
if (!accountQuery) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const items = await this._getItems(accountQuery);
|
|
46
|
+
if (!items.length) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const picker = this._createQuickPick(accountQuery);
|
|
50
|
+
picker.items = items;
|
|
51
|
+
picker.selectedItems = items.filter((i) => i.type !== 'separator' && !!i.picked);
|
|
52
|
+
picker.show();
|
|
53
|
+
}
|
|
54
|
+
async _resolveAccountQuery(providerId, accountLabel) {
|
|
55
|
+
if (providerId && accountLabel) {
|
|
56
|
+
return this._authenticationQueryService.provider(providerId).account(accountLabel);
|
|
57
|
+
}
|
|
58
|
+
const accounts = await this._getAllAvailableAccounts();
|
|
59
|
+
const pick = await this._quickInputService.pick(accounts, {
|
|
60
|
+
placeHolder: ( localize(4324, "Pick an account to manage trusted MCP servers for")),
|
|
61
|
+
matchOnDescription: true,
|
|
62
|
+
});
|
|
63
|
+
return pick ? this._authenticationQueryService.provider(pick.providerId).account(pick.label) : undefined;
|
|
64
|
+
}
|
|
65
|
+
async _getAllAvailableAccounts() {
|
|
66
|
+
const accounts = [];
|
|
67
|
+
for (const providerId of this._mcpServerAuthenticationService.getProviderIds()) {
|
|
68
|
+
const provider = this._mcpServerAuthenticationService.getProvider(providerId);
|
|
69
|
+
const sessions = await this._mcpServerAuthenticationService.getSessions(providerId);
|
|
70
|
+
const uniqueLabels = ( new Set());
|
|
71
|
+
for (const session of sessions) {
|
|
72
|
+
if (!( uniqueLabels.has(session.account.label))) {
|
|
73
|
+
uniqueLabels.add(session.account.label);
|
|
74
|
+
accounts.push({
|
|
75
|
+
providerId,
|
|
76
|
+
label: session.account.label,
|
|
77
|
+
description: provider.label
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return accounts;
|
|
83
|
+
}
|
|
84
|
+
async _getItems(accountQuery) {
|
|
85
|
+
const allowedMcpServers = accountQuery.mcpServers().getAllowedMcpServers();
|
|
86
|
+
const serverIdToLabel = ( new Map(( this._mcpServerService.servers.get().map(s => [s.definition.id, s.definition.label]))));
|
|
87
|
+
const filteredMcpServers = ( allowedMcpServers
|
|
88
|
+
.filter(server => ( serverIdToLabel.has(server.id)))
|
|
89
|
+
.map(server => {
|
|
90
|
+
const usage = accountQuery.mcpServer(server.id).getUsage();
|
|
91
|
+
return {
|
|
92
|
+
...server,
|
|
93
|
+
name: serverIdToLabel.get(server.id),
|
|
94
|
+
lastUsed: usage.length > 0 ? Math.max(...( usage.map(u => u.lastUsed))) : server.lastUsed
|
|
95
|
+
};
|
|
96
|
+
}));
|
|
97
|
+
if (!filteredMcpServers.length) {
|
|
98
|
+
this._dialogService.info(( localize(4325, "This account has not been used by any MCP servers.")));
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const trustedServers = filteredMcpServers.filter(s => s.trusted);
|
|
102
|
+
const otherServers = filteredMcpServers.filter(s => !s.trusted);
|
|
103
|
+
const sortByLastUsed = (a, b) => (b.lastUsed || 0) - (a.lastUsed || 0);
|
|
104
|
+
return [
|
|
105
|
+
...( otherServers.sort(sortByLastUsed).map(this._toQuickPickItem)),
|
|
106
|
+
{ type: 'separator', label: ( localize(4326, "Trusted by Microsoft")) },
|
|
107
|
+
...( trustedServers.sort(sortByLastUsed).map(this._toQuickPickItem))
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
_toQuickPickItem(mcpServer) {
|
|
111
|
+
const lastUsed = mcpServer.lastUsed;
|
|
112
|
+
const description = lastUsed
|
|
113
|
+
? ( localize(4327, "Last used this account {0}", fromNow(lastUsed, true)))
|
|
114
|
+
: ( localize(4328, "Has not used this account"));
|
|
115
|
+
let tooltip;
|
|
116
|
+
let disabled;
|
|
117
|
+
if (mcpServer.trusted) {
|
|
118
|
+
tooltip = ( localize(
|
|
119
|
+
4329,
|
|
120
|
+
"This MCP server is trusted by Microsoft and\nalways has access to this account"
|
|
121
|
+
));
|
|
122
|
+
disabled = true;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
label: mcpServer.name,
|
|
126
|
+
mcpServer,
|
|
127
|
+
description,
|
|
128
|
+
tooltip,
|
|
129
|
+
disabled,
|
|
130
|
+
buttons: [{
|
|
131
|
+
tooltip: ( localize(4330, "Manage account preferences for this MCP server")),
|
|
132
|
+
iconClass: ThemeIcon.asClassName(Codicon.settingsGear),
|
|
133
|
+
}],
|
|
134
|
+
picked: mcpServer.allowed === undefined || mcpServer.allowed
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
_createQuickPick(accountQuery) {
|
|
138
|
+
const disposableStore = ( new DisposableStore());
|
|
139
|
+
const quickPick = disposableStore.add(this._quickInputService.createQuickPick({ useSeparators: true }));
|
|
140
|
+
quickPick.canSelectMany = true;
|
|
141
|
+
quickPick.customButton = true;
|
|
142
|
+
quickPick.customLabel = ( localize(4331, 'Cancel'));
|
|
143
|
+
quickPick.title = ( localize(4332, "Manage Trusted MCP Servers"));
|
|
144
|
+
quickPick.placeholder = ( localize(4333, "Choose which MCP servers can access this account"));
|
|
145
|
+
disposableStore.add(quickPick.onDidAccept(() => {
|
|
146
|
+
quickPick.hide();
|
|
147
|
+
const allServers = ( quickPick.items
|
|
148
|
+
.filter((item) => item.type !== 'separator')
|
|
149
|
+
.map((i) => i.mcpServer));
|
|
150
|
+
const selectedServers = ( new Set(( quickPick.selectedItems.map((i) => i.mcpServer))));
|
|
151
|
+
for (const mcpServer of allServers) {
|
|
152
|
+
const isAllowed = ( selectedServers.has(mcpServer));
|
|
153
|
+
accountQuery.mcpServer(mcpServer.id).setAccessAllowed(isAllowed, mcpServer.name);
|
|
154
|
+
}
|
|
155
|
+
}));
|
|
156
|
+
disposableStore.add(quickPick.onDidHide(() => disposableStore.dispose()));
|
|
157
|
+
disposableStore.add(quickPick.onDidCustom(() => quickPick.hide()));
|
|
158
|
+
disposableStore.add(quickPick.onDidTriggerItemButton((e) => this._commandService.executeCommand('_manageAccountPreferencesForMcpServer', e.item.mcpServer.id, accountQuery.providerId)));
|
|
159
|
+
return quickPick;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
ManageTrustedMcpServersForAccountActionImpl = ( __decorate([
|
|
163
|
+
( __param(0, IMcpService)),
|
|
164
|
+
( __param(1, IDialogService)),
|
|
165
|
+
( __param(2, IQuickInputService)),
|
|
166
|
+
( __param(3, IAuthenticationService)),
|
|
167
|
+
( __param(4, IAuthenticationQueryService)),
|
|
168
|
+
( __param(5, ICommandService))
|
|
169
|
+
], ManageTrustedMcpServersForAccountActionImpl));
|
|
170
|
+
|
|
171
|
+
export { ManageTrustedMcpServersForAccountAction };
|
package/vscode/src/vs/workbench/contrib/authentication/browser/actions/signOutOfAccountAction.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Action2 } from "@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions";
|
|
2
|
+
import { ServicesAccessor } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
|
|
3
|
+
export declare class SignOutOfAccountAction extends Action2 {
|
|
4
|
+
constructor();
|
|
5
|
+
run(accessor: ServicesAccessor, { providerId, accountLabel }: {
|
|
6
|
+
providerId: string;
|
|
7
|
+
accountLabel: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
}
|
package/vscode/src/vs/workbench/contrib/authentication/browser/actions/signOutOfAccountAction.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
import Severity from '@codingame/monaco-vscode-api/vscode/vs/base/common/severity';
|
|
3
|
+
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
4
|
+
import { Action2 } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
|
|
5
|
+
import { IDialogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service';
|
|
6
|
+
import { IAuthenticationAccessService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/browser/authenticationAccessService.service';
|
|
7
|
+
import { IAuthenticationUsageService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/browser/authenticationUsageService.service';
|
|
8
|
+
import { IAuthenticationService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authentication.service';
|
|
9
|
+
|
|
10
|
+
class SignOutOfAccountAction extends Action2 {
|
|
11
|
+
constructor() {
|
|
12
|
+
super({
|
|
13
|
+
id: '_signOutOfAccount',
|
|
14
|
+
title: ( localize(4334, "Sign out of account")),
|
|
15
|
+
f1: false
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async run(accessor, { providerId, accountLabel }) {
|
|
19
|
+
const authenticationService = accessor.get(IAuthenticationService);
|
|
20
|
+
const authenticationUsageService = accessor.get(IAuthenticationUsageService);
|
|
21
|
+
const authenticationAccessService = accessor.get(IAuthenticationAccessService);
|
|
22
|
+
const dialogService = accessor.get(IDialogService);
|
|
23
|
+
if (!providerId || !accountLabel) {
|
|
24
|
+
throw ( new Error(
|
|
25
|
+
'Invalid arguments. Expected: { providerId: string; accountLabel: string }'
|
|
26
|
+
));
|
|
27
|
+
}
|
|
28
|
+
const allSessions = await authenticationService.getSessions(providerId);
|
|
29
|
+
const sessions = allSessions.filter(s => s.account.label === accountLabel);
|
|
30
|
+
const accountUsages = authenticationUsageService.readAccountUsages(providerId, accountLabel);
|
|
31
|
+
const { confirmed } = await dialogService.confirm({
|
|
32
|
+
type: Severity.Info,
|
|
33
|
+
message: accountUsages.length
|
|
34
|
+
? ( localize(
|
|
35
|
+
4335,
|
|
36
|
+
"The account '{0}' has been used by: \n\n{1}\n\n Sign out from these extensions?",
|
|
37
|
+
accountLabel,
|
|
38
|
+
( accountUsages.map(usage => usage.extensionName)).join('\n')
|
|
39
|
+
))
|
|
40
|
+
: ( localize(4336, "Sign out of '{0}'?", accountLabel)),
|
|
41
|
+
primaryButton: ( localize(4337, "&&Sign Out"))
|
|
42
|
+
});
|
|
43
|
+
if (confirmed) {
|
|
44
|
+
const removeSessionPromises = ( sessions.map(session => authenticationService.removeSession(providerId, session.id)));
|
|
45
|
+
await Promise.all(removeSessionPromises);
|
|
46
|
+
authenticationUsageService.removeAccountUsage(providerId, accountLabel);
|
|
47
|
+
authenticationAccessService.removeAllowedExtensions(providerId, accountLabel);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { SignOutOfAccountAction };
|
package/vscode/src/vs/workbench/contrib/authentication/browser/authentication.contribution.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
|
|
2
|
+
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
4
|
+
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
5
|
+
import { registerAction2 } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
|
|
6
|
+
import { CommandsRegistry } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands';
|
|
7
|
+
import { SyncDescriptor } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/descriptors';
|
|
8
|
+
import { Registry } from '@codingame/monaco-vscode-api/vscode/vs/platform/registry/common/platform';
|
|
9
|
+
import { registerWorkbenchContribution2, WorkbenchPhase } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/contributions';
|
|
10
|
+
import { SignOutOfAccountAction } from './actions/signOutOfAccountAction.js';
|
|
11
|
+
import { IBrowserWorkbenchEnvironmentService } from '@codingame/monaco-vscode-34a0ffd3-b9f5-5699-b43b-38af5732f38a-common/vscode/vs/workbench/services/environment/browser/environmentService.service';
|
|
12
|
+
import { Extensions } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures';
|
|
13
|
+
import { ManageTrustedExtensionsForAccountAction } from './actions/manageTrustedExtensionsForAccountAction.js';
|
|
14
|
+
import { ManageAccountPreferencesForExtensionAction } from './actions/manageAccountPreferencesForExtensionAction.js';
|
|
15
|
+
import { IAuthenticationUsageService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/browser/authenticationUsageService.service';
|
|
16
|
+
import { ManageAccountPreferencesForMcpServerAction } from './actions/manageAccountPreferencesForMcpServerAction.js';
|
|
17
|
+
import { ManageTrustedMcpServersForAccountAction } from './actions/manageTrustedMcpServersForAccountAction.js';
|
|
18
|
+
import { RemoveDynamicAuthenticationProvidersAction } from './actions/manageDynamicAuthenticationProvidersAction.js';
|
|
19
|
+
import { IAuthenticationQueryService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authenticationQuery.service';
|
|
20
|
+
import { IMcpRegistry } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes.service';
|
|
21
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
|
22
|
+
import { IAuthenticationService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/authentication/common/authentication.service';
|
|
23
|
+
import { Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
24
|
+
import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
|
|
25
|
+
|
|
26
|
+
const codeExchangeProxyCommand = CommandsRegistry.registerCommand('workbench.getCodeExchangeProxyEndpoints', function (accessor, _) {
|
|
27
|
+
const environmentService = accessor.get(IBrowserWorkbenchEnvironmentService);
|
|
28
|
+
return environmentService.options?.codeExchangeProxyEndpoints;
|
|
29
|
+
});
|
|
30
|
+
class AuthenticationDataRenderer extends Disposable {
|
|
31
|
+
constructor() {
|
|
32
|
+
super(...arguments);
|
|
33
|
+
this.type = 'table';
|
|
34
|
+
}
|
|
35
|
+
shouldRender(manifest) {
|
|
36
|
+
return !!manifest.contributes?.authentication;
|
|
37
|
+
}
|
|
38
|
+
render(manifest) {
|
|
39
|
+
const authentication = manifest.contributes?.authentication || [];
|
|
40
|
+
if (!authentication.length) {
|
|
41
|
+
return { data: { headers: [], rows: [] }, dispose: () => { } };
|
|
42
|
+
}
|
|
43
|
+
const headers = [
|
|
44
|
+
( localize(4338, "Label")),
|
|
45
|
+
( localize(4339, "ID")),
|
|
46
|
+
( localize(4340, "MCP Authorization Servers"))
|
|
47
|
+
];
|
|
48
|
+
const rows = ( authentication
|
|
49
|
+
.sort((a, b) => a.label.localeCompare(b.label))
|
|
50
|
+
.map(auth => {
|
|
51
|
+
return [
|
|
52
|
+
auth.label,
|
|
53
|
+
auth.id,
|
|
54
|
+
(auth.authorizationServerGlobs ?? []).join(',\n')
|
|
55
|
+
];
|
|
56
|
+
}));
|
|
57
|
+
return {
|
|
58
|
+
data: {
|
|
59
|
+
headers,
|
|
60
|
+
rows
|
|
61
|
+
},
|
|
62
|
+
dispose: () => { }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const extensionFeature = ( Registry.as(Extensions.ExtensionFeaturesRegistry)).registerExtensionFeature({
|
|
67
|
+
id: 'authentication',
|
|
68
|
+
label: ( localize(4341, "Authentication")),
|
|
69
|
+
access: {
|
|
70
|
+
canToggle: false
|
|
71
|
+
},
|
|
72
|
+
renderer: ( new SyncDescriptor(AuthenticationDataRenderer)),
|
|
73
|
+
});
|
|
74
|
+
class AuthenticationContribution extends Disposable {
|
|
75
|
+
static { this.ID = 'workbench.contrib.authentication'; }
|
|
76
|
+
constructor() {
|
|
77
|
+
super();
|
|
78
|
+
this._register(codeExchangeProxyCommand);
|
|
79
|
+
this._register(extensionFeature);
|
|
80
|
+
this._registerActions();
|
|
81
|
+
}
|
|
82
|
+
_registerActions() {
|
|
83
|
+
this._register(registerAction2(SignOutOfAccountAction));
|
|
84
|
+
this._register(registerAction2(ManageTrustedExtensionsForAccountAction));
|
|
85
|
+
this._register(registerAction2(ManageAccountPreferencesForExtensionAction));
|
|
86
|
+
this._register(registerAction2(ManageTrustedMcpServersForAccountAction));
|
|
87
|
+
this._register(registerAction2(ManageAccountPreferencesForMcpServerAction));
|
|
88
|
+
this._register(registerAction2(RemoveDynamicAuthenticationProvidersAction));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
let AuthenticationUsageContribution = class AuthenticationUsageContribution {
|
|
92
|
+
static { this.ID = 'workbench.contrib.authenticationUsage'; }
|
|
93
|
+
constructor(_authenticationUsageService) {
|
|
94
|
+
this._authenticationUsageService = _authenticationUsageService;
|
|
95
|
+
this._initializeExtensionUsageCache();
|
|
96
|
+
}
|
|
97
|
+
async _initializeExtensionUsageCache() {
|
|
98
|
+
await this._authenticationUsageService.initializeExtensionUsageCache();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
AuthenticationUsageContribution = ( __decorate([
|
|
102
|
+
( __param(0, IAuthenticationUsageService))
|
|
103
|
+
], AuthenticationUsageContribution));
|
|
104
|
+
let AuthenticationMcpContribution = class AuthenticationMcpContribution extends Disposable {
|
|
105
|
+
static { this.ID = 'workbench.contrib.authenticationMcp'; }
|
|
106
|
+
constructor(_mcpRegistry, _authenticationQueryService, _authenticationService) {
|
|
107
|
+
super();
|
|
108
|
+
this._mcpRegistry = _mcpRegistry;
|
|
109
|
+
this._authenticationQueryService = _authenticationQueryService;
|
|
110
|
+
this._authenticationService = _authenticationService;
|
|
111
|
+
this._cleanupRemovedMcpServers();
|
|
112
|
+
this._register(autorun(reader => {
|
|
113
|
+
this._mcpRegistry.collections.read(reader);
|
|
114
|
+
queueMicrotask(() => this._cleanupRemovedMcpServers());
|
|
115
|
+
}));
|
|
116
|
+
this._register(Event.any(this._authenticationService.onDidChangeDeclaredProviders, this._authenticationService.onDidRegisterAuthenticationProvider)(() => this._cleanupRemovedMcpServers()));
|
|
117
|
+
}
|
|
118
|
+
_cleanupRemovedMcpServers() {
|
|
119
|
+
const currentServerIds = ( new Set(( this._mcpRegistry.collections.get().flatMap(c => c.serverDefinitions.get()).map(s => s.id))));
|
|
120
|
+
const providerIds = this._authenticationQueryService.getProviderIds();
|
|
121
|
+
for (const providerId of providerIds) {
|
|
122
|
+
this._authenticationQueryService.provider(providerId).forEachAccount(account => {
|
|
123
|
+
account.mcpServers().forEach(server => {
|
|
124
|
+
if (!( currentServerIds.has(server.mcpServerId))) {
|
|
125
|
+
server.removeUsage();
|
|
126
|
+
server.setAccessAllowed(false);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
AuthenticationMcpContribution = ( __decorate([
|
|
134
|
+
( __param(0, IMcpRegistry)),
|
|
135
|
+
( __param(1, IAuthenticationQueryService)),
|
|
136
|
+
( __param(2, IAuthenticationService))
|
|
137
|
+
], AuthenticationMcpContribution));
|
|
138
|
+
registerWorkbenchContribution2(AuthenticationContribution.ID, AuthenticationContribution, WorkbenchPhase.AfterRestored);
|
|
139
|
+
registerWorkbenchContribution2(AuthenticationUsageContribution.ID, AuthenticationUsageContribution, WorkbenchPhase.Eventually);
|
|
140
|
+
registerWorkbenchContribution2(AuthenticationMcpContribution.ID, AuthenticationMcpContribution, WorkbenchPhase.Eventually);
|
package/vscode/src/vs/workbench/services/authentication/browser/authenticationAccessService.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
3
|
import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
4
4
|
import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
5
|
+
import { ExtensionIdentifier } from '@codingame/monaco-vscode-api/vscode/vs/platform/extensions/common/extensions';
|
|
5
6
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/extensions';
|
|
6
7
|
import { IProductService } from '@codingame/monaco-vscode-api/vscode/vs/platform/product/common/productService.service';
|
|
7
8
|
import { StorageScope, StorageTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage';
|
|
@@ -18,16 +19,17 @@ let AuthenticationAccessService = class AuthenticationAccessService extends Disp
|
|
|
18
19
|
}
|
|
19
20
|
isAccessAllowed(providerId, accountName, extensionId) {
|
|
20
21
|
const trustedExtensionAuthAccess = this._productService.trustedExtensionAuthAccess;
|
|
22
|
+
const extensionKey = ExtensionIdentifier.toKey(extensionId);
|
|
21
23
|
if (Array.isArray(trustedExtensionAuthAccess)) {
|
|
22
|
-
if (trustedExtensionAuthAccess.includes(
|
|
24
|
+
if (trustedExtensionAuthAccess.includes(extensionKey)) {
|
|
23
25
|
return true;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
|
-
else if (trustedExtensionAuthAccess?.[providerId]?.includes(
|
|
28
|
+
else if (trustedExtensionAuthAccess?.[providerId]?.includes(extensionKey)) {
|
|
27
29
|
return true;
|
|
28
30
|
}
|
|
29
31
|
const allowList = this.readAllowedExtensions(providerId, accountName);
|
|
30
|
-
const extensionData = allowList.find(extension => extension.id ===
|
|
32
|
+
const extensionData = allowList.find(extension => extension.id === extensionKey);
|
|
31
33
|
if (!extensionData) {
|
|
32
34
|
return undefined;
|
|
33
35
|
}
|
|
@@ -44,20 +46,51 @@ let AuthenticationAccessService = class AuthenticationAccessService extends Disp
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
catch (err) { }
|
|
49
|
+
const trustedExtensionAuthAccess = this._productService.trustedExtensionAuthAccess;
|
|
50
|
+
const trustedExtensionIds =
|
|
51
|
+
Array.isArray(trustedExtensionAuthAccess)
|
|
52
|
+
? trustedExtensionAuthAccess
|
|
53
|
+
: typeof trustedExtensionAuthAccess === 'object'
|
|
54
|
+
? trustedExtensionAuthAccess[providerId] ?? []
|
|
55
|
+
: [];
|
|
56
|
+
for (const extensionId of trustedExtensionIds) {
|
|
57
|
+
const extensionKey = ExtensionIdentifier.toKey(extensionId);
|
|
58
|
+
const existingExtension = trustedExtensions.find(extension => extension.id === extensionKey);
|
|
59
|
+
if (!existingExtension) {
|
|
60
|
+
trustedExtensions.push({
|
|
61
|
+
id: extensionKey,
|
|
62
|
+
name: extensionId,
|
|
63
|
+
allowed: true,
|
|
64
|
+
trusted: true
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
existingExtension.allowed = true;
|
|
69
|
+
existingExtension.trusted = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
47
72
|
return trustedExtensions;
|
|
48
73
|
}
|
|
49
74
|
updateAllowedExtensions(providerId, accountName, extensions) {
|
|
50
75
|
const allowList = this.readAllowedExtensions(providerId, accountName);
|
|
51
76
|
for (const extension of extensions) {
|
|
52
|
-
const
|
|
77
|
+
const extensionKey = ExtensionIdentifier.toKey(extension.id);
|
|
78
|
+
const index = allowList.findIndex(e => e.id === extensionKey);
|
|
53
79
|
if (index === -1) {
|
|
54
|
-
allowList.push(
|
|
80
|
+
allowList.push({
|
|
81
|
+
...extension,
|
|
82
|
+
id: extensionKey
|
|
83
|
+
});
|
|
55
84
|
}
|
|
56
85
|
else {
|
|
57
86
|
allowList[index].allowed = extension.allowed;
|
|
87
|
+
if (extension.name && extension.name !== extensionKey && allowList[index].name !== extension.name) {
|
|
88
|
+
allowList[index].name = extension.name;
|
|
89
|
+
}
|
|
58
90
|
}
|
|
59
91
|
}
|
|
60
|
-
|
|
92
|
+
const userManagedExtensions = allowList.filter(extension => !extension.trusted);
|
|
93
|
+
this._storageService.store(`${providerId}-${accountName}`, JSON.stringify(userManagedExtensions), StorageScope.APPLICATION, StorageTarget.USER);
|
|
61
94
|
this._onDidChangeExtensionSessionAccess.fire({ providerId, accountName });
|
|
62
95
|
}
|
|
63
96
|
removeAllowedExtensions(providerId, accountName) {
|