From 715171d995ff891e4f7f049687e2b73884e336ea Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jun 2023 20:15:22 +0100 Subject: [PATCH] feat: replace keyar with vscode SecretStorage (#1600) --- package.json | 4 +- src/extension.ts | 5 +- src/historyView/branchChangesProvider.ts | 6 ++- src/historyView/repoLogProvider.ts | 2 +- src/repository.ts | 41 +++++++++----- src/source_control_manager.ts | 10 +++- src/treeView/dataProviders/svnProvider.ts | 2 +- src/types/keytar.d.ts | 65 ----------------------- src/vscodeModules.ts | 2 - yarn.lock | 8 +-- 10 files changed, 51 insertions(+), 94 deletions(-) delete mode 100644 src/types/keytar.d.ts diff --git a/package.json b/package.json index 406fc0d28..a814fcf51 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "version": "2.16.1", "publisher": "johnstoncode", "engines": { - "vscode": "^1.44.0" + "vscode": "^1.53.0" }, "private": true, "enableProposedApi": false, @@ -61,7 +61,7 @@ "@types/node": "^12.11.7", "@types/semver": "^7.3.8", "@types/tmp": "0.2.1", - "@types/vscode": "1.44.0", + "@types/vscode": "1.53.0", "@types/xml2js": "^0.4.9", "@typescript-eslint/eslint-plugin": "^4.29.0", "@typescript-eslint/parser": "^4.29.0", diff --git a/src/extension.ts b/src/extension.ts index e5c698967..f929ced3d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -27,7 +27,7 @@ import { tempSvnFs } from "./temp_svn_fs"; import { SvnFileSystemProvider } from "./svnFileSystemProvider"; async function init( - _context: ExtensionContext, + extensionContext: ExtensionContext, outputChannel: OutputChannel, disposables: Disposable[] ) { @@ -38,7 +38,8 @@ async function init( const svn = new Svn({ svnPath: info.path, version: info.version }); const sourceControlManager = await new SourceControlManager( svn, - ConstructorPolicy.Async + ConstructorPolicy.Async, + extensionContext ); registerCommands(sourceControlManager, disposables); diff --git a/src/historyView/branchChangesProvider.ts b/src/historyView/branchChangesProvider.ts index 0d8ab39d6..8953b34de 100644 --- a/src/historyView/branchChangesProvider.ts +++ b/src/historyView/branchChangesProvider.ts @@ -27,10 +27,12 @@ export class BranchChangesProvider ), commands.registerCommand( "svn.branchchanges.refresh", - () => this._onDidChangeTreeData.fire(), + () => this._onDidChangeTreeData.fire(undefined), this ), - this.model.onDidChangeRepository(() => this._onDidChangeTreeData.fire()) + this.model.onDidChangeRepository(() => + this._onDidChangeTreeData.fire(undefined) + ) ); } diff --git a/src/historyView/repoLogProvider.ts b/src/historyView/repoLogProvider.ts index 4cd6d1641..79200aaf9 100644 --- a/src/historyView/repoLogProvider.ts +++ b/src/historyView/repoLogProvider.ts @@ -196,7 +196,7 @@ export class RepoLogProvider return; } this.logCache.set(repoName, item); - this._onDidChangeTreeData.fire(); + this._onDidChangeTreeData.fire(undefined); } public addRepolikeGui() { diff --git a/src/repository.ts b/src/repository.ts index 39c4ef212..5c7ada783 100644 --- a/src/repository.ts +++ b/src/repository.ts @@ -7,6 +7,7 @@ import { EventEmitter, ProgressLocation, scm, + SecretStorage, SourceControl, SourceControlInputBox, TextDocument, @@ -53,7 +54,6 @@ import { } from "./util"; import { match, matchAll } from "./util/globMatch"; import { RepositoryFilesWatcher } from "./watchers/repositoryFilesWatcher"; -import { keytar } from "./vscodeModules"; function shouldShowProgress(operation: Operation): boolean { switch (operation) { @@ -184,7 +184,10 @@ export class Repository implements IRemoteRepository { this.repository.password = password; } - constructor(public repository: BaseRepository) { + constructor( + public repository: BaseRepository, + private secrets: SecretStorage + ) { this._fsWatcher = new RepositoryFilesWatcher(repository.root); this.disposables.push(this._fsWatcher); @@ -1007,24 +1010,36 @@ export class Repository implements IRemoteRepository { await this.lastPromptAuth; } - try { - return keytar.findCredentials(this.getCredentialServiceName()); - } catch (error) { + const secret = await this.secrets.get(this.getCredentialServiceName()); + + if (typeof secret === "undefined") { return []; } + + const credentials = JSON.parse(secret) as Array; + + return credentials; } public async saveAuth(): Promise { if (this.canSaveAuth && this.username && this.password) { - try { - await keytar.setPassword( - this.getCredentialServiceName(), - this.username, - this.password - ); - } catch (error) { - console.log(error); + const secret = await this.secrets.get(this.getCredentialServiceName()); + let credentials: Array = []; + + if (typeof secret === "string") { + credentials = JSON.parse(secret) as Array; } + + credentials.push({ + account: this.username, + password: this.password + }); + + await this.secrets.store( + this.getCredentialServiceName(), + JSON.stringify(credentials) + ); + this.canSaveAuth = false; } } diff --git a/src/source_control_manager.ts b/src/source_control_manager.ts index 39237685f..5b915e609 100644 --- a/src/source_control_manager.ts +++ b/src/source_control_manager.ts @@ -5,6 +5,7 @@ import { Disposable, Event, EventEmitter, + ExtensionContext, Uri, window, workspace, @@ -94,7 +95,11 @@ export class SourceControlManager implements IDisposable { return this._svn; } - constructor(private _svn: Svn, policy: ConstructorPolicy) { + constructor( + private _svn: Svn, + policy: ConstructorPolicy, + private extensionContact: ExtensionContext + ) { if (policy !== ConstructorPolicy.Async) { throw new Error("Unsopported policy"); } @@ -288,7 +293,8 @@ export class SourceControlManager implements IDisposable { const repositoryRoot = await this.svn.getRepositoryRoot(path); const repository = new Repository( - await this.svn.open(repositoryRoot, path) + await this.svn.open(repositoryRoot, path), + this.extensionContact.secrets ); this.open(repository); diff --git a/src/treeView/dataProviders/svnProvider.ts b/src/treeView/dataProviders/svnProvider.ts index 7a9d96bd3..9ecdba589 100644 --- a/src/treeView/dataProviders/svnProvider.ts +++ b/src/treeView/dataProviders/svnProvider.ts @@ -31,7 +31,7 @@ export default class SvnProvider } public refresh(): void { - this._onDidChangeTreeData.fire(); + this._onDidChangeTreeData.fire(undefined); } public getTreeItem(element: RepositoryNode): TreeItem { diff --git a/src/types/keytar.d.ts b/src/types/keytar.d.ts deleted file mode 100644 index 408921c8e..000000000 --- a/src/types/keytar.d.ts +++ /dev/null @@ -1,65 +0,0 @@ -// Definitions by: Milan Burda , Brendan Forster , Hari Juturu -// Adapted from DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/keytar/index.d.ts - -declare module "keytar" { - /** - * Get the stored password for the service and account. - * - * @param service The string service name. - * @param account The string account name. - * - * @returns A promise for the password string. - */ - export declare function getPassword( - service: string, - account: string - ): Promise; - - /** - * Add the password for the service and account to the keychain. - * - * @param service The string service name. - * @param account The string account name. - * @param password The string password. - * - * @returns A promise for the set password completion. - */ - export declare function setPassword( - service: string, - account: string, - password: string - ): Promise; - - /** - * Delete the stored password for the service and account. - * - * @param service The string service name. - * @param account The string account name. - * - * @returns A promise for the deletion status. True on success. - */ - export declare function deletePassword( - service: string, - account: string - ): Promise; - - /** - * Find a password for the service in the keychain. - * - * @param service The string service name. - * - * @returns A promise for the password string. - */ - export declare function findPassword(service: string): Promise; - - /** - * Find all accounts and passwords for `service` in the keychain. - * - * @param service The string service name. - * - * @returns A promise for the array of found credentials. - */ - export declare function findCredentials( - service: string - ): Promise>; -} diff --git a/src/vscodeModules.ts b/src/vscodeModules.ts index 9794df314..1483a4497 100644 --- a/src/vscodeModules.ts +++ b/src/vscodeModules.ts @@ -33,8 +33,6 @@ function getNodeModule(moduleName: string, showError = true): T | undefined { return undefined; } -export const keytar = getNodeModule("keytar", false) as typeof import("keytar"); - let iconv_lite = getNodeModule( "iconv-lite-umd", false diff --git a/yarn.lock b/yarn.lock index 8473e0f91..b22d7efcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -389,10 +389,10 @@ resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.1.tgz#83ecf4ec22a8c218c71db25f316619fe5b986011" integrity sha512-7cTXwKP/HLOPVgjg+YhBdQ7bMiobGMuoBmrGmqwIWJv8elC6t1DfVc/mn4fD9UE1IjhwmhaQ5pGVXkmXbH0rhg== -"@types/vscode@1.44.0": - version "1.44.0" - resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.44.0.tgz#62ecfe3d0e38942fce556574da54ee1013c775b7" - integrity sha512-WJZtZlinE3meRdH+I7wTsIhpz/GLhqEQwmPGeh4s1irWLwMzCeTV8WZ+pgPTwrDXoafVUWwo1LiZ9HJVHFlJSQ== +"@types/vscode@1.53.0": + version "1.53.0" + resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.53.0.tgz#47b53717af6562f2ad05171bc9c8500824a3905c" + integrity sha512-XjFWbSPOM0EKIT2XhhYm3D3cx3nn3lshMUcWNy1eqefk+oqRuBq8unVb6BYIZqXy9lQZyeUl7eaBCOZWv+LcXQ== "@types/xml2js@^0.4.9": version "0.4.9"