Class: MPW::Cli

Inherits:
Object
  • Object
show all
Defined in:
lib/mpw/cli.rb

Instance Method Summary collapse

Constructor Details

#initialize(config, clipboard = true, sync = true, otp = false) ⇒ Cli

Constructor @args: config -> the config

sync -> boolean for sync or not
clipboard -> enable clopboard
otp -> enable otp


35
36
37
38
39
40
# File 'lib/mpw/cli.rb', line 35

def initialize(config, clipboard=true, sync=true, otp=false)
	@config    = config
	@clipboard = clipboard
	@sync      = sync
	@otp       = otp
end

Instance Method Details

#addObject

Form to add a new item



340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/mpw/cli.rb', line 340

def add
	options = {}

	puts I18n.t('form.add_item.title')
	puts '--------------------'
	options[:name]     = ask(I18n.t('form.add_item.name')).to_s
	options[:group]    = ask(I18n.t('form.add_item.group')).to_s
	options[:host]     = ask(I18n.t('form.add_item.server')).to_s
	options[:protocol] = ask(I18n.t('form.add_item.protocol')).to_s
	options[:user]     = ask(I18n.t('form.add_item.login')).to_s
	password           = ask(I18n.t('form.add_item.password')).to_s
	options[:port]     = ask(I18n.t('form.add_item.port')).to_s
	options[:comment]  = ask(I18n.t('form.add_item.comment')).to_s

	if @otp
		otp_key = ask(I18n.t('form.add_item.otp_key')).to_s
	end

	item = Item.new(options)

	@mpw.add(item)
	@mpw.set_password(item.id, password)
	@mpw.set_otp_key(item.id, otp_key)
	@mpw.write_data
	@mpw.sync(true) if @sync

	puts "#{I18n.t('form.add_item.valid')}".green
end

#add_key(key, file = nil) ⇒ Object

Add a new public key args: key -> the key name to add

file -> gpg public file to import


317
318
319
320
321
322
323
324
325
# File 'lib/mpw/cli.rb', line 317

def add_key(key, file=nil)
	@mpw.add_key(key, file)
	@mpw.write_data
	@mpw.sync(true) if @sync

	puts "#{I18n.t('form.add_key.valid')}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #13: #{e}".red
end

#clipboard(item) ⇒ Object

Copy in clipboard the login and password @args: item -> the item



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/mpw/cli.rb', line 232

def clipboard(item)
	pid = nil

	# Security: force quit after 90s
	Thread.new do
		sleep 90
		exit
	end
	
	while true
		choice = ask(I18n.t('form.clipboard.choice')).to_s
		
		case choice
		when 'q', 'quit'
			break

		when 'l', 'login'
			Clipboard.copy(item.user)
			puts I18n.t('form.clipboard.login').green

		when 'p', 'password'
			Clipboard.copy(@mpw.get_password(item.id))
			puts I18n.t('form.clipboard.password').yellow

			Thread.new do
				sleep 30

				Clipboard.clear
			end

		when 'o', 'otp'
			Clipboard.copy(@mpw.get_otp_code(item.id))
			puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow

		else
			puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan
			puts I18n.t('form.clipboard.help.login')
			puts I18n.t('form.clipboard.help.password')
			puts I18n.t('form.clipboard.help.otp_code')
			next
		end
	end

	Clipboard.clear
rescue SystemExit, Interrupt
	Clipboard.clear
end

#decryptObject

Request the GPG password and decrypt the file



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/mpw/cli.rb', line 129

def decrypt
	if not defined?(@mpw)
		@password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false}
		@mpw      = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe)
	end

	@mpw.read_data
	@mpw.sync if @sync
rescue Exception => e
	puts "#{I18n.t('display.error')} #11: #{e}".red
	exit 2
end

#delete(id, force = false) ⇒ Object

Remove an item @args: id -> the item’s id

force -> no resquest a validation


411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/mpw/cli.rb', line 411

def delete(id, force=false)
	@clipboard = false
	item       = @mpw.search_by_id(id)

	if item.nil?
		puts I18n.t('form.delete_item.not_valid', id: id)
		return
	end

	if not force
		display_item(item)

		confirm = ask("#{I18n.t('form.delete_item.ask', id: id)} (y/N) ").to_s
		if not confirm =~ /^(y|yes|YES|Yes|Y)$/
			return
		end
	end

	item.delete
	@mpw.write_data
	@mpw.sync(true) if @sync

	puts "#{I18n.t('form.delete_item.valid', id: id)}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #16: #{e}".red
end

#delete_key(key) ⇒ Object

Add new public key args: key -> the key name to delete



329
330
331
332
333
334
335
336
337
# File 'lib/mpw/cli.rb', line 329

def delete_key(key)
	@mpw.delete_key(key)
	@mpw.write_data
	@mpw.sync(true) if @sync

	puts "#{I18n.t('form.delete_key.valid')}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #15: #{e}".red
end

#display(options = {}) ⇒ Object

Display the query’s result @args: search -> the string to search

protocol -> search from a particular protocol


145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/mpw/cli.rb', line 145

def display(options={})
	result = @mpw.list(options)

	case result.length
	when 0
		puts I18n.t('display.nothing')

	when 1
		display_item(result.first)

	else
		group = nil
		i     = 1

		result.sort! { |a,b| a.group.downcase <=> b.group.downcase }

		result.each do |item|
			if group != item.group
				group = item.group

				if group.empty?
					puts I18n.t('display.no_group').yellow
				else
					puts "\n#{group}".yellow
				end
			end

			print " |_ ".yellow
			print "#{i}: ".cyan
			print item.name
			print " -> #{item.comment}".magenta if not item.comment.to_s.empty?
			print "\n"

			i += 1
		end

		print "\n"
		choice = ask(I18n.t('form.select')).to_i

		if choice >= 1 and choice < i 
			display_item(result[choice-1])
		else
			puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
		end
	end
end

#display_item(item) ⇒ Object

Display an item in the default format @args: item -> an array with the item information



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/mpw/cli.rb', line 194

def display_item(item)
	puts '--------------------'.cyan
	print 'Id: '.cyan
	puts  item.id
	print "#{I18n.t('display.name')}: ".cyan
	puts  item.name
	print "#{I18n.t('display.group')}: ".cyan
	puts  item.group
	print "#{I18n.t('display.server')}: ".cyan
	puts  item.host
	print "#{I18n.t('display.protocol')}: ".cyan
	puts  item.protocol
	print "#{I18n.t('display.login')}: ".cyan
	puts  item.user

	if @clipboard
		print "#{I18n.t('display.password')}: ".cyan
		puts '***********'
	else
		print "#{I18n.t('display.password')}: ".cyan
		puts  @mpw.get_password(item.id)

		if @mpw.get_otp_code(item.id) > 0
			print "#{I18n.t('display.otp_code')}: ".cyan
			puts "#{@mpw.get_otp_code(item.id)} (#{@mpw.get_otp_remaining_time}s)"
		end
	end

	print "#{I18n.t('display.port')}: ".cyan
	puts  item.port
	print "#{I18n.t('display.comment')}: ".cyan
	puts  item.comment

	clipboard(item) if @clipboard
end

#export(file) ⇒ Object

Export the items in a CSV file @args: file -> the destination file



440
441
442
443
444
445
446
# File 'lib/mpw/cli.rb', line 440

def export(file)
	@mpw.export(file)

	puts "#{I18n.t('export.export.valid', file)}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #17: #{e}".red
end

#get_wallet(wallet = nil) ⇒ Object

Display the wallet @args: wallet -> the wallet name



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/mpw/cli.rb', line 282

def get_wallet(wallet=nil)
	if wallet.to_s.empty?
		wallets = Dir.glob("#{@config.wallet_dir}/*.mpw")

		case wallets.length
		when 0
			puts I18n.t('display.nothing')
		when 1
			@wallet_file = wallets[0]
		else
			i = 1
			wallets.each do |wallet|
					print "#{i}: ".cyan
					puts File.basename(wallet, '.mpw')

					i += 1
			end

			choice = ask(I18n.t('form.select')).to_i

			if choice >= 1 and choice < i
				@wallet_file = wallets[choice-1]
			else
				puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
				exit 2
			end
		end
	else
		@wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw"
	end
end

#import(file) ⇒ Object

Import items from a YAML file @args: file -> the import file



450
451
452
453
454
455
456
457
# File 'lib/mpw/cli.rb', line 450

def import(file)
	@mpw.import(file)
	@mpw.write_data

	puts "#{I18n.t('form.import.valid')}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #18: #{e}".red
end

#setup(lang) ⇒ Object

Create a new config file @args: lang -> the software language



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/mpw/cli.rb', line 44

def setup(lang)
	puts I18n.t('form.setup_config.title')
	puts '--------------------'
	language   = ask(I18n.t('form.setup_config.lang', lang: lang)).to_s
	key        = ask(I18n.t('form.setup_config.gpg_key')).to_s
	wallet_dir = ask(I18n.t('form.setup_config.wallet_dir', home: "#{@config.config_dir}")).to_s
	gpg_exe    = ask(I18n.t('form.setup_config.gpg_exe')).to_s

	if language.nil? or language.empty?
		language = lang
	end
	I18n.locale = language.to_sym

	@config.setup(key, lang, wallet_dir, gpg_exe)

	raise I18n.t('error.config.check') if not @config.is_valid?

	puts "#{I18n.t('form.setup_config.valid')}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #8: #{e}".red
	exit 2
end

#setup_gpg_keyObject

Setup a new GPG key



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/mpw/cli.rb', line 68

def setup_gpg_key
	puts I18n.t('form.setup_gpg_key.title')
	puts '--------------------'
	ask      = ask(I18n.t('form.setup_gpg_key.ask')).to_s
	
	if not ['Y', 'y', 'O', 'o'].include?(ask)
		raise I18n.t('form.setup_gpg_key.no_create')
	end

	name     = ask(I18n.t('form.setup_gpg_key.name')).to_s
	password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false}
	confirm  = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false}

	if password != confirm 
		raise I18n.t('form.setup_gpg_key.error_password')
	end

	length   = ask(I18n.t('form.setup_gpg_key.length')).to_s
	expire   = ask(I18n.t('form.setup_gpg_key.expire')).to_s
	password = password.to_s

	length = length.nil? or length.empty? ? 2048 : length.to_i
	expire = expire.nil? or expire.empty? ? 0    : expire.to_i

	puts I18n.t('form.setup_gpg_key.wait')
	
	@config.setup_gpg_key(password, name, length, expire)

	puts "#{I18n.t('form.setup_gpg_key.valid')}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #8: #{e}".red
	exit 2
end

#setup_wallet_configObject

Setup wallet config for sync



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/mpw/cli.rb', line 103

def setup_wallet_config
	config         = {}
	config['sync'] = {}

	puts I18n.t('form.setup_wallet.title')
	puts '--------------------'
	config['sync']['type']     = ask(I18n.t('form.setup_wallet.sync_type')).to_s

	if ['ftp', 'ssh'].include?(config['sync']['type'].downcase)
		config['sync']['host']     = ask(I18n.t('form.setup_wallet.sync_host')).to_s
		config['sync']['port']     = ask(I18n.t('form.setup_wallet.sync_port')).to_s
		config['sync']['user']     = ask(I18n.t('form.setup_wallet.sync_user')).to_s
		config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s
		config['sync']['path']     = ask(I18n.t('form.setup_wallet.sync_path')).to_s
	end

	@mpw.set_config(config)
	@mpw.write_data

	puts "#{I18n.t('form.setup_wallet.valid')}".green
rescue Exception => e
	puts "#{I18n.t('display.error')} #10: #{e}".red
	exit 2
end

#update(id) ⇒ Object

Update an item @args: id -> the item’s id



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/mpw/cli.rb', line 371

def update(id)
	item = @mpw.search_by_id(id)

	if not item.nil?
		options = {}

		puts I18n.t('form.update_item.title')
		puts '--------------------'
		options[:name]     = ask(I18n.t('form.update_item.name'    , name:     item.name)).to_s
		options[:group]    = ask(I18n.t('form.update_item.group'   , group:    item.group)).to_s
		options[:host]     = ask(I18n.t('form.update_item.server'  , server:   item.host)).to_s
		options[:protocol] = ask(I18n.t('form.update_item.protocol', protocol: item.protocol)).to_s
		options[:user]     = ask(I18n.t('form.update_item.login'   , login:    item.user)).to_s
		password           = ask(I18n.t('form.update_item.password')).to_s
		options[:port]     = ask(I18n.t('form.update_item.port'    , port:     item.port)).to_s
		options[:comment]  = ask(I18n.t('form.update_item.comment' , comment:  item.comment)).to_s

		if @otp
			otp_key = ask(I18n.t('form.update_item.otp_key')).to_s
		end

		options.delete_if { |k,v| v.empty? }

		item.update(options)
		@mpw.set_password(item.id, password) if not password.empty?
		@mpw.set_otp_key(item.id, otp_key)   if not otp_key.to_s.empty?
		@mpw.write_data
		@mpw.sync(true) if @sync

		puts "#{I18n.t('form.update_item.valid')}".green
	else
		puts I18n.t('display.nothing')
	end
rescue Exception => e
	puts "#{I18n.t('display.error')} #14: #{e}".red
end