/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { AppContext } from '../appContext'; import { SqlOpsDataClient, ISqlOpsFeature, SqlOpsFeature } from 'dataprotocol-client'; import * as Utils from '../utils'; import { ClientCapabilities, RPCMessageType, ServerCapabilities } from 'vscode-languageclient'; import * as Contracts from './contracts'; import { Disposable, SecretStorage } from 'vscode'; import * as azdata from 'azdata'; import * as UUID from 'vscode-languageclient/lib/utils/uuid'; export class SqlCredentialService extends SqlOpsFeature { private static readonly messagesTypes: RPCMessageType[] = [ Contracts.DeleteCredentialRequest.type, Contracts.SaveCredentialRequest.type, Contracts.ReadCredentialRequest.type ]; public static asFeature(context: AppContext): ISqlOpsFeature { return class extends SqlCredentialService { private _secretStorage: SecretStorage; constructor(client: SqlOpsDataClient) { super(context, client); this._secretStorage = context.extensionContext.secrets; } override fillClientCapabilities(capabilities: ClientCapabilities): void { Utils.ensure(Utils.ensure(capabilities, 'credentials')!, 'credentials')!.dynamicRegistration = true; } override async initialize(capabilities: ServerCapabilities): Promise { this.register(this.messages, { id: UUID.generateUuid(), registerOptions: undefined }); } protected override registerProvider(options: any): Disposable { let readCredential = async (credentialId: string): Promise => { if (Utils.isLinux) { const password = await this._secretStorage.get(credentialId); return { credentialId: credentialId, password: password }; } return this._client.sendRequest(Contracts.ReadCredentialRequest.type, { credentialId, password: undefined }); }; let saveCredential = async (credentialId: string, password: string): Promise => { if (Utils.isLinux) { await this._secretStorage.store(credentialId, password); return true; } return this._client.sendRequest(Contracts.SaveCredentialRequest.type, { credentialId, password }); }; let deleteCredential = async (credentialId: string): Promise => { if (Utils.isLinux) { try { await this._secretStorage.delete(credentialId); return true; } catch (e) { console.log('credential does not exist in native secret store'); } } return this._client.sendRequest(Contracts.DeleteCredentialRequest.type, { credentialId, password: undefined }); }; return azdata.credentials.registerProvider({ deleteCredential, readCredential, saveCredential, handle: 0 }); } }; } fillClientCapabilities(capabilities: ClientCapabilities): void { } initialize(capabilities: ServerCapabilities): void { } protected registerProvider(options: any): Disposable { return undefined; } private constructor(context: AppContext, protected readonly client: SqlOpsDataClient) { super(client, SqlCredentialService.messagesTypes); } }