Add CLI
parent
033309696b
commit
46417ae3b5
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'twik/cli'
|
||||||
|
|
||||||
|
Twik::Cli.new(ARGV).run
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
|
||||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||||
spec.require_paths = ["lib"]
|
spec.require_paths = ["lib"]
|
||||||
|
|
||||||
|
spec.add_dependency 'xdg'
|
||||||
|
|
||||||
spec.add_development_dependency "bundler", "~> 1.7"
|
spec.add_development_dependency "bundler", "~> 1.7"
|
||||||
spec.add_development_dependency "rake", "~> 10.0"
|
spec.add_development_dependency "rake", "~> 10.0"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue