diff --git a/Gemfile b/Gemfile index a76b2c1..f3660b8 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,7 @@ source 'https://rubygems.org' gem 'clipboard', '~> 1.1', '>= 1.1.1' gem 'colorize', '~> 0.8', '>= 0.8.1' +gem 'git', '~> 1.3', '>= 1.3.0' gem 'gpgme', '~> 2.0', '>= 2.0.14' gem 'highline', '~> 1.7', '>= 1.7.8' gem 'i18n', '~> 0.9', '>= 0.9.1' diff --git a/bin/mpw-wallet b/bin/mpw-wallet index ea40de2..3107a53 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -47,6 +47,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-i', '--init', I18n.t('option.init_wallet')) do + options[:init] = true + end + opts.on('-l', '--list', I18n.t('option.list')) do options[:list] = true end @@ -55,6 +59,10 @@ OptionParser.new do |opts| options[:list_keys] = true end + opts.on('-r', '--remote URI', I18n.t('option.remote_uri')) do |uri| + options[:remote] = uri + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -65,7 +73,10 @@ cli = MPW::Cli.new(config) cli.load_config -if options.key?(:list_keys) || options.key?(:gpg_key) +if options[:init] + cli.get_wallet(options[:wallet]) + cli.init_wallet(options[:remote]) +elsif options.key?(:list_keys) || options.key?(:gpg_key) cli.get_wallet(options[:wallet]) cli.decrypt diff --git a/i18n/en.yml b/i18n/en.yml index 36eb7b3..9883585 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -17,6 +17,7 @@ en: gpg_file: decrypt: "Can't decrypt file!" encrypt: "Can't encrypt the GPG file!" + init_wallet: "Can't initialize the wallet!" mpw_file: read_data: "Can't read the MPW file!" write_data: "Can't write the MPW file!" @@ -63,6 +64,7 @@ en: group: "Search the items with specified group" help: "Show this help message" init: "Initialize mpw" + init_wallet: "Initialize a new wallet" import: "Import item from an yaml file" key: "Define the key name" lang: "Set the software language" @@ -75,6 +77,7 @@ en: pattern: "Given search pattern" pinmode: "Enable pinentry mode (available with gpg >= 2.1)" random_password: "Generate a random password" + remote_uri: "Set remote GIT repository URL" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" special_chars: "Use special char to create a password" @@ -130,6 +133,8 @@ en: format_unknown: "The import format '%{file_format} is unknown!" valid: "The import is successful!" not_valid: "No data to import!" + init_wallet: + valid: "The wallet has been initialized!" set_config: valid: "The config file has been edited!" setup_config: diff --git a/i18n/fr.yml b/i18n/fr.yml index 4c474a5..435e5b3 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -17,6 +17,7 @@ fr: gpg_file: decrypt: "Impossible de déchiffrer le fichier GPG!" encrypt: "Impossible de chiffrer le fichier GPG!" + init_wallet: "Impossible d'initialiser le porte-feuille!" mpw_file: read_data: "Impossible de lire le fichier MPW!" write_data: "Impossible d'écrire le fichier MPW!" @@ -64,6 +65,7 @@ fr: help: "Affiche ce message d'aide" import: "Importe des éléments depuis un fichier yaml" init: "Initialise mpw" + init_wallet: "Initialise un nouveau porte-feuille" key: "Spécifie le nom d'une clé" lang: "Spécifie la langue du logiciel (ex: fr)" length: "Taille du mot de passe" @@ -75,6 +77,7 @@ fr: pattern: "Motif de donnée à chercher" pinmode: "Active le mode pinentry (valable avec gpg >= 2.1)" random_password: "Génére un mot de passe aléatoire" + remote_uri: "Spécifie l'url d'un dépôt git distant" 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" @@ -130,6 +133,8 @@ fr: format_unknown: "Le format d'import '%{file_format}' est inconnu!" valid: "L'import est un succès!" not_valid: "Aucune donnée à importer!" + init_wallet: + valid: "Le porte-feuille a bien été initialisé!" set_config: valid: "Le fichier de configuration a bien été modifié!" setup_config: diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index f3397b8..d8091fa 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -35,6 +35,18 @@ module MPW @config = config end + # Init a wallet folder + # @param remote_uri [String] the uri of the remote git repository + def init_wallet(remote_uri) + @mpw = MPW.new(@config.gpg_key, @wallet_path, nil, @config.gpg_exe, @config.pinmode) + @mpw.init_wallet(remote_uri) + + puts I18n.t('form.init_wallet.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #20: #{e}".red + exit 2 + end + # Change a parameter int the config after init # @param options [Hash] param to change def set_config(options) @@ -42,7 +54,7 @@ module MPW puts I18n.t('form.set_config.valid').to_s.green rescue => e - puts "#{I18n.t('display.error')} #15: #{e}".red + puts "#{I18n.t('display.error')} #19: #{e}".red exit 2 end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 915ad49..3e309a4 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -19,6 +19,7 @@ # under the License. require 'gpgme' +require 'git' require 'i18n' require 'yaml' require 'rotp' @@ -37,17 +38,30 @@ module MPW @gpg_exe = gpg_exe @pinmode = pinmode @wallet_path = wallet_path + @wallet_name = File.basename(@wallet_path) + @git = Git.open(@wallet_path) if Dir.exist?(@wallet_path) @data = [] @keys = {} @passwords = {} @otp_keys = {} GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") unless @gpg_exe.to_s.empty? + end + # Init a wallet folder + # @param remote_uri [String] the uri of the remote git repository + def init_wallet(remote_uri) Dir.mkdir(@wallet_path) unless Dir.exist?(@wallet_path) %w[passwords otp_keys keys].each do |folder| Dir.mkdir("#{@wallet_path}/#{folder}") unless Dir.exist?("#{@wallet_path}/#{folder}") end + + @git = remote_uri ? Git.clone(remote_uri, @wallet_name, path: @wallet_path) : Git.init(@wallet_path) + @git.config('user.name', @key.split('@').first) + @git.config('user.email', @key) + @git.commit('init wallet', allow_empty: true) unless remote_uri + rescue => e + raise "#{I18n.t('error.init_wallet')}\n#{e}" end # Read mpw file @@ -118,6 +132,9 @@ module MPW File.unlink(file) unless data.key?(File.basename(file, '.gpg')) end end + + @git.add + @git.commit('wallet updated') rescue => e raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" end diff --git a/mpw.gemspec b/mpw.gemspec index abcb375..934637c 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.1' spec.add_dependency 'i18n', '~> 0.9', '>= 0.9.1' + spec.add_dependency 'git', '~> 1.3', '>= 1.3.0' spec.add_dependency 'gpgme', '~> 2.0', '>= 2.0.14' spec.add_dependency 'highline', '~> 1.7', '>= 1.7.8' spec.add_dependency 'locale', '~> 2.1', '>= 2.1.2' diff --git a/test/test_cli.rb b/test/test_cli.rb index 69e3e85..e470dcd 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -24,6 +24,13 @@ class TestConfig < Test::Unit::TestCase ) assert_match(I18n.t('form.setup_config.valid'), output) assert_match(I18n.t('form.setup_gpg_key.valid'), output) + + output = %x( + mpw wallet \ + --init \ + 2>/dev/null + ) + assert_match(I18n.t('form.init_wallet.valid'), output) end def test_01_add_item