-
-
Notifications
You must be signed in to change notification settings - Fork 710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(bitwarden): added field for server url during setup for self-hosted servers and others #2246
base: master
Are you sure you want to change the base?
Changes from all commits
145af86
317ab4d
332110e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
const ProcessSpawner = require('util/process.js') | ||
const path = require('path') | ||
|
||
const { join } = require('path') | ||
const fs = require('fs') | ||
var { ipcRenderer } = require('electron') | ||
const { ipcRenderer } = require('electron') | ||
|
||
const ProcessSpawner = require('util/process.js') | ||
|
||
// Bitwarden password manager. Requires session key to unlock the vault. | ||
class Bitwarden { | ||
|
@@ -12,18 +14,17 @@ class Bitwarden { | |
} | ||
|
||
getDownloadLink () { | ||
switch (window.platformType) { | ||
case 'mac': | ||
return 'https://vault.bitwarden.com/download/?app=cli&platform=macos' | ||
case 'windows': | ||
return 'https://vault.bitwarden.com/download/?app=cli&platform=windows' | ||
case 'linux': | ||
return 'https://vault.bitwarden.com/download/?app=cli&platform=linux' | ||
if (window.platformType === 'mac') { | ||
return 'https://vault.bitwarden.com/download/?app=cli&platform=macos' | ||
} | ||
if (window.platformType === 'windows') { | ||
return 'https://vault.bitwarden.com/download/?app=cli&platform=windows' | ||
} | ||
return 'https://vault.bitwarden.com/download/?app=cli&platform=linux' | ||
} | ||
|
||
getLocalPath () { | ||
return path.join(window.globalArgs['user-data-path'], 'tools', (platformType === 'windows' ? 'bw.exe' : 'bw')) | ||
return join(window.globalArgs['user-data-path'], 'tools', (platformType === 'windows' ? 'bw.exe' : 'bw')) | ||
} | ||
|
||
getSetupMode () { | ||
|
@@ -41,7 +42,7 @@ class Bitwarden { | |
try { | ||
await fs.promises.access(localPath, fs.constants.X_OK) | ||
local = true | ||
} catch (e) { } | ||
} catch { } | ||
if (local) { | ||
return localPath | ||
} | ||
|
@@ -71,7 +72,7 @@ class Bitwarden { | |
|
||
// Tries to get a list of credential suggestions for a given domain name. | ||
async getSuggestions (domain) { | ||
if (this.lastCallList[domain] != null) { | ||
if (this.lastCallList[domain]) { | ||
return this.lastCallList[domain] | ||
} | ||
|
||
|
@@ -84,32 +85,24 @@ class Bitwarden { | |
throw new Error() | ||
} | ||
|
||
this.lastCallList[domain] = this.loadSuggestions(command, domain).then(suggestions => { | ||
this.lastCallList[domain] = null | ||
return suggestions | ||
}).catch(ex => { | ||
this.lastCallList[domain] = null | ||
}) | ||
|
||
this.lastCallList[domain] = await this.loadSuggestions(command, domain) | ||
return this.lastCallList[domain] | ||
} | ||
|
||
// Loads credential suggestions for given domain name. | ||
async loadSuggestions (command, domain) { | ||
try { | ||
const process = new ProcessSpawner(command, ['list', 'items', '--url', this.sanitize(domain), '--session', this.sessionKey]) | ||
const data = await process.execute() | ||
|
||
const matches = JSON.parse(data) | ||
const credentials = matches.map(match => { | ||
const { login: { username, password } } = match | ||
return { username, password, manager: 'Bitwarden' } | ||
}) | ||
|
||
return credentials | ||
} catch (ex) { | ||
const { error, data } = ex | ||
console.error('Error accessing Bitwarden CLI. STDOUT: ' + data + '. STDERR: ' + error) | ||
const process = new ProcessSpawner( | ||
command, | ||
['list', 'items', '--url', domain.replace(/[^a-zA-Z0-9.-]/g, ''), '--session', this.sessionKey] | ||
) | ||
const matches = JSON.parse(await process.execute()) | ||
return matches.map( | ||
({ login: { username, password } }) => | ||
({ username, password, manager: 'Bitwarden' }) | ||
) | ||
} catch ({ error, data }) { | ||
console.error(`Error accessing Bitwarden CLI. STDOUT: ${data}. STDERR: ${error}`) | ||
return [] | ||
} | ||
} | ||
|
@@ -118,9 +111,8 @@ class Bitwarden { | |
try { | ||
const process = new ProcessSpawner(command, ['sync', '--session', this.sessionKey]) | ||
await process.execute() | ||
} catch (ex) { | ||
const { error, data } = ex | ||
console.error('Error accessing Bitwarden CLI. STDOUT: ' + data + '. STDERR: ' + error) | ||
} catch ({ error, data }) { | ||
console.error(`Error accessing Bitwarden CLI. STDOUT: ${data}. STDERR: ${error}`) | ||
} | ||
} | ||
|
||
|
@@ -138,17 +130,17 @@ class Bitwarden { | |
await this.forceSync(this.path) | ||
|
||
return true | ||
} catch (ex) { | ||
const { error, data } = ex | ||
} catch (err) { | ||
const { error, data } = err | ||
|
||
console.error('Error accessing Bitwarden CLI. STDOUT: ' + data + '. STDERR: ' + error) | ||
console.error(`Error accessing Bitwarden CLI. STDOUT: ${data}. STDERR: ${error}`) | ||
|
||
if (error.includes('not logged in')) { | ||
await this.signInAndSave() | ||
return await this.unlockStore(password) | ||
} | ||
|
||
throw ex | ||
throw err | ||
} | ||
} | ||
|
||
|
@@ -161,41 +153,43 @@ class Bitwarden { | |
console.warn(e) | ||
} | ||
|
||
// show credentials dialog | ||
|
||
var signInFields = [ | ||
// show ask-for-credential dialog | ||
const signInFields = [ | ||
{ placeholder: 'Server URL (Leave blank for the default Bitwarden server)', id: 'url', type: 'text' }, | ||
{ placeholder: 'Client ID', id: 'clientID', type: 'password' }, | ||
{ placeholder: 'Client Secret', id: 'clientSecret', type: 'password' } | ||
] | ||
|
||
const credentials = ipcRenderer.sendSync('prompt', { | ||
text: l('passwordManagerBitwardenSignIn'), | ||
values: signInFields, | ||
ok: l('dialogConfirmButton'), | ||
cancel: l('dialogSkipButton'), | ||
width: 500, | ||
height: 260 | ||
}) | ||
|
||
for (const key in credentials) { | ||
if (credentials[key] === '') { | ||
throw new Error('no credentials entered') | ||
const credentials = ipcRenderer.sendSync( | ||
'prompt', | ||
{ | ||
text: l('passwordManagerBitwardenSignIn'), | ||
values: signInFields, | ||
ok: l('dialogConfirmButton'), | ||
cancel: l('dialogSkipButton'), | ||
width: 500, | ||
height: 260 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
) | ||
|
||
if (credentials.clientID === '' || credentials.clientSecret === '') { | ||
throw new Error('no credentials entered') | ||
} | ||
|
||
const process = new ProcessSpawner(path, ['login', '--apikey'], { | ||
BW_CLIENTID: credentials.clientID.trim(), | ||
BW_CLIENTSECRET: credentials.clientSecret.trim() | ||
}) | ||
credentials.url = credentials.url || 'bitwarden.com' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It wasn't clear to me whether I was supposed to type "bitwarden.com" or "vault.bitwarden.com" - do they both work? If not, maybe we should special-case this so if the user enters one we convert to the other. |
||
|
||
await process.execute() | ||
const process1 = new ProcessSpawner(path, ['config', 'server', credentials.url.trim()]) | ||
await process1.execute() | ||
|
||
return true | ||
} | ||
|
||
// Basic domain name cleanup. Removes any non-ASCII symbols. | ||
sanitize (domain) { | ||
return domain.replace(/[^a-zA-Z0-9.-]/g, '') | ||
const process2 = new ProcessSpawner( | ||
path, | ||
['login', '--apikey'], | ||
{ | ||
BW_CLIENTID: credentials.clientID.trim(), | ||
BW_CLIENTSECRET: credentials.clientSecret.trim() | ||
} | ||
) | ||
await process2.execute() | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a translated string - add it to
en-US.json
, then dol(stringName)
like the examples below.Actually, maybe "client ID" and "Client Secret" should be translated also, although I think the reason not to translate them was so that it would be clear in Bitwarden what we're referring to.