Browse Source

bitwarden: refactor runcmd to return error strings

This cleans up the automatic unlock code to use recursion and abstracts
our error strings as well.
Sean Farley 7 years ago
parent
commit
42ad04caa8
1 changed files with 43 additions and 32 deletions
  1. 43 32
      bitwarden.el

+ 43 - 32
bitwarden.el

@@ -57,6 +57,10 @@ example, this can be the :secret plist from
   :group 'bitwarden
   :group 'bitwarden
   :type 'function)
   :type 'function)
 
 
+(defconst bitwarden--err-logged-in "you are not logged in")
+(defconst bitwarden--err-multiple  "more than one result found")
+(defconst bitwarden--err-locked    "vault is locked")
+
 (defun bitwarden-logged-in-p ()
 (defun bitwarden-logged-in-p ()
   "Check if `bitwarden-user' is logged in.
   "Check if `bitwarden-user' is logged in.
 Returns nil if not logged in."
 Returns nil if not logged in."
@@ -93,15 +97,10 @@ for common errors."
             (if (eq exit-code 0)
             (if (eq exit-code 0)
                 output
                 output
               (cond ((string-match "^More than one result was found." output)
               (cond ((string-match "^More than one result was found." output)
-                     (message "Bitwarden: more than one result found")
-                     nil)
-                    (t
-                     (message "Bitwarden: unknown error: %s" output)
-                     nil))))
-        (message "Bitwarden: vault is locked")
-        nil)
-    (message "Bitwarden: you are not logged in")
-    nil))
+                     bitwarden--err-multiple)
+                    (t nil))))
+        bitwarden--err-locked)
+    bitwarden--err-logged-in))
 
 
 (defun bitwarden--login-proc-filter (proc string)
 (defun bitwarden--login-proc-filter (proc string)
   "Interacts with PROC by sending line-by-line STRING."
   "Interacts with PROC by sending line-by-line STRING."
@@ -198,33 +197,45 @@ since that could be set yet could be expired or incorrect."
     (bitwarden-lock)))
     (bitwarden-lock)))
 
 
 ;;;###autoload
 ;;;###autoload
-(defun bitwarden-getpass (account &optional print-message)
+(defun bitwarden-getpass (account &optional print-message recursive-pass)
   "Get password associated with ACCOUNT.
   "Get password associated with ACCOUNT.
+
 If run interactively PRINT-MESSAGE gets set and password is
 If run interactively PRINT-MESSAGE gets set and password is
-printed to minibuffer."
+printed to minibuffer.
+
+If RECURSIVE-PASS is set, then treat this call as an attempt to auto-unlock."
   (interactive "MBitwarden account name: \np")
   (interactive "MBitwarden account name: \np")
-  (let ((pass (bitwarden-runcmd "get" "password" account)))
-    (if (not pass)
-        ;; try to unlock automatically, if possible
-        (if bitwarden-automatic-unlock
-            (progn
-              ;; because I don't understand how emacs is asyncronous here nor
-              ;; how to tell it to wait until the process is done, we do so here
-              ;; manually
-              (bitwarden-unlock)
-              (while (get-process "bitwarden")
-                (sleep-for 0.1))
-
-              (setq pass (bitwarden-runcmd "get" "password" account))
-              (if (not pass)
-                  (message "Bitwarden: could not get password for %s" account)
-                (when print-message
-                  (message "Bitwarden: password for account %s is: %s" account pass))
-                pass))
-          (message "Bitwarden: could not get password for %s" account))
+  (let* ((pass (or recursive-pass
+                   (bitwarden-runcmd "get" "password" account))))
+    (cond
+     ((string-match bitwarden--err-locked pass)
+      ;; try to unlock automatically, if possible
+      (if (not bitwarden-automatic-unlock)
+          (progn
+            (when print-message
+              (message "Bitwarden: error: %s" pass))
+            nil)
+
+        ;; only attempt a retry once; to prevent infinite recursion
+        (when (not recursive-pass)
+          ;; because I don't understand how emacs is asyncronous here nor
+          ;; how to tell it to wait until the process is done, we do so here
+          ;; manually
+          (bitwarden-unlock)
+          (while (get-process "bitwarden")
+            (sleep-for 0.1))
+          (bitwarden-getpass account print-message
+                             (bitwarden-runcmd "get" "password" account)))))
+
+     ((string-match bitwarden--err-logged-in pass)
+      (when print-message
+        (message "Bitwarden: error: %s" pass))
+      nil)
+     ((string-match bitwarden--err-multiple pass)
       (when print-message
       (when print-message
-        (message "Bitwarden: password for account %s is: %s" account pass))
-      pass)))
+        (message "Bitwarden: error: %s" pass))
+      nil)
+     (t pass))))
 
 
 (provide 'bitwarden)
 (provide 'bitwarden)