dmenu for bitwarden-cli
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.9 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. #!/usr/bin/env node
  2. const os = require('os')
  3. const path = require('path')
  4. const { exec } = require('child_process')
  5. const minimist = require('minimist')
  6. const menu = require('../src')
  7. const obfuscateState = require('../src/util/obfuscate')
  8. const scheduleCleanup = require('../src/schedule-cleanup')
  9. const bwListArgsDefault = ''
  10. const cachePasswordDefault = 15
  11. const dmenuArgsDefault = ''
  12. const dmenuPswdArgsDefault = ''
  13. const lengthDefault = 0
  14. const sessionTimeoutDefault = 0
  15. const syncVaultAfterDefault = 0
  16. const stdoutDefault = false
  17. const args = minimist(process.argv.slice(2))
  18. if (args.help) {
  19. console.log(
  20. `Usage: bitwarden-dmenu [options]
  21. The DMENU_PATH environment variable can be used to point to an alternative dmenu implementation. Defaults to 'dmenu'.
  22. Options:
  23. --bw-list-args Arbitrary arguments to pass to bitwarden's 'list' command
  24. Defaults to nothing.
  25. --clear-clipboard Number of seconds to keep selected field in the clipboard.
  26. Defaults to ${cachePasswordDefault}s.
  27. --dmenu-args Sets arbitrary arguments to pass to dmenu
  28. Defaults to nothing.
  29. --dmenu-pswd-args Sets arbitrary arguments to pass to the dmenu password prompt
  30. Defaults to nothing.
  31. --session-timeout Number of seconds after an unlock that the menu can be accessed
  32. without providing a password again. Defaults to ${sessionTimeoutDefault}s.
  33. --stdout Prints the password and username to stdout
  34. --sync-vault-after Number of seconds allowable between last bitwarden sync and
  35. current time. Defaults to ${syncVaultAfterDefault}s.
  36. --on-error Arbitrary command to run if the program fails. The thrown error
  37. is piped to the given command. Defaults to none.
  38. --debug Show extra logs useful for debugging.
  39. --debug-unsafe Show debug logs WITHOUT obfuscating your sensitive info. Do not share!
  40. `
  41. )
  42. process.exit()
  43. }
  44. const bwListArgs = args['bw-list-args'] || bwListArgsDefault
  45. const dmenuArgs = args['dmenu-args'] || dmenuArgsDefault
  46. const dmenuPswdArgs = args['dmenu-pswd-args'] || dmenuPswdArgsDefault
  47. const unsafeDebug = args['debug-unsafe']
  48. const length = args['l'] || lengthDefault
  49. const sessionTimeout = args['session-timeout'] || sessionTimeoutDefault
  50. const syncVaultAfter = args['sync-vault-after'] || syncVaultAfterDefault
  51. const onErrorCommand = args['on-error']
  52. const stdout = args['stdout'] || stdoutDefault
  53. // prevent clipboard clearing from locking up process when printing to stdout
  54. const clearClipboardAfter = stdout ? 0 : args['clear-clipboard'] || cachePasswordDefault
  55. console.debug =
  56. args['debug'] || args['debug-unsafe'] ? (...msgs) => console.log(...msgs, '\n') : () => {}
  57. console.info = args['stdout'] ? () => {} : console.info
  58. if (args['debug-unsafe']) obfuscateState.turnOff()
  59. const oldestAllowedVaultSync = syncVaultAfter
  60. const saveSession = Boolean(sessionTimeout)
  61. const sessionFile = path.resolve(os.tmpdir(), 'bitwarden-session.txt')
  62. menu({
  63. bwListArgs,
  64. dmenuArgs,
  65. dmenuPswdArgs,
  66. saveSession,
  67. sessionFile,
  68. stdout,
  69. oldestAllowedVaultSync,
  70. unsafeDebug
  71. })
  72. .then(() =>
  73. scheduleCleanup({
  74. lockBitwardenAfter: sessionTimeout,
  75. clearClipboardAfter,
  76. sessionFile,
  77. stdout
  78. })
  79. )
  80. .catch(e => {
  81. console.error(e)
  82. // if something goes wrong, immediately clear the clipboard & lock bitwarden,
  83. // then run error command
  84. scheduleCleanup({
  85. lockBitwardenAfter: 0,
  86. clearClipboardAfter: 0,
  87. sessionFile,
  88. stdout
  89. })
  90. .catch(e => {
  91. // simply log an error with cleanup
  92. console.error(e)
  93. })
  94. .then(() => {
  95. if (onErrorCommand) {
  96. const errorCommand = exec(onErrorCommand)
  97. errorCommand.stdin.write(`'${e.toString()}'`)
  98. errorCommand.stdin.end()
  99. }
  100. })
  101. })