commit bd23de7b9f560da8c989b179954e9edf53a3452b
parent 8f1b0f7f01b23261d36c757c3c8cb6b306d8356f
Author: Daniel Barlow <dan@telent.net>
Date: Mon, 9 Feb 2026 13:51:42 +0000
add "moss qr" command
Diffstat:
7 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,12 +3,14 @@ default: moss.rb
AGE?=$(shell command -v age)
AGE_KEYGEN?=$(shell command -v age-keygen)
GIT?=$(shell command -v git)
+QRENCODE?=$(shell command -v qrencode)
install: default
mkdir -p $(prefix)/bin
sed < moss.rb > $(prefix)/bin/moss \
-e 's@^AGE=.*$$@AGE="$(AGE)"@' \
-e 's@^AGE_KEYGEN=.*$$@AGE_KEYGEN="$(AGE_KEYGEN)"@' \
+ -e 's@^QRENCODE=.*$$@QRENCODE="$(QRENCODE)"@' \
-e 's@^GIT=.*$$@GIT="$(GIT)"@'
chmod a+rx $(prefix)/bin/moss
diff --git a/default.nix b/default.nix
@@ -2,11 +2,12 @@
, git
, ruby
, age ? (callPackage ./age.nix {})
+, qrencode
, callPackage}:
stdenv.mkDerivation {
name = "moss";
src = ./.;
- buildInputs = [ age git ruby ];
+ buildInputs = [ age git ruby qrencode ];
installPhase = ''
make install prefix=$out
'';
diff --git a/features/fixtures/horsebattery.qransi b/features/fixtures/horsebattery.qransi
@@ -0,0 +1,15 @@
+[40;37;1m█████████████████████████████[0m
+[40;37;1m█████████████████████████████[0m
+[40;37;1m████ ▄▄▄▄▄ ██ ▄ ▄█ ▄▄▄▄▄ ████[0m
+[40;37;1m████ █ █ █▀ ▀▀██ █ █ ████[0m
+[40;37;1m████ █▄▄▄█ █▄█ ▄ █ █▄▄▄█ ████[0m
+[40;37;1m████▄▄▄▄▄▄▄█▄▀ ▀ █▄▄▄▄▄▄▄████[0m
+[40;37;1m████ ▀▀▀ ▄ █ ▀█ ▀▀▀▄ ███████[0m
+[40;37;1m████▄█▀▄ ▄▀ ▄█▄█▀█▀█ ▀▄█████[0m
+[40;37;1m█████▄▄▄▄█▄█ ▀██▀▀█▄ █▀▄▀████[0m
+[40;37;1m████ ▄▄▄▄▄ █ ▀▀ ▀▀██▀▀▄▀████[0m
+[40;37;1m████ █ █ ██▀ ▀█▀▄▄▀▄▀▄▄████[0m
+[40;37;1m████ █▄▄▄█ █▀█ █▄▀▄▀▄▀▀▄▄████[0m
+[40;37;1m████▄▄▄▄▄▄▄█▄▄▄█▄▄▄████▄█████[0m
+[40;37;1m█████████████████████████████[0m
+[40;37;1m█████████████████████████████[0m
diff --git a/features/moss.feature b/features/moss.feature
@@ -34,6 +34,11 @@ Feature: command-line password management
When I view the secret "home/ebay"
Then I see the string "horsebattery"
+ Scenario: I can view a secret as a QR code
+ Given I am using the example password store
+ When I view the secret "home/ebay" as QR code
+ Then I see a QR code for "horsebattery"
+
Scenario: I can list secrets
Given I am using the example password store
When I list the secrets
diff --git a/features/step_definitions/steps.rb b/features/step_definitions/steps.rb
@@ -91,6 +91,10 @@ Then("I see the string {string}") do |s|
expect(@i_see).to match(s)
end
+Then("I see a QR code for {string}") do |s|
+ expect(@i_see).to eq(File.read("#{__dir__}/../fixtures/#{s}.qransi"))
+end
+
Then("{string} plaintext is {string}") do |name, expected|
path_name = store_path(name)
contents = File.read(path_name)
@@ -134,6 +138,10 @@ When("I view the secret {string}") do |name|
@i_see = shell "#{MOSS} cat #{name}"
end
+When("I view the secret {string} as QR code") do |name|
+ @i_see = shell "#{MOSS} qr #{name}"
+end
+
When("I search for {string}") do |term|
@i_see = shell "#{MOSS} search #{term}"
end
diff --git a/moss.rb b/moss.rb
@@ -8,6 +8,7 @@ require "json"
AGE='age'
AGE_KEYGEN='age-keygen'
GIT='git'
+QRENCODE='qrencode'
def xdg_data_home
ENV.fetch("XDG_DATA_HOME", "#{ENV['HOME']}/.local/share")
@@ -338,6 +339,13 @@ def cli
end
link :cat => :show
+ command :qr, "display QR code for a secret" do |file:|
+ secret = MOSS.read_secret(file)
+ IO.popen([QRENCODE,"-t", "ansiutf8"], "w") do |f|
+ f.write(secret)
+ end
+ end
+
command :search, "search secrets with names matching term" do |*term|
files = MOSS.secrets.filter { |f|
f.match(Regexp.new(term.join(" ")))
diff --git a/shell.nix b/shell.nix
@@ -4,13 +4,14 @@ let gems = bundlerEnv {
groups = [ "default" "production" "development" "test" ];
gemdir = ./.;
};
- age = pkgs.callPackage ./age.nix {};
+ package = callPackage ./. { } ;
in mkShell {
MOSS_HOME = "/tmp/${builtins.getEnv "USER"}/moss_home";
CUCUMBER_PUBLISH_QUIET = "true";
- packages = [
+ packages = package.buildInputs ++ [
gems gems.wrappedRuby
pkgs.expect
- bundix age pkgs.entr
+ bundix
+ pkgs.entr
];
}