diff --git a/src/vs/base/test/node/keytar.test.ts b/src/vs/base/test/node/keytar.test.ts index 96ca335e940..53f1c31a1a6 100644 --- a/src/vs/base/test/node/keytar.test.ts +++ b/src/vs/base/test/node/keytar.test.ts @@ -18,6 +18,8 @@ suite('Keytar', () => { const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`; try { await keytar.setPassword(name, 'foo', 'bar'); + assert.equal(await keytar.findPassword(name), 'bar'); + assert.equal((await keytar.findCredentials(name)).length, 1); assert.equal(await keytar.getPassword(name, 'foo'), 'bar'); await keytar.deletePassword(name, 'foo'); assert.equal(await keytar.getPassword(name, 'foo'), undefined); diff --git a/src/vs/workbench/api/browser/mainThreadKeytar.ts b/src/vs/workbench/api/browser/mainThreadKeytar.ts index f07b7688801..ddcf676a10c 100644 --- a/src/vs/workbench/api/browser/mainThreadKeytar.ts +++ b/src/vs/workbench/api/browser/mainThreadKeytar.ts @@ -31,6 +31,10 @@ export class MainThreadKeytar implements MainThreadKeytarShape { return this._credentialsService.findPassword(service); } + async $findCredentials(service: string): Promise> { + return this._credentialsService.findCredentials(service); + } + dispose(): void { // } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 4157cf87e78..a6ac9b8086c 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -263,6 +263,7 @@ export interface MainThreadKeytarShape extends IDisposable { $setPassword(service: string, account: string, password: string): Promise; $deletePassword(service: string, account: string): Promise; $findPassword(service: string): Promise; + $findCredentials(service: string): Promise>; } export interface IRegExpDto { diff --git a/src/vs/workbench/api/common/extHostRequireInterceptor.ts b/src/vs/workbench/api/common/extHostRequireInterceptor.ts index 46866f7db08..9e4cdb09361 100644 --- a/src/vs/workbench/api/common/extHostRequireInterceptor.ts +++ b/src/vs/workbench/api/common/extHostRequireInterceptor.ts @@ -129,6 +129,7 @@ interface IKeytarModule { setPassword(service: string, account: string, password: string): Promise; deletePassword(service: string, account: string): Promise; findPassword(service: string): Promise; + findCredentials(service: string): Promise>; } class KeytarNodeModuleFactory implements INodeModuleFactory { @@ -169,6 +170,9 @@ class KeytarNodeModuleFactory implements INodeModuleFactory { }, findPassword: (service: string): Promise => { return mainThreadKeytar.$findPassword(service); + }, + findCredentials(service: string): Promise> { + return mainThreadKeytar.$findCredentials(service); } }; } diff --git a/src/vs/workbench/services/credentials/browser/credentialsService.ts b/src/vs/workbench/services/credentials/browser/credentialsService.ts index b7613b9c23c..4abc7eae62b 100644 --- a/src/vs/workbench/services/credentials/browser/credentialsService.ts +++ b/src/vs/workbench/services/credentials/browser/credentialsService.ts @@ -13,6 +13,7 @@ export interface ICredentialsProvider { setPassword(service: string, account: string, password: string): Promise; deletePassword(service: string, account: string): Promise; findPassword(service: string): Promise; + findCredentials(service: string): Promise>; } export class BrowserCredentialsService implements ICredentialsService { @@ -29,21 +30,25 @@ export class BrowserCredentialsService implements ICredentialsService { } } - async getPassword(service: string, account: string): Promise { + getPassword(service: string, account: string): Promise { return this.credentialsProvider.getPassword(service, account); } - async setPassword(service: string, account: string, password: string): Promise { + setPassword(service: string, account: string, password: string): Promise { return this.credentialsProvider.setPassword(service, account, password); } - async deletePassword(service: string, account: string): Promise { + deletePassword(service: string, account: string): Promise { return this.credentialsProvider.deletePassword(service, account); } - async findPassword(service: string): Promise { + findPassword(service: string): Promise { return this.credentialsProvider.findPassword(service); } + + findCredentials(service: string): Promise> { + return this.credentialsProvider.findCredentials(service); + } } interface ICredential { @@ -127,6 +132,12 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider { async findPassword(service: string): Promise { return this.doGetPassword(service); } + + async findCredentials(service: string): Promise> { + return this.credentials + .filter(credential => credential.service === service) + .map(({ account, password }) => ({ account, password })); + } } registerSingleton(ICredentialsService, BrowserCredentialsService, true); diff --git a/src/vs/workbench/services/credentials/common/credentials.ts b/src/vs/workbench/services/credentials/common/credentials.ts index 8fa520c374e..3aab67233a1 100644 --- a/src/vs/workbench/services/credentials/common/credentials.ts +++ b/src/vs/workbench/services/credentials/common/credentials.ts @@ -15,4 +15,5 @@ export interface ICredentialsService { setPassword(service: string, account: string, password: string): Promise; deletePassword(service: string, account: string): Promise; findPassword(service: string): Promise; + findCredentials(service: string): Promise>; } diff --git a/src/vs/workbench/services/credentials/node/credentialsService.ts b/src/vs/workbench/services/credentials/node/credentialsService.ts index 1361f169be3..575517e9c6e 100644 --- a/src/vs/workbench/services/credentials/node/credentialsService.ts +++ b/src/vs/workbench/services/credentials/node/credentialsService.ts @@ -8,13 +8,7 @@ import { IdleValue } from 'vs/base/common/async'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -type KeytarModule = { - getPassword(service: string, account: string): Promise; - setPassword(service: string, account: string, password: string): Promise; - deletePassword(service: string, account: string): Promise; - findPassword(service: string): Promise; -}; - +type KeytarModule = typeof import('keytar'); export class KeytarCredentialsService implements ICredentialsService { _serviceBrand!: ServiceIdentifier; @@ -40,6 +34,11 @@ export class KeytarCredentialsService implements ICredentialsService { const keytar = await this._keytar.getValue(); return keytar.findPassword(service); } + + async findCredentials(service: string): Promise> { + const keytar = await this._keytar.getValue(); + return keytar.findCredentials(service); + } } registerSingleton(ICredentialsService, KeytarCredentialsService, true);