lib/keylime/credential.rb in keylime-0.1.2 vs lib/keylime/credential.rb in keylime-0.2.0
- old
+ new
@@ -1,6 +1,7 @@
require 'userinput'
+require 'yaml'
module Keylime
ENABLED = begin
require 'keychain'
true
@@ -45,11 +46,11 @@
).ask
end
def keychain
return @keychain if @keychain
- @keychain = StubKeychain.new unless Keylime::ENABLED
+ @keychain = FileKeychain.new(@options[:keychain]) unless Keylime::ENABLED
@keychain ||= Keychain.open(@options[:keychain]) if @options[:keychain]
@keychain ||= Keychain
end
def key_type
@@ -61,23 +62,101 @@
end
end
##
# Stub keychain for if keylime is running on a non-Mac
- class StubKeychain
+ class FileKeychain
+ def initialize(keychain)
+ @keychain = keychain
+ end
+
def segment
- StubKeychainSegment.new
+ @segment ||= FileKeychainSegment.new(@keychain)
end
alias internet_passwords segment
alias generic_passwords segment
end
##
# Stub segment for if keylime is running on a non-Mac
- class StubKeychainSegment
- def where(_)
- []
+ class FileKeychainSegment
+ def initialize(keychain)
+ @keychain = keychain || '~/.keylime'
end
- def create(_) end
+ def where(fields = {})
+ fields = stringify(fields)
+ entries.select do |x|
+ fields.all? { |k, v| x[k] == v }
+ end
+ end
+
+ def create(fields = {})
+ raise('No fields given') if fields.empty?
+ fields = stringify(fields)
+ fields['ref'] = self
+ new = FileKeychainObject.new(fields)
+ write_file! entries + [new]
+ new
+ end
+
+ def delete(fields = {})
+ raise('No fields given') if fields.empty?
+ fields = stringify(fields)
+ new = entries.select do |x|
+ fields.any? { |k, v| x[k] != v }
+ end
+ write_file! new
+ end
+
+ private
+
+ def entries
+ create_file! unless File.exist? file
+ YAML.safe_load(File.read(file))['credentials'].map do |x|
+ x['ref'] = self
+ FileKeychainObject.new(x)
+ end
+ end
+
+ def create_file!
+ write_file!([])
+ end
+
+ def write_file!(entries)
+ File.open(file, 'w') do |fh|
+ fh << YAML.dump('credentials' => entries.map(&:fields))
+ end
+ end
+
+ def file
+ @file ||= File.expand_path @keychain
+ end
+
+ def stringify(fields)
+ fields.map { |k, v| [k.to_s, v] }.to_h
+ end
+ end
+
+ ##
+ # Object for stub file keychain
+ class FileKeychainObject
+ attr_reader :fields
+
+ def initialize(params = {})
+ @ref = params.delete('ref')
+ @fields = params
+ end
+
+ def delete
+ @ref.delete(@fields)
+ end
+
+ def respond_to_missing?(method, _)
+ @fields.include?(method.to_s) || super
+ end
+
+ def method_missing(sym, *args, &block)
+ @fields[sym.to_s] || super
+ end
end
end