1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
;;; kasi-auth-source.el --- auth-sources backend for kasi -*- lexical-binding: t -*-
;; Copyright (C) 2026 Vineet K
;; Author: Vineet K <git@vineetk.net>
;; Version: 1.0
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Provides an auth-sources backend for kasi.el. After loading, add
;; 'kasi to `auth-sources', e.g.:
;;
;; (add-to-list 'auth-sources 'kasi)
;; (auth-source-forget-all-cached)
;;
;; The kasi file path (e.g. "category/file") is matched against the
;; `:host' parameter. The `:user' parameter can optionally be used to
;; filter by the username stored in the kasi entry.
;;; Code:
(require 'auth-source)
(require 'kasi)
(require 'cl-lib)
(require 'seq)
(eval-when-compile (require 'subr-x))
(defgroup kasi-auth-source nil
"auth-sources integration for kasi."
:prefix "kasi-auth-source-"
:group 'auth-source
:group 'kasi)
(cl-defun kasi-auth-source--search (&rest spec
&key backend type host user
port require max
&allow-other-keys)
"Search kasi entries matching SPEC.
See `auth-source-search' for details on SPEC, BACKEND, TYPE, HOST,
USER, PORT, REQUIRE, and MAX."
(cl-assert (or (null type) (eq type (oref backend type)))
t "Invalid kasi search: %s %s" type (oref backend type))
(when (eq host t)
(warn "kasi-auth-source does not handle host wildcards.")
(cl-return-from kasi-auth-source--search nil))
(when-let* ((results (kasi-auth-source--find host user port require)))
(when (and max (> (length results) max))
(setq results (seq-take results max)))
results))
(defun kasi-auth-source--find (host user port require)
"Find kasi entries matching HOST, USER, PORT and REQUIRE.
Searches all kasi files under `kasi-dir`. HOST is matched against
the kasi file path (e.g. \"category/file\"). USER is matched against
the username stored in each kasi entry. PORT and REQUIRE are
optional filters."
(let ((files (file-expand-wildcards (concat kasi-dir "/*/*")))
result)
(cl-block nil
(dolist (file files)
(message "kasi-auth-source: checking %s" file)
(when-let* ((short-name (kasi--filename-short file))
((or (not host) (string= short-name host)))
(entry-user (kasi--get file 'username))
(entry-email (kasi--get file 'email))
((or (not user) (string= entry-user user)))
(require-match (seq-every-p
(lambda (key)
(pcase key
('user (and user (string= entry-user user)))
('host t)
('port t)
(_ t)))
(or require '()))))
(setq result (list (list :host short-name
:user entry-user
:port port
:email entry-email
:secret (lambda ()
(let ((pw (kasi--get file 'password)))
pw)))))
(cl-return-from nil result)))
result)))
(defvar kasi-auth-source-backend
(auth-source-backend
:source "."
:type 'kasi
:search-function #'kasi-auth-source--search)
"Auth-source backend for kasi.")
(defun kasi-auth-source-backend-parse (entry)
"Create a kasi auth-source backend from ENTRY."
(when (eq entry 'kasi)
(auth-source-backend-parse-parameters entry kasi-auth-source-backend)))
(add-hook 'auth-source-backend-parser-functions
#'kasi-auth-source-backend-parse)
;;;###autoload
(defun kasi-auth-source-enable ()
"Enable kasi as an auth-source backend.
This adds 'kasi to `auth-sources' and clears the auth-source cache."
(interactive)
(add-to-list 'auth-sources 'kasi)
(auth-source-forget-all-cached)
(message "kasi auth-source backend enabled"))
(provide 'kasi-auth-source)
;;; kasi-auth-source.el ends here
|