master
Guillaume Dott 2014-10-21 09:23:37 +02:00
parent 033309696b
commit 46417ae3b5
6 changed files with 172 additions and 0 deletions

5
bin/twik 100755
View File

@ -0,0 +1,5 @@
#!/usr/bin/env ruby
require 'twik/cli'
Twik::Cli.new(ARGV).run

30
lib/twik/cli.rb 100644
View File

@ -0,0 +1,30 @@
require 'twik'
require 'twik/cli/config'
require 'twik/cli/options'
class Twik
class Cli
attr_reader :config
def initialize(args)
@config = Config.new(args)
end
def twik
@twik ||= Twik.new(config.privatekey, length: config.length, type: config.type.to_sym)
end
def run
masterkey = ask('Master key: ')
puts twik.generate(config.tag, masterkey)
end
def ask(prompt)
print prompt
res = STDIN.noecho(&:gets).chomp
puts
res
end
end
end

View File

@ -0,0 +1,64 @@
require 'twik/private_key'
require 'xdg'
require 'yaml'
class Twik
class Cli
class Config
CONFIG_FILE = [XDG['CONFIG_HOME'], 'twik', 'config.yml'].join(File::SEPARATOR)
def self.default
{
'profiles' => {
'default' => {
'privatekey' => Twik::PrivateKey.generate,
'length' => 16,
'type' => 'alphanumeric_and_special_chars',
}
}
}
end
attr_reader :yaml, :args
def initialize(args)
file = File.new(CONFIG_FILE)
@args = Options.parse(args)
@yaml = YAML.load_file(file.path)
end
def profile
args['profile'] || 'default'
end
def options
@options ||= yaml['profiles'][profile].merge(args)
end
def method_missing(symbol)
options.key?(symbol.to_s) ? options[symbol.to_s] : super
end
class File
attr_reader :path
def initialize(path)
@path = path
create unless ::File.exist?(path)
end
private
def create
directory = ::File.dirname(path)
::FileUtils.mkdir_p directory unless ::File.directory?(directory)
::File.open(path, 'w') do |file|
file.write(YAML.dump(Twik::Cli::Config.default))
end
end
end
end
end
end

View File

@ -0,0 +1,56 @@
require 'optparse'
class Twik
class Cli
class Options
def self.parse(args)
options = {}
parser = ::OptionParser.new do |opts|
opts.banner = 'Usage: twik [options] tag'
opts.separator ''
opts.separator 'Specific options:'
opts.on('-l', '--length LENGTH', 'length of generated password (4-26). Default: 16') do |length|
options['length'] = length.to_i
end
opts.on('-p', '--profile PROFILE', "profile to use. Default: 'default'") do |profile|
options['profile'] = profile
end
opts.on('-t', '--type TYPE', Twik::TYPE,
"type of password:", " #{Twik::TYPE.join(', ')}", " Default: alphanumeric_and_special_chars") do |type|
options['type'] = type.to_sym
end
opts.separator ''
opts.separator 'Common options:'
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
opts.on_tail('--version', 'Show version') do
puts "#{opts.program_name} #{Immoconv::VERSION}"
exit
end
end
begin
parser.parse!(args)
rescue OptionParser::MissingArgument, OptionParser::InvalidOption => e
puts e.message
puts parser
exit
end
options['tag'] = args.shift
options
end
end
end
end

View File

@ -0,0 +1,15 @@
class Twik
class PrivateKey
def self.generate
format = [8, 4, 4, 4, 12]
separator = '-'
chars = ('A'..'Z').to_a + ('0'..'9').to_a
format.map do |i|
i.times.inject('') do |res, j|
res + chars[Random.rand(chars.length)]
end
end.join(separator)
end
end
end

View File

@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_dependency 'xdg'
spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0"