leeloo 0.4.1 → 0.5.3

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: 7117e8aaf24a2b7dec0e8d516f81aa6491b9d1e8360907d99e1f41848fdeae87
4
- data.tar.gz: e687c77e4e8a17f9bbe9ece480da789c80327f1d6bc8831da04ddd1a7b0d677a
3
+ metadata.gz: 970efe43f2eb851d19e0b84eae77acb8aad964e6cb52f12e99a4acab4403d32c
4
+ data.tar.gz: 784fbd32ee2a217ddf86e3321beb9ac73d0924438cb4074834f2306490b4de12
5
5
  SHA512:
6
- metadata.gz: 8690b0dd0e1e8788332c30ae6c54a144749aba2b04574ddaabfd3336b5fbf1a3b289943d3b8ec098ec07d139c73ff0095667c2cfc7588c9eeef60a5807d72754
7
- data.tar.gz: 5e5f54a09b03a45e9b574adbad70268d1aec1cdc4fbc7adf0228798a115130bbddd88ca560cf70c54fb6960dc0d719be86513b5d01acb6f36f8e5d0724abcf18
6
+ metadata.gz: 9cbe579613ee7f78367e4a513aed089709282c1d11fafc3a2288a56671cecf1436062f5bdae8c409a0fef5e98655c805b8cf0d881a02ce63003fe822a6a2b76f
7
+ data.tar.gz: 8b20416ae3a71911bb0deabd0c8ab11ae8bf80bd314ee2e73eb8ada3cdb4e4d67d0d5ac59f5e03d7ad697ca75a858731e304da07b307f51e8e742e5d79ed5e7f
@@ -23,11 +23,34 @@ module Leeloo
23
23
  program :help, 'GitHub', 'https://github.com/sylvek'
24
24
  program :help_formatter, :compact
25
25
 
26
- default_command :"list"
26
+ default_command :wrapper
27
+
28
+ command :wrapper do |c|
29
+ c.syntax = 'leeloo [options]'
30
+ c.description = "Display secrets"
31
+ c.option '--ascii', nil, 'display secrets without unicode tree'
32
+ c.option '--keystore STRING', String, 'a selected keystore'
33
+ c.option '--clipboard', nil, 'copy to clipboard'
34
+ c.action do |args, options|
35
+ unless args == []
36
+ name = args.first
37
+ ctl = SecretController.new(options)
38
+ ctl.read(name)
39
+ ctl.display
40
+ else
41
+ SecretsController.new(options).display
42
+ end
43
+ end
44
+ end
45
+
46
+ command :init do |c|
47
+ c.syntax = 'leeloo init'
48
+ c.description = "Just to be compatible with passwordstore.org"
49
+ end
27
50
 
28
51
  command :list do |c|
29
52
  c.syntax = 'leeloo list [options]'
30
- c.description = "Display secrets list of keystore"
53
+ c.description = "Display secrets list of stored on a keystore"
31
54
  c.option '--ascii', nil, 'display secrets without unicode tree'
32
55
  c.option '--keystore STRING', String, 'a selected keystore'
33
56
 
@@ -61,7 +84,7 @@ module Leeloo
61
84
  end
62
85
  end
63
86
 
64
- command "keystore remove" do |c|
87
+ command :"keystore remove" do |c|
65
88
  c.syntax = 'leeloo keystore remove <name>'
66
89
  c.description = "remove a keystore (path/to/keystore is not destroyed)"
67
90
 
@@ -74,7 +97,7 @@ module Leeloo
74
97
  end
75
98
  end
76
99
 
77
- command "keystore add" do |c|
100
+ command :"keystore add" do |c|
78
101
  c.syntax = 'leeloo keystore add <name> <path/to/keystore>'
79
102
  c.description = "add a keystore"
80
103
 
@@ -88,7 +111,7 @@ module Leeloo
88
111
  end
89
112
  end
90
113
 
91
- command "keystore default" do |c|
114
+ command :"keystore default" do |c|
92
115
  c.syntax = 'leeloo keystore default name'
93
116
  c.description = "set the default keystore"
94
117
 
@@ -101,12 +124,63 @@ module Leeloo
101
124
  end
102
125
  end
103
126
 
127
+ command :key do |c|
128
+ c.syntax = 'leeloo keys'
129
+ c.description = "list keys from this keystore"
130
+ c.option '--ascii', nil, 'display secrets without unicode tree'
131
+ c.option '--keystore STRING', String, 'a selected keystore'
132
+
133
+ c.action do |args, options|
134
+ ctl = KeysController.new(options)
135
+ ctl.display
136
+ end
137
+ end
138
+
139
+ command :"key sync" do |c|
140
+ c.syntax = 'leeloo keys sync'
141
+ c.description = "synchronize secrets with keys"
142
+ c.option '--keystore STRING', String, 'a selected keystore'
143
+
144
+ c.action do |args, options|
145
+ ctl = KeysController.new(options)
146
+ ctl.sync
147
+ ctl.display
148
+ end
149
+ end
150
+
151
+ command :"key add" do |c|
152
+ c.syntax = 'leeloo key add <email>'
153
+ c.description = "add a dedicated key"
154
+ c.option '--keystore STRING', String, 'a selected keystore'
155
+
156
+ c.action do |args, options|
157
+ abort "email is missing" unless args.length == 1
158
+ email = args.first
159
+ ctl = KeysController.new(options)
160
+ ctl.add_key(email)
161
+ ctl.display
162
+ end
163
+ end
164
+
165
+ command :"key remove" do |c|
166
+ c.syntax = 'leeloo key remove <email>'
167
+ c.description = "remove a dedicated key"
168
+ c.option '--keystore STRING', String, 'a selected keystore'
169
+
170
+ c.action do |args, options|
171
+ abort "email is missing" unless args.length == 1
172
+ email = args.first
173
+ ctl = KeysController.new(options)
174
+ ctl.remove_key(email)
175
+ ctl.display
176
+ end
177
+ end
178
+
104
179
  command :read do |c|
105
180
  c.syntax = 'leeloo read <name>'
106
181
  c.description = "Display a secret from a keystore"
107
182
  c.option '--keystore STRING', String, 'a selected keystore'
108
183
  c.option '--clipboard', nil, 'copy to clipboard'
109
- c.option '--keystore STRING', String, 'a selected keystore'
110
184
 
111
185
  c.action do |args, options|
112
186
  abort "name is missing" unless args.length == 1
@@ -133,6 +207,23 @@ module Leeloo
133
207
  ctl.display
134
208
  end
135
209
  end
210
+ alias_command :insert, :write
211
+
212
+ command :generate do |c|
213
+ c.syntax = 'leeloo generate <name> <number of randomized characters>'
214
+ c.description = "Generate a secret from a keystore"
215
+ c.option '--keystore STRING', String, 'a selected keystore'
216
+ c.option '--clipboard', nil, 'copy to clipboard'
217
+
218
+ c.action do |args, options|
219
+ abort "name or number are missing" unless args.length == 2
220
+ name = args.first
221
+ options.__hash__[:generate] = args.last.to_i
222
+ ctl = SecretController.new(options)
223
+ ctl.write(name)
224
+ ctl.display
225
+ end
226
+ end
136
227
 
137
228
  command :translate do |c|
138
229
  c.syntax = 'leeloo translate'
@@ -156,11 +247,13 @@ module Leeloo
156
247
  name = args.first
157
248
  ctl = SecretController.new(options)
158
249
  ctl.remove(name)
159
- ctl.display
250
+ #ctl.display
251
+ puts "done."
160
252
  end
161
253
  end
254
+ alias_command :rm, :remove
162
255
 
163
- command :sync do |c|
256
+ command :"keystore sync" do |c|
164
257
  c.syntax = 'leeloo sync'
165
258
  c.description = "Synchronize a keystore"
166
259
  c.option '--keystore STRING', String, 'a selected keystore'
@@ -172,7 +265,18 @@ module Leeloo
172
265
  end
173
266
  end
174
267
 
175
- command :init do |c|
268
+ command :"keystore export" do |c|
269
+ c.syntax = 'leeloo export'
270
+ c.description = "Export all secrets from a keystore"
271
+ c.option '--keystore STRING', String, 'a selected keystore'
272
+
273
+ c.action do |args, options|
274
+ ctl = ExportController.new(options)
275
+ ctl.display
276
+ end
277
+ end
278
+
279
+ command :"keystore init" do |c|
176
280
  c.syntax = 'leeloo init'
177
281
  c.description = "Initialize a keystore"
178
282
  c.option '--keystore STRING', String, 'a selected keystore'
@@ -32,16 +32,46 @@ module Leeloo
32
32
  class SecretsController < PrivateLocalFileSystemController
33
33
  def initialize options
34
34
  super options
35
- @secrets = @preferences.keystore(@options.keystore).secrets
35
+ @secrets = @keystore.secrets
36
36
  end
37
37
  def search name
38
38
  @secrets = @secrets.select { |secret| secret.name.downcase.include? name.downcase } || []
39
39
  end
40
+ def list
41
+ @secrets
42
+ end
40
43
  def display
41
44
  @output.render_secrets @secrets
42
45
  end
43
46
  end
44
47
 
48
+ class ExportController < PrivateLocalFileSystemController
49
+ def display
50
+ @keystore.secrets.each do |secret|
51
+ @output.render_name_and_secret(secret.name, @keystore.secret_from_name(secret.name))
52
+ end
53
+ end
54
+ end
55
+
56
+ class KeysController < PrivateLocalFileSystemController
57
+ def add_key email
58
+ @keystore.add_key(email)
59
+ end
60
+ def remove_key email
61
+ @keystore.remove_key(email)
62
+ end
63
+ def sync
64
+ @keystore.secrets.each do |secret|
65
+ phrase = @keystore.secret_from_name(secret.name).read
66
+ @keystore.secret_from_name(secret.name).write(phrase)
67
+ end
68
+ end
69
+ def display
70
+ @keys = @keystore.keys
71
+ @output.render_keys @keys
72
+ end
73
+ end
74
+
45
75
  class SecretController < PrivateLocalFileSystemController
46
76
  def read name
47
77
  @secret = @keystore.secret_from_name(name)
@@ -53,8 +83,8 @@ module Leeloo
53
83
  phrase = SecureRandom.base64(32).truncate(@options.generate.to_i) if @options.generate
54
84
 
55
85
  unless phrase
56
- phrase = password "secret"
57
- confirm = password "confirm it"
86
+ phrase = password "Enter password for #{name}"
87
+ confirm = password "Confirm it"
58
88
  abort "not the same secret" unless phrase == confirm
59
89
  end
60
90
 
@@ -72,6 +72,7 @@ module Leeloo
72
72
  def initialize name, path
73
73
  super name
74
74
  @path = path
75
+ File.write("#{@path}/.gpg-id", 'empty')
75
76
  FileUtils.mkdir_p "#{@path}/secrets"
76
77
  end
77
78
 
@@ -79,6 +80,10 @@ module Leeloo
79
80
  find_secrets "#{@path}/secrets"
80
81
  end
81
82
 
83
+ def keys
84
+ []
85
+ end
86
+
82
87
  def find_secrets path
83
88
  elements = []
84
89
  Dir.glob("#{path}/**") do |element|
@@ -121,7 +126,10 @@ module Leeloo
121
126
  def initialize name, path
122
127
  super name, path
123
128
  FileUtils.mkdir_p "#{@path}/keys"
129
+ populate_recipients
130
+ end
124
131
 
132
+ def populate_recipients
125
133
  @recipients = []
126
134
  Dir.glob("#{path}/keys/*") { |key| @recipients << File.basename(key) }
127
135
  @recipients.each { |key| GPGME::Key.import(File.open("#{path}/keys/#{key}")) }
@@ -129,7 +137,30 @@ module Leeloo
129
137
 
130
138
  def init
131
139
  super
132
- GPGME::Key.find(:public, nil, ).each { |key| key.export(:output => File.open("#{path}/keys/#{key.uids.first.email}", "w+")) }
140
+ File.write("#{@path}/keys/do_not_remove_me", "do not remove me")
141
+ end
142
+
143
+ def keys
144
+ available = GPGME::Key.find(:public, nil, ).map { |key| key.email }
145
+ actual = Dir.glob("#{@path}/keys/**").map { |path| path.split('/').last }
146
+ available.map { |email| actual.include?(email) ? "#{email}::true" : "#{email}::false" }
147
+ end
148
+
149
+ def add_key email
150
+ paths = []
151
+ GPGME::Key.find(:public, email).each do |key|
152
+ key.export(:output => File.open("#{path}/keys/#{key.uids.first.email}", "w+"))
153
+ paths << "#{path}/keys/#{key.uids.first.email}"
154
+ end
155
+ return paths
156
+ end
157
+
158
+ def remove_key email
159
+ if File.exist?("#{path}/keys/#{email}")
160
+ File.delete("#{path}/keys/#{email}")
161
+ return "#{path}/keys/#{email}"
162
+ end
163
+ return nil
133
164
  end
134
165
 
135
166
  def secret_of path
@@ -172,6 +203,25 @@ module Leeloo
172
203
  secret_of @keystore.secret_from_name(element)
173
204
  end
174
205
 
206
+ def keys
207
+ @keystore.keys
208
+ end
209
+
210
+ def add_key email
211
+ @keystore.add_key(email).each do |path|
212
+ @git.add path
213
+ @git.commit "#{email} added"
214
+ end
215
+ end
216
+
217
+ def remove_key email
218
+ deleted = @keystore.remove_key email
219
+ if deleted
220
+ @git.add deleted
221
+ @git.commit "#{email} removed"
222
+ end
223
+ end
224
+
175
225
  def secrets
176
226
  @keystore.secrets
177
227
  end
data/lib/leeloo/output.rb CHANGED
@@ -21,6 +21,12 @@ module Leeloo
21
21
  def render_text text
22
22
  end
23
23
 
24
+ def render_name_and_secret name, secret
25
+ end
26
+
27
+ def render_keys keys
28
+ end
29
+
24
30
  def render_footprint footprint
25
31
  end
26
32
 
@@ -46,10 +52,20 @@ module Leeloo
46
52
  end
47
53
  end
48
54
 
55
+ def render_name_and_secret name, secret
56
+ self.render_text name
57
+ self.render_secret secret
58
+ self.render_text '------'
59
+ end
60
+
49
61
  def render_text text
50
62
  puts text
51
63
  end
52
64
 
65
+ def render_keys keys
66
+ self.render_text keys
67
+ end
68
+
53
69
  def render_footprint footprint
54
70
  puts "token:"
55
71
  puts Base64.strict_encode64 footprint.to_json
@@ -69,11 +85,21 @@ module Leeloo
69
85
  end
70
86
 
71
87
  def render_secrets secrets
72
- hash = {:secrets => []}
73
- secrets.sort_by(&:name).each { |secret| sort(hash[:secrets], secret.name) }
88
+ hash = {'Password Store' => []}
89
+ secrets.sort_by(&:name).each { |secret| sort(hash['Password Store'], secret.name) }
74
90
  puts TTY::Tree.new(hash).render
75
91
  end
76
92
 
93
+ def render_keys keys
94
+ rows = []
95
+ keys.each do |key|
96
+ splitted = key.split('::')
97
+ is_present = '*' if splitted[1] == 'true'
98
+ rows << [splitted[0], is_present]
99
+ end
100
+ puts TTY::Table.new(header: ['Email', 'Selected'], rows: rows).render(:ascii)
101
+ end
102
+
77
103
  def sort array, element
78
104
  if element
79
105
  e = element.split("/", 2)
@@ -1,4 +1,4 @@
1
1
  module Leeloo
2
- VERSION = '0.4.1'.freeze
2
+ VERSION = '0.5.3'.freeze
3
3
  DESCRIPTION = "The easiest way to share securely your secrets".freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leeloo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - sylvek
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-02 00:00:00.000000000 Z
11
+ date: 2022-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander
@@ -201,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
201
  - !ruby/object:Gem::Version
202
202
  version: '0'
203
203
  requirements: []
204
- rubygems_version: 3.1.4
204
+ rubygems_version: 3.3.3
205
205
  signing_key:
206
206
  specification_version: 4
207
207
  summary: The easiest way to share securely your secrets