Last active
July 7, 2024 01:13
-
-
Save chaorace/98417a693ca73c51a8688ac09e61d2b0 to your computer and use it in GitHub Desktop.
Nyxt extension nx-passt: a pass interface with filename-based username support. See also: https://github.com/atlas-engineer/nyxt/issues/3293
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(define-nyxt-user-system-and-load "nyxt-user/nx-passt" | |
:depends-on (:nx-passt) :components ("passt.lisp")) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defmethod initialize-instance :after | |
((interface nx-passt:password-store-interface) &key &allow-other-keys) | |
;; Leave this as the default t if you only want to get username from the filename as a last resort | |
(setf (nx-passt:use-encrypted-username interface) nil)) | |
(define-configuration nyxt/mode/password:password-mode | |
((nyxt/mode/password:password-interface | |
(make-instance 'nx-passt:password-store-interface)))) | |
(define-configuration buffer | |
((default-modes | |
(append (list 'nyxt/mode/password:password-mode) %slot-value%)))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(asdf:defsystem #:nx-passt | |
:description "Introduces pass provider with filename-based username support" | |
:author "Christopher Crockett" | |
:license "MIT" | |
:version "1.0.0" | |
:serial t | |
:depends-on (#:nyxt) | |
:components ((:file "package") | |
(:file "nx-passt"))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(in-package #:nx-passt) | |
(define-class password-store-interface (password:password-store-interface) | |
((use-encrypted-username t :documentation | |
"If nil, Nyxt skips decrypting credentials to look for *username-keys* and instead immediately uses the fallback filename-based strategy.")) | |
(:export-class-name-p t) | |
(:export-accessor-names-p t)) | |
(push 'password-store-interface password:*interfaces*) | |
(defun username-from-name (password-name) | |
"Compute a username using the path of the credential file. | |
The strategy for deriving the username is context dependent: | |
- If the credential exists in a subdirectory of the password store (e.g.: example.com/[email protected]), username is taken as-is from the filename ([email protected]) | |
- If the credential exists in the root of the password store (e.g.: [email protected]@example.com), username will be the first half of the filename ([email protected]) | |
This is meant to handle the naming patterns described in Emacs documentation | |
https://www.gnu.org/software/emacs/manual/html_node/auth/The-Unix-password-store.html | |
" | |
(multiple-value-bind (_ parent-dirs credential-name) (uiop/pathname:split-unix-namestring-directory-components password-name) | |
(declare (ignore _)) | |
(if parent-dirs | |
credential-name | |
(subseq credential-name 0 (position #\@ credential-name :from-end t))))) | |
(defun username-from-key (password-interface password-name) | |
"Decrypt the `password-name' credential and extract username from the first key matching one of `*username-keys*'" | |
(let* ((content (password::execute password-interface (list "show" password-name) | |
:output '(:string :stripped t))) | |
(entries (password::parse-multiline content)) | |
(username-entry (when entries | |
(some (lambda (key) | |
(find key entries :test #'string-equal :key #'first)) | |
password::*username-keys*)))) | |
(when username-entry (second username-entry)))) | |
(defmethod password:clip-username ((password-interface password-store-interface) &key password-name service) | |
"Save the username of the `password-name' credential to clipboard. | |
If `use-encrypted-username' is t, the credential will be decrypted to look for a key matching one of `*username-keys'. | |
If a matching key is found, the corresponding multiline entry will be saved to clipboard. | |
If no matching key is found or `*use-encrypted-username' is nil, username detection falls back to deriving a username based upon `password-name'. | |
Case is ignored. | |
The resulting username is also returned." | |
(declare (ignore service)) | |
(when password-name | |
(let ((username | |
(or (when (use-encrypted-username password-interface) | |
(username-from-key password-interface password-name)) | |
(username-from-name password-name)))) | |
(when username | |
(trivial-clipboard:text username) | |
username)))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(nyxt:define-package #:nx-passt | |
(:use #:nyxt/mode/password)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For those unfamiliar: Extension files go in
.local/share/nyxt/extensions/nx-passt
. Config files go in.config/nyxt