2pass 1.2.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: dbffa6c36a23a40c4ec93bc9f0277cf43d3e2388b61459a89aad0bb89458451e
4
- data.tar.gz: 5ab72d0c03fb7b718aaec180fdb530755ad69394acb6f808918b978044174e47
3
+ metadata.gz: 1236ce26a8191128890f5d302ae31ebe607f51dd6018bdbc1dd561f782909748
4
+ data.tar.gz: b5b6cb1c22ce47f83df9a1f403ffce5628ae1d7a9d496b3ccbcc7c79f6a4726b
5
5
  SHA512:
6
- metadata.gz: 0f0bce6612b408712dac5d313331b8721703f89a4a695ff0d7fd23076d6fcaf7bd2fdec67bdf75c1504f98d59dd400fe04bfa70f729847e234b13ab114d03eb6
7
- data.tar.gz: 06d625e2325531c59eff3d197eab64ed3265de9c93ab4046ff39c81f7057ceecb3c2cd640cccc70f9073da3975a3eac9e14fdbaf185242ff4141a0ea1bc6a517
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,12 +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 as key-value pairs
11
- 2pass list <vault_name> --json - List the content of the specified vault as JSON
12
- 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.)
13
- 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
14
15
  HELP
15
16
  end
16
17
 
@@ -24,12 +25,12 @@ OptionParser.new do |opts|
24
25
  opts.on("-v", "--version", "Display the version") do
25
26
  options[:version] = true
26
27
  end
27
- opts.on("-f", "--format", "Specify output format (e.g., json)") do |format|
28
- options[:format] = format == "json" ? :json : :text
29
- end
30
- opts.on("--json", "Use JSON output format (same as -f json)") do
28
+ opts.on("--json", "Use JSON output format") do
31
29
  options[:format] = :json
32
30
  end
31
+ opts.on("--dotenv", "Use key=value output format") do
32
+ options[:format] = :dotenv
33
+ end
33
34
  end.parse!
34
35
 
35
36
  if options[:help]
@@ -56,19 +57,23 @@ begin
56
57
  help_message
57
58
  exit(1)
58
59
  end
59
- id = args[0]
60
- puts TwoPass.get_secret(vault_name, id)
60
+ id, env = args[0], args[1]
61
+ puts TwoPass.get_secret(vault_name, id, env: env)
61
62
  when :add
62
63
  if args.length != 2
63
64
  help_message
64
65
  exit(1)
65
66
  end
66
- TwoPass.add_secret(vault_name, args[0], args[1])
67
+ id, value, env = args[0], args[1], args[2]
68
+ TwoPass.add_secret(vault_name, id, value, env: env)
67
69
  when :list
70
+ env = args[0]
68
71
  if options[:format] == :json
69
- puts TwoPass.list_content(vault_name, 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)
70
75
  else
71
- puts TwoPass.list_content(vault_name)
76
+ puts TwoPass.list_content(vault_name, env: env)
72
77
  end
73
78
  exit(1)
74
79
  when :link
@@ -76,8 +81,8 @@ begin
76
81
  help_message
77
82
  exit(1)
78
83
  end
79
- target_path = args[0]
80
- TwoPass.create_symlink(vault_name, target_path)
84
+ target_path, env = args[0], args[1]
85
+ TwoPass.create_symlink(vault_name, target_path, env: env)
81
86
  when :help
82
87
  help_message
83
88
  else
data/lib/2pass/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module TwoPass
2
- VERSION = "1.2.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,30 +24,31 @@ 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, format: :text)
42
- vault = load_vault(vault_name)
43
- if format == :text
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
44
47
  vault
45
48
  .map { |h| "#{h[:id]}=#{h[:value]}" }
46
49
  .sort
47
50
  .join("\n")
48
- else
51
+ elsif format == :json
49
52
  JSON.pretty_generate(
50
53
  vault
51
54
  .map { |hash| hash.slice(:id, :value) }
@@ -54,23 +57,22 @@ module TwoPass
54
57
  end
55
58
  end
56
59
 
57
- def add_secret(vault_name, id, value)
60
+ def add_secret(vault_name, id, value, env: nil)
58
61
  new_secret = {
59
62
  id: id,
60
- value: value,
61
- uuid: SecureRandom.uuid
63
+ value: value
62
64
  }
63
- data = load_vault(vault_name)
65
+ data = load_vault(vault_name, env: env)
64
66
  existing_entry_id = data.find_index { |hash| hash[:id] == new_secret[:id] }
65
67
  if existing_entry_id
66
68
  raise "The secret already exists"
67
69
  end
68
70
  data << new_secret
69
- save_vault(vault_name, data)
71
+ save_vault(vault_name, data, env: env)
70
72
  end
71
73
 
72
- def get_secret(vault_name, id)
73
- vault = load_vault(vault_name)
74
+ def get_secret(vault_name, id, env: nil)
75
+ vault = load_vault(vault_name, env: env)
74
76
  entry = vault.find { |hash| hash[:id] == id }
75
77
  if entry
76
78
  entry[:value]
@@ -78,5 +80,24 @@ module TwoPass
78
80
  raise "Entry not found"
79
81
  end
80
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
81
102
  end
82
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.2.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: 2025-01-09 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