1- const ProcessSpawner = require ( 'util/process.js' )
2- const path = require ( 'path' )
1+
2+ const { join } = require ( 'path' )
33const fs = require ( 'fs' )
4- var { ipcRenderer } = require ( 'electron' )
4+ const { ipcRenderer } = require ( 'electron' )
5+
6+ const ProcessSpawner = require ( 'util/process.js' )
57
68// Bitwarden password manager. Requires session key to unlock the vault.
79class Bitwarden {
@@ -12,18 +14,17 @@ class Bitwarden {
1214 }
1315
1416 getDownloadLink ( ) {
15- switch ( window . platformType ) {
16- case 'mac' :
17- return 'https://vault.bitwarden.com/download/?app=cli&platform=macos'
18- case 'windows' :
19- return 'https://vault.bitwarden.com/download/?app=cli&platform=windows'
20- case 'linux' :
21- return 'https://vault.bitwarden.com/download/?app=cli&platform=linux'
17+ if ( window . platformType === 'mac' ) {
18+ return 'https://vault.bitwarden.com/download/?app=cli&platform=macos'
2219 }
20+ if ( window . platformType === 'windows' ) {
21+ return 'https://vault.bitwarden.com/download/?app=cli&platform=windows'
22+ }
23+ return 'https://vault.bitwarden.com/download/?app=cli&platform=linux'
2324 }
2425
2526 getLocalPath ( ) {
26- return path . join ( window . globalArgs [ 'user-data-path' ] , 'tools' , ( platformType === 'windows' ? 'bw.exe' : 'bw' ) )
27+ return join ( window . globalArgs [ 'user-data-path' ] , 'tools' , ( platformType === 'windows' ? 'bw.exe' : 'bw' ) )
2728 }
2829
2930 getSetupMode ( ) {
@@ -41,7 +42,7 @@ class Bitwarden {
4142 try {
4243 await fs . promises . access ( localPath , fs . constants . X_OK )
4344 local = true
44- } catch ( e ) { }
45+ } catch { }
4546 if ( local ) {
4647 return localPath
4748 }
@@ -71,7 +72,7 @@ class Bitwarden {
7172
7273 // Tries to get a list of credential suggestions for a given domain name.
7374 async getSuggestions ( domain ) {
74- if ( this . lastCallList [ domain ] != null ) {
75+ if ( this . lastCallList [ domain ] ) {
7576 return this . lastCallList [ domain ]
7677 }
7778
@@ -84,32 +85,31 @@ class Bitwarden {
8485 throw new Error ( )
8586 }
8687
87- this . lastCallList [ domain ] = this . loadSuggestions ( command , domain ) . then ( suggestions => {
88- this . lastCallList [ domain ] = null
88+ try {
89+ const suggestions = await this . loadSuggestions ( command , domain )
90+ this . lastCallList [ domain ] = suggestions
8991 return suggestions
90- } ) . catch ( ex => {
92+ } catch ( e ) {
9193 this . lastCallList [ domain ] = null
92- } )
94+ }
9395
9496 return this . lastCallList [ domain ]
9597 }
9698
9799 // Loads credential suggestions for given domain name.
98100 async loadSuggestions ( command , domain ) {
99101 try {
100- const process = new ProcessSpawner ( command , [ 'list' , 'items' , '--url' , this . sanitize ( domain ) , '--session' , this . sessionKey ] )
101- const data = await process . execute ( )
102-
103- const matches = JSON . parse ( data )
104- const credentials = matches . map ( match => {
105- const { login : { username, password } } = match
106- return { username, password, manager : 'Bitwarden' }
107- } )
108-
109- return credentials
110- } catch ( ex ) {
111- const { error, data } = ex
112- console . error ( 'Error accessing Bitwarden CLI. STDOUT: ' + data + '. STDERR: ' + error )
102+ const process = new ProcessSpawner (
103+ command ,
104+ [ 'list' , 'items' , '--url' , domain . replace ( / [ ^ a - z A - Z 0 - 9 . - ] / g, '' ) , '--session' , this . sessionKey ]
105+ )
106+ const matches = JSON . parse ( await process . execute ( ) )
107+ return matches . map (
108+ ( { login : { username, password } } ) =>
109+ ( { username, password, manager : 'Bitwarden' } )
110+ )
111+ } catch ( { error, data } ) {
112+ console . error ( `Error accessing Bitwarden CLI. STDOUT: ${ data } . STDERR: ${ error } ` )
113113 return [ ]
114114 }
115115 }
@@ -118,9 +118,8 @@ class Bitwarden {
118118 try {
119119 const process = new ProcessSpawner ( command , [ 'sync' , '--session' , this . sessionKey ] )
120120 await process . execute ( )
121- } catch ( ex ) {
122- const { error, data } = ex
123- console . error ( 'Error accessing Bitwarden CLI. STDOUT: ' + data + '. STDERR: ' + error )
121+ } catch ( { error, data } ) {
122+ console . error ( `Error accessing Bitwarden CLI. STDOUT: ${ data } . STDERR: ${ error } ` )
124123 }
125124 }
126125
@@ -138,17 +137,17 @@ class Bitwarden {
138137 await this . forceSync ( this . path )
139138
140139 return true
141- } catch ( ex ) {
142- const { error, data } = ex
140+ } catch ( err ) {
141+ const { error, data } = err
143142
144- console . error ( ' Error accessing Bitwarden CLI. STDOUT: ' + data + ' . STDERR: ' + error )
143+ console . error ( ` Error accessing Bitwarden CLI. STDOUT: ${ data } . STDERR: ${ error } ` )
145144
146145 if ( error . includes ( 'not logged in' ) ) {
147146 await this . signInAndSave ( )
148147 return await this . unlockStore ( password )
149148 }
150149
151- throw ex
150+ throw err
152151 }
153152 }
154153
@@ -161,41 +160,43 @@ class Bitwarden {
161160 console . warn ( e )
162161 }
163162
164- // show credentials dialog
165-
166- var signInFields = [
163+ // show ask-for-credential dialog
164+ const signInFields = [
165+ { placeholder : 'Server URL (Leave blank for the default Bitwarden server)' , id : 'url' , type : 'text' } ,
167166 { placeholder : 'Client ID' , id : 'clientID' , type : 'password' } ,
168167 { placeholder : 'Client Secret' , id : 'clientSecret' , type : 'password' }
169168 ]
170169
171- const credentials = ipcRenderer . sendSync ( 'prompt' , {
172- text : l ( 'passwordManagerBitwardenSignIn' ) ,
173- values : signInFields ,
174- ok : l ( 'dialogConfirmButton' ) ,
175- cancel : l ( 'dialogSkipButton' ) ,
176- width : 500 ,
177- height : 260
178- } )
179-
180- for ( const key in credentials ) {
181- if ( credentials [ key ] === '' ) {
182- throw new Error ( 'no credentials entered' )
170+ const credentials = ipcRenderer . sendSync (
171+ 'prompt' ,
172+ {
173+ text : l ( 'passwordManagerBitwardenSignIn' ) ,
174+ values : signInFields ,
175+ ok : l ( 'dialogConfirmButton' ) ,
176+ cancel : l ( 'dialogSkipButton' ) ,
177+ width : 500 ,
178+ height : 260
183179 }
184- }
180+ )
185181
186- const process = new ProcessSpawner ( path , [ 'login' , '--apikey' ] , {
187- BW_CLIENTID : credentials . clientID . trim ( ) ,
188- BW_CLIENTSECRET : credentials . clientSecret . trim ( )
189- } )
182+ if ( credentials . clientID === '' || credentials . clientSecret === '' ) {
183+ throw new Error ( 'no credentials entered' )
184+ }
190185
191- await process . execute ( )
186+ credentials . url = credentials . url || 'bitwarden.com'
192187
193- return true
194- }
188+ const process1 = new ProcessSpawner ( path , [ 'config' , 'server' , credentials . url . trim ( ) ] )
189+ await process1 . execute ( )
195190
196- // Basic domain name cleanup. Removes any non-ASCII symbols.
197- sanitize ( domain ) {
198- return domain . replace ( / [ ^ a - z A - Z 0 - 9 . - ] / g, '' )
191+ const process2 = new ProcessSpawner (
192+ path ,
193+ [ 'login' , '--apikey' ] ,
194+ {
195+ BW_CLIENTID : credentials . clientID . trim ( ) ,
196+ BW_CLIENTSECRET : credentials . clientSecret . trim ( )
197+ }
198+ )
199+ await process2 . execute ( )
199200 }
200201}
201202
0 commit comments