diff --git a/src/vs/platform/auth/common/auth.ts b/src/vs/platform/auth/common/auth.ts new file mode 100644 index 00000000000..729e3f07665 --- /dev/null +++ b/src/vs/platform/auth/common/auth.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { Event } from 'vs/base/common/event'; + +export const enum AuthTokenStatus { + Unavailable = 'Unavailable', + Available = 'Available' +} + +export const IAuthTokenService = createDecorator('IAuthTokenService'); + +export interface IAuthTokenService { + _serviceBrand: undefined; + + readonly status: AuthTokenStatus; + readonly onDidChangeStatus: Event; + + getToken(): Promise; + updateToken(token: string): Promise; + refreshToken(): Promise; + deleteToken(): Promise; + +} + diff --git a/src/vs/platform/auth/common/authTokenIpc.ts b/src/vs/platform/auth/common/authTokenIpc.ts new file mode 100644 index 00000000000..a5c78c4a8dd --- /dev/null +++ b/src/vs/platform/auth/common/authTokenIpc.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IServerChannel } from 'vs/base/parts/ipc/common/ipc'; +import { Event } from 'vs/base/common/event'; +import { IAuthTokenService } from 'vs/platform/auth/common/auth'; + +export class AuthTokenChannel implements IServerChannel { + + constructor(private readonly service: IAuthTokenService) { } + + listen(_: unknown, event: string): Event { + switch (event) { + case 'onDidChangeStatus': return this.service.onDidChangeStatus; + } + throw new Error(`Event not found: ${event}`); + } + + call(context: any, command: string, args?: any): Promise { + switch (command) { + case '_getInitialStatus': return Promise.resolve(this.service.status); + case 'getToken': return this.service.getToken(); + case 'updateToken': return this.service.updateToken(args[0]); + case 'refreshToken': return this.service.refreshToken(); + case 'deleteToken': return this.service.deleteToken(); + } + throw new Error('Invalid call'); + } +} diff --git a/src/vs/platform/auth/common/authTokenService.ts b/src/vs/platform/auth/common/authTokenService.ts new file mode 100644 index 00000000000..d6b38fcbb4a --- /dev/null +++ b/src/vs/platform/auth/common/authTokenService.ts @@ -0,0 +1,54 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event, Emitter } from 'vs/base/common/event'; +import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth'; +import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; +import { Disposable } from 'vs/base/common/lifecycle'; + +const SERVICE_NAME = 'settingsSync'; +const ACCOUNT = 'Test'; + +export class AuthTokenService extends Disposable implements IAuthTokenService { + _serviceBrand: undefined; + + private _status: AuthTokenStatus = AuthTokenStatus.Unavailable; + get status(): AuthTokenStatus { return this._status; } + private _onDidChangeStatus: Emitter = this._register(new Emitter()); + readonly onDidChangeStatus: Event = this._onDidChangeStatus.event; + + constructor( + @ICredentialsService private readonly credentialsService: ICredentialsService, + ) { + super(); + } + + getToken(): Promise { + return this.credentialsService.getPassword(SERVICE_NAME, ACCOUNT); + } + + async updateToken(token: string): Promise { + await this.credentialsService.setPassword(SERVICE_NAME, ACCOUNT, token); + this.setStatus(AuthTokenStatus.Available); + } + + async refreshToken(): Promise { + await this.deleteToken(); + } + + async deleteToken(): Promise { + await this.credentialsService.deletePassword(SERVICE_NAME, ACCOUNT); + this.setStatus(AuthTokenStatus.Unavailable); + } + + private setStatus(status: AuthTokenStatus): void { + if (this._status !== status) { + this._status = status; + this._onDidChangeStatus.fire(status); + } + } + +} + diff --git a/src/vs/platform/credentials/common/credentials.ts b/src/vs/platform/credentials/common/credentials.ts new file mode 100644 index 00000000000..6fcb7dffaa0 --- /dev/null +++ b/src/vs/platform/credentials/common/credentials.ts @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const ICredentialsService = createDecorator('ICredentialsService'); + +export interface ICredentialsService { + + _serviceBrand: undefined; + + getPassword(service: string, account: string): Promise; + 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/authToken/electron-browser/authTokenService.ts b/src/vs/workbench/services/authToken/electron-browser/authTokenService.ts new file mode 100644 index 00000000000..d6b995d830d --- /dev/null +++ b/src/vs/workbench/services/authToken/electron-browser/authTokenService.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IChannel } from 'vs/base/parts/ipc/common/ipc'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth'; + +export class AuthTokenService extends Disposable implements IAuthTokenService { + + _serviceBrand: undefined; + + private readonly channel: IChannel; + + private _status: AuthTokenStatus = AuthTokenStatus.Unavailable; + get status(): AuthTokenStatus { return this._status; } + private _onDidChangeStatus: Emitter = this._register(new Emitter()); + readonly onDidChangeStatus: Event = this._onDidChangeStatus.event; + + constructor( + @ISharedProcessService sharedProcessService: ISharedProcessService + ) { + super(); + this.channel = sharedProcessService.getChannel('authToken'); + this.channel.call('_getInitialStatus').then(status => { + this.updateStatus(status); + this._register(this.channel.listen('onDidChangeStatus')(status => this.updateStatus(status))); + }); + } + + getToken(): Promise { + return this.channel.call('getToken'); + } + + updateToken(token: string): Promise { + return this.channel.call('updateToken', [token]); + } + + refreshToken(): Promise { + return this.channel.call('getToken'); + } + + deleteToken(): Promise { + return this.channel.call('deleteToken'); + } + + private async updateStatus(status: AuthTokenStatus): Promise { + this._status = status; + this._onDidChangeStatus.fire(status); + } + +} + +registerSingleton(IAuthTokenService, AuthTokenService);