Skip to content

Commit d0026f3

Browse files
Introduce cool new Query Service for Auth stuff (#252023)
Nice cleanup with tests
1 parent e55ba96 commit d0026f3

File tree

6 files changed

+2710
-55
lines changed

6 files changed

+2710
-55
lines changed

src/vs/workbench/contrib/authentication/browser/actions/manageAccountPreferencesForMcpServerAction.ts

Lines changed: 38 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ import { IDialogService } from '../../../../../platform/dialogs/common/dialogs.j
1111
import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
1212
import { ILogService } from '../../../../../platform/log/common/log.js';
1313
import { IQuickInputService, IQuickPick, IQuickPickItem, QuickPickInput } from '../../../../../platform/quickinput/common/quickInput.js';
14-
import { AuthenticationSessionAccount, IAuthenticationService, INTERNAL_AUTH_PROVIDER_PREFIX } from '../../../../services/authentication/common/authentication.js';
15-
import { IAuthenticationMcpService } from '../../../../services/authentication/browser/authenticationMcpService.js';
14+
import { AuthenticationSessionAccount, IAuthenticationService } from '../../../../services/authentication/common/authentication.js';
15+
import { IAuthenticationQueryService } from '../../../../services/authentication/common/authenticationQuery.js';
1616
import { IMcpService } from '../../../mcp/common/mcpTypes.js';
17-
import { IAuthenticationMcpUsage, IAuthenticationMcpUsageService } from '../../../../services/authentication/browser/authenticationMcpUsageService.js';
1817

1918
export class ManageAccountPreferencesForMcpServerAction extends Action2 {
2019
constructor() {
@@ -35,7 +34,7 @@ type AccountPreferenceQuickPickItem = NewAccountQuickPickItem | ExistingAccountQ
3534

3635
interface NewAccountQuickPickItem extends IQuickPickItem {
3736
account?: undefined;
38-
scopes: string[];
37+
scopes: readonly string[];
3938
providerId: string;
4039
}
4140

@@ -50,8 +49,7 @@ class ManageAccountPreferenceForMcpServerActionImpl {
5049
@IAuthenticationService private readonly _authenticationService: IAuthenticationService,
5150
@IQuickInputService private readonly _quickInputService: IQuickInputService,
5251
@IDialogService private readonly _dialogService: IDialogService,
53-
@IAuthenticationMcpUsageService private readonly _authenticationUsageService: IAuthenticationMcpUsageService,
54-
@IAuthenticationMcpService private readonly _authenticationMcpServersService: IAuthenticationMcpService,
52+
@IAuthenticationQueryService private readonly _authenticationQueryService: IAuthenticationQueryService,
5553
@IMcpService private readonly _mcpService: IMcpService,
5654
@ILogService private readonly _logService: ILogService
5755
) { }
@@ -65,66 +63,50 @@ class ManageAccountPreferenceForMcpServerActionImpl {
6563
throw new Error(`No MCP server with id ${mcpServerId}`);
6664
}
6765

68-
const providerIds = new Array<string>();
69-
const providerIdToAccounts = new Map<string, ReadonlyArray<AuthenticationSessionAccount & { lastUsed?: number }>>();
70-
if (providerId) {
71-
providerIds.push(providerId);
72-
providerIdToAccounts.set(providerId, await this._authenticationService.getAccounts(providerId));
73-
} else {
74-
for (const providerId of this._authenticationService.getProviderIds()) {
75-
if (providerId.startsWith(INTERNAL_AUTH_PROVIDER_PREFIX)) {
76-
// Don't show internal providers
77-
continue;
78-
}
79-
const accounts = await this._authenticationService.getAccounts(providerId);
80-
for (const account of accounts) {
81-
const usage = this._authenticationUsageService.readAccountUsages(providerId, account.label).find(u => u.mcpServerId === mcpServerId);
82-
if (usage) {
83-
providerIds.push(providerId);
84-
providerIdToAccounts.set(providerId, accounts);
85-
break;
66+
if (!providerId) {
67+
// Use the query service's MCP server-centric approach to find providers that have been used
68+
const mcpServerQuery = this._authenticationQueryService.mcpServer(mcpServerId);
69+
const providersWithAccess = await mcpServerQuery.getProvidersWithAccess();
70+
if (!providersWithAccess.length) {
71+
await this._dialogService.info(localize('noAccountUsage', "This MCP server has not used any accounts yet."));
72+
return;
73+
}
74+
providerId = providersWithAccess[0]; // Default to the first provider
75+
if (providersWithAccess.length > 1) {
76+
const result = await this._quickInputService.pick(
77+
providersWithAccess.map(providerId => ({
78+
label: this._authenticationService.getProvider(providerId).label,
79+
id: providerId,
80+
})),
81+
{
82+
placeHolder: localize('selectProvider', "Select an authentication provider to manage account preferences for"),
83+
title: localize('pickAProviderTitle', "Manage MCP Server Account Preferences")
8684
}
85+
);
86+
if (!result) {
87+
return; // User cancelled
8788
}
89+
providerId = result.id;
8890
}
8991
}
9092

91-
let chosenProviderId: string | undefined = providerIds[0];
92-
if (providerIds.length > 1) {
93-
const result = await this._quickInputService.pick(
94-
providerIds.map(providerId => ({
95-
label: this._authenticationService.getProvider(providerId).label,
96-
id: providerId,
97-
})),
98-
{
99-
placeHolder: localize('selectProvider', "Select an authentication provider to manage account preferences for"),
100-
title: localize('pickAProviderTitle', "Manage MCP Server Account Preferences")
101-
}
102-
);
103-
chosenProviderId = result?.id;
104-
}
105-
106-
if (!chosenProviderId) {
107-
await this._dialogService.info(localize('noAccountUsage', "This MCP server has not used any accounts yet."));
108-
return;
109-
}
110-
111-
const currentAccountNamePreference = this._authenticationMcpServersService.getAccountPreference(mcpServerId, chosenProviderId);
112-
const accounts = providerIdToAccounts.get(chosenProviderId)!;
113-
const items: Array<QuickPickInput<AccountPreferenceQuickPickItem>> = this._getItems(accounts, chosenProviderId, currentAccountNamePreference);
93+
// Only fetch accounts for the chosen provider
94+
const accounts = await this._authenticationService.getAccounts(providerId);
95+
const currentAccountNamePreference = this._authenticationQueryService.provider(providerId).mcpServer(mcpServerId).getPreferredAccount();
96+
const items: Array<QuickPickInput<AccountPreferenceQuickPickItem>> = this._getItems(accounts, providerId, currentAccountNamePreference);
11497

11598
// If the provider supports multiple accounts, add an option to use a new account
116-
const provider = this._authenticationService.getProvider(chosenProviderId);
99+
const provider = this._authenticationService.getProvider(providerId);
117100
if (provider.supportsMultipleAccounts) {
118101
// Get the last used scopes for the last used account. This will be used to pre-fill the scopes when adding a new account.
119102
// If there's no scopes, then don't add this option.
120103
const lastUsedScopes = accounts
121-
.flatMap(account => this._authenticationUsageService.readAccountUsages(chosenProviderId!, account.label).find(u => u.mcpServerId === mcpServerId))
122-
.filter((usage): usage is IAuthenticationMcpUsage => !!usage)
123-
.sort((a, b) => b.lastUsed - a.lastUsed)?.[0]?.scopes;
104+
.flatMap(account => this._authenticationQueryService.provider(providerId).account(account.label).mcpServer(mcpServerId).getUsage())
105+
.sort((a, b) => b.lastUsed - a.lastUsed)[0]?.scopes; // Sort by timestamp and take the most recent
124106
if (lastUsedScopes) {
125107
items.push({ type: 'separator' });
126108
items.push({
127-
providerId: chosenProviderId,
109+
providerId: providerId,
128110
scopes: lastUsedScopes,
129111
label: localize('use new account', "Use a new account..."),
130112
});
@@ -186,7 +168,7 @@ class ManageAccountPreferenceForMcpServerActionImpl {
186168
let account: AuthenticationSessionAccount;
187169
if (!item.account) {
188170
try {
189-
const session = await this._authenticationService.createSession(item.providerId, item.scopes);
171+
const session = await this._authenticationService.createSession(item.providerId, [...item.scopes]);
190172
account = session.account;
191173
} catch (e) {
192174
this._logService.error(e);
@@ -196,12 +178,13 @@ class ManageAccountPreferenceForMcpServerActionImpl {
196178
account = item.account;
197179
}
198180
const providerId = item.providerId;
199-
const currentAccountName = this._authenticationMcpServersService.getAccountPreference(mcpServerId, providerId);
181+
const mcpQuery = this._authenticationQueryService.provider(providerId).mcpServer(mcpServerId);
182+
const currentAccountName = mcpQuery.getPreferredAccount();
200183
if (currentAccountName === account.label) {
201184
// This account is already the preferred account
202185
continue;
203186
}
204-
this._authenticationMcpServersService.updateAccountPreference(mcpServerId, providerId, account);
187+
mcpQuery.setPreferredAccount(account);
205188
}
206189
}
207190
}

0 commit comments

Comments
 (0)