aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorDamien Cassou2019-05-14 05:50:59 +0200
committerDamien Cassou2019-06-24 09:15:41 +0200
commit7022e3fde6bc577cc281bd8770fe5a41f7492b4f (patch)
tree7c423e6931eb57a3a5d0bf7ec7c3153cbfbbf0a3 /lisp
parent736f78bb1af0593d9b02f0a45a64b1422a6fcc12 (diff)
downloademacs-7022e3fde6bc577cc281bd8770fe5a41f7492b4f.tar.gz
emacs-7022e3fde6bc577cc281bd8770fe5a41f7492b4f.zip
Refactoring of auth-source-pass
* lisp/auth-source-pass.el (auth-source-pass--find-match): Refactor by moving some code to auth-source-pass--disambiguate. (auth-source-pass--disambiguate) (auth-source-pass--entries-matching-suffix): New function. (auth-source-pass--find-match-unambiguous) (auth-source-pass--select-from-entries) (auth-source-pass--entry-reducer): Refactor to simplify and improve logging. (auth-source-pass--matching-entries) (auth-source-pass--accumulate-matches): Remove. * test/lisp/auth-source-pass-tests.el: Complete rewrite to facilitate maintenance. (auth-source-pass--have-message-containing): Remove. (auth-source-pass--have-message-matching) (auth-source-pass--explain--have-message-matching) (auth-source-pass--explain-match-entry-p) (auth-source-pass--includes-sorted-entries) (auth-source-pass--explain-includes-sorted-entries) (auth-source-pass--explain-match-any-entry-p) (auth-source-pass--matching-entries) (auth-source-pass-match-entry-p) (auth-source-pass-match-any-entry-p): New function.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/auth-source-pass.el108
1 files changed, 45 insertions, 63 deletions
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index af421645cbc..295bda507b0 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -197,10 +197,17 @@ CONTENTS is the contents of a password-store formatted file."
197 197
198Disambiguate between user provided inside HOST (e.g., user@server.com) and 198Disambiguate between user provided inside HOST (e.g., user@server.com) and
199inside USER by giving priority to USER. Same for PORT." 199inside USER by giving priority to USER. Same for PORT."
200 (apply #'auth-source-pass--find-match-unambiguous (auth-source-pass--disambiguate host user port)))
201
202(defun auth-source-pass--disambiguate (host &optional user port)
203 "Return (HOST USER PORT) after disambiguation.
204Disambiguate between having user provided inside HOST (e.g.,
205user@server.com) and inside USER by giving priority to USER.
206Same for PORT."
200 (let* ((url (url-generic-parse-url (if (string-match-p ".*://" host) 207 (let* ((url (url-generic-parse-url (if (string-match-p ".*://" host)
201 host 208 host
202 (format "https://%s" host))))) 209 (format "https://%s" host)))))
203 (auth-source-pass--find-match-unambiguous 210 (list
204 (or (url-host url) host) 211 (or (url-host url) host)
205 (or user (url-user url)) 212 (or user (url-user url))
206 ;; url-port returns 443 (because of the https:// above) by default 213 ;; url-port returns 443 (because of the https:// above) by default
@@ -212,74 +219,49 @@ If many matches are found, return the first one. If no match is found,
212return nil. 219return nil.
213 220
214HOSTNAME should not contain any username or port number." 221HOSTNAME should not contain any username or port number."
215 (cl-reduce 222 (let ((all-entries (auth-source-pass-entries))
216 (lambda (result entries) 223 (suffixes (auth-source-pass--generate-entry-suffixes hostname user port)))
217 (or result 224 (auth-source-pass--do-debug "searching for entries matching hostname=%S, user=%S, port=%S"
218 (pcase (length entries) 225 hostname (or user "") (or port ""))
219 (0 nil) 226 (auth-source-pass--do-debug "corresponding suffixes to search for: %S" suffixes)
220 (1 (auth-source-pass-parse-entry (car entries))) 227 (catch 'auth-source-pass-break
221 (_ (auth-source-pass--select-from-entries entries user))))) 228 (dolist (suffix suffixes)
222 (auth-source-pass--matching-entries hostname user port) 229 (let* ((matching-entries (auth-source-pass--entries-matching-suffix suffix all-entries))
223 :initial-value nil)) 230 (best-entry-data (auth-source-pass--select-from-entries matching-entries user)))
231 (pcase (length matching-entries)
232 (0 (auth-source-pass--do-debug "found no entries matching %S" suffix))
233 (1 (auth-source-pass--do-debug "found 1 entry matching %S: %S"
234 suffix
235 (car matching-entries)))
236 (_ (auth-source-pass--do-debug "found %s entries matching %S: %S"
237 (length matching-entries)
238 suffix
239 matching-entries)))
240 (when best-entry-data
241 (throw 'auth-source-pass-break best-entry-data)))))))
224 242
225(defun auth-source-pass--select-from-entries (entries user) 243(defun auth-source-pass--select-from-entries (entries user)
226 "Return best matching password-store entry data from ENTRIES. 244 "Return best matching password-store entry data from ENTRIES.
227 245
228If USER is non nil, give precedence to entries containing a user field 246If USER is non nil, give precedence to entries containing a user field
229matching USER." 247matching USER."
230 (cl-reduce 248 (let (fallback)
231 (lambda (result entry) 249 (catch 'auth-source-pass-break
232 (let ((entry-data (auth-source-pass-parse-entry entry))) 250 (dolist (entry entries fallback)
233 (cond ((equal (auth-source-pass--get-attr "user" result) user) 251 (let ((entry-data (auth-source-pass-parse-entry entry)))
234 result) 252 (when (and entry-data (not fallback))
235 ((equal (auth-source-pass--get-attr "user" entry-data) user) 253 (setq fallback entry-data)
236 entry-data) 254 (when (or (not user) (equal (auth-source-pass--get-attr "user" entry-data) user))
237 (t 255 (throw 'auth-source-pass-break entry-data))))))))
238 result)))) 256
239 entries 257(defun auth-source-pass--entries-matching-suffix (suffix entries)
240 :initial-value (auth-source-pass-parse-entry (car entries)))) 258 "Return entries matching SUFFIX.
241 259If ENTRIES is nil, use the result of calling `auth-source-pass-entries' instead."
242(defun auth-source-pass--matching-entries (hostname user port) 260 (cl-remove-if-not
243 "Return all matching password-store entries for HOSTNAME, USER, & PORT. 261 (lambda (entry) (string-match-p
244 262 (format "\\(^\\|/\\)%s$" (regexp-quote suffix))
245The result is a list of lists of password-store entries, where 263 entry))
246each sublist contains entries that actually exist in the 264 (or entries (auth-source-pass-entries))))
247password-store matching one of the entry name formats that
248auth-source-pass expects, most specific to least specific."
249 (let* ((entries-lists (mapcar
250 #'cdr
251 (auth-source-pass--accumulate-matches hostname user port)))
252 (entries (apply #'cl-concatenate (cons 'list entries-lists))))
253 (if entries
254 (auth-source-pass--do-debug (format "found: %S" entries))
255 (auth-source-pass--do-debug "no matches found"))
256 entries-lists))
257
258(defun auth-source-pass--accumulate-matches (hostname user port)
259 "Accumulate matching password-store entries into sublists.
260
261Entries matching supported formats that combine HOSTNAME, USER, &
262PORT are accumulated into sublists where the car of each sublist
263is a regular expression for matching paths in the password-store
264and the remainder is the list of matching entries."
265 (let ((suffix-match-lists
266 (mapcar (lambda (suffix) (list (format "\\(^\\|/\\)%s$" suffix)))
267 (auth-source-pass--generate-entry-suffixes hostname user port))))
268 (cl-reduce #'auth-source-pass--entry-reducer
269 (auth-source-pass-entries)
270 :initial-value suffix-match-lists)))
271
272(defun auth-source-pass--entry-reducer (match-lists entry)
273 "Match MATCH-LISTS sublists against ENTRY.
274
275The result is a copy of match-lists with the entry added to the
276end of any sublists for which the regular expression at the head
277of the list matches the entry name."
278 (mapcar (lambda (match-list)
279 (if (string-match (car match-list) entry)
280 (append match-list (list entry))
281 match-list))
282 match-lists))
283 265
284(defun auth-source-pass--generate-entry-suffixes (hostname user port) 266(defun auth-source-pass--generate-entry-suffixes (hostname user port)
285 "Return a list of possible entry path suffixes in the password-store. 267 "Return a list of possible entry path suffixes in the password-store.