Commit b8a3266
Changed files (3)
lib
tfa
spec
lib/tfa/cli.rb
@@ -33,13 +33,61 @@ module TFA
TotpCommand.new(storage).run('', secret)
end
+ desc "upgrade", "upgrade the pstore database to a yml database."
+ def upgrade
+ pstore_path = File.join(directory, ".#{filename}.pstore")
+ yml_path = File.join(directory, ".#{filename}.yml")
+
+ if !File.exist?(pstore_path)
+ say "Unable to detect #{pstore_path}"
+ return ""
+ end
+
+ say "Detected #{pstore_path}"
+ case ask "Would you like to upgrade to #{yml_path}", limited_to: ["yes", "no"]
+ when "yes"
+ say "Let's begin..."
+ pstore_storage = Storage.new(pstore_path)
+ yaml_storage = Storage.new(yml_path)
+ pstore_storage.each do |row|
+ row.each do |name, secret|
+ case ask "Would you like to migrate `#{name}`?", limited_to: ["yes", "no"]
+ when "yes"
+ say "Migrating `#{name}`..."
+ yaml_storage.save(name, secret)
+ end
+ end
+ end
+ case ask "Would you like to delete `#{pstore_path}`? (this action cannot be undone.)", limited_to: ["yes", "no"]
+ when "yes"
+ File.delete(pstore_path)
+ end
+ else
+ say "Nothing to do. Goodbye!"
+ end
+ ""
+ end
+
private
def storage
- @storage ||= Storage.new(
- filename: options[:filename] || 'tfa',
- directory: options[:directory] || Dir.home,
- )
+ @storage ||= Storage.new(File.exist?(pstore_path) ? pstore_path : yml_path)
+ end
+
+ def filename
+ options[:filename] || 'tfa'
+ end
+
+ def directory
+ options[:directory] || Dir.home
+ end
+
+ def pstore_path
+ File.join(directory, ".#{filename}.pstore")
+ end
+
+ def yml_path
+ File.join(directory, ".#{filename}.yml")
end
def clean(secret)
lib/tfa/storage.rb
@@ -2,14 +2,13 @@ module TFA
class Storage
include Enumerable
- def initialize(filename: 'tfa', directory: Dir.home)
- pstore_path = File.join(directory, ".#{filename}.pstore")
- if File.exist?(pstore_path)
- @storage = PStore.new(pstore_path)
- else
- path = File.join(directory, ".#{filename}.yml")
- @storage = YAML::Store.new(path)
- end
+ def initialize(path)
+ @storage =
+ if ".pstore" == File.extname(path)
+ PStore.new(path)
+ else
+ YAML::Store.new(path)
+ end
end
def each
spec/lib/totp_command_spec.rb
@@ -1,7 +1,7 @@
module TFA
describe TotpCommand do
subject { TotpCommand.new(storage) }
- let(:storage) { Storage.new(filename: SecureRandom.uuid, directory: Dir.tmpdir) }
+ let(:storage) { Storage.new(File.join(Dir.tmpdir, ".#{SecureRandom.uuid}.yml")) }
def code_for(secret)
::ROTP::TOTP.new(secret).now