credentialsService.ts 3.9 KB
Newer Older
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6
import { ICredentialsService, ICredentialsProvider, ICredentialsChangeEvent } from 'vs/workbench/services/credentials/common/credentials';
7 8
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
9
import { Emitter } from 'vs/base/common/event';
10
import { Disposable } from 'vs/base/common/lifecycle';
11

12
export class BrowserCredentialsService extends Disposable implements ICredentialsService {
13

14
	declare readonly _serviceBrand: undefined;
15

16
	private _onDidChangePassword = this._register(new Emitter<ICredentialsChangeEvent>());
17
	readonly onDidChangePassword = this._onDidChangePassword.event;
18

19 20 21
	private credentialsProvider: ICredentialsProvider;

	constructor(@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService) {
22 23
		super();

24 25 26
		if (environmentService.options && environmentService.options.credentialsProvider) {
			this.credentialsProvider = environmentService.options.credentialsProvider;
		} else {
27
			this.credentialsProvider = new InMemoryCredentialsProvider();
28 29 30
		}
	}

31
	getPassword(service: string, account: string): Promise<string | null> {
32 33 34
		return this.credentialsProvider.getPassword(service, account);
	}

35 36
	async setPassword(service: string, account: string, password: string): Promise<void> {
		await this.credentialsProvider.setPassword(service, account, password);
37

38
		this._onDidChangePassword.fire({ service, account });
39 40
	}

41
	deletePassword(service: string, account: string): Promise<boolean> {
42 43
		const didDelete = this.credentialsProvider.deletePassword(service, account);
		if (didDelete) {
44
			this._onDidChangePassword.fire({ service, account });
45 46 47
		}

		return didDelete;
48 49
	}

50
	findPassword(service: string): Promise<string | null> {
51 52
		return this.credentialsProvider.findPassword(service);
	}
53

54
	findCredentials(service: string): Promise<Array<{ account: string, password: string; }>> {
55 56
		return this.credentialsProvider.findCredentials(service);
	}
57 58 59 60 61 62 63 64
}

interface ICredential {
	service: string;
	account: string;
	password: string;
}

65
class InMemoryCredentialsProvider implements ICredentialsProvider {
66

67
	private credentials: ICredential[] = [];
68 69

	async getPassword(service: string, account: string): Promise<string | null> {
70
		const credential = this.doFindPassword(service, account);
71

72
		return credential ? credential.password : null;
73 74 75 76 77 78 79 80
	}

	async setPassword(service: string, account: string, password: string): Promise<void> {
		this.deletePassword(service, account);
		this.credentials.push({ service, account, password });
	}

	async deletePassword(service: string, account: string): Promise<boolean> {
81 82 83 84
		const credential = this.doFindPassword(service, account);
		if (credential) {
			this.credentials = this.credentials.splice(this.credentials.indexOf(credential), 1);
		}
85

86 87
		return !!credential;
	}
88

89 90
	async findPassword(service: string): Promise<string | null> {
		const credential = this.doFindPassword(service);
91

92 93
		return credential ? credential.password : null;
	}
94

95
	private doFindPassword(service: string, account?: string): ICredential | undefined {
96
		return this.credentials.find(credential =>
97
			credential.service === service && (typeof account !== 'string' || credential.account === account));
98
	}
99

100
	async findCredentials(service: string): Promise<Array<{ account: string, password: string; }>> {
101 102 103 104
		return this.credentials
			.filter(credential => credential.service === service)
			.map(({ account, password }) => ({ account, password }));
	}
105 106 107
}

registerSingleton(ICredentialsService, BrowserCredentialsService, true);