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'.
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.
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
without providing a password again. Defaults to 0s.
--stdout Prints the password and username to stdout
@ -27,7 +31,6 @@ Options:
current time. Defaults to 0s.
--on-error Arbitrary command to run if the program fails. The thrown error
is piped to the given command. Defaults to none.
--url Url to filter by.
--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 scheduleCleanup = require('../src/schedule-cleanup')
const bwListArgsDefault = ""
const cachePasswordDefault = 15
const dmenuArgsDefault = ""
const dmenuPswdArgsDefault = ""
const lengthDefault = 0
const sessionTimeoutDefault = 0
const syncVaultAfterDefault = 0
const stdoutDefault = false
const urlFilterDefault = null
const args = minimist(process.argv.slice(2))
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'.
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.
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
without providing a password again. Defaults to ${sessionTimeoutDefault}s.
--stdout Prints the password and username to stdout
@ -33,7 +39,6 @@ Options:
current time. Defaults to ${syncVaultAfterDefault}s.
--on-error Arbitrary command to run if the program fails. The thrown error
is piped to the given command. Defaults to none.
--url Url to filter by.
--verbose Show extra logs useful for debugging.
`
@ -41,13 +46,17 @@ Options:
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 sessionTimeout = args['session-timeout'] || sessionTimeoutDefault
const syncVaultAfter = args['sync-vault-after'] || syncVaultAfterDefault
const onErrorCommand = args['on-error']
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']
? (...msgs) => console.log(...msgs, '\n')
@ -57,7 +66,7 @@ const oldestAllowedVaultSync = syncVaultAfter
const saveSession = Boolean(sessionTimeout)
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(() =>
scheduleCleanup({
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')
// 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) {
console.debug(`checking for session file at ${sessionFile}`)
const sessionFileExists = existsSync(sessionFile)
@ -19,7 +19,7 @@ const getSessionVar = async ({ saveSession, sessionFile }) => {
} else {
console.debug('no session file found.')
// 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!')
const session = bwRun('unlock', password, '--raw')
writeFileSync(sessionFile, session)
@ -27,7 +27,8 @@ const getSessionVar = async ({ saveSession, sessionFile }) => {
return session
}
} 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!')
const session = bwRun('unlock', password, '--raw')
return session
@ -47,23 +48,20 @@ const syncIfNecessary = ({ session, oldestAllowedVaultSync }) => {
}
// 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)
return list
}
// choose one account with dmenu
const chooseAccount = async ({ list, length }) => {
const chooseAccount = async ({ list, dmenuArgs }) => {
const LOGIN_TYPE = 1
const loginList = list.filter(a => a.type === LOGIN_TYPE)
const accountNames = loginList.map(a => `${a.name}: ${a.login.username}`)
// -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)
// accountNames indexes match loginList indexes
const selectedAccount = loginList[index]
@ -72,7 +70,7 @@ const chooseAccount = async ({ list, length }) => {
}
// choose one field with dmenu
const chooseField = async ({ selectedAccount, length }) => {
const chooseField = async ({ selectedAccount, dmenuArgs }) => {
if (!selectedAccount) throw new Error('no account selected!')
const copyable = {
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}'`)
const valueToCopy = copyable[field]
return valueToCopy
}
module.exports = async ({
length,
bwListArgs,
dmenuArgs,
dmenuPswdArgs,
saveSession,
sessionFile,
stdout,
oldestAllowedVaultSync,
urlFilter,
oldestAllowedVaultSync
}) => {
const session = await getSessionVar({ saveSession, sessionFile })
const session = await getSessionVar({ dmenuPswdArgs, saveSession, sessionFile })
// bw sync if necessary
syncIfNecessary({ session, oldestAllowedVaultSync })
// bw list
const list = getAccounts({ session, urlFilter })
const list = getAccounts({ session, bwListArgs })
// choose account in dmenu
const selectedAccount = await chooseAccount({ list, length })
const selectedAccount = await chooseAccount({ list, dmenuArgs })
if(stdout) {
console.log(`${selectedAccount.login.username}\n${selectedAccount.login.password}`)
} else {
// choose field to copy in dmenu
const valueToCopy = await chooseField({ selectedAccount, length })
const valueToCopy = await chooseField({ selectedAccount, dmenuArgs })
// copy to clipboard
clipboardy.writeSync(valueToCopy)


Loading…
Cancel
Save