[gopass] Add rofi-gopass menu for quick secret entry
Allows auto-filling and copying secrets to the clipboard. Works on the secrets themselves and any fields contained within the secrets. Key bindings and options can be configured through a file or the environment.
This commit is contained in:
parent
2c11d14cbd
commit
3f958a65d6
6 changed files with 317 additions and 266 deletions
BIN
.assets/gopass/rofi-menu.gif
Normal file
BIN
.assets/gopass/rofi-menu.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 217 KiB |
|
@ -1,20 +1,2 @@
|
||||||
root:
|
root:
|
||||||
askformore: false
|
path: gpgcli-gitcli-fs+file://~/.local/share/gopass/passwords
|
||||||
autoclip: true
|
|
||||||
autoprint: false
|
|
||||||
autoimport: true
|
|
||||||
autosync: false
|
|
||||||
check_recipient_hash: false
|
|
||||||
cliptimeout: 45
|
|
||||||
concurrency: 1
|
|
||||||
editrecipients: false
|
|
||||||
nocolor: false
|
|
||||||
noconfirm: true
|
|
||||||
nopager: false
|
|
||||||
notifications: true
|
|
||||||
path: gpgcli-gitcli-fs+file:///home/marty/.local/share/gopass/passwords
|
|
||||||
recipient_hash:
|
|
||||||
.gpg-id: 353145383639394133414439344537334641363830434541313341433036443341444345413339410a423038433639313143453343313539463643373831324546334641423133324534463946343433390aa69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26
|
|
||||||
safecontent: false
|
|
||||||
usesymbols: false
|
|
||||||
mounts: {}
|
|
||||||
|
|
261
gopass/.local/bin/rofi-gopass
Executable file
261
gopass/.local/bin/rofi-gopass
Executable file
|
@ -0,0 +1,261 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Original inspiration from https://github.com/carnager/rofi-pass/
|
||||||
|
|
||||||
|
# selector wrapper
|
||||||
|
# uses rofi if found, or dmenu if found, complains if no selector available
|
||||||
|
# passes along any options given to main script
|
||||||
|
rofi_opts=("$@")
|
||||||
|
_rofi() {
|
||||||
|
if type rofi 1>/dev/null 2>/dev/null; then
|
||||||
|
rofi -dmenu -no-auto-select -i "${rofi_opts[@]}" "$@" -p "Entry"
|
||||||
|
elif type dmenu 1>/dev/null 2>/dev/null; then
|
||||||
|
dmenu -i "${rofi_opts[@]}" "$@" -p "Entry"
|
||||||
|
else
|
||||||
|
exist rofi critical "rofi-gopass" || exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse, see https://unix.stackexchange.com/a/331965/8541
|
||||||
|
_parse_config() {
|
||||||
|
(grep -E "^$2=" -m 1 "$1" 2>/dev/null || printf "VAR=__UNDEFINED__\n") | head -n1 | cut -d '=' -f 2-
|
||||||
|
}
|
||||||
|
|
||||||
|
# read config file
|
||||||
|
get_config() {
|
||||||
|
local locations=(
|
||||||
|
"$RGP_CONFIGURATION_FILE"
|
||||||
|
"${XDG_CONFIG_HOME:-$HOME/.config}/rofi-gopass/rofi-gopass.conf"
|
||||||
|
"$HOME/.rofi-gopass.conf"
|
||||||
|
"/etc/rofi-gopass.conf"
|
||||||
|
)
|
||||||
|
|
||||||
|
# return the first config file with a valid path
|
||||||
|
for config in "${locations[@]}"; do
|
||||||
|
if [[ -n "$config" && -f "$config" ]]; then
|
||||||
|
# see if the config has been given a value
|
||||||
|
local val
|
||||||
|
val="$(_parse_config "$config" "$1")"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# if there was a config file but no value
|
||||||
|
# or there was no config file at all
|
||||||
|
if [ "$val" = "__UNDEFINED__" ] || [ -z "$val" ]; then
|
||||||
|
val="$2"
|
||||||
|
fi
|
||||||
|
printf -- "%s" "$val"
|
||||||
|
}
|
||||||
|
|
||||||
|
set_defaults() {
|
||||||
|
# The location of the rofi-gopass config file
|
||||||
|
# ROFI_PASS_CONFIGURATION_FILE="~/.config/rofi-gopass"
|
||||||
|
# set options, leaving already set environment variables intact
|
||||||
|
# try to read any settings from config files
|
||||||
|
KEY_AUTOFILL="${RGP_KEY_AUTOFILL:-$(get_config KEY_AUTOFILL Return)}"
|
||||||
|
KEY_ENTRY_OPEN="${RGP_KEY_ENTRY_OPEN:-$(get_config KEY_ENTRY_OPEN Alt+Return)}"
|
||||||
|
KEY_FILL_USER="${RGP_KEY_FILL_USER:-$(get_config KEY_FILL_USER Alt+u)}"
|
||||||
|
KEY_CLIP_USER="${RGP_KEY_CLIP_USER:-$(get_config KEY_CLIP_USER Ctrl+Alt+u)}"
|
||||||
|
KEY_FILL_PASS="${RGP_KEY_FILL_PASS:-$(get_config KEY_FILL_PASS Alt+p)}"
|
||||||
|
KEY_CLIP_PASS="${RGP_KEY_CLIP_PASS:-$(get_config KEY_CLIP_PASS Ctrl+Alt+p)}"
|
||||||
|
KEY_ENTRYMENU_FILL="${RGP_KEY_ENTRYMENU_FILL:-$(get_config KEY_ENTRYMENU_FILL Return)}"
|
||||||
|
KEY_ENTRYMENU_CLIP="${RGP_KEY_ENTRYMENU_CLIP:-$(get_config KEY_ENTRYMENU_CLIP Alt+Return)}"
|
||||||
|
KEY_ENTRYMENU_QUIT="${RGP_KEY_ENTRYMENU_QUIT:-$(get_config KEY_ENTRYMENU_QUIT Alt+BackSpace)}"
|
||||||
|
|
||||||
|
AUTOFILL_BACKEND="${RGP_BACKEND:-$(get_config AUTOFILL_BACKEND xdotool)}"
|
||||||
|
AUTOFILL_CHAIN="${RGP_AUTOENTRY_CHAIN:-$(get_config AUTOFILL_CHAIN 'username :tab password')}"
|
||||||
|
AUTOFILL_DELAY="${RGP_AUTOENTRY_DELAY:-$(get_config AUTOFILL_DELAY 30)}"
|
||||||
|
GOPASS_USERNAME_FIELD="${RGP_GOPASS_USERNAME_FIELD:-$(get_config GOPASS_USERNAME_FIELD 'username user login')}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# exit on escape pressed
|
||||||
|
# rofi returns exit code 1 on esc
|
||||||
|
exit_check() {
|
||||||
|
[ "$1" -eq 1 ] && exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# simply return a list of all passwords in gopass store
|
||||||
|
# TODO choose password store
|
||||||
|
# TODO only show website names (+ folder names), and account names for multiple accounts on one site
|
||||||
|
list_passwords() {
|
||||||
|
gopass list --flat
|
||||||
|
}
|
||||||
|
|
||||||
|
# return password for argument passed
|
||||||
|
show_password() {
|
||||||
|
gopass show -f --password "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# send password to clipboard
|
||||||
|
clip_password() {
|
||||||
|
gopass show -c "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# attempt to return the field specified
|
||||||
|
# attempts all (space separated) fields until the
|
||||||
|
# first one successfully returned
|
||||||
|
_gp_get_field() {
|
||||||
|
local gp_entry="$1"
|
||||||
|
local gp_field="$2"
|
||||||
|
local clip="$3"
|
||||||
|
|
||||||
|
for key in $gp_field; do
|
||||||
|
# return on first successfully returned key
|
||||||
|
if [ -n "$clip" ]; then
|
||||||
|
gopass show -c "$gp_entry" "$key" && break
|
||||||
|
else
|
||||||
|
gopass show -f "$gp_entry" "$key" && break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# return username for argument passed
|
||||||
|
show_username() {
|
||||||
|
_gp_get_field "$1" "${GOPASS_USERNAME_FIELD}"
|
||||||
|
}
|
||||||
|
|
||||||
|
clip_username() {
|
||||||
|
_gp_get_field "$1" "${GOPASS_USERNAME_FIELD}" "-c"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_field() {
|
||||||
|
_gp_get_field "$1" "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
clip_field() {
|
||||||
|
_gp_get_field "$1" "$2" "-c"
|
||||||
|
}
|
||||||
|
|
||||||
|
list_fields() {
|
||||||
|
gopass show -f "$1" | tail -n+2
|
||||||
|
}
|
||||||
|
|
||||||
|
# invoke the dotool to type inputs
|
||||||
|
_type() {
|
||||||
|
local tool="${AUTOFILL_BACKEND}"
|
||||||
|
local toolmode="$1"
|
||||||
|
local key="$2"
|
||||||
|
|
||||||
|
"$tool" "$toolmode" --delay "${AUTOFILL_DELAY}" "$key"
|
||||||
|
}
|
||||||
|
|
||||||
|
# automatically fill out fields
|
||||||
|
# transform special chain entries into valid dotool commands
|
||||||
|
autofill() {
|
||||||
|
local selected="${1}"
|
||||||
|
local autoentry_chain="${2}"
|
||||||
|
|
||||||
|
for part in $autoentry_chain; do
|
||||||
|
case "$part" in
|
||||||
|
":tab") _type key Tab ;;
|
||||||
|
":return") _type key Return ;;
|
||||||
|
":space") _type key space ;;
|
||||||
|
"username") _type type "$(show_username "$selected")" ;;
|
||||||
|
"password") _type type "$(show_password "$selected")" ;;
|
||||||
|
":direct") _type type "$selected" ;;
|
||||||
|
*) printf '%s' "$selected" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# opens a menu for the specified gopass entry, containing its individual fields
|
||||||
|
entrymenu() {
|
||||||
|
local entry="$1"
|
||||||
|
local k_entrymenu_fill="${KEY_ENTRYMENU_FILL}"
|
||||||
|
local k_entrymenu_clip="${KEY_ENTRYMENU_CLIP}"
|
||||||
|
local k_entrymenu_quit="${KEY_ENTRYMENU_QUIT}"
|
||||||
|
|
||||||
|
local pass_obfuscation="(hidden)"
|
||||||
|
|
||||||
|
local field
|
||||||
|
field=$(
|
||||||
|
printf "password: %s\n%s" "$pass_obfuscation" "$(list_fields "$entry")" |
|
||||||
|
_rofi \
|
||||||
|
-kb-accept-entry "" \
|
||||||
|
-kb-custom-1 "$k_entrymenu_fill" \
|
||||||
|
-kb-custom-2 "$k_entrymenu_clip" \
|
||||||
|
-kb-custom-3 "$k_entrymenu_quit" \
|
||||||
|
-mesg " ᐊ $k_entrymenu_quit ᐊ | $k_entrymenu_fill: fill selection | $k_entrymenu_clip: clip selection |"
|
||||||
|
)
|
||||||
|
exit_value=$?
|
||||||
|
exit_check "$exit_value"
|
||||||
|
|
||||||
|
# get field name
|
||||||
|
field=${field%%:*}
|
||||||
|
case "$exit_value" in
|
||||||
|
"10")
|
||||||
|
if [ "$field" = "password" ]; then
|
||||||
|
autofill "$entry" "password"
|
||||||
|
else
|
||||||
|
autofill "$(show_field "$entry" "$field")" ":direct"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"11")
|
||||||
|
if [ "$field" = "password" ]; then
|
||||||
|
clip_password "$entry"
|
||||||
|
else
|
||||||
|
clip_field "$entry" "$field"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"12")
|
||||||
|
main
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local autoentry_chain="${AUTOFILL_CHAIN}"
|
||||||
|
local k_autofill="${KEY_AUTOFILL}"
|
||||||
|
local k_fill_user="${KEY_FILL_USER}"
|
||||||
|
local k_clip_user="${KEY_CLIP_USER}"
|
||||||
|
local k_fill_pass="${KEY_FILL_PASS}"
|
||||||
|
local k_clip_pass="${KEY_CLIP_PASS}"
|
||||||
|
local k_submenu="${KEY_ENTRY_OPEN}"
|
||||||
|
|
||||||
|
entry="$(
|
||||||
|
list_passwords |
|
||||||
|
_rofi -kb-accept-entry "" \
|
||||||
|
-kb-custom-1 "$k_autofill" \
|
||||||
|
-kb-custom-2 "$k_clip_user" \
|
||||||
|
-kb-custom-3 "$k_clip_pass" \
|
||||||
|
-kb-custom-4 "$k_fill_user" \
|
||||||
|
-kb-custom-5 "$k_fill_pass" \
|
||||||
|
-kb-custom-6 "$k_submenu" \
|
||||||
|
-mesg "| $k_autofill: fill credentials | $k_submenu: open entry | $k_fill_user: fill username | $k_fill_pass: fill password | $k_clip_user: clip username | $k_clip_pass: clip password |"
|
||||||
|
)"
|
||||||
|
exit_value=$?
|
||||||
|
|
||||||
|
exit_check "$exit_value"
|
||||||
|
case "$exit_value" in
|
||||||
|
"10")
|
||||||
|
autofill "$entry" "$autoentry_chain"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"11")
|
||||||
|
clip_username "$entry"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"12")
|
||||||
|
clip_password "$entry"
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"13")
|
||||||
|
autofill "$entry" "username"
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"14")
|
||||||
|
autofill "$entry" "password"
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"15")
|
||||||
|
entrymenu "$entry"
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
set_defaults
|
||||||
|
main
|
54
gopass/README.md
Normal file
54
gopass/README.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# gopass
|
||||||
|
|
||||||
|
[gopass](https://www.gopass.pw/) - command-line password manager, [pass](https://www.passwordstore.org) compatible, git by default
|
||||||
|
|
||||||
|
The gopass module tries to make interacting with the basic necessities of gopass painless and quick -- it is focused on accessing secrets, and quickly auto-filling forms or copying secrets to the clipboard. It relies on the default gopass auto-deleting clipping, so your secrets are automatically removed after a short while.
|
||||||
|
|
||||||
|
The configuration of gopass is relatively standard, it tries to follow XDG_specifications, putting the default pass store into `~/.local/share/gopass/passwords`.
|
||||||
|
|
||||||
|
## rofi-gopass
|
||||||
|
|
||||||
|
To make accessing secrets easy, it uses the `rofi-gopass` script, which creates a small rofi menu displaying all your secrets (names only), and from which you have quick access to copy, fill, or open the individual entries. An example of the menu in action:
|
||||||
|
|
||||||
|
![rofi-gopass demonstration](.assets/gopass/rofi-menu.gif)
|
||||||
|
|
||||||
|
There are several keybindings available, to either fill or copy to clipboard the username, password, or open the full view to an individual entry. For every send to clipboard action, the clipboard will be automatically cleared after the time specified in your gopass settings. For auto-filling to work correctly, the username field will (by default) have to be highlighted.
|
||||||
|
|
||||||
|
| keybinding | function | setting name |
|
||||||
|
| -------- | -------- | ---------- |
|
||||||
|
| Return | Auto-fill username & password | KEY_AUTOFILL |
|
||||||
|
| Alt+Return | Open individual entry | KEY_OPEN_ENTRY |
|
||||||
|
| Alt+u | Auto-fill username | KEY_FILL_USER |
|
||||||
|
| Alt+p | Auto-fill password | KEY_FILL_PASS |
|
||||||
|
| Ctrl+Alt+u | Send username to clipboard | KEY_CLIP_USER |
|
||||||
|
| Ctrl+Alt+p | Send password to clipboard | KEY_CLIP_PASS |
|
||||||
|
| Return | Auto-fill selected field (from opened entry) | KEY_ENTRYMENU_FILL |
|
||||||
|
| Alt+Return | Send selected field to clipboard (from opened entry) | KEY_ENTRYMENU_CLIP |
|
||||||
|
| Alt+BackSpace | Close individual entry, return to overview | KEY_ENTRYMENU_QUIT |
|
||||||
|
|
||||||
|
These keys, as well as the additional configuration can be changed by setting the corresponding environment variable, through a configuration file, or at the top of the script file itself. The script tries to follow xdg-specification, meaning it looks for a configuration file in the following directories (in descending order):
|
||||||
|
|
||||||
|
* `XDG_CONFIG_HOME/rofi-gopass/rofi-gopass.conf`
|
||||||
|
* `~/.config/rofi-gopass/rofi-gopass.conf`
|
||||||
|
* `~/.rofi-gopass.conf`
|
||||||
|
* `/etc/rofi-gopass.conf`
|
||||||
|
|
||||||
|
or, alternatively, a custom directory if the `RGP_CONFIGURATION_FILE` variable points to a configuration file.
|
||||||
|
|
||||||
|
To use environment variables to configure any of these options or keys, prefix them with `RGP_`, so that e.g. `KEY_AUTOFILL` becomes `RGP_KEY_AUTOFILL`. Environment variables take precedence over configuration file settings.
|
||||||
|
|
||||||
|
Additional configuration options:
|
||||||
|
|
||||||
|
* `AUTOFILL_BACKEND`
|
||||||
|
:sets the auto-filling tool used, only tested with `xdotool` currently.
|
||||||
|
|
||||||
|
* `AUTOFILL_CHAIN`
|
||||||
|
:sets the chain of keys that should be sent to auto-fill an entry. Can use the following special fields: `:tab`, `:space`, `:return`, `username`, `password`.
|
||||||
|
|
||||||
|
The default chain is `username :tab password`, which will enter the username, simulate the tab-key to switch from the username to the password field, and enter the password. This can be changed to suit your needs. To, for example, log in fully automatically at the end of the sequence, change it to `username :tab password :return`, and there will be no further user input for the login required.
|
||||||
|
|
||||||
|
* `AUTOFILL_DELAY`
|
||||||
|
:sets the time for xdotool to wait in-between simulated actions, if some letters appear missing or the fields are not switched between quickly enough, it can usually be fixed by increasing this delay (though typing will also take longer)
|
||||||
|
|
||||||
|
* `GOPASS_USERNAME_FIELD`
|
||||||
|
:sets the name of the field in gopass secrets which contain the username. Usually, the default setting should be fine (it will look for `user`, then `username`, then `login`) but custom field names can be supplied. If multiple field names are given, it will use the first supplied field name a secret contains.
|
|
@ -1,9 +1,3 @@
|
||||||
if mp.get_script_directory == nil then
|
if mp.get_script_directory == nil then
|
||||||
local scriptpath = debug.getinfo(1).short_src:match('.*/')
|
dofile(mp.find_config_file("scripts/sponsorblock/main.lua"))
|
||||||
local originalpath = package.path
|
|
||||||
package.path = scriptpath .. "?.lua"
|
|
||||||
|
|
||||||
require 'sponsorblock/main'
|
|
||||||
|
|
||||||
package.path = originalpath
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Code belongs to https://github.com/carnager/rofi-pass/
|
|
||||||
# Copyright (C) 2019 carnager
|
|
||||||
|
|
||||||
# rofi wrapper. Add custom settings here.
|
|
||||||
_rofi() {
|
|
||||||
rofi -dmenu -no-auto-select -i "$@" -theme /themes/dmenu
|
|
||||||
}
|
|
||||||
|
|
||||||
# default settings
|
|
||||||
backend=xdotool
|
|
||||||
dotool_delay=20
|
|
||||||
daemon_wait=2
|
|
||||||
autotype_delay=2
|
|
||||||
key_autotype="Return"
|
|
||||||
key_usertype="Alt+2"
|
|
||||||
key_passtype="Alt+3"
|
|
||||||
key_actions="Alt+a"
|
|
||||||
key_clipboard="Alt+1"
|
|
||||||
key_fieldtype="Return"
|
|
||||||
|
|
||||||
# read config file
|
|
||||||
get_config_file() {
|
|
||||||
configs=("$ROFI_PASS_CONFIG"
|
|
||||||
"$HOME/.config/rofi-pass/rofi-gopass.conf"
|
|
||||||
"/etc/rofi-gopass.conf")
|
|
||||||
|
|
||||||
# return the first config file with a valid path
|
|
||||||
for config in "${configs[@]}"; do
|
|
||||||
# '! -z' is needed in case ROFI_PASS_CONFIG is not set
|
|
||||||
if [[ ! -z "${config}" && -f "${config}" ]]; then
|
|
||||||
printf "%s" "$config"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Make sure ESC will always end the programm.
|
|
||||||
# Call this function with "exit_check $?" after each rofi call.
|
|
||||||
exit_check() {
|
|
||||||
exit_value=$1
|
|
||||||
if [[ "${exit_value}" == "1" ]]; then
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
clipboard() {
|
|
||||||
local entry
|
|
||||||
local key
|
|
||||||
local value
|
|
||||||
entry="${1}"
|
|
||||||
key="${2}"
|
|
||||||
value="$(gopass show "${entry}" "${key}")"
|
|
||||||
printf '%s' "${value}" | xclip -sel clip
|
|
||||||
notify-send "rofi-gopass" "Copied ${key} to clipboard\nClearing in 45 seconds."
|
|
||||||
(
|
|
||||||
sleep 45
|
|
||||||
printf '%s' "" | xclip
|
|
||||||
printf '%s' "" | xclip -selection clipboard | notify-send "rofi-gopass" "Clipboard cleared"
|
|
||||||
) &
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
_ydotoold() {
|
|
||||||
if ! pgrep -x "ydotoold" >/dev/null; then
|
|
||||||
# ydotoold blocks the terminal, so we need to background it.
|
|
||||||
# Sadly this way we never know when the process finished starting up.
|
|
||||||
# Until ydotoold receives proper daemonizing we add a sleep value here.
|
|
||||||
ydotoold &
|
|
||||||
sleep "${daemon_wait}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_dotool() {
|
|
||||||
local mode
|
|
||||||
local key
|
|
||||||
mode="${1}"
|
|
||||||
key="${2:-null}"
|
|
||||||
case "${mode}" in
|
|
||||||
"type")
|
|
||||||
case "${backend}" in
|
|
||||||
"xdotool") xdotool type --delay "${dotool_delay}" --file - ;;
|
|
||||||
"ydotool")
|
|
||||||
_ydotoold
|
|
||||||
ydotool type --delay "${dotool_delay}" --file -
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"key")
|
|
||||||
case "${backend}" in
|
|
||||||
"xdotool") xdotool key "${key}" ;;
|
|
||||||
"ydotool")
|
|
||||||
_ydotoold
|
|
||||||
ydotool key "${key}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
list_passwords() {
|
|
||||||
gopass list --flat
|
|
||||||
}
|
|
||||||
|
|
||||||
autopass() {
|
|
||||||
local entry
|
|
||||||
local autotype
|
|
||||||
entry="${1}"
|
|
||||||
autotype="$(gopass show "${entry}" autotype)"
|
|
||||||
autotype="${autotype:-username :tab pass}"
|
|
||||||
|
|
||||||
for word in ${autotype}; do
|
|
||||||
case "$word" in
|
|
||||||
":tab") _dotool key Tab ;;
|
|
||||||
":space") _dotool key " " ;;
|
|
||||||
":delay") sleep "${autotype_delay}" ;;
|
|
||||||
":enter") _dotool key enter ;;
|
|
||||||
"pass") printf '%s' "$(gopass show --password "${entry}")" | _dotool type ;;
|
|
||||||
*) printf '%s' "$(gopass show "${entry}" "${word}")" | _dotool type ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
list_keys() {
|
|
||||||
# gopass has no option to only list keys, so we need to build the list ourselves.
|
|
||||||
local entry
|
|
||||||
local keys
|
|
||||||
entry="${1}"
|
|
||||||
keys="$(gopass show "${entry}")"
|
|
||||||
printf '%s\n' "${keys}" | while read -r line; do
|
|
||||||
if [[ "${line}" == *": "* ]]; then
|
|
||||||
printf '%s\n' "${line%: *}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
edit_key() {
|
|
||||||
local entry
|
|
||||||
local keys
|
|
||||||
entry="${1}"
|
|
||||||
keys="$(list_keys "${entry}")"
|
|
||||||
key_name=$(printf '%s\n' "${keys}" | _rofi -mesg "Enter new key or chose existing one")
|
|
||||||
exit_check $?
|
|
||||||
value_name=$(printf '%s' "" | _rofi -mesg "Enter Value for key \"${key_name}\"")
|
|
||||||
exit_check $?
|
|
||||||
if [[ -z "${key_name}" ]]; then
|
|
||||||
printf '%s' "${value_name}" | gopass insert -a "${entry}" "${key_name}"
|
|
||||||
else
|
|
||||||
printf '%s' "${value_name}" | gopass insert "${entry}" "${key_name}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# For dangerous operations call this function first. You can provide a message as argument.
|
|
||||||
# Example: confirm "Are you sure you want to delete entry?"
|
|
||||||
confirm() {
|
|
||||||
local message
|
|
||||||
message="${1}"
|
|
||||||
confirm_content=(
|
|
||||||
"Yes"
|
|
||||||
"No")
|
|
||||||
|
|
||||||
confirm_menu=$(printf '%s\n' "${confirm_content[@]}" | _rofi -mesg "${message}")
|
|
||||||
exit_check $?
|
|
||||||
case "${confirm_menu}" in
|
|
||||||
"Yes") : ;;
|
|
||||||
"No") exit ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
custom_type() {
|
|
||||||
local entry
|
|
||||||
local keys
|
|
||||||
entry="${1}"
|
|
||||||
keys="$(list_keys "${entry}")"
|
|
||||||
key_name=$(printf '%s\n' "${keys}" | _rofi -kb-accept-entry "" -no-custom -kb-custom-1 "${key_clipboard}" -kb-custom-2 "${key_fieldtype}" -mesg "${key_clipboard}: Copy to Clipboard | ${key_fieldtype}: Type Field")
|
|
||||||
local exit_value=$?
|
|
||||||
exit_check "${exit_value}"
|
|
||||||
case "${exit_value}" in
|
|
||||||
"10") clipboard "${entry}" "${key_name}" ;;
|
|
||||||
"11")
|
|
||||||
printf '%s' "$(gopass show "${entry}" "${key_name}")" | _dotool type
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
do_menu() {
|
|
||||||
local entry
|
|
||||||
entry="${1}"
|
|
||||||
action_menu_content=(
|
|
||||||
"< Go Back"
|
|
||||||
"---"
|
|
||||||
"Show Fields"
|
|
||||||
"Add/Edit Keys"
|
|
||||||
"Generate New Password"
|
|
||||||
"Delete Entry"
|
|
||||||
)
|
|
||||||
|
|
||||||
action_menu="$(printf '%s\n' "${action_menu_content[@]}" | _rofi -no-custom -mesg "Selected Entry: ${entry}" -p '> ')"
|
|
||||||
exit_value=$?
|
|
||||||
exit_check "${exit_value}"
|
|
||||||
|
|
||||||
case "${action_menu}" in
|
|
||||||
"< Go Back") main ;;
|
|
||||||
"Show Fields") custom_type "${entry}" ;;
|
|
||||||
"Add/Edit Keys") edit_key "${entry}" ;;
|
|
||||||
"Delete Entry")
|
|
||||||
confirm "Delete ${entry}?"
|
|
||||||
gopass rm -f "${entry}"
|
|
||||||
;;
|
|
||||||
"Generate New Password")
|
|
||||||
confirm "Generate a new password for ${entry}?"
|
|
||||||
gopass generate -f "${entry}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
entry="$(list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${key_autotype}" -kb-custom-2 "${key_usertype}" -kb-custom-3 "${key_passtype}" -kb-custom-4 "${key_actions}" -mesg "${key_autotype}: Autotype | ${key_usertype}: Type User | ${key_passtype}: Type Pass | ${key_actions}: More Actions")"
|
|
||||||
exit_value=$?
|
|
||||||
exit_check "${exit_value}"
|
|
||||||
case "${exit_value}" in
|
|
||||||
"10")
|
|
||||||
autopass "${entry}"
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
"11")
|
|
||||||
printf '%s' "$(gopass show "${entry}" username)" | _dotool type
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
"12")
|
|
||||||
printf '%s' "$(gopass show --password "${entry}")" | _dotool type
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
do_menu "${entry}"
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
Loading…
Reference in a new issue