commit 9f7956e3395dd4c027de244dc1a92f9a1d431524
parent a780a142f8d00d88618e658bb7965259427428c2
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 8 Aug 2021 23:57:19 +0100
support password editing
Diffstat:
4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/features/rjpass.feature b/features/rjpass.feature
@@ -31,8 +31,8 @@ Feature: command-line password management
@wip
Scenario: I can edit a secret
Given I am using the example password store
- When I edit work/gmail
- Then the editor opens with a plaintext file "horsebattery"
+ When I edit "work/gmail"
+ Then the editor opens a temporary file containing "horsebattery"
Scenario: Secrets are stored in a git repo
diff --git a/features/step_definitions/steps.rb b/features/step_definitions/steps.rb
@@ -62,3 +62,17 @@ end
When("I search for {string}") do |term|
@i_see = shell "#{RJPASS} search #{term}"
end
+
+When("I edit {string}") do |name|
+ ENV["EDITOR"] = "./fixtures/fakedit.sh"
+ @i_see = shell "#{RJPASS} edit #{name}"
+end
+
+Then("the editor opens a temporary file containing {string}") do |expected|
+ magic, pathname, content = @i_see.split("\0")
+ # we test for this magic string to make sure that our fake editor was
+ # invoked
+ expect(magic).to eq('fakedit-magic')
+ expect(pathname).to start_with(ENV['TMPDIR'])
+ expect(content).to eq(expected)
+end
diff --git a/fixtures/fakedit.sh b/fixtures/fakedit.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+echo -en "fakedit-magic\0"
+echo -en "$1\0"
+cat $1
diff --git a/rjpass.rb b/rjpass.rb
@@ -1,5 +1,6 @@
#!/usr/bin/env ruby
require 'pathname'
+require 'tempfile'
STORE = Pathname.new(ENV['RJPASS_STORE'] || "/tmp/store")
IDENTITY = "age1wc392uhfm04sy5nmpu86ea077ymjxs6e3gnda54jvpmuqchj9d5s6d0q2x"
@@ -49,6 +50,20 @@ when 'insert'
when 'cat','show'
file, = ARGV[1..]
STDOUT.write(read_secret(file))
+when 'edit'
+ file, = ARGV[1..]
+ content = read_secret(file)
+ Tempfile.create(file.gsub(/[\W]/,"")) do |f|
+ f.write(content)
+ f.flush
+ if Kernel.system(ENV['EDITOR'], f.path)
+ f.rewind
+ secret = f.read
+ write_secret(file, secret)
+ else
+ raise "#{$!}"
+ end
+ end
when 'search'
term = ARGV[1..].join(" ")
files = Dir[STORE.join('**/*.age')].filter {|f| f.match(Regexp.new(term)) }