all repos — dotfiles @ 9f2aa547dae45c6183baab3dbe54bae3bed6050b

my *nix dotfiles

nix/bin/pw.nix (view raw)

  1{ pkgs, ... }:
  2
  3let
  4  name = "pw";
  5  gpg = "${pkgs.gnupg}/bin/gpg";
  6  pwgen = "${pkgs.pwgen}/bin/pwgen";
  7  git = "${pkgs.git}/bin/git";
  8  copy = "${pkgs.wl-clipboard}/bin/wl-copy";
  9in
 10pkgs.writeShellScriptBin name
 11  ''
 12    # pw - a mnml password manager
 13    [[ -z "$PW_DIR" ]] && PW_DIR="$HOME/.pw"
 14    init() {
 15        if [[ ! -e "$PW_DIR" ]]; then
 16            mkdir -p "$PW_DIR"
 17            printf "pw: password directory initialized at %s\n" "$PW_DIR"
 18        else
 19            printf "PW_DIR is %s\n" "$PW_DIR"
 20            die "$PW_DIR exists"
 21        fi
 22    }
 23    add() {
 24        # $1: path to file
 25        # $2 [optional]: password text
 26        [[ -z "$PW_KEY" ]] && die "\$PW_KEY not set"
 27        if [[ "$#" -eq 2 ]]; then
 28            pass="$2"
 29        else
 30            # uses default length of 25 chars, unless PW_LEN is set
 31            pass="$(${pwgen} "''${PW_LEN:-25}" 1 -s)"
 32            printf "pw: generated password for %s\n" "$1"
 33        fi
 34        if [[ ! -f "$PW_DIR/$1.gpg" ]]; then
 35            printf "%s" "$pass" | ${gpg} -aer "$PW_KEY" -o "$PW_DIR/$1.gpg"
 36            printf "pw: %s/%s.gpg created\n" "$PW_DIR" "$1"
 37        else
 38            die "the file $PW_DIR/$1.gpg exists"
 39        fi
 40        (
 41            cd $PW_DIR
 42            ${git} add .
 43            ${git} commit -m "$(date)"
 44            remote="$(${git} remote show)"
 45            branch="$(${git} branch --show-current)"
 46            ${git} pull -r "$remote" "$branch"
 47            ${git} push "$remote" "$branch"
 48        )
 49    }
 50    list() {
 51        (cd "$PW_DIR"; find *.gpg | awk -F '.gpg' '{ print $1 }' )
 52    }
 53    del() {
 54        checkf "$PW_DIR/$1.gpg"
 55        read -rn 1 -p "pw: are you sure you want to delete $1? [y/n]: "
 56        printf "\n"
 57        [[ "$REPLY" == [yY] ]] && {
 58            rm -f "$PW_DIR/$1.gpg"
 59            printf "pw: deleted %s" "$1"
 60        }
 61    }
 62    show() {
 63        checkf "$PW_DIR/$1.gpg"
 64        ${gpg} --decrypt --quiet --use-agent "$PW_DIR/$1.gpg"
 65    }
 66    # TODO: rework having to checkf twice
 67    copy() {
 68        checkf "$PW_DIR/$1.gpg"
 69        if [[ "$OSTYPE" =~ darwin* ]]; then
 70            show "$1" | head -1 | pbcopy | tr -d '\n'
 71        else
 72            show "$1" | head -1 | ${copy} -n
 73        fi
 74        printf "pw: copied %s to clipboard\n" "$1"
 75    }
 76    usage() {
 77        usage="
 78    pw - mnml password manager
 79    usage: pw [options] [NAME]
 80    All options except -i and -h require a NAME argument.
 81    options:
 82      -i            Initializes password directory at \$HOME/.pw or at \$PW_DIR, if it exists.
 83      -a            Add a password.
 84      -g            Generate a password.
 85      -s            Print password to STDOUT.
 86      -l            List out all passwords.
 87      -c            Copy existing password to clipboard.
 88      -d            Delete password.
 89      -h            Display this help message and exit.
 90    Requires PW_KEY to be set. Optionally, set PW_DIR for custom directory location.
 91    Set PW_LEN to an integer of your choice, to override the default password length of 25.
 92    "
 93        printf "%s" "$usage"
 94        exit 1
 95    }
 96    checkf() {
 97        [[ ! -f "$1" ]] &&
 98            die "$1 does not exist"
 99    }
100    die() {
101        printf "error: %s\n" "$1" >&2
102        exit 1
103    }
104    main() {
105        [[ -z "$1" ]] && {
106            usage
107        }
108        while getopts "ila:g:s:c:d:h" options
109        do
110            # shellcheck disable=SC2221,SC2222
111            case "$options" in
112                i) init ;;
113                l) list ;;
114                g) add "$OPTARG" ;;
115                a)
116                   read -rsp "enter password: " pass
117                   printf "\n"
118                   add "$OPTARG" "$pass"
119                   ;;
120                s) show "$OPTARG" ;;
121                c) copy "$OPTARG" ;;
122                d) del "$OPTARG" ;;
123                *|h) usage ;;
124            esac
125        done
126        shift $(( OPTIND -1 ))
127    }
128    main "$@"
129  ''