2pass 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 671d7c33b6f4e5e79ef13a88986405674f456dc06e23f5cc7450fb495ecdcb71
4
- data.tar.gz: 415390e6ac546a6af7678058e1231a4ade807df151dca0b163aa4023da8fe229
3
+ metadata.gz: 1236ce26a8191128890f5d302ae31ebe607f51dd6018bdbc1dd561f782909748
4
+ data.tar.gz: b5b6cb1c22ce47f83df9a1f403ffce5628ae1d7a9d496b3ccbcc7c79f6a4726b
5
5
  SHA512:
6
- metadata.gz: f865bb6fac54e13f4ac4c7c917680b0a0ef92194d1a2f1f97cc72333de8215466d4ab598a0a2ddb5360bc61b489c9a0231fa2ec3d53afd98b7e9f15aecb58fb1
7
- data.tar.gz: e01b0c574e69fcd8096605c7b7a2f383aad580dbbfd72ec6a89701573ee75a182303b5bd6349bc8022a9354e4a4bc042a090435016bba213aca0c37d54fcf5eb
6
+ metadata.gz: da6f2bacdade151d6ab41d815aec44f4f21dbd5b14ee330a06a4bf34efcda2b1d7d7f1eefbf455058002ca524f1369e577245692f5329b6a2938348c5799a6c9
7
+ data.tar.gz: 165926fcf9576c49b62a628beb4ec16cff3ea01a58d07854f88c5e7891d73c40af22406183dfbacd138794fb477c90094e8d208844eac9188adc828c6dd22765
data/2pass.gemspec CHANGED
@@ -24,4 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "rake", "~> 13.0"
25
25
  spec.add_development_dependency "minitest", "~> 5.0"
26
26
  spec.add_development_dependency "minitest-reporters", "~> 1.3", ">= 1.3.0"
27
+
28
+ spec.add_dependency "terminal-table", "~> 4.0"
27
29
  end
data/README.md CHANGED
@@ -17,13 +17,12 @@ An array of hashes with the following keys:
17
17
 
18
18
  - id
19
19
  - value
20
- - uuid
21
20
 
22
21
  ```sh
23
22
  touch ~/.2pass/vault_name.yml
24
23
  ```
25
24
 
26
- Alternatively, if you have a vault file in a different location, you can link it.
25
+ Alternatively, if you already have a vault file in a different location, you can link it.
27
26
 
28
27
  ```sh
29
28
  2pass link vault_name /path/to/vault_name.yml
@@ -44,6 +43,10 @@ Then build the gem and install it.
44
43
  2pass list <vault_name>
45
44
  2pass add <vault_name> <id> <value>
46
45
  ```
46
+ You can also pass an optional environment to most commands:
47
+ `2pass get myproject mykey production`
48
+
49
+ This will search for `mykey` within `myproject.production.yml`
47
50
 
48
51
  ## Development
49
52
 
data/bin/2pass CHANGED
@@ -5,11 +5,13 @@ require_relative "../lib/2pass"
5
5
  def help_message
6
6
  puts <<~HELP
7
7
  Usage:
8
- 2pass add <vault_name> <id> <value> - Add new secret
9
- 2pass get <vault_name> <id> - Get content by ID from the specified vault
10
- 2pass list <vault_name> - List the content of the specified vault
11
- 2pass link <vault_name> <target_path> - Create a symlink for an existing vault. Useful when the vault is stored in a synced place (iCloud, Dropbox, etc.)
12
- 2pass -h - Display this help message
8
+ 2pass add <vault_name> <id> <value> <env> - Add new secret. env is optional
9
+ 2pass get <vault_name> <id> <env> - Get content by ID from the specified vault. env is optional
10
+ 2pass list <vault_name> <env> - List the content of the specified vault as key=value pairs. env is optional
11
+ 2pass list <vault_name> <env> --json - List the content of the specified vault as JSON. env is optional
12
+ 2pass list <vault_name> <env> --dotenv - List the content of the specified vault as key=value pairs. env is optional
13
+ 2pass link <vault_name> <target_path> <env> - Create a symlink for an existing vault. Useful when the vault is stored in a synced place (iCloud, Dropbox, etc.). env is optional
14
+ 2pass -h - Display this help message
13
15
  HELP
14
16
  end
15
17
 
@@ -23,6 +25,12 @@ OptionParser.new do |opts|
23
25
  opts.on("-v", "--version", "Display the version") do
24
26
  options[:version] = true
25
27
  end
28
+ opts.on("--json", "Use JSON output format") do
29
+ options[:format] = :json
30
+ end
31
+ opts.on("--dotenv", "Use key=value output format") do
32
+ options[:format] = :dotenv
33
+ end
26
34
  end.parse!
27
35
 
28
36
  if options[:help]
@@ -43,30 +51,39 @@ end
43
51
  command, vault_name, *args = ARGV
44
52
 
45
53
  begin
46
- case command
47
- when "get"
54
+ case command&.to_sym
55
+ when :get
48
56
  if args.length < 1
49
57
  help_message
50
58
  exit(1)
51
59
  end
52
- id = args[0]
53
- puts TwoPass.get_secret(vault_name, id)
54
- when "add"
60
+ id, env = args[0], args[1]
61
+ puts TwoPass.get_secret(vault_name, id, env: env)
62
+ when :add
55
63
  if args.length != 2
56
64
  help_message
57
65
  exit(1)
58
66
  end
59
- TwoPass.add_secret(vault_name, args[0], args[1])
60
- when "list"
61
- puts TwoPass.list_content(vault_name)
62
- when "link"
67
+ id, value, env = args[0], args[1], args[2]
68
+ TwoPass.add_secret(vault_name, id, value, env: env)
69
+ when :list
70
+ env = args[0]
71
+ if options[:format] == :json
72
+ puts TwoPass.list_content(vault_name, env: env, format: :json)
73
+ elsif options[:format] == :dotenv
74
+ puts TwoPass.list_content(vault_name, env: env, format: :dotenv)
75
+ else
76
+ puts TwoPass.list_content(vault_name, env: env)
77
+ end
78
+ exit(1)
79
+ when :link
63
80
  if args.length < 1
64
81
  help_message
65
82
  exit(1)
66
83
  end
67
- target_path = args[0]
68
- TwoPass.create_symlink(vault_name, target_path)
69
- when "help"
84
+ target_path, env = args[0], args[1]
85
+ TwoPass.create_symlink(vault_name, target_path, env: env)
86
+ when :help
70
87
  help_message
71
88
  else
72
89
  help_message
@@ -79,5 +96,5 @@ rescue => e
79
96
  STDERR.puts e.backtrace
80
97
  end
81
98
 
82
- exit 1
99
+ exit(1)
83
100
  end
data/lib/2pass/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module TwoPass
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/2pass.rb CHANGED
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "optparse"
2
4
  require "json"
3
5
  require "yaml"
4
6
  require "fileutils"
5
- require "securerandom"
7
+ require "terminal-table"
6
8
 
7
9
  require_relative "2pass/version"
8
10
 
@@ -10,9 +12,9 @@ module TwoPass
10
12
  VAULT_DIR = "#{Dir.home}/.2pass"
11
13
 
12
14
  class << self
13
- def create_symlink(vault_name, target_path)
15
+ def create_symlink(vault_name, target_path, env: nil)
14
16
  FileUtils.mkdir_p(VAULT_DIR)
15
- symlink_path = "#{VAULT_DIR}/#{vault_name}.yml"
17
+ symlink_path = vault_file_path(vault_name, env: env)
16
18
 
17
19
  if File.exist?(symlink_path)
18
20
  puts "Symlink already exists: #{symlink_path}"
@@ -22,44 +24,55 @@ module TwoPass
22
24
  end
23
25
  end
24
26
 
25
- def load_vault(vault_name)
26
- file_path = "#{VAULT_DIR}/#{vault_name}.yml"
27
- return [] unless File.exist?(file_path)
28
-
29
- YAML.load_file(file_path, symbolize_names: true) || []
30
- rescue Psych::SyntaxError => e
31
- STDERR.puts "Error parsing YAML file: #{e.message}"
32
- []
33
- end
34
-
35
- def save_vault(vault_name, data)
27
+ def save_vault(vault_name, data, env: nil)
36
28
  FileUtils.mkdir_p(VAULT_DIR)
37
- file_path = "#{VAULT_DIR}/#{vault_name}.yml"
29
+ file_path = vault_file_path(vault_name, env: env)
38
30
  File.write(file_path, YAML.dump(data))
39
31
  end
40
32
 
41
- def list_content(vault_name)
42
- vault = load_vault(vault_name)
43
- JSON.pretty_generate(vault)
33
+ def list_content(vault_name, env: nil, format: :table)
34
+ vault = load_vault(vault_name, env: env)
35
+ if format == :table
36
+ rows = vault
37
+ .sort_by { |hash| hash[:id] }
38
+ .each_with_object([]) do |h, arr|
39
+ arr << [h[:id], h[:value]]
40
+ end
41
+ Terminal::Table.new(
42
+ rows: rows,
43
+ title: env || nil,
44
+ style: {all_separators: true}
45
+ ).to_s
46
+ elsif format == :dotenv
47
+ vault
48
+ .map { |h| "#{h[:id]}=#{h[:value]}" }
49
+ .sort
50
+ .join("\n")
51
+ elsif format == :json
52
+ JSON.pretty_generate(
53
+ vault
54
+ .map { |hash| hash.slice(:id, :value) }
55
+ .sort_by { |hash| hash[:id] }
56
+ )
57
+ end
44
58
  end
45
59
 
46
- def add_secret(vault_name, id, value)
60
+ def add_secret(vault_name, id, value, env: nil)
47
61
  new_secret = {
48
62
  id: id,
49
- value: value,
50
- uuid: SecureRandom.uuid
63
+ value: value
51
64
  }
52
- data = load_vault(vault_name)
65
+ data = load_vault(vault_name, env: env)
53
66
  existing_entry_id = data.find_index { |hash| hash[:id] == new_secret[:id] }
54
67
  if existing_entry_id
55
68
  raise "The secret already exists"
56
69
  end
57
70
  data << new_secret
58
- save_vault(vault_name, data)
71
+ save_vault(vault_name, data, env: env)
59
72
  end
60
73
 
61
- def get_secret(vault_name, id)
62
- vault = load_vault(vault_name)
74
+ def get_secret(vault_name, id, env: nil)
75
+ vault = load_vault(vault_name, env: env)
63
76
  entry = vault.find { |hash| hash[:id] == id }
64
77
  if entry
65
78
  entry[:value]
@@ -67,5 +80,24 @@ module TwoPass
67
80
  raise "Entry not found"
68
81
  end
69
82
  end
83
+
84
+ private
85
+
86
+ def load_vault(vault_name, env: nil)
87
+ file_path = self.vault_file_path(vault_name, env: env)
88
+ return [] unless File.exist?(file_path)
89
+
90
+ YAML.load_file(file_path, symbolize_names: true) || []
91
+ rescue Psych::SyntaxError => e
92
+ STDERR.puts "Error parsing YAML file: #{e.message}"
93
+ []
94
+ end
95
+
96
+ def vault_file_path(vault_name, env: nil)
97
+ [
98
+ VAULT_DIR,
99
+ [vault_name, env].compact.join(".")
100
+ ].join("/") + ".yml"
101
+ end
70
102
  end
71
103
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: 2pass
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Olivier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-19 00:00:00.000000000 Z
11
+ date: 2025-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -72,6 +72,20 @@ dependencies:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: 1.3.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: terminal-table
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '4.0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '4.0'
75
89
  description: 2pass is a CLI application for managing YAML-based vaults.
76
90
  email:
77
91
  - contact@yafoy.com