mirror of
https://github.com/nishiki/manage-password.git
synced 2025-02-20 01:50:04 +00:00
merge text_editor branch
This commit is contained in:
commit
50a75450fd
24 changed files with 1230 additions and 715 deletions
128
README.md
128
README.md
|
@ -1,128 +0,0 @@
|
|||
# Manage your passwords!
|
||||
|
||||
MPW is a little software which stores your passwords in an GPG encrypted file.
|
||||
MPW can synchronize your password with SSH or FTP.
|
||||
|
||||
# Installation
|
||||
|
||||
This program work with ruby >= 2.0
|
||||
|
||||
* install ruby and rubygems on your computer
|
||||
* install xclip
|
||||
* gem install mpw
|
||||
|
||||
# How to use
|
||||
|
||||
* Show help
|
||||
```
|
||||
mpw --help
|
||||
```
|
||||
|
||||
* Setup a new config file
|
||||
```
|
||||
mpw --setup
|
||||
mpw --setup --config /path/conf/file.cfg
|
||||
```
|
||||
|
||||
* Create and setup a new wallet
|
||||
```
|
||||
mpw --setup-wallet --wallet new_wallet_name
|
||||
mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg
|
||||
```
|
||||
|
||||
* Add a GPG key in wallet
|
||||
```
|
||||
mpw --add --key root@localhost.local
|
||||
mpw --add --key root@localhost.local --config /path/conf/file.cfg
|
||||
mpw --add --key root@localhost.local --wallet wallet_name
|
||||
mpw --add --key root@localhost.local --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Add a new GPG key in wallet
|
||||
```
|
||||
mpw --add --key root@localhost.local --file /path/gpg/file.pub
|
||||
mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg
|
||||
mpw --add --key root@localhost.local --file /path/gpg/file.pub --wallet wallet_name
|
||||
mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Delete a GPG key in wallet
|
||||
```
|
||||
mpw --delete --key root@localhost.local
|
||||
mpw --delete --key root@localhost.local --wallet wallet_name
|
||||
mpw --delete --key root@localhost.local --wallet wallet_name --config /path/conf/file.cfg
|
||||
```
|
||||
|
||||
* Add a new item in wallet
|
||||
```
|
||||
mpw --add
|
||||
mpw --add --config /path/conf/file.cfg
|
||||
mpw --add --wallet wallet_name
|
||||
mpw --add --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Update an item
|
||||
```
|
||||
mpw --update --id uniq_id
|
||||
mpw --update --id uniq_id --config /path/conf/file.cfg
|
||||
mpw --update --id uniq_id --wallet wallet_name
|
||||
mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Delete an item
|
||||
```
|
||||
mpw --delete --id uniq_id
|
||||
mpw --delete --id uniq_id --config /path/conf/file.cfg
|
||||
mpw --delete --id uniq_id --wallet wallet_name
|
||||
mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Show an item
|
||||
```
|
||||
mpw --show 'string to search'
|
||||
mpw --show 'string to search' --config /path/conf/file.cfg
|
||||
mpw --show 'string to search' --wallet wallet_name
|
||||
mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name
|
||||
mpw --show 'string to search' --group group_name
|
||||
mpw --show 'string to search' --group group_name --config /path/conf/file.cfg
|
||||
mpw --show 'string to search' --group group_name --wallet wallet_name
|
||||
mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Export data in YAML file
|
||||
```
|
||||
mpw --export --file /path/file/to/export.yml
|
||||
mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg
|
||||
mpw --export --file /path/file/to/export.yml --wallet wallet_name
|
||||
mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
* Import data from YAML file
|
||||
```
|
||||
mpw --import --file /path/file/to/export.yml
|
||||
mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg
|
||||
mpw --import --file /path/file/to/export.yml --wallet wallet_name
|
||||
mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name
|
||||
```
|
||||
|
||||
Format file to import:
|
||||
```
|
||||
1:
|
||||
name: Website perso
|
||||
group: Perso
|
||||
host: localhost.local
|
||||
protocol: ftp
|
||||
user: test
|
||||
password: letoortue
|
||||
port: 21
|
||||
comment: Mysuper website
|
||||
2:
|
||||
name: Linuxfr
|
||||
group: Pro
|
||||
host: Linuxfr.org
|
||||
protocol: https
|
||||
user: test
|
||||
password: coucou
|
||||
port:
|
||||
comment:
|
||||
```
|
53
README.rst
Normal file
53
README.rst
Normal file
|
@ -0,0 +1,53 @@
|
|||
MPW: Manage your passwords!
|
||||
*******************************************************
|
||||
|
||||
mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>` encrypted files.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
* generate OTP code
|
||||
* synchronize your passwords with SSH or FTP.
|
||||
* copy your login, password or otp in clipboard
|
||||
|
||||
Install
|
||||
=======
|
||||
|
||||
On debian or ubuntu::
|
||||
|
||||
apt install ruby ruby-dev xclip
|
||||
gem install mpw
|
||||
|
||||
|
||||
How to use
|
||||
==========
|
||||
|
||||
A simple mpw usage::
|
||||
|
||||
mpw config --init user@host.com
|
||||
mpw add
|
||||
mpw copy
|
||||
mpw add
|
||||
mpw list
|
||||
|
||||
Output::
|
||||
|
||||
Bank
|
||||
==============================================================================
|
||||
ID | Host | User | Protocol | Port | OTP | Comment
|
||||
==============================================================================
|
||||
1 | bank.com | 1234456 | https | | X |
|
||||
|
||||
Linux
|
||||
==============================================================================
|
||||
ID | Host | User | Protocol | Port | OTP | Comment
|
||||
==============================================================================
|
||||
2 | linuxfr.org | example | https | | | Da Linux French Site
|
||||
|
||||
|
||||
Licence |License|
|
||||
=================
|
||||
|
||||
Full license here: `LICENSE <https://github.com/nishiki/manage-password/blob/master/LICENSE>`
|
||||
|
||||
.. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
3.2.1
|
||||
4.0.0-beta
|
||||
|
|
193
bin/mpw
193
bin/mpw
|
@ -18,13 +18,9 @@
|
|||
|
||||
$: << File.expand_path('../../lib', __FILE__)
|
||||
|
||||
require 'optparse'
|
||||
require 'locale'
|
||||
require 'set'
|
||||
require 'i18n'
|
||||
require 'mpw/mpw'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Set local
|
||||
|
@ -45,190 +41,9 @@ I18n.locale = lang.to_sym
|
|||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options_password = {}
|
||||
options = {}
|
||||
options[:force] = false
|
||||
options[:otp] = false
|
||||
options[:sync] = true
|
||||
options[:clipboard] = true
|
||||
options[:group] = nil
|
||||
options[:config] = nil
|
||||
options[:wallet] = nil
|
||||
bin_dir = File.dirname(__FILE__)
|
||||
command = "#{bin_dir}/mpw-#{ARGV[0]}"
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw [options]"
|
||||
|
||||
opts.on('-a', '--add', I18n.t('option.add')) do
|
||||
options[:add] = true
|
||||
end
|
||||
|
||||
opts.on('-A', '--show-all', I18n.t('option.show_all')) do
|
||||
options[:type] = nil
|
||||
options[:show] = ''
|
||||
end
|
||||
|
||||
opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-C', '--no-clipboard', I18n.t('option.clipboard')) do
|
||||
options[:clipboard] = false
|
||||
end
|
||||
|
||||
opts.on('-d', '--delete', I18n.t('option.remove')) do
|
||||
options[:delete] = true
|
||||
end
|
||||
|
||||
opts.on('-e', '--export', I18n.t('option.export')) do
|
||||
options[:export] = true
|
||||
end
|
||||
|
||||
opts.on('-f', '--file FILE', I18n.t('option.file')) do |file|
|
||||
options[:file] = file
|
||||
end
|
||||
|
||||
opts.on('-F', '--force', I18n.t('option.force')) do
|
||||
options[:force] = true
|
||||
end
|
||||
|
||||
opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group|
|
||||
options[:group] = group
|
||||
end
|
||||
|
||||
opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length|
|
||||
options_password[:length] = length
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-i', '--id ID', I18n.t('option.id')) do |id|
|
||||
options[:id] = id
|
||||
end
|
||||
|
||||
opts.on('-I', '--import', I18n.t('option.import')) do
|
||||
options[:import] = true
|
||||
end
|
||||
|
||||
opts.on('-k', '--key KEY', I18n.t('option.key')) do |key|
|
||||
options[:key] = key
|
||||
end
|
||||
|
||||
opts.on('-n', '--numeric', I18n.t('option.numeric')) do
|
||||
options_password[:numeric] = true
|
||||
end
|
||||
|
||||
opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-O', '--otp', I18n.t('option.otp')) do
|
||||
options[:otp] = true
|
||||
end
|
||||
|
||||
opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search|
|
||||
search.nil? ? (options[:show] = '') : (options[:show] = search)
|
||||
end
|
||||
|
||||
opts.on('-S', '--setup', I18n.t('option.setup')) do
|
||||
options[:setup] = true
|
||||
end
|
||||
|
||||
opts.on('-u', '--update', I18n.t('option.update')) do
|
||||
options[:update] = true
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
|
||||
opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do
|
||||
options[:setup_wallet] = true
|
||||
end
|
||||
|
||||
opts.on('-x', '--special-chars', I18n.t('option.special_chars')) do
|
||||
options_password[:special] = true
|
||||
end
|
||||
|
||||
opts.on('-y', '--alpha', I18n.t('option.alpha')) do
|
||||
options_password[:alpha] = true
|
||||
end
|
||||
end.parse!
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Main
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
# Generate password
|
||||
if not options_password.empty?
|
||||
puts MPW::MPW::password(options_password)
|
||||
exit 0
|
||||
end
|
||||
|
||||
begin
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp])
|
||||
|
||||
# Setup a new config
|
||||
if not options[:setup].nil?
|
||||
cli.setup(lang)
|
||||
exit 0
|
||||
end
|
||||
|
||||
cli.setup(lang) if not config.is_valid?
|
||||
cli.setup_gpg_key if not config.check_gpg_key?
|
||||
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
|
||||
# Display the item's informations
|
||||
if not options[:show].nil?
|
||||
opts = {search: options[:show],
|
||||
group: options[:group],
|
||||
}
|
||||
|
||||
cli.display(opts)
|
||||
|
||||
# Remove an item
|
||||
elsif not options[:delete].nil? and not options[:id].nil?
|
||||
cli.delete(options[:id], options[:force])
|
||||
|
||||
# Update an item
|
||||
elsif not options[:update].nil? and not options[:id].nil?
|
||||
cli.update(options[:id])
|
||||
|
||||
# Add a new item
|
||||
elsif not options[:add].nil? and options[:key].nil?
|
||||
cli.add
|
||||
|
||||
# Add a new public key in wallet
|
||||
elsif not options[:add].nil? and not options[:key].nil?
|
||||
cli.add_key(options[:key], options[:file])
|
||||
|
||||
# Delete a public key in wallet
|
||||
elsif not options[:delete].nil? and not options[:key].nil?
|
||||
cli.delete_key(options[:key])
|
||||
|
||||
# Export
|
||||
elsif not options[:export].nil? and not options[:file].nil?
|
||||
cli.export(options[:file])
|
||||
|
||||
# Add a new item
|
||||
elsif not options[:import].nil? and not options[:file].nil?
|
||||
cli.import(options[:file])
|
||||
|
||||
# Setup wallet config
|
||||
elsif not options[:setup_wallet].nil?
|
||||
cli.setup_wallet_config
|
||||
|
||||
end
|
||||
|
||||
cli = nil
|
||||
|
||||
exit 0
|
||||
|
||||
rescue SystemExit, Interrupt
|
||||
exit 3
|
||||
if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}")
|
||||
Kernel.load(command)
|
||||
end
|
||||
|
|
61
bin/mpw-add
Normal file
61
bin/mpw-add
Normal file
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw add [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-r', '--random', I18n.t('option.random_password')) do
|
||||
options[:password] = true
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.add(options[:password])
|
75
bin/mpw-config
Normal file
75
bin/mpw-config
Normal file
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw config [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe|
|
||||
values[:gpg_exe] = gpg_exe
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-i', '--init GPG_KEY', I18n.t('option.init')) do |gpg_key|
|
||||
options[:init] = true
|
||||
values[:gpg_key] = gpg_key
|
||||
end
|
||||
|
||||
opts.on('-k', '--key GPG_KEY', I18n.t('option.gpg_key')) do |gpg_key|
|
||||
values[:gpg_key] = gpg_key
|
||||
end
|
||||
|
||||
opts.on('-l', '--lang LANG', I18n.t('option.lang')) do |lang|
|
||||
values[:lang] = lang
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir|
|
||||
values[:wallet_dir] = wallet_dir
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, nil)
|
||||
|
||||
if not options[:init].nil?
|
||||
cli.setup(values)
|
||||
cli.load_config
|
||||
cli.get_wallet
|
||||
cli.setup_gpg_key(options[:init])
|
||||
cli.setup_wallet_config
|
||||
else
|
||||
cli.set_config(values)
|
||||
end
|
71
bin/mpw-copy
Normal file
71
bin/mpw-copy
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
options[:clipboard] = true
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-d', '--disable-clipboard', I18n.t('option.clipboard')) do
|
||||
options[:clipboard] = false
|
||||
end
|
||||
|
||||
opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
|
||||
values[:group] = group
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
|
||||
values[:pattern] = pattern
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.copy(options[:clipboard], values)
|
66
bin/mpw-delete
Normal file
66
bin/mpw-delete
Normal file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
|
||||
values[:group] = group
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
|
||||
values[:pattern] = pattern
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.delete(values)
|
70
bin/mpw-export
Normal file
70
bin/mpw-export
Normal file
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-f', '--file PATH', I18n.t('option.file_export')) do |file|
|
||||
options[:file] = file
|
||||
end
|
||||
|
||||
opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group|
|
||||
values[:group] = group
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
|
||||
values[:pattern] = pattern
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.export(options[:file], values)
|
50
bin/mpw-genpwd
Normal file
50
bin/mpw-genpwd
Normal file
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/mpw'
|
||||
|
||||
options = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw passwd [options]"
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length|
|
||||
options[:length] = length.to_i
|
||||
end
|
||||
|
||||
opts.on('-n', '--numeric', I18n.t('option.numeric')) do
|
||||
options[:numeric] = true
|
||||
end
|
||||
|
||||
opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do
|
||||
options[:special] = true
|
||||
end
|
||||
|
||||
opts.on('-a', '--alpha', I18n.t('option.alpha')) do
|
||||
options[:alpha] = true
|
||||
end
|
||||
end.parse!
|
||||
|
||||
puts MPW::MPW::password(options)
|
||||
exit 0
|
61
bin/mpw-import
Normal file
61
bin/mpw-import
Normal file
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw import [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-f', '--file PATH', I18n.t('option.file_import')) do |file|
|
||||
options[:file] = file
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.import(options[:file])
|
66
bin/mpw-list
Normal file
66
bin/mpw-list
Normal file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw list [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
|
||||
values[:group] = group
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
|
||||
values[:pattern] = pattern
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.list(values)
|
66
bin/mpw-update
Normal file
66
bin/mpw-update
Normal file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = true
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw update [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
|
||||
values[:group] = group
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
|
||||
values[:pattern] = pattern
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.update(values)
|
91
bin/mpw-wallet
Normal file
91
bin/mpw-wallet
Normal file
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/ruby
|
||||
# MPW is a software to crypt and manage your passwords
|
||||
# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'optparse'
|
||||
require 'mpw/config'
|
||||
require 'mpw/cli'
|
||||
|
||||
# --------------------------------------------------------- #
|
||||
# Options
|
||||
# --------------------------------------------------------- #
|
||||
|
||||
options = {}
|
||||
options[:sync] = {}
|
||||
values = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]"
|
||||
|
||||
opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', I18n.t('option.help')) do
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
|
||||
opts.on('--host NAME', I18n.t('option.host')) do |host|
|
||||
values[:host] = host
|
||||
end
|
||||
|
||||
opts.on('-l', '--list', I18n.t('option.list')) do |list|
|
||||
options[:list] = true
|
||||
end
|
||||
|
||||
opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
|
||||
options[:sync] = false
|
||||
end
|
||||
|
||||
opts.on('--password', I18n.t('option.password')) do
|
||||
values[:password] = true
|
||||
end
|
||||
|
||||
opts.on('--path PATH', I18n.t('option.path')) do |path|
|
||||
values[:path] = path
|
||||
end
|
||||
|
||||
opts.on('--port NUMBER', I18n.t('option.port')) do |port|
|
||||
values[:port] = port
|
||||
end
|
||||
|
||||
opts.on('--protocol NAME', I18n.t('option.protocol')) do |protocol|
|
||||
values[:protocol] = protocol
|
||||
end
|
||||
|
||||
opts.on('--user NAME', I18n.t('option.user')) do |user|
|
||||
values[:user] = user
|
||||
end
|
||||
|
||||
opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
|
||||
options[:wallet] = wallet
|
||||
end
|
||||
end.parse!
|
||||
|
||||
config = MPW::Config.new(options[:config])
|
||||
cli = MPW::Cli.new(config, options[:sync])
|
||||
|
||||
cli.load_config
|
||||
|
||||
if not options[:list].nil?
|
||||
cli.list_wallet
|
||||
else
|
||||
cli.get_wallet(options[:wallet])
|
||||
cli.decrypt
|
||||
cli.setup_wallet_config(values)
|
||||
end
|
69
i18n/en.yml
69
i18n/en.yml
|
@ -3,15 +3,13 @@ en:
|
|||
error:
|
||||
config:
|
||||
write: "Can't write the config file!"
|
||||
check: "Checkconfig failed!"
|
||||
load: "Checkconfig failed!"
|
||||
key_bad_format: "The key string isn't in good format!"
|
||||
no_key_public: "You haven't the public key of %{key}!"
|
||||
genkey_gpg:
|
||||
exception: "Can't create the GPG key!"
|
||||
name: "You must define a name for your GPG key!"
|
||||
password: "You must define a password for your GPG key!"
|
||||
delete:
|
||||
id_no_exist: "Can't delete the item %{id}, it doesn't exist!"
|
||||
export: "Can't export, unable to write in %{file}!"
|
||||
gpg_file:
|
||||
decrypt: "Can't decrypt file!"
|
||||
|
@ -41,41 +39,51 @@ en:
|
|||
config: "Specify the configuration file to use"
|
||||
clipboard: "Disable the clipboard feature"
|
||||
export: "Export a wallet in an yaml file"
|
||||
file: "Specify a file, to use with the options [--import | --export | --add]"
|
||||
file_export: "Specify the file where export data"
|
||||
file_import: "Specify the file to import"
|
||||
force: "No ask to confirm when you delete an item"
|
||||
generate_password: "Generate a random password (default 8 characters)"
|
||||
gpg_exe: "Set the gpg binary path to use"
|
||||
gpg_key: "Specify a GPG key (ex: user@example.com)"
|
||||
group: "Search the items with specified group"
|
||||
help: "Show this help message"
|
||||
id: "Specify an id, to use with the options [--delete | --update]"
|
||||
host: "Specify the server for the synchronization"
|
||||
init: "Initialize mpw"
|
||||
import: "Import item since a yaml file"
|
||||
key: "Specify the key name, to use with the options [--add | --delete | --update]"
|
||||
key: "Specify the key name"
|
||||
lang: "Set the software language"
|
||||
list: "List the wallets"
|
||||
no_sync: "Disable synchronization with the server"
|
||||
numeric: "Use number to generate a password"
|
||||
password: "Change the password for the synchronization"
|
||||
path: "Specify the remote path"
|
||||
pattern: "Given search pattern"
|
||||
port: "Specify the connection port"
|
||||
protocol: "Specify the protocol for the connection"
|
||||
setup: "Create a new configuration file"
|
||||
setup_wallet: "Create a new configuration file for a wallet"
|
||||
special_chars: "Use special char to generate a password"
|
||||
show: "Search and show the items"
|
||||
show_all: "List all items"
|
||||
remove: "Delete an item"
|
||||
update: "Update an item"
|
||||
usage: "Usage"
|
||||
user: "Specify the user for the connection"
|
||||
wallet: "Specify a wallet to use"
|
||||
wallet_dir: "Set the wallets folder"
|
||||
|
||||
form:
|
||||
select: "Select the item: "
|
||||
add_key:
|
||||
valid: "Key has been added!"
|
||||
add_item:
|
||||
title: "Add a new item"
|
||||
name: "Enter the name: "
|
||||
group: "Enter the group (optional): "
|
||||
server: "Enter the hostname or ip: "
|
||||
protocol: "Enter the protocol of the connection (ssh, http, other): "
|
||||
login: "Enter the login connection: "
|
||||
password: "Enter the the password: "
|
||||
port: "Enter the connection port (optional): "
|
||||
comment: "Enter a comment (optional): "
|
||||
otp_key: "Enter the otp secret (base32 secret key): "
|
||||
name: "The item's name (mandatory"
|
||||
group: "The group's name"
|
||||
host: "The hostname or ip"
|
||||
protocol: "The protocol of the connection (ssh, http, ...)"
|
||||
login: "The login of connection"
|
||||
password: "The password"
|
||||
port: "The connection port"
|
||||
comment: "A comment"
|
||||
otp_key: "The OTP secret"
|
||||
valid: "Item has been added!"
|
||||
clipboard:
|
||||
choice: "What do you want to copy ? [q = quit, p = password, l = login]: "
|
||||
|
@ -88,12 +96,12 @@ en:
|
|||
login: "Press <l> to copy the login"
|
||||
password: "Press <p> to copy the password"
|
||||
otp_code: "Press <o> to copy the otp code"
|
||||
quit: "Press <q> to quit"
|
||||
delete_key:
|
||||
valid: "Key has been deleted!"
|
||||
delete_item:
|
||||
ask: "Are you sure you want to remove the item %{id} ?"
|
||||
valid: "The item %{id} has been removed!"
|
||||
not_valid: "The item %{id} hasn't been removed, because it doesn't exist!"
|
||||
ask: "Are you sure you want to remove the item ?"
|
||||
valid: "The item has been removed!"
|
||||
import:
|
||||
ask: "Are you sure you want to import this file %{file} ?"
|
||||
valid: "The import is succesfull!"
|
||||
|
@ -127,16 +135,15 @@ en:
|
|||
wait: "Please waiting during the GPG key generate, this process can take few minutes."
|
||||
valid: "Your GPG key has been created ;-)"
|
||||
update_item:
|
||||
title: "Update an item"
|
||||
name: "Enter the name [%{name}]: "
|
||||
group: "Enter the group [%{group}]: "
|
||||
server: "Enter the hostname or ip [%{server}]: "
|
||||
protocol: "Enter the protocol of the connection [%{protocol}]: "
|
||||
login: "Enter the login connection [%{login}]: "
|
||||
password: "Enter the the password: "
|
||||
port: "Enter the connection port [%{port}]: "
|
||||
comment: "Enter a comment [%{comment}]: "
|
||||
otp_key: "Enter the otp secret (base32 secret key): "
|
||||
name: "The item's name (mandatory"
|
||||
group: "The group's name"
|
||||
host: "The hostname or ip"
|
||||
protocol: "The protocol of the connection (ssh, http, ...)"
|
||||
login: "The login of connection"
|
||||
password: "The password (leave empty if you don't want change)"
|
||||
port: "The connection port"
|
||||
comment: "A comment"
|
||||
otp_key: "The OTP secret (leave empty if you don't want change"
|
||||
valid: "Item has been updated!"
|
||||
export:
|
||||
valid: "The export in %{file} is succesfull!"
|
||||
|
|
69
i18n/fr.yml
69
i18n/fr.yml
|
@ -3,15 +3,13 @@ fr:
|
|||
error:
|
||||
config:
|
||||
write: "Impossible d'écrire le fichier de configuration!"
|
||||
check: "Le fichier de configuration est invalide!"
|
||||
load: "Le fichier de configuration est invalide!"
|
||||
key_bad_format: "La clé GPG est invalide!"
|
||||
no_key_public: "Vous ne possédez pas la clé publique de %{key}!"
|
||||
genkey_gpg:
|
||||
exception: "La création de la clé GPG n'a pas pu aboutir!"
|
||||
name: "Vous devez définir un nom pour votre clé GPG!"
|
||||
password: "Vous devez définir un mot de passe pour votre clé GPG!"
|
||||
delete:
|
||||
id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!"
|
||||
export: "Impossible d'exporter les données dans le fichier %{file}!"
|
||||
gpg_file:
|
||||
decrypt: "Impossible de déchiffrer le fichier GPG!"
|
||||
|
@ -41,41 +39,51 @@ fr:
|
|||
config: "Spécifie le fichier de configuration à utiliser"
|
||||
clipboard: "Désactive la fonction presse papier"
|
||||
export: "Exporte un portefeuille dans un fichier yaml"
|
||||
file: "Spécifie un fichier, à utiliser avec les options [--import | --export | --add]"
|
||||
file_export: "Spécifie le fichier où exporter les données"
|
||||
file_import: "Spécifie le fichier à importer"
|
||||
force: "Ne demande pas de confirmation pour la suppression d'un élément"
|
||||
generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)"
|
||||
gpg_exe: "Spécifie le chemin du binaire gpg à utiliser"
|
||||
gpg_key: "Spécifie une clé GPG (ex: user@example.com)"
|
||||
group: "Recherche les éléments appartenant au groupe spécifié"
|
||||
help: "Affiche ce message d'aide"
|
||||
id: "Spécifie un identifiant, à utiliser avec les options [--delete | --update]"
|
||||
host: "Spécifie le serveur pour la synchronisation"
|
||||
import: "Importe des éléments depuis un fichier yaml"
|
||||
key: "Spécifie le nom d'une clé, à utiliser avec les options [--add | --delete | --update]"
|
||||
init: "Initialise mpw"
|
||||
key: "Spécifie le nom d'une clé"
|
||||
lang: "Spécifie la langue du logiciel (ex: fr)"
|
||||
list: "Liste les portefeuilles"
|
||||
no_sync: "Désactive la synchronisation avec le serveur"
|
||||
numeric: "Utilise des chiffre dans la génération d'un mot de passe"
|
||||
password: "Changer le mot de passe de connexion"
|
||||
path: "Spécifie le chemin distant"
|
||||
pattern: "Motif de donnée à chercher"
|
||||
port: "Spécifie le port de connexion"
|
||||
protocol: "Spécifie le protocol utilisé pour la connexion"
|
||||
setup: "Création d'un nouveau fichier de configuration"
|
||||
setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille"
|
||||
special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe"
|
||||
show: "Recherche et affiche les éléments"
|
||||
show_all: "Liste tous les éléments"
|
||||
remove: "Supprime un élément"
|
||||
update: "Met à jour un élément"
|
||||
usage: "Utilisation"
|
||||
user: "Spécifie l'identifiant de connection"
|
||||
wallet: "Spécifie le portefeuille à utiliser"
|
||||
wallet_dir: "Spécifie le répertoire des portefeuilles"
|
||||
|
||||
form:
|
||||
select: "Sélectionner l'élément: "
|
||||
add_key:
|
||||
valid: "La clé a bien été ajoutée!"
|
||||
add_item:
|
||||
title: "Ajout d'un nouvel élément"
|
||||
name: "Entrez le nom: "
|
||||
group: "Entrez le groupe (optionnel): "
|
||||
server: "Entrez le nom de domaine ou l'ip: "
|
||||
protocol: "Entrez le protocole de connexion (ssh, http, other): "
|
||||
login: "Entrez l'identifiant de connexion: "
|
||||
password: "Entrez le mot de passe: "
|
||||
port: "Entrez le port de connexion (optionnel): "
|
||||
comment: "Entrez un commentaire (optionnel): "
|
||||
otp_key: "Entrez le secret OTP: "
|
||||
name: "Le nom de l'élément (obligatoire)"
|
||||
group: "Le nom du groupe"
|
||||
host: "Le nom de domaine ou l'ip"
|
||||
protocol: "Le protocole de connexion (ssh, http, ...)"
|
||||
login: "L'identifiant de connexion"
|
||||
password: "Le mot de passe"
|
||||
port: "Le port de connexion"
|
||||
comment: "Un commentaire"
|
||||
otp_key: "Le secret OTP"
|
||||
valid: "L'élément a bien été ajouté!"
|
||||
clipboard:
|
||||
choice: "Que voulez-vous copier ? : "
|
||||
|
@ -88,12 +96,12 @@ fr:
|
|||
login: "Pressez <l> pour copier l'identifiant"
|
||||
password: "Pressez <p> pour copier le mot de passe"
|
||||
otp_code: "Pressez <o> pour copier le code OTP"
|
||||
quit: "Pressez <q> pour quitter"
|
||||
delete_key:
|
||||
valid: "La clé a bien été supprimée!"
|
||||
delete_item:
|
||||
ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?"
|
||||
valid: "L'élément %{id} a bien été supprimé!"
|
||||
not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!"
|
||||
ask: "Êtes vous sûre de vouloir supprimer l'élément ?"
|
||||
valid: "L'élément a bien été supprimé!"
|
||||
import:
|
||||
ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?"
|
||||
valid: "L'import est un succès!"
|
||||
|
@ -127,16 +135,15 @@ fr:
|
|||
wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes."
|
||||
valid: "Votre clé GPG a bien été créée ;-)"
|
||||
update_item:
|
||||
title: "Mis à jour d'un élément"
|
||||
name: "Entrez le nom [%{name}]: "
|
||||
group: "Entrez le groupe [%{group}]: "
|
||||
server: "Entrez le nom de domaine ou l'ip du serveur [%{server}]: "
|
||||
protocol: "Entrez le protocole de connexion [%{protocol}]: "
|
||||
login: "Entrez votre identifiant de connexion [%{login}]: "
|
||||
password: "Entrez le mot de passe: "
|
||||
port: "Entrez un port de connexion [%{port}]: "
|
||||
comment: "Entrez un commentaire [%{comment}]: "
|
||||
otp_key: "Entrez le secret OTP: "
|
||||
name: "Le nom de l'élément (obligatoire)"
|
||||
group: "Le nom du groupe"
|
||||
host: "Le nom de domaine ou l'ip"
|
||||
protocol: "Le protocole de connexion (ssh, http, ...)"
|
||||
login: "L'identifiant de connexion"
|
||||
password: "Le mot de passe (laissez vide si vous ne voulez pas le changer)"
|
||||
port: "Le port de connexion"
|
||||
comment: "Un commentaire"
|
||||
otp_key: "Le secret OTP (laissez vide si vous ne voulez pas le changer)"
|
||||
valid: "L'élément a bien été mis à jour!"
|
||||
export:
|
||||
valid: "L'export dans %{file} est un succès!"
|
||||
|
|
522
lib/mpw/cli.rb
522
lib/mpw/cli.rb
|
@ -17,10 +17,12 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'readline'
|
||||
require 'locale'
|
||||
require 'i18n'
|
||||
require 'colorize'
|
||||
require 'highline/import'
|
||||
require 'clipboard'
|
||||
require 'tmpdir'
|
||||
require 'mpw/item'
|
||||
require 'mpw/mpw'
|
||||
|
||||
|
@ -30,33 +32,35 @@ class Cli
|
|||
# Constructor
|
||||
# @args: config -> the config
|
||||
# sync -> boolean for sync or not
|
||||
# clipboard -> enable clopboard
|
||||
# otp -> enable otp
|
||||
def initialize(config, clipboard=true, sync=true, otp=false)
|
||||
def initialize(config, sync=true)
|
||||
@config = config
|
||||
@clipboard = clipboard
|
||||
@sync = sync
|
||||
@otp = otp
|
||||
end
|
||||
|
||||
# Change a parameter int the config after init
|
||||
# @args: options -> param to change
|
||||
def set_config(options)
|
||||
gpg_key = options[:gpg_key] || @config.key
|
||||
lang = options[:lang] || @config.lang
|
||||
wallet_dir = options[:wallet_dir] || @config.wallet_dir
|
||||
gpg_exe = options[:gpg_exe] || @config.gpg_exe
|
||||
|
||||
@config.setup(gpg_key, lang, wallet_dir, gpg_exe)
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('display.error')} #15: #{e}".red
|
||||
exit 2
|
||||
end
|
||||
|
||||
# Create a new config file
|
||||
# @args: lang -> the software language
|
||||
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
|
||||
# @args: options -> set param
|
||||
def setup(options)
|
||||
lang = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
|
||||
|
||||
if language.nil? or language.empty?
|
||||
language = lang
|
||||
end
|
||||
I18n.locale = language.to_sym
|
||||
I18n.locale = lang.to_sym
|
||||
|
||||
@config.setup(key, lang, wallet_dir, gpg_exe)
|
||||
@config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:gpg_exe])
|
||||
|
||||
raise I18n.t('error.config.check') if not @config.is_valid?
|
||||
load_config
|
||||
|
||||
puts "#{I18n.t('form.setup_config.valid')}".green
|
||||
rescue Exception => e
|
||||
|
@ -65,16 +69,10 @@ class Cli
|
|||
end
|
||||
|
||||
# Setup a new GPG key
|
||||
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
|
||||
# @args: gpg_key -> the key name
|
||||
def setup_gpg_key(gpg_key)
|
||||
return if @config.check_gpg_key?
|
||||
|
||||
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}
|
||||
|
||||
|
@ -82,16 +80,11 @@ class Cli
|
|||
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
|
||||
@password = password.to_s
|
||||
|
||||
puts I18n.t('form.setup_gpg_key.wait')
|
||||
|
||||
@config.setup_gpg_key(password, name, length, expire)
|
||||
@config.setup_gpg_key(@password, gpg_key)
|
||||
|
||||
puts "#{I18n.t('form.setup_gpg_key.valid')}".green
|
||||
rescue Exception => e
|
||||
|
@ -100,23 +93,17 @@ class Cli
|
|||
end
|
||||
|
||||
# Setup wallet config for sync
|
||||
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
|
||||
# @args: options -> value to change
|
||||
def setup_wallet_config(options={})
|
||||
if not options[:password].nil?
|
||||
options[:password] = ask(I18n.t('form.setup_wallet.password')) {|q| q.echo = false}
|
||||
end
|
||||
|
||||
@mpw.set_config(config)
|
||||
#wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw"
|
||||
|
||||
@mpw = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe)
|
||||
@mpw.read_data
|
||||
@mpw.set_config(options)
|
||||
@mpw.write_data
|
||||
|
||||
puts "#{I18n.t('form.setup_wallet.valid')}".green
|
||||
|
@ -125,6 +112,15 @@ class Cli
|
|||
exit 2
|
||||
end
|
||||
|
||||
# Load config
|
||||
def load_config
|
||||
@config.load_config
|
||||
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('display.error')} #10: #{e}".red
|
||||
exit 2
|
||||
end
|
||||
|
||||
# Request the GPG password and decrypt the file
|
||||
def decrypt
|
||||
if not defined?(@mpw)
|
||||
|
@ -139,97 +135,119 @@ class Cli
|
|||
exit 2
|
||||
end
|
||||
|
||||
# Display the query's result
|
||||
# @args: search -> the string to search
|
||||
# protocol -> search from a particular protocol
|
||||
def display(options={})
|
||||
result = @mpw.list(options)
|
||||
# Format items on a table
|
||||
def table(items=[])
|
||||
group = '.'
|
||||
i = 1
|
||||
length_total = 10
|
||||
data = { id: { length: 3, color: 'cyan' },
|
||||
host: { length: 9, color: 'yellow' },
|
||||
user: { length: 7, color: 'green' },
|
||||
protocol: { length: 9, color: 'white' },
|
||||
port: { length: 5, color: 'white' },
|
||||
otp: { length: 4, color: 'white' },
|
||||
comment: { length: 14, color: 'magenta' },
|
||||
}
|
||||
|
||||
case result.length
|
||||
when 0
|
||||
puts I18n.t('display.nothing')
|
||||
items.each do |item|
|
||||
data.each do |k, v|
|
||||
next if k == :id or k == :otp
|
||||
|
||||
when 1
|
||||
display_item(result.first)
|
||||
v[:length] = item.send(k.to_s).length + 3 if item.send(k.to_s).to_s.length >= v[:length]
|
||||
end
|
||||
end
|
||||
data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length]
|
||||
|
||||
data.each_value { |v| length_total += v[:length] }
|
||||
items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase }
|
||||
|
||||
else
|
||||
group = nil
|
||||
i = 1
|
||||
items.each do |item|
|
||||
if group != item.group
|
||||
group = item.group
|
||||
|
||||
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
|
||||
if group.to_s.empty?
|
||||
puts "\n#{I18n.t('display.no_group')}".red
|
||||
else
|
||||
puts "\n#{group}".red
|
||||
end
|
||||
|
||||
print " |_ ".yellow
|
||||
print "#{i}: ".cyan
|
||||
print item.name
|
||||
print " -> #{item.comment}".magenta if not item.comment.to_s.empty?
|
||||
print ' '
|
||||
length_total.times { print '=' }
|
||||
print "\n "
|
||||
data.each do |k, v|
|
||||
case k
|
||||
when :id
|
||||
print ' ID'
|
||||
when :otp
|
||||
print '| OTP'
|
||||
else
|
||||
print "| #{k.to_s.capitalize}"
|
||||
end
|
||||
|
||||
(v[:length] - k.to_s.length).times { print ' ' }
|
||||
end
|
||||
print "\n "
|
||||
length_total.times { print '=' }
|
||||
print "\n"
|
||||
|
||||
i += 1
|
||||
end
|
||||
|
||||
print " #{i}".send(data[:id][:color])
|
||||
(data[:id][:length] - i.to_s.length).times { print ' ' }
|
||||
data.each do |k, v|
|
||||
next if k == :id
|
||||
|
||||
if k == :otp
|
||||
print '| '
|
||||
if item.otp; print ' X ' else 4.times { print ' ' } end
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
print '| '
|
||||
print "#{item.send(k.to_s)}".send(v[:color])
|
||||
(v[:length] - item.send(k.to_s).to_s.length).times { print ' ' }
|
||||
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
|
||||
i += 1
|
||||
end
|
||||
|
||||
print "\n"
|
||||
end
|
||||
|
||||
# Display the query's result
|
||||
# @args: options -> the option to search
|
||||
def list(options={})
|
||||
result = @mpw.list(options)
|
||||
|
||||
if result.length == 0
|
||||
puts I18n.t('display.nothing')
|
||||
|
||||
else
|
||||
table(result)
|
||||
end
|
||||
end
|
||||
|
||||
# Display an item in the default format
|
||||
# @args: item -> an array with the item information
|
||||
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
|
||||
# Get an item when multiple choice
|
||||
# @args: items -> array of items
|
||||
# @rtrn: item
|
||||
def get_item(items)
|
||||
return items[0] if items.length == 1
|
||||
|
||||
if @clipboard
|
||||
print "#{I18n.t('display.password')}: ".cyan
|
||||
puts '***********'
|
||||
items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase }
|
||||
choice = ask(I18n.t('form.select')).to_i
|
||||
|
||||
if choice >= 1 and choice <= items.length
|
||||
return items[choice-1]
|
||||
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
|
||||
return nil
|
||||
end
|
||||
|
||||
print "#{I18n.t('display.port')}: ".cyan
|
||||
puts item.port
|
||||
print "#{I18n.t('display.comment')}: ".cyan
|
||||
puts item.comment
|
||||
|
||||
clipboard(item) if @clipboard
|
||||
end
|
||||
|
||||
# Copy in clipboard the login and password
|
||||
# @args: item -> the item
|
||||
def clipboard(item)
|
||||
# clipboard -> enable clipboard
|
||||
def clipboard(item, clipboard=true)
|
||||
pid = nil
|
||||
|
||||
# Security: force quit after 90s
|
||||
|
@ -246,21 +264,33 @@ class Cli
|
|||
break
|
||||
|
||||
when 'l', 'login'
|
||||
Clipboard.copy(item.user)
|
||||
puts I18n.t('form.clipboard.login').green
|
||||
if clipboard
|
||||
Clipboard.copy(item.user)
|
||||
puts I18n.t('form.clipboard.login').green
|
||||
else
|
||||
puts item.user
|
||||
end
|
||||
|
||||
when 'p', 'password'
|
||||
Clipboard.copy(@mpw.get_password(item.id))
|
||||
puts I18n.t('form.clipboard.password').yellow
|
||||
if clipboard
|
||||
Clipboard.copy(@mpw.get_password(item.id))
|
||||
puts I18n.t('form.clipboard.password').yellow
|
||||
|
||||
Thread.new do
|
||||
sleep 30
|
||||
Thread.new do
|
||||
sleep 30
|
||||
|
||||
Clipboard.clear
|
||||
Clipboard.clear
|
||||
end
|
||||
else
|
||||
puts @mpw.get_password(item.id)
|
||||
end
|
||||
|
||||
when 'o', 'otp'
|
||||
Clipboard.copy(@mpw.get_otp_code(item.id))
|
||||
if clipboard
|
||||
Clipboard.copy(@mpw.get_otp_code(item.id))
|
||||
else
|
||||
puts @mpw.get_otp_code(item.id)
|
||||
end
|
||||
puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow
|
||||
|
||||
else
|
||||
|
@ -268,6 +298,7 @@ class Cli
|
|||
puts I18n.t('form.clipboard.help.login')
|
||||
puts I18n.t('form.clipboard.help.password')
|
||||
puts I18n.t('form.clipboard.help.otp_code')
|
||||
puts I18n.t('form.clipboard.help.quit')
|
||||
next
|
||||
end
|
||||
end
|
||||
|
@ -277,34 +308,25 @@ class Cli
|
|||
Clipboard.clear
|
||||
end
|
||||
|
||||
# List all wallets
|
||||
def list_wallet
|
||||
wallets = Dir.glob("#{@config.wallet_dir}/*.mpw")
|
||||
|
||||
wallets.each do |wallet|
|
||||
puts File.basename(wallet, '.mpw')
|
||||
end
|
||||
end
|
||||
|
||||
# Display the wallet
|
||||
# @args: wallet -> the wallet name
|
||||
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
|
||||
if wallets.length == 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
|
||||
@wallet_file = "#{@config.wallet_dir}/default.mpw"
|
||||
end
|
||||
else
|
||||
@wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw"
|
||||
|
@ -336,111 +358,158 @@ class Cli
|
|||
puts "#{I18n.t('display.error')} #15: #{e}".red
|
||||
end
|
||||
|
||||
# Form to add a new item
|
||||
def add
|
||||
options = {}
|
||||
# Text editor interface
|
||||
# @args: template -> template name
|
||||
# item -> the item to edit
|
||||
# password -> disable field password
|
||||
def text_editor(template_name, item=nil, password=false)
|
||||
editor = ENV['EDITOR'] || 'nano'
|
||||
options = {}
|
||||
opts = {}
|
||||
template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb"
|
||||
template = ERB.new(IO.read(template_file))
|
||||
|
||||
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
|
||||
Dir.mktmpdir do |dir|
|
||||
tmp_file = "#{dir}/#{template_name}.yml"
|
||||
|
||||
if @otp
|
||||
otp_key = ask(I18n.t('form.add_item.otp_key')).to_s
|
||||
File.open(tmp_file, 'w') do |f|
|
||||
f << template.result(binding)
|
||||
end
|
||||
|
||||
system("#{editor} #{tmp_file}")
|
||||
|
||||
opts = YAML::load_file(tmp_file)
|
||||
end
|
||||
|
||||
item = Item.new(options)
|
||||
opts.delete_if { |k,v| v.to_s.empty? }
|
||||
|
||||
opts.each do |k,v|
|
||||
options[k.to_sym] = v
|
||||
end
|
||||
|
||||
return options
|
||||
end
|
||||
|
||||
# Form to add a new item
|
||||
# @args: password -> generate a random password
|
||||
def add(password=false)
|
||||
options = text_editor('add_form', nil, password)
|
||||
item = Item.new(options)
|
||||
|
||||
if password
|
||||
options[:password] = MPW::password(length: 24)
|
||||
end
|
||||
|
||||
@mpw.add(item)
|
||||
@mpw.set_password(item.id, password)
|
||||
@mpw.set_otp_key(item.id, otp_key)
|
||||
@mpw.set_password(item.id, options[:password]) if options.has_key?(:password)
|
||||
@mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key)
|
||||
@mpw.write_data
|
||||
@mpw.sync(true) if @sync
|
||||
|
||||
puts "#{I18n.t('form.add_item.valid')}".green
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('display.error')} #13: #{e}".red
|
||||
end
|
||||
|
||||
# Update an item
|
||||
# @args: id -> the item's id
|
||||
def update(id)
|
||||
item = @mpw.search_by_id(id)
|
||||
# @args: options -> the option to search
|
||||
def update(options={})
|
||||
items = @mpw.list(options)
|
||||
|
||||
if items.length == 0
|
||||
puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
|
||||
else
|
||||
table(items) if items.length > 1
|
||||
|
||||
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 = get_item(items)
|
||||
options = text_editor('update_form', item)
|
||||
|
||||
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.set_password(item.id, options[:password]) if options.has_key?(:password)
|
||||
@mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key)
|
||||
@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
|
||||
|
||||
# Remove an item
|
||||
# @args: id -> the item's id
|
||||
# force -> no resquest a validation
|
||||
def delete(id, force=false)
|
||||
@clipboard = false
|
||||
item = @mpw.search_by_id(id)
|
||||
# @args: options -> the option to search
|
||||
def delete(options={})
|
||||
items = @mpw.list(options)
|
||||
|
||||
if items.length == 0
|
||||
puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
|
||||
else
|
||||
table(items)
|
||||
|
||||
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
|
||||
item = get_item(items)
|
||||
confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s
|
||||
|
||||
if not confirm =~ /^(y|yes|YES|Yes|Y)$/
|
||||
return
|
||||
return false
|
||||
end
|
||||
|
||||
item.delete
|
||||
@mpw.write_data
|
||||
@mpw.sync(true) if @sync
|
||||
|
||||
puts "#{I18n.t('form.delete_item.valid')}".green
|
||||
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
|
||||
|
||||
# Copy a password, otp, login
|
||||
# @args: clipboard -> enable clipboard
|
||||
# options -> the option to search
|
||||
def copy(clipboard=true, options={})
|
||||
items = @mpw.list(options)
|
||||
|
||||
if items.length == 0
|
||||
puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
|
||||
else
|
||||
table(items)
|
||||
|
||||
item = get_item(items)
|
||||
clipboard(item, clipboard)
|
||||
end
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('display.error')} #14: #{e}".red
|
||||
end
|
||||
|
||||
# Export the items in a CSV file
|
||||
# @args: file -> the destination file
|
||||
def export(file)
|
||||
@mpw.export(file)
|
||||
# options -> option to search
|
||||
def export(file, options)
|
||||
file = 'export-mpw.yml' if file.to_s.empty?
|
||||
items = @mpw.list(options)
|
||||
data = {}
|
||||
i = 1
|
||||
|
||||
puts "#{I18n.t('export.export.valid', file)}".green
|
||||
items.each do |item|
|
||||
data.merge!(i => { 'host' => item.host,
|
||||
'user' => item.user,
|
||||
'group' => item.group,
|
||||
'password' => @mpw.get_password(item.id),
|
||||
'protocol' => item.protocol,
|
||||
'port' => item.port,
|
||||
'otp_key' => @mpw.get_otp_key(item.id),
|
||||
'comment' => item.comment,
|
||||
'last_edit' => item.last_edit,
|
||||
'created' => item.created,
|
||||
}
|
||||
)
|
||||
|
||||
i += 1
|
||||
end
|
||||
|
||||
File.open(file, 'w') {|f| f << data.to_yaml}
|
||||
|
||||
puts "#{I18n.t('export.valid', file)}".green
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('display.error')} #17: #{e}".red
|
||||
end
|
||||
|
@ -448,7 +517,26 @@ class Cli
|
|||
# Import items from a YAML file
|
||||
# @args: file -> the import file
|
||||
def import(file)
|
||||
@mpw.import(file)
|
||||
raise I18n.t('import.file_empty') if file.to_s.empty?
|
||||
raise I18n.t('import.file_not_exist') if not File.exist?(file)
|
||||
|
||||
YAML::load_file(file).each_value do |row|
|
||||
|
||||
item = Item.new(group: row['group'],
|
||||
host: row['host'],
|
||||
protocol: row['protocol'],
|
||||
user: row['user'],
|
||||
port: row['port'],
|
||||
comment: row['comment'],
|
||||
)
|
||||
|
||||
next if item.empty?
|
||||
|
||||
@mpw.add(item)
|
||||
@mpw.set_password(item.id, row['password']) if not row['password'].to_s.empty?
|
||||
@mpw.set_otp_key(item.id, row['otp_key']) if not row['otp_key'].to_s.empty?
|
||||
end
|
||||
|
||||
@mpw.write_data
|
||||
|
||||
puts "#{I18n.t('form.import.valid')}".green
|
||||
|
|
|
@ -57,20 +57,18 @@ class Config
|
|||
# gpg_exe -> the path of gpg executable
|
||||
# @rtrn: true if le config file is create
|
||||
def setup(key, lang, wallet_dir, gpg_exe)
|
||||
|
||||
if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
|
||||
raise I18n.t('error.config.key_bad_format')
|
||||
end
|
||||
|
||||
if wallet_dir.empty?
|
||||
if wallet_dir.to_s.empty?
|
||||
wallet_dir = "#{@config_dir}/wallets"
|
||||
end
|
||||
|
||||
config = {'config' => {'key' => key,
|
||||
'lang' => lang,
|
||||
'wallet_dir' => wallet_dir,
|
||||
'gpg_exe' => gpg_exe,
|
||||
}
|
||||
config = { 'key' => key,
|
||||
'lang' => lang,
|
||||
'wallet_dir' => wallet_dir,
|
||||
'gpg_exe' => gpg_exe,
|
||||
}
|
||||
|
||||
FileUtils.mkdir_p(wallet_dir, mode: 0700)
|
||||
|
@ -89,9 +87,9 @@ class Config
|
|||
# expire -> the time of expire to GPG key
|
||||
# @rtrn: true if the GPG key is create, else false
|
||||
def setup_gpg_key(password, name, length = 4096, expire = 0)
|
||||
if name.nil? or name.empty?
|
||||
if name.to_s.empty?
|
||||
raise "#{I18n.t('error.config.genkey_gpg.name')}"
|
||||
elsif password.nil? or password.empty?
|
||||
elsif password.to_s.empty?
|
||||
raise "#{I18n.t('error.config.genkey_gpg.password')}"
|
||||
end
|
||||
|
||||
|
@ -114,22 +112,20 @@ class Config
|
|||
raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}"
|
||||
end
|
||||
|
||||
# Check the config file
|
||||
# @rtrn: true if the config file is correct
|
||||
def is_valid?
|
||||
# Load the config file
|
||||
def load_config
|
||||
config = YAML::load_file(@config_file)
|
||||
@key = config['config']['key']
|
||||
@lang = config['config']['lang']
|
||||
@wallet_dir = config['config']['wallet_dir']
|
||||
@gpg_exe = config['config']['gpg_exe']
|
||||
@key = config['key']
|
||||
@lang = config['lang']
|
||||
@wallet_dir = config['wallet_dir']
|
||||
@gpg_exe = config['gpg_exe']
|
||||
|
||||
raise if @key.empty? or @wallet_dir.empty?
|
||||
|
||||
I18n.locale = @lang.to_sym
|
||||
|
||||
return true
|
||||
rescue
|
||||
return false
|
||||
rescue Exception => e
|
||||
raise "#{I18n.t('error.config.load')}\n#{e}"
|
||||
end
|
||||
|
||||
# Check if private key exist
|
||||
|
|
|
@ -22,12 +22,12 @@ module MPW
|
|||
class Item
|
||||
|
||||
attr_accessor :id
|
||||
attr_accessor :name
|
||||
attr_accessor :group
|
||||
attr_accessor :host
|
||||
attr_accessor :protocol
|
||||
attr_accessor :user
|
||||
attr_accessor :port
|
||||
attr_accessor :otp
|
||||
attr_accessor :comment
|
||||
attr_accessor :last_edit
|
||||
attr_accessor :last_sync
|
||||
|
@ -38,15 +38,15 @@ class Item
|
|||
# @args: options -> a hash of parameter
|
||||
# raise an error if the hash hasn't the key name
|
||||
def initialize(options={})
|
||||
if not options.has_key?(:name) or options[:name].to_s.empty?
|
||||
if not options.has_key?(:host) or options[:host].to_s.empty?
|
||||
raise I18n.t('error.update.name_empty')
|
||||
end
|
||||
|
||||
if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty?
|
||||
@id = generate_id
|
||||
if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty?
|
||||
@id = generate_id
|
||||
@created = Time.now.to_i
|
||||
else
|
||||
@id = options[:id]
|
||||
@id = options[:id]
|
||||
@created = options[:created]
|
||||
@last_edit = options[:last_edit]
|
||||
options[:no_update_last_edit] = true
|
||||
|
@ -58,16 +58,16 @@ class Item
|
|||
# Update the item
|
||||
# @args: options -> a hash of parameter
|
||||
def update(options={})
|
||||
if options.has_key?(:name) and options[:name].to_s.empty?
|
||||
if options.has_key?(:host) and options[:host].to_s.empty?
|
||||
raise I18n.t('error.update.name_empty')
|
||||
end
|
||||
|
||||
@name = options[:name] if options.has_key?(:name)
|
||||
@group = options[:group] if options.has_key?(:group)
|
||||
@host = options[:host] if options.has_key?(:host)
|
||||
@protocol = options[:protocol] if options.has_key?(:protocol)
|
||||
@user = options[:user] if options.has_key?(:user)
|
||||
@port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty?
|
||||
@otp = options[:otp] if options.has_key?(:otp)
|
||||
@comment = options[:comment] if options.has_key?(:comment)
|
||||
@last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit)
|
||||
end
|
||||
|
@ -80,12 +80,12 @@ class Item
|
|||
# Delete all data
|
||||
def delete
|
||||
@id = nil
|
||||
@name = nil
|
||||
@group = nil
|
||||
@host = nil
|
||||
@protocol = nil
|
||||
@user = nil
|
||||
@port = nil
|
||||
@otp = nil
|
||||
@comment = nil
|
||||
@created = nil
|
||||
@last_edit = nil
|
||||
|
@ -93,7 +93,7 @@ class Item
|
|||
end
|
||||
|
||||
def empty?
|
||||
return @name.to_s.empty?
|
||||
return @id.to_s.empty?
|
||||
end
|
||||
|
||||
def nil?
|
||||
|
@ -104,6 +104,6 @@ class Item
|
|||
private
|
||||
def generate_id
|
||||
return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
139
lib/mpw/mpw.rb
139
lib/mpw/mpw.rb
|
@ -33,7 +33,7 @@ class MPW
|
|||
@gpg_exe = gpg_exe
|
||||
@wallet_file = wallet_file
|
||||
|
||||
if @gpg_exe
|
||||
if not @gpg_exe.to_s.empty?
|
||||
GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg")
|
||||
end
|
||||
end
|
||||
|
@ -83,12 +83,12 @@ class MPW
|
|||
if not data.nil? and not data.empty?
|
||||
YAML.load(data).each_value do |d|
|
||||
@data.push(Item.new(id: d['id'],
|
||||
name: d['name'],
|
||||
group: d['group'],
|
||||
host: d['host'],
|
||||
protocol: d['protocol'],
|
||||
user: d['user'],
|
||||
port: d['port'],
|
||||
otp: @otp_keys.has_key?(d['id']),
|
||||
comment: d['comment'],
|
||||
last_edit: d['last_edit'],
|
||||
created: d['created'],
|
||||
|
@ -110,16 +110,15 @@ class MPW
|
|||
@data.each do |item|
|
||||
next if item.empty?
|
||||
|
||||
data.merge!(item.id => {'id' => item.id,
|
||||
'name' => item.name,
|
||||
'group' => item.group,
|
||||
'host' => item.host,
|
||||
'protocol' => item.protocol,
|
||||
'user' => item.user,
|
||||
'port' => item.port,
|
||||
'comment' => item.comment,
|
||||
'last_edit' => item.last_edit,
|
||||
'created' => item.created,
|
||||
data.merge!(item.id => { 'id' => item.id,
|
||||
'group' => item.group,
|
||||
'host' => item.host,
|
||||
'protocol' => item.protocol,
|
||||
'user' => item.user,
|
||||
'port' => item.port,
|
||||
'comment' => item.comment,
|
||||
'last_edit' => item.last_edit,
|
||||
'created' => item.created,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
@ -158,7 +157,7 @@ class MPW
|
|||
|
||||
File.rename(tmp_file, @wallet_file)
|
||||
rescue Exception => e
|
||||
File.unlink(tmp_file)
|
||||
File.unlink(tmp_file) if File.exist?(tmp_file)
|
||||
|
||||
raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}"
|
||||
end
|
||||
|
@ -211,16 +210,16 @@ class MPW
|
|||
|
||||
# Set config
|
||||
# args: config -> a hash with config options
|
||||
def set_config(config)
|
||||
@config['sync'] = {} if @config['sync'].nil?
|
||||
def set_config(options={})
|
||||
@config = {} if @config.nil?
|
||||
|
||||
@config['sync']['type'] = config['sync']['type']
|
||||
@config['sync']['host'] = config['sync']['host']
|
||||
@config['sync']['port'] = config['sync']['port']
|
||||
@config['sync']['user'] = config['sync']['user']
|
||||
@config['sync']['password'] = config['sync']['password']
|
||||
@config['sync']['path'] = config['sync']['path']
|
||||
@config['sync']['last_sync'] = @config['sync']['last_sync'].nil? ? 0 : @config['sync']['last_sync']
|
||||
@config['protocol'] = options[:protocol] if options.has_key?(:protocol)
|
||||
@config['host'] = options[:host] if options.has_key?(:host)
|
||||
@config['port'] = options[:port] if options.has_key?(:port)
|
||||
@config['user'] = options[:user] if options.has_key?(:user)
|
||||
@config['password'] = options[:password] if options.has_key?(:password)
|
||||
@config['path'] = options[:path] if options.has_key?(:path)
|
||||
@config['last_sync'] = @config['last_sync'].nil? ? 0 : @config['last_sync']
|
||||
end
|
||||
|
||||
# Add a new item
|
||||
|
@ -241,18 +240,17 @@ class MPW
|
|||
def list(options={})
|
||||
result = []
|
||||
|
||||
search = options[:search].to_s.downcase
|
||||
group = options[:group].to_s.downcase
|
||||
search = options[:pattern].to_s.downcase
|
||||
group = options[:group].to_s.downcase
|
||||
|
||||
@data.each do |item|
|
||||
next if item.empty?
|
||||
next if not group.empty? and not group.eql?(item.group.downcase)
|
||||
next if not group.empty? and not group.eql?(item.group.to_s.downcase)
|
||||
|
||||
name = item.name.to_s.downcase
|
||||
host = item.host.to_s.downcase
|
||||
comment = item.comment.to_s.downcase
|
||||
|
||||
if not name =~ /^.*#{search}.*$/ and not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/
|
||||
if not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/
|
||||
next
|
||||
end
|
||||
|
||||
|
@ -273,56 +271,9 @@ class MPW
|
|||
return nil
|
||||
end
|
||||
|
||||
# Export to yaml
|
||||
# @args: file -> file where you export the data
|
||||
def export(file)
|
||||
data = {}
|
||||
@data.each do |item|
|
||||
data.merge!(item.id => {'id' => item.id,
|
||||
'name' => item.name,
|
||||
'group' => item.group,
|
||||
'host' => item.host,
|
||||
'protocol' => item.protocol,
|
||||
'user' => item.user,
|
||||
'password' => get_password(item.id),
|
||||
'port' => item.port,
|
||||
'comment' => item.comment,
|
||||
'last_edit' => item.last_edit,
|
||||
'created' => item.created,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
File.open(file, 'w') {|f| f << data.to_yaml}
|
||||
rescue Exception => e
|
||||
raise "#{I18n.t('error.export', file: file)}\n#{e}"
|
||||
end
|
||||
|
||||
# Import to yaml
|
||||
# @args: file -> path to file import
|
||||
def import(file)
|
||||
YAML::load_file(file).each_value do |row|
|
||||
item = Item.new(name: row['name'],
|
||||
group: row['group'],
|
||||
host: row['host'],
|
||||
protocol: row['protocol'],
|
||||
user: row['user'],
|
||||
port: row['port'],
|
||||
comment: row['comment'],
|
||||
)
|
||||
|
||||
raise 'Item is empty' if item.empty?
|
||||
|
||||
@data.push(item)
|
||||
set_password(item.id, row['password'])
|
||||
end
|
||||
rescue Exception => e
|
||||
raise "#{I18n.t('error.import', file: file)}\n#{e}"
|
||||
end
|
||||
|
||||
# Get last sync
|
||||
def get_last_sync
|
||||
return @config['sync']['last_sync'].to_i
|
||||
return @config['last_sync'].to_i
|
||||
rescue
|
||||
return 0
|
||||
end
|
||||
|
@ -330,18 +281,18 @@ class MPW
|
|||
# Sync data with remote file
|
||||
# @args: force -> force the sync
|
||||
def sync(force=false)
|
||||
return if @config.empty? or @config['sync']['type'].to_s.empty?
|
||||
return if @config.empty? or @config['protocol'].to_s.empty?
|
||||
return if get_last_sync + 300 > Time.now.to_i and not force
|
||||
|
||||
tmp_file = "#{@wallet_file}.sync"
|
||||
|
||||
case @config['sync']['type']
|
||||
case @config['protocol']
|
||||
when 'sftp', 'scp', 'ssh'
|
||||
require "mpw/sync/ssh"
|
||||
sync = SyncSSH.new(@config['sync'])
|
||||
sync = SyncSSH.new(@config)
|
||||
when 'ftp'
|
||||
require 'mpw/sync/ftp'
|
||||
sync = SyncFTP.new(@config['sync'])
|
||||
sync = SyncFTP.new(@config)
|
||||
else
|
||||
raise I18n.t('error.sync.unknown_type')
|
||||
end
|
||||
|
@ -365,8 +316,7 @@ class MPW
|
|||
|
||||
# Update item
|
||||
if item.last_edit < r.last_edit
|
||||
item.update(name: r.name,
|
||||
group: r.group,
|
||||
item.update(group: r.group,
|
||||
host: r.host,
|
||||
protocol: r.protocol,
|
||||
user: r.user,
|
||||
|
@ -394,7 +344,6 @@ class MPW
|
|||
next if r.last_edit <= get_last_sync
|
||||
|
||||
item = Item.new(id: r.id,
|
||||
name: r.name,
|
||||
group: r.group,
|
||||
host: r.host,
|
||||
protocol: r.protocol,
|
||||
|
@ -415,7 +364,7 @@ class MPW
|
|||
item.set_last_sync
|
||||
end
|
||||
|
||||
@config['sync']['last_sync'] = Time.now.to_i
|
||||
@config['last_sync'] = Time.now.to_i
|
||||
|
||||
write_data
|
||||
sync.update(@wallet_file)
|
||||
|
@ -429,13 +378,27 @@ class MPW
|
|||
# args: id -> the item id
|
||||
# key -> the new key
|
||||
def set_otp_key(id, key)
|
||||
@otp_keys[id] = encrypt(key)
|
||||
if not key.to_s.empty?
|
||||
@otp_keys[id] = encrypt(key.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
# Get an opt key
|
||||
# args: id -> the item id
|
||||
# key -> the new key
|
||||
def get_otp_key(id)
|
||||
if @otp_keys.has_key?(id)
|
||||
return decrypt(@otp_keys[id])
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Get an otp code
|
||||
# @args: id -> the item id
|
||||
# @rtrn: an otp code
|
||||
def get_otp_code(id)
|
||||
def get_otp_code(id)
|
||||
if not @otp_keys.has_key?(id)
|
||||
return 0
|
||||
else
|
||||
|
@ -481,6 +444,8 @@ class MPW
|
|||
# @args: data -> string to decrypt
|
||||
private
|
||||
def decrypt(data)
|
||||
return nil if data.to_s.empty?
|
||||
|
||||
crypto = GPGME::Crypto.new(armor: true)
|
||||
|
||||
return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8')
|
||||
|
@ -495,12 +460,12 @@ class MPW
|
|||
recipients = []
|
||||
crypto = GPGME::Crypto.new(armor: true, always_trust: true)
|
||||
|
||||
recipients.push(@key)
|
||||
@keys.each_key do |key|
|
||||
next if key == @key
|
||||
recipients.push(key)
|
||||
end
|
||||
|
||||
recipients.push(@key) if not recipients.index(@key).nil?
|
||||
|
||||
return crypto.encrypt(data, recipients: recipients).read
|
||||
rescue Exception => e
|
||||
raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}"
|
||||
|
|
|
@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|||
spec.add_dependency "locale"
|
||||
spec.add_dependency "colorize"
|
||||
spec.add_dependency "net-ssh"
|
||||
spec.add_dependency "net-scp"
|
||||
spec.add_dependency "net-sftp"
|
||||
spec.add_dependency "clipboard"
|
||||
spec.add_dependency "rotp"
|
||||
end
|
||||
|
|
9
templates/add_form.erb
Normal file
9
templates/add_form.erb
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
host: # <%= I18n.t('form.add_item.host') %>
|
||||
user: # <%= I18n.t('form.add_item.login') %>
|
||||
group: # <%= I18n.t('form.add_item.group') %>
|
||||
protocol: # <%= I18n.t('form.add_item.protocol') %><% if not password %>
|
||||
password: # <%= I18n.t('form.add_item.password') %><% end %>
|
||||
port: # <%= I18n.t('form.add_item.port') %>
|
||||
comment: # <%= I18n.t('form.add_item.comment') %>
|
||||
otp_key: # <%= I18n.t('form.add_item.otp_key') %>
|
9
templates/setup_form.erb
Normal file
9
templates/setup_form.erb
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
# <%= I18n.t('form.setup_config.lang') %>
|
||||
language: <%= @config.lang %>
|
||||
# <%= I18n.t('form.setup_config.gpg_key') %>
|
||||
gpg_key: <%= @config.key %>
|
||||
# <%= I18n.t('form.setup_config.wallet_dir') %>
|
||||
wallet_dir: <%= @config.config_dir %>
|
||||
# <%= I18n.t('form.setup_config.gpg_exe') %>
|
||||
gpg_exe: <%= @config.gpg_exe %>
|
17
templates/update_form.erb
Normal file
17
templates/update_form.erb
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
# <%= I18n.t('form.update_item.host') %>
|
||||
host: <%= item.host %>
|
||||
# <%= I18n.t('form.update_item.login') %>
|
||||
user: <%= item.user %>
|
||||
# <%= I18n.t('form.update_item.password') %>
|
||||
password:
|
||||
# <%= I18n.t('form.update_item.group') %>
|
||||
group: <%= item.group %>
|
||||
# <%= I18n.t('form.update_item.protocol') %>
|
||||
protocol: <%= item.protocol %>
|
||||
# <%= I18n.t('form.update_item.port') %>
|
||||
port: <%= item.port %>
|
||||
# <%= I18n.t('form.update_item.otp_key') %>
|
||||
opt_key:
|
||||
# <%= I18n.t('form.update_item.comment') %>
|
||||
comment: <%= item.comment %>
|
Loading…
Add table
Reference in a new issue