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