Browse Source

Made all arguments changeable by user

master
AGitBoy 6 years ago
parent
commit
3251bbcc9f
3 changed files with 40 additions and 29 deletions
  1. +6
    -3
      README.md
  2. +16
    -7
      bin/cli.js
  3. +18
    -19
      src/index.js

+ 6
- 3
README.md View File

@ -16,10 +16,14 @@ Usage: bitwarden-dmenu [options]
The DMENU_PATH environment variable can be used to point to an alternative dmenu implementation. Defaults to 'dmenu'. The DMENU_PATH environment variable can be used to point to an alternative dmenu implementation. Defaults to 'dmenu'.
Options: Options:
--bw-list-args Arbitrary arguments to pass to bitwarden's 'list' command
Defaults to nothing.
--clear-clipboard Number of seconds to keep selected field in the clipboard. --clear-clipboard Number of seconds to keep selected field in the clipboard.
Defaults to 15s. Defaults to 15s.
-l Sets the -l parameter value passed to dmenu.
Defaults to 0
--dmenu-args Sets arbitrary arguments to pass to dmenu
Defaults to nothing.
--dmenu-pswd-args Sets arbitrary arguments to pass to the dmenu password prompt
Defaults to nothing.
--session-timeout Number of seconds after an unlock that the menu can be accessed --session-timeout Number of seconds after an unlock that the menu can be accessed
without providing a password again. Defaults to 0s. without providing a password again. Defaults to 0s.
--stdout Prints the password and username to stdout --stdout Prints the password and username to stdout
@ -27,7 +31,6 @@ Options:
current time. Defaults to 0s. current time. Defaults to 0s.
--on-error Arbitrary command to run if the program fails. The thrown error --on-error Arbitrary command to run if the program fails. The thrown error
is piped to the given command. Defaults to none. is piped to the given command. Defaults to none.
--url Url to filter by.
--verbose Show extra logs useful for debugging. --verbose Show extra logs useful for debugging.
``` ```


+ 16
- 7
bin/cli.js View File

@ -7,12 +7,14 @@ const minimist = require('minimist')
const menu = require('../src') const menu = require('../src')
const scheduleCleanup = require('../src/schedule-cleanup') const scheduleCleanup = require('../src/schedule-cleanup')
const bwListArgsDefault = ""
const cachePasswordDefault = 15 const cachePasswordDefault = 15
const dmenuArgsDefault = ""
const dmenuPswdArgsDefault = ""
const lengthDefault = 0 const lengthDefault = 0
const sessionTimeoutDefault = 0 const sessionTimeoutDefault = 0
const syncVaultAfterDefault = 0 const syncVaultAfterDefault = 0
const stdoutDefault = false const stdoutDefault = false
const urlFilterDefault = null
const args = minimist(process.argv.slice(2)) const args = minimist(process.argv.slice(2))
if (args.help) { if (args.help) {
@ -22,10 +24,14 @@ if (args.help) {
The DMENU_PATH environment variable can be used to point to an alternative dmenu implementation. Defaults to 'dmenu'. The DMENU_PATH environment variable can be used to point to an alternative dmenu implementation. Defaults to 'dmenu'.
Options: Options:
--bw-list-args Arbitrary arguments to pass to bitwarden's 'list' command
Defaults to nothing.
--clear-clipboard Number of seconds to keep selected field in the clipboard. --clear-clipboard Number of seconds to keep selected field in the clipboard.
Defaults to ${cachePasswordDefault}s. Defaults to ${cachePasswordDefault}s.
-l Sets the -l parameter value passed to dmenu.
Defaults to ${lengthDefault}
--dmenu-args Sets arbitrary arguments to pass to dmenu
Defaults to nothing.
--dmenu-pswd-args Sets arbitrary arguments to pass to the dmenu password prompt
Defaults to nothing.
--session-timeout Number of seconds after an unlock that the menu can be accessed --session-timeout Number of seconds after an unlock that the menu can be accessed
without providing a password again. Defaults to ${sessionTimeoutDefault}s. without providing a password again. Defaults to ${sessionTimeoutDefault}s.
--stdout Prints the password and username to stdout --stdout Prints the password and username to stdout
@ -33,7 +39,6 @@ Options:
current time. Defaults to ${syncVaultAfterDefault}s. current time. Defaults to ${syncVaultAfterDefault}s.
--on-error Arbitrary command to run if the program fails. The thrown error --on-error Arbitrary command to run if the program fails. The thrown error
is piped to the given command. Defaults to none. is piped to the given command. Defaults to none.
--url Url to filter by.
--verbose Show extra logs useful for debugging. --verbose Show extra logs useful for debugging.
` `
@ -41,13 +46,17 @@ Options:
process.exit() process.exit()
} }
const clearClipboardAfter = args['clear-clipboard'] || cachePasswordDefault
const bwListArgs = args['bw-list-args'] || bwListArgsDefault
const dmenuArgs = args['dmenu-args'] || dmenuArgsDefault
const dmenuPswdArgs = args['dmenu-pswd-args'] || dmenuPswdArgsDefault
const length = args['l'] || lengthDefault const length = args['l'] || lengthDefault
const sessionTimeout = args['session-timeout'] || sessionTimeoutDefault const sessionTimeout = args['session-timeout'] || sessionTimeoutDefault
const syncVaultAfter = args['sync-vault-after'] || syncVaultAfterDefault const syncVaultAfter = args['sync-vault-after'] || syncVaultAfterDefault
const onErrorCommand = args['on-error'] const onErrorCommand = args['on-error']
const stdout = args['stdout'] || stdoutDefault const stdout = args['stdout'] || stdoutDefault
const urlFilter = args['url'] || urlFilterDefault
// prevent clipboard clearing from locking up process when printing to stdout
const clearClipboardAfter = stdout ? 0 : args['clear-clipboard'] || cachePasswordDefault
console.debug = args['verbose'] console.debug = args['verbose']
? (...msgs) => console.log(...msgs, '\n') ? (...msgs) => console.log(...msgs, '\n')
@ -57,7 +66,7 @@ const oldestAllowedVaultSync = syncVaultAfter
const saveSession = Boolean(sessionTimeout) const saveSession = Boolean(sessionTimeout)
const sessionFile = path.resolve(os.tmpdir(), 'bitwarden-session.txt') const sessionFile = path.resolve(os.tmpdir(), 'bitwarden-session.txt')
menu({ length, saveSession, sessionFile, stdout, oldestAllowedVaultSync, urlFilter })
menu({ bwListArgs, dmenuArgs, dmenuPswdArgs, saveSession, sessionFile, stdout, oldestAllowedVaultSync })
.then(() => .then(() =>
scheduleCleanup({ scheduleCleanup({
lockBitwardenAfter: sessionTimeout, lockBitwardenAfter: sessionTimeout,


+ 18
- 19
src/index.js View File

@ -5,7 +5,7 @@ const bwRun = require('./exec-bitwarden-cli')
const obfuscate = require('./util/obfuscate/object') const obfuscate = require('./util/obfuscate/object')
// get a session token, either from existing sessionFile or by `bw unlock [password]` // get a session token, either from existing sessionFile or by `bw unlock [password]`
const getSessionVar = async ({ saveSession, sessionFile }) => {
const getSessionVar = async ({ dmenuPswdArgs, saveSession, sessionFile }) => {
if (saveSession) { if (saveSession) {
console.debug(`checking for session file at ${sessionFile}`) console.debug(`checking for session file at ${sessionFile}`)
const sessionFileExists = existsSync(sessionFile) const sessionFileExists = existsSync(sessionFile)
@ -19,7 +19,7 @@ const getSessionVar = async ({ saveSession, sessionFile }) => {
} else { } else {
console.debug('no session file found.') console.debug('no session file found.')
// prompt for password in dmenu // prompt for password in dmenu
const password = await dmenuRun('-p Password: -nf black -nb black')('\n')
const password = await dmenuRun(`-p Password: -nf black -nb black ${dmenuPswdArgs}`)('\n')
if (!password) throw new Error('no password given!') if (!password) throw new Error('no password given!')
const session = bwRun('unlock', password, '--raw') const session = bwRun('unlock', password, '--raw')
writeFileSync(sessionFile, session) writeFileSync(sessionFile, session)
@ -27,7 +27,8 @@ const getSessionVar = async ({ saveSession, sessionFile }) => {
return session return session
} }
} else { } else {
const password = await dmenuRun('-p Password: -nf black -nb black')('\n')
// Why doesn't dmenuRun('...', dmenuPswdArgs)('\n') work here?
const password = await dmenuRun(`-p Password: -nf black -nb black ${dmenuPswdArgs}`)('\n')
if (!password) throw new Error('no password given!') if (!password) throw new Error('no password given!')
const session = bwRun('unlock', password, '--raw') const session = bwRun('unlock', password, '--raw')
return session return session
@ -47,23 +48,20 @@ const syncIfNecessary = ({ session, oldestAllowedVaultSync }) => {
} }
// get the list all password accounts in the vault // get the list all password accounts in the vault
const getAccounts = ({ session, urlFilter }) => {
const listStr = urlFilter
? bwRun('list', 'items', `--url=${urlFilter}`, `--session=${session}`)
: bwRun('list', 'items', `--session=${session}`)
const getAccounts = ({ session, bwListArgs }) => {
const listStr = bwRun('list', 'items', bwListArgs, `--session=${session}`)
const list = JSON.parse(listStr) const list = JSON.parse(listStr)
return list return list
} }
// choose one account with dmenu // choose one account with dmenu
const chooseAccount = async ({ list, length }) => {
const chooseAccount = async ({ list, dmenuArgs }) => {
const LOGIN_TYPE = 1 const LOGIN_TYPE = 1
const loginList = list.filter(a => a.type === LOGIN_TYPE) const loginList = list.filter(a => a.type === LOGIN_TYPE)
const accountNames = loginList.map(a => `${a.name}: ${a.login.username}`) const accountNames = loginList.map(a => `${a.name}: ${a.login.username}`)
// -i allows case insensitive matching // -i allows case insensitive matching
const selected = await dmenuRun(`-l ${length}`)(accountNames.join('\n'))
const selected = await dmenuRun(dmenuArgs)(accountNames.join('\n'))
const index = accountNames.indexOf(selected) const index = accountNames.indexOf(selected)
// accountNames indexes match loginList indexes // accountNames indexes match loginList indexes
const selectedAccount = loginList[index] const selectedAccount = loginList[index]
@ -72,7 +70,7 @@ const chooseAccount = async ({ list, length }) => {
} }
// choose one field with dmenu // choose one field with dmenu
const chooseField = async ({ selectedAccount, length }) => {
const chooseField = async ({ selectedAccount, dmenuArgs }) => {
if (!selectedAccount) throw new Error('no account selected!') if (!selectedAccount) throw new Error('no account selected!')
const copyable = { const copyable = {
password: selectedAccount.login.password, password: selectedAccount.login.password,
@ -86,36 +84,37 @@ const chooseField = async ({ selectedAccount, length }) => {
{} {}
) )
} }
const field = await dmenuRun(`-l ${length}`)(Object.keys(copyable).join('\n'))
const field = await dmenuRun(dmenuArgs)(Object.keys(copyable).join('\n'))
console.debug(`selected field '${field}'`) console.debug(`selected field '${field}'`)
const valueToCopy = copyable[field] const valueToCopy = copyable[field]
return valueToCopy return valueToCopy
} }
module.exports = async ({ module.exports = async ({
length,
bwListArgs,
dmenuArgs,
dmenuPswdArgs,
saveSession, saveSession,
sessionFile, sessionFile,
stdout, stdout,
oldestAllowedVaultSync,
urlFilter,
oldestAllowedVaultSync
}) => { }) => {
const session = await getSessionVar({ saveSession, sessionFile })
const session = await getSessionVar({ dmenuPswdArgs, saveSession, sessionFile })
// bw sync if necessary // bw sync if necessary
syncIfNecessary({ session, oldestAllowedVaultSync }) syncIfNecessary({ session, oldestAllowedVaultSync })
// bw list // bw list
const list = getAccounts({ session, urlFilter })
const list = getAccounts({ session, bwListArgs })
// choose account in dmenu // choose account in dmenu
const selectedAccount = await chooseAccount({ list, length })
const selectedAccount = await chooseAccount({ list, dmenuArgs })
if(stdout) { if(stdout) {
console.log(`${selectedAccount.login.username}\n${selectedAccount.login.password}`) console.log(`${selectedAccount.login.username}\n${selectedAccount.login.password}`)
} else { } else {
// choose field to copy in dmenu // choose field to copy in dmenu
const valueToCopy = await chooseField({ selectedAccount, length })
const valueToCopy = await chooseField({ selectedAccount, dmenuArgs })
// copy to clipboard // copy to clipboard
clipboardy.writeSync(valueToCopy) clipboardy.writeSync(valueToCopy)


Loading…
Cancel
Save