From 5f6645c032a2b1a2e30c1b9bbd27c813ec5b279b Mon Sep 17 00:00:00 2001 From: Lucien Cartier-Tilet Date: Mon, 14 Feb 2022 11:28:49 +0100 Subject: [PATCH] =?UTF-8?q?Login=20improvements,=20rename=20transient?= =?UTF-8?q?=E2=80=99s=20variables=20and=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New file: TODOs.org Keep track of what I need to do New variable: bitwarden--session. See TODOs.org Rename variables generated for transient infixes Rename action function for transients Add action "get-server" Rewrite login action Begin to implement bitwarden-lock --- TODOs.org | 49 +++++++++++++++ bitwarden.el | 168 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 161 insertions(+), 56 deletions(-) create mode 100644 TODOs.org diff --git a/TODOs.org b/TODOs.org new file mode 100644 index 0000000..c0fd197 --- /dev/null +++ b/TODOs.org @@ -0,0 +1,49 @@ +* Bitwarden TODO list [0/22] +** TODO [#A] Read the session key from ~$HOME/.config/Bitwarden CLI/data.json~ +** TODO [#A] ~bitwarden-login~ [1/2] +*** DONE Implementation +CLOSED: [2022-02-14 Mon 11:42] +The variable ~bitwarden--session~ should be initialized when loading the +library. +*** TODO Test ~bitwarden-login~ [0/5] +**** TODO [#A] Test authinfo login +**** TODO [#A] Test plain password login +**** TODO [#B] Test password env login +**** TODO [#B] Test password file login +**** TODO [#C] Test SSO login +I don’t have access to SSO login, I’ll have to rely on someone else to +do it for me. + +** TODO [#A] ~bitwarden-get~ [0/0] +** TODO [#A] ~bitwarden-create~ [0/0] +** TODO [#A] ~bitwarden-edit~ [0/0] +** TODO [#A] ~bitwarden-delete~ [0/0] +** TODO [#A] ~bitwarden-list~ [0/0] +** TODO [#B] ~bitwarden-config~ [1/2] +*** DONE Implementation +CLOSED: [2022-02-14 Mon 11:43] +*** TODO Test ~bitwarden-config~ [0/3] +**** TODO [#B] Test setting server information +**** TODO [#C] Test getting server information +**** TODO [#C] Extra URLs should be stored in variables +They can be read from the ~$HOME/.config/Bitwarden CLI/data.json~ file. +** TODO [#B] ~bitwarden-unlock~ [0/2] +*** TODO Implementation +*** TODO Test ~bitwarden-unlock~ +** TODO [#B] ~bitwarden-lock~ [1/2] +*** DONE Implementation +CLOSED: [2022-02-14 Mon 11:49] +*** TODO Test ~bitwarden-lock~ +** TODO [#B] Bitwarden status [0/0] +To be displayed in the main bitwarden transient +** TODO [#B] ~bitwarden-export~ [0/0] +** TODO [#B] ~bitwarden-restore~ [0/0] +** TODO [#A] ~bitwarden-generate~ [0/0] +** TODO [#C] ~bitwarden-sync~ [0/0] +** TODO [#C] ~bitwarden-encode~ [0/0] +** TODO [#C] ~bitwarden-update~ [0/0] +** TODO [#C] ~bitwarden-move~ [0/0] +** TODO [#C] ~bitwarden-confirm~ [0/0] +** TODO [#C] ~bitwarden-import~ [0/0] +** TODO [#C] ~bitwarden-share~ [0/0] +** TODO [#C] ~bitwarden-send~ [0/0] diff --git a/bitwarden.el b/bitwarden.el index e818ed4..836cf3f 100644 --- a/bitwarden.el +++ b/bitwarden.el @@ -104,6 +104,7 @@ :version "0.1.0") (defvar bitwarden--shell-status) +(defvar bitwarden--session) ;;; Internal Functions @@ -114,8 +115,8 @@ The default arguments specified by `bitwarden-default-cli-arguments' immediately follow the cli’s name defined in `bitwarden-cli-executable'. -The output status of the command is stored in RESULT, which -should be a variable’s symbol." +The exit status of the command is stored in +`bitwarden--shell-status'." (eshell-command-result (mapconcat #'identity (flatten-tree `(,bitwarden-cli-executable ,bitwarden-default-cli-arguments ,args)) @@ -137,7 +138,7 @@ DESCRIPTION and a specified VERSION. The KEY and READER are for the infix declaration. This macro is largely copied from Tecosaur’s screenshot.el" - (let ((var-name (concat "bitwarden-" name))) + (let ((var-name (concat "bitwarden--" name))) `(progn (defcustom ,(intern var-name) ,default ,description @@ -154,9 +155,8 @@ This macro is largely copied from Tecosaur’s screenshot.el" :reader (lambda (&rest _) ,@reader))))) ;; Config - (bitwarden--define-infix - "-s" "server" "On-premises hosted installation URL" + "-s" "config-server" "On-premises hosted installation URL" 'string "0.1.0" (let ((output-str (bitwarden--run-cli "config" "server"))) (if (eq 0 bitwarden--shell-status) @@ -167,48 +167,95 @@ This macro is largely copied from Tecosaur’s screenshot.el" ;; Login (bitwarden--define-infix - "-u" "username" "Email of the user." + "-u" "login-username" "Email of the user." 'string "0.1.0" - "" + nil (read-string "Email address: ")) (bitwarden--define-infix - "-p" "password" "Password of the user" + "-p" "login-password" "Password of the user" 'string "0.1.0" - "" + nil (read-string "Password: ")) (bitwarden--define-infix - "-s" "sso" "Log in with Single-Sign On" - 'boolean "0.1.0" nil + "-s" "login-sso" "Log in with Single-Sign On" + 'boolean "0.1.0" + nil (not bitwarden-sso)) (bitwarden--define-infix - "-e" "passwordenv" "Environment variable storing your password" + "-e" "login-passwordenv" "Environment variable storing your password" 'string "0.1.0" - "" + nil (read-string "Environment variable: ")) (bitwarden--define-infix - "-f" "passwordfile" + "-f" "login-passwordfile" "Path to a file containing your password as its first line" - 'string "0.1.0" "" + 'string "0.1.0" + nil (read-file-name "Password file: ")) (bitwarden--define-infix - "-c" "code" + "-c" "login-code" "Two-step login code" - 'string "0.1.0" "" + 'string "0.1.0" + nil (read-string "Two-step code: ")) (bitwarden--define-infix - "-m" "method" + "-m" "login-method" "Two-step login method" - 'string "0.1.0" "0" + 'string "0.1.0" + "0" (cdr (assoc (completing-read "Two-step login method: " bitwarden-login-methods) bitwarden-login-methods)))) +(defsubst bitwarden--empty-or-nil (var) + "Return t if VAR is an empty string or nil. +Return nil otherwise." + (or (not var) + (string= "" var))) + +(defsubst bitwarden--quote-string (str) + "Escape STR and surround it by single quotes." + (format "\'%s\'" + (replace-regexp-in-string "'" + (regexp-quote "\\'") + str))) + +(defun bitwarden--get-username () + "Get username. +If the `bitwarden--username' variable is empty, retrieve it from +the authinfo source." + (if (bitwarden--empty-or-nil bitwarden--username) + (plist-get (car (auth-source-search :max 1 + :host bitwarden--server)) + :user) + bitwarden--username)) + +(defun bitwarden--get-password () + "Get password or password source. +By order of preference, retrieve the password from either the +Elisp variable `bitwarden--password', from the environment file +designated by the variable `bitwarden--passwordenv', by the file +designated by the variable `bitwarden-passwordfile', or from the +authinfo source." + (cond + ((not (bitwarden--empty-or-nil bitwarden-password)) + bitwarden--password) + ((! (bitwarden--empty-or-nil bitwarden--passwordenv)) + `("--passwordenv" ,bitwarden--passwordenv)) + ((! (bitwarden--set-passwordfile bitwarden--passwordfile)) + `("--passwordfile" ,bitwarden--passwordfile)) + (t (funcall + (plist-get + (car (auth-source-search :max 1 + :host bitwarden--server)) + :secret))))) + ;;; Transient Actions (eval-when-compile @@ -229,7 +276,13 @@ This function is meant to be called by a transient.") "set-server" "Set the Bitwarden server." 'bitwarden--server - (message "%s" (format "%S" _args))) + (bitwarden--run-cli "config" "server" bitwarden--server)) + + (bitwarden--def-action + "get-server" + "Get the URL of the on-premises hosted installation." + 'bitwarden--server + (bitwarden--run-cli "config" "server")) ;; Login @@ -237,30 +290,21 @@ This function is meant to be called by a transient.") "login" "Log in Bitwarden." 'bitwarden--login - (if bitwarden-sso + (if bitwarden--sso (bitwarden--run-cli "login" "--raw" "--sso") (bitwarden--run-cli "login" "--raw" - ;; bitwarden-username - (format "\"%s\"" - (if (string= "" bitwarden-username)) - (plist-get (car (auth-source-search - :max 1 - :host bitwarden-server)) - :user) - bitwarden-username) - (format "\"%s\"" - (cond - ((not (string= "" bitwarden-password)) - bitwarden-password) - ((! (string= "" bitwarden-passwordenv)) - bitwarden-passwordenv) - ((! (string= "" bitwarden-passwordfile)) - bitwarden-passwordfile) - (t (funcall - (plist-get - (car (auth-source-search :max 1 - :host bitwarden-server)) - :secret)))))))) + (format "\"%s\"" (bitwarden--get-username)) + (cond + ((not (bitwarden--empty-or-nil bitwarden--login-password)) + (bitwarden--quote-string bitwarden--login-password)) + ((not (bitwarden--empty-or-nil bitwarden--login-passwordenv)) + `("--passwordenv" ,(bitwarden--quote-string bitwarden--login-passwordenv))) + ((not (bitwarden--empty-or-nil bitwarden--login-passwordfile)) + `("--paswordfile" ,(bitwarden--quote-string bitwarden--login-passwordfile))) + (t + (funcall (plist-get (car (auth-source-search :max 1 + :host bitwarden--config-server)) + :secret))))))) (bitwarden--def-action "logout" @@ -272,29 +316,41 @@ This function is meant to be called by a transient.") ;;; Transient Prefixes (transient-define-prefix bitwarden-config () ["Options" - (bitwarden--set-server)] + (bitwarden--set-config-server)] ["Actions" - ("g" "Get current server" bitwarden-hello) - ("s" "Set current server" bitwarden-hello)]) + ("g" "Get current server" bitwarden--action-get-server) + ("s" "Set current server" bitwarden--action-set-server)]) (transient-define-prefix bitwarden-login () ["Options" - (bitwarden--set-username) - (bitwarden--set-password) - (bitwarden--set-passwordenv) - (bitwarden--set-passwordfile) - (bitwarden--set-method) - (bitwarden--set-code)] + (bitwarden--set-login-username) + (bitwarden--set-login-password) + (bitwarden--set-login-passwordenv) + (bitwarden--set-login-passwordfile) + (bitwarden--set-login-method) + (bitwarden--set-login-code)] ["Actions" - ("l" "Login" bitwarden-login) - ("L" "Logout" bitwarden-logout)]) + ("l" "Login" bitwarden--action-login) + ("L" "Logout" bitwarden--action-logout)]) (transient-define-prefix bitwarden-transient () ["Actions" ("c" "Config" bitwarden--config) - ("l" "Login" bitwarden--login) - ("L" "Lock" bitwarden-hello) - ("s" "sync" bitwarden-hello)]) + ("l" "Login" bitwarden--login) + ("L" "Lock" bitwarden-lock) + ("s" "sync" bitwarden-hello)]) + +;;; Public functions +(defun bitwarden-lock () + "Lock the vault and destroy active session keys." + (progn + (setq bitwarden--session nil + bitwarden--password nil + bitwarden--passwordenv nil + bitwarden--passwordfile nil + bitwarden--code nil) + (bitwarden--run-cli "lock"))) + ;; (defun bitwarden () ;; (interactive)