1
- const ProcessSpawner = require ( 'util/process.js' )
2
- const path = require ( 'path' )
1
+
2
+ const { join } = require ( 'path' )
3
3
const fs = require ( 'fs' )
4
- var { ipcRenderer } = require ( 'electron' )
4
+ const { ipcRenderer } = require ( 'electron' )
5
+
6
+ const ProcessSpawner = require ( 'util/process.js' )
5
7
6
8
// Bitwarden password manager. Requires session key to unlock the vault.
7
9
class Bitwarden {
@@ -12,18 +14,17 @@ class Bitwarden {
12
14
}
13
15
14
16
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'
22
19
}
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'
23
24
}
24
25
25
26
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' ) )
27
28
}
28
29
29
30
getSetupMode ( ) {
@@ -41,7 +42,7 @@ class Bitwarden {
41
42
try {
42
43
await fs . promises . access ( localPath , fs . constants . X_OK )
43
44
local = true
44
- } catch ( e ) { }
45
+ } catch { }
45
46
if ( local ) {
46
47
return localPath
47
48
}
@@ -71,7 +72,7 @@ class Bitwarden {
71
72
72
73
// Tries to get a list of credential suggestions for a given domain name.
73
74
async getSuggestions ( domain ) {
74
- if ( this . lastCallList [ domain ] != null ) {
75
+ if ( this . lastCallList [ domain ] ) {
75
76
return this . lastCallList [ domain ]
76
77
}
77
78
@@ -84,32 +85,34 @@ class Bitwarden {
84
85
throw new Error ( )
85
86
}
86
87
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
91
+ console . log ( 'getSuggestions' , suggestions )
89
92
return suggestions
90
- } ) . catch ( ex => {
93
+ } catch ( e ) {
91
94
this . lastCallList [ domain ] = null
92
- } )
95
+ }
93
96
94
97
return this . lastCallList [ domain ]
95
98
}
96
99
97
100
// Loads credential suggestions for given domain name.
98
101
async loadSuggestions ( command , domain ) {
102
+ console . log ( domain . replace ( / [ ^ a - z A - Z 0 - 9 . - ] / g, '' ) )
99
103
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 )
104
+ const process = new ProcessSpawner (
105
+ command ,
106
+ [ 'list' , 'items' , '--url' , domain . replace ( / [ ^ a - z A - Z 0 - 9 . - ] / g, '' ) , '--session' , this . sessionKey ]
107
+ )
108
+ const matches = JSON . parse ( await process . execute ( ) )
109
+ console . log ( matches )
110
+ return matches . map (
111
+ ( { login : { username, password } } ) =>
112
+ ( { username, password, manager : 'Bitwarden' } )
113
+ )
114
+ } catch ( { error, data } ) {
115
+ console . error ( `Error accessing Bitwarden CLI. STDOUT: ${ data } . STDERR: ${ error } ` )
113
116
return [ ]
114
117
}
115
118
}
@@ -118,9 +121,8 @@ class Bitwarden {
118
121
try {
119
122
const process = new ProcessSpawner ( command , [ 'sync' , '--session' , this . sessionKey ] )
120
123
await process . execute ( )
121
- } catch ( ex ) {
122
- const { error, data } = ex
123
- console . error ( 'Error accessing Bitwarden CLI. STDOUT: ' + data + '. STDERR: ' + error )
124
+ } catch ( { error, data } ) {
125
+ console . error ( `Error accessing Bitwarden CLI. STDOUT: ${ data } . STDERR: ${ error } ` )
124
126
}
125
127
}
126
128
@@ -138,17 +140,17 @@ class Bitwarden {
138
140
await this . forceSync ( this . path )
139
141
140
142
return true
141
- } catch ( ex ) {
142
- const { error, data } = ex
143
+ } catch ( err ) {
144
+ const { error, data } = err
143
145
144
- console . error ( ' Error accessing Bitwarden CLI. STDOUT: ' + data + ' . STDERR: ' + error )
146
+ console . error ( ` Error accessing Bitwarden CLI. STDOUT: ${ data } . STDERR: ${ error } ` )
145
147
146
148
if ( error . includes ( 'not logged in' ) ) {
147
149
await this . signInAndSave ( )
148
150
return await this . unlockStore ( password )
149
151
}
150
152
151
- throw ex
153
+ throw err
152
154
}
153
155
}
154
156
@@ -161,41 +163,43 @@ class Bitwarden {
161
163
console . warn ( e )
162
164
}
163
165
164
- // show credentials dialog
165
-
166
- var signInFields = [
166
+ // show ask-for-credential dialog
167
+ const signInFields = [
168
+ { placeholder : 'Server URL (Leave blank for the default Bitwarden server)' , id : 'url' , type : 'text' } ,
167
169
{ placeholder : 'Client ID' , id : 'clientID' , type : 'password' } ,
168
170
{ placeholder : 'Client Secret' , id : 'clientSecret' , type : 'password' }
169
171
]
170
172
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' )
173
+ const credentials = ipcRenderer . sendSync (
174
+ 'prompt' ,
175
+ {
176
+ text : l ( 'passwordManagerBitwardenSignIn' ) ,
177
+ values : signInFields ,
178
+ ok : l ( 'dialogConfirmButton' ) ,
179
+ cancel : l ( 'dialogSkipButton' ) ,
180
+ width : 500 ,
181
+ height : 260
183
182
}
184
- }
183
+ )
185
184
186
- const process = new ProcessSpawner ( path , [ 'login' , '--apikey' ] , {
187
- BW_CLIENTID : credentials . clientID . trim ( ) ,
188
- BW_CLIENTSECRET : credentials . clientSecret . trim ( )
189
- } )
185
+ if ( credentials . clientID === '' || credentials . clientSecret === '' ) {
186
+ throw new Error ( 'no credentials entered' )
187
+ }
190
188
191
- await process . execute ( )
189
+ credentials . url = credentials . url || 'bitwarden.com'
192
190
193
- return true
194
- }
191
+ const process1 = new ProcessSpawner ( path , [ 'config' , 'server' , credentials . url . trim ( ) ] )
192
+ await process1 . execute ( )
195
193
196
- // Basic domain name cleanup. Removes any non-ASCII symbols.
197
- sanitize ( domain ) {
198
- return domain . replace ( / [ ^ a - z A - Z 0 - 9 . - ] / g, '' )
194
+ const process2 = new ProcessSpawner (
195
+ path ,
196
+ [ 'login' , '--apikey' ] ,
197
+ {
198
+ BW_CLIENTID : credentials . clientID . trim ( ) ,
199
+ BW_CLIENTSECRET : credentials . clientSecret . trim ( )
200
+ }
201
+ )
202
+ await process2 . execute ( )
199
203
}
200
204
}
201
205
0 commit comments