make state of trusted extensions correct in storage. Fixes #118486

This commit is contained in:
Tyler Leonhardt 2021-06-11 17:21:37 -07:00
parent 53350bc666
commit 66ecd8f6a8
No known key found for this signature in database
GPG key ID: 1BC2B6244363E77E
3 changed files with 164 additions and 2 deletions

View file

@ -17,6 +17,12 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { fromNow } from 'vs/base/common/date';
import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
interface TrustedExtensionsQuickPickItem {
label: string;
description: string;
extension: AllowedExtension;
}
export class MainThreadAuthenticationProvider extends Disposable {
constructor(
private readonly _proxy: ExtHostAuthenticationShape,
@ -38,7 +44,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
return;
}
const quickPick = this.quickInputService.createQuickPick<{ label: string, description: string, extension: AllowedExtension }>();
const quickPick = this.quickInputService.createQuickPick<TrustedExtensionsQuickPickItem>();
quickPick.canSelectMany = true;
quickPick.customButton = true;
quickPick.customLabel = nls.localize('manageTrustedExtensions.cancel', 'Cancel');
@ -60,12 +66,23 @@ export class MainThreadAuthenticationProvider extends Disposable {
quickPick.placeholder = nls.localize('manageExensions', "Choose which extensions can access this account");
quickPick.onDidAccept(() => {
const updatedAllowedList = quickPick.selectedItems.map(item => item.extension);
const updatedAllowedList = quickPick.items
.map(i => (i as TrustedExtensionsQuickPickItem).extension);
this.storageService.store(`${this.id}-${accountName}`, JSON.stringify(updatedAllowedList), StorageScope.GLOBAL, StorageTarget.USER);
quickPick.dispose();
});
quickPick.onDidChangeSelection((changed) => {
quickPick.items.forEach(item => {
if ((item as TrustedExtensionsQuickPickItem).extension) {
(item as TrustedExtensionsQuickPickItem).extension.allowed = false;
}
});
changed.forEach((item) => item.extension.allowed = true);
});
quickPick.onDidHide(() => {
quickPick.dispose();
});

View file

@ -0,0 +1,126 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { AuthenticationProviderInformation } from 'vs/editor/common/modes';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { IQuickInputHideEvent, IQuickInputService, IQuickPickDidAcceptEvent } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { MainThreadAuthentication } from 'vs/workbench/api/browser/mainThreadAuthentication';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
import { AuthenticationService, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
import { ExtensionHostKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { TestRemoteAgentService } from 'vs/workbench/services/remote/test/common/testServices';
import { TestQuickInputService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestActivityService, TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
function createSession(id: string = '1234', scope: string[] = []) {
return {
accessToken: '1234',
account: {
id: 'test@test.com',
label: 'Test Person'
},
id: id,
scopes: scope
};
}
class AuthQuickPick {
private listener: ((e: IQuickPickDidAcceptEvent) => any) | undefined;
public items = [];
public get selectedItems(): string[] {
return this.items;
}
onDidAccept(listener: (e: IQuickPickDidAcceptEvent) => any) {
this.listener = listener;
}
onDidHide(listener: (e: IQuickInputHideEvent) => any) {
}
dispose() {
}
show() {
this.listener!({
inBackground: false
});
}
}
class AuthTestQuickInputService extends TestQuickInputService {
override createQuickPick() {
return <any>new AuthQuickPick();
}
}
suite('MainThreadAuthentication', () => {
let mainThreadAuthentication: MainThreadAuthentication;
suiteSetup(async () => {
// extHostContext: IExtHostContext,
const services = new ServiceCollection();
const dialogService = new TestDialogService();
const storageService = new TestStorageService();
const quickInputService = new AuthTestQuickInputService();
const extensionService = new TestExtensionService();
const activityService = new TestActivityService();
const remoteAgentService = new TestRemoteAgentService();
services.set(IDialogService, dialogService);
services.set(IStorageService, storageService);
services.set(INotificationService, new TestNotificationService());
services.set(IQuickInputService, quickInputService);
services.set(IExtensionService, extensionService);
services.set(IActivityService, activityService);
services.set(IRemoteAgentService, remoteAgentService);
const instaService = new InstantiationService(services);
services.set(IAuthenticationService, instaService.createInstance(AuthenticationService));
mainThreadAuthentication = instaService.createInstance(MainThreadAuthentication,
new class implements IExtHostContext {
remoteAuthority = '';
extensionHostKind = ExtensionHostKind.LocalProcess;
assertRegistered() { }
set(v: any): any { return null; }
getProxy(): any {
return {
$getSessions(id: string, scopes: string[]) {
return Promise.resolve([createSession(id, scopes)]);
},
$createSession(id: string, scopes: string[]) {
return Promise.resolve(createSession(id, scopes));
},
$removeSession(id: string, sessionId: string) { return Promise.resolve(); },
$onDidChangeAuthenticationSessions(id: string, label: string) { return Promise.resolve(); },
$onDidChangeAuthenticationProviders(added: AuthenticationProviderInformation[], removed: AuthenticationProviderInformation[]) { return Promise.resolve(); },
$setProviders(providers: AuthenticationProviderInformation[]) { return Promise.resolve(); }
};
}
drain(): any { return null; }
});
await mainThreadAuthentication.$registerAuthenticationProvider('test', 'test provider', true);
});
suiteTeardown(() => {
mainThreadAuthentication.$unregisterAuthenticationProvider('test');
mainThreadAuthentication.dispose();
});
test('Can get a session', async () => {
const session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false });
assert.strictEqual(session?.id, 'test');
assert.strictEqual(session?.scopes[0], 'foo');
});
});

View file

@ -22,6 +22,7 @@ import { IFileStatWithMetadata } from 'vs/platform/files/common/files';
import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
import { CancellationToken } from 'vs/base/common/cancellation';
import product from 'vs/platform/product/common/product';
import { IActivity, IActivityService } from 'vs/workbench/services/activity/common/activity';
export class TestTextResourcePropertiesService implements ITextResourcePropertiesService {
@ -214,3 +215,21 @@ export interface Ctor<T> {
export class TestExtensionService extends NullExtensionService { }
export const TestProductService = { _serviceBrand: undefined, ...product };
export class TestActivityService implements IActivityService {
_serviceBrand: undefined;
showViewContainerActivity(viewContainerId: string, badge: IActivity): IDisposable {
return this;
}
showViewActivity(viewId: string, badge: IActivity): IDisposable {
return this;
}
showAccountsActivity(activity: IActivity): IDisposable {
return this;
}
showGlobalActivity(activity: IActivity): IDisposable {
return this;
}
dispose() { }
}