one_pass 0.1.0 → 0.3.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
  SHA1:
3
- metadata.gz: 7774961c176b2d6ebc5729b68030132c93d9d9df
4
- data.tar.gz: 1e670ffa2e34cd27a9db1b1b947eac101a67763a
3
+ metadata.gz: 0cc1151fd6e205e25446f3ccc96ea2ade11ae65f
4
+ data.tar.gz: 38a4224636c6cdd21c05bb4e468b95326ebbe271
5
5
  SHA512:
6
- metadata.gz: 1026704202367e43c49d6da76355dc65c48b5559b17097ab39482b60d7c99fe7bdc2556878a32021f81831cb946e91d6c7f211d38ca45629bc3e6ea0b4e10c37
7
- data.tar.gz: 9c5d4b84d154cb5013b1839b946665c1dd445be8b379ad294922c4879b038acb5cff4845a12300922506c596b75ca10bdb6c111091644b2aeec0696f098c012f
6
+ metadata.gz: 4b8ecca56031bbfc20f1f59be2386f52ba18cf57cf9067738498b7fccf1f0fda6c68071719f2d4c9b3b4efada10f137bd08f04aead0948ba91400d3fb1522c27
7
+ data.tar.gz: c24eed919126dae1d4dd16f763d29690f2a4cd2dd5d2e1e87b1a10ac6202709f9e5a2be3c1bc3a4bee8b8fb5922c31cdbe562adc66a20e1e158de632f5c40cc7
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ *.gem
data/Gemfile.lock CHANGED
@@ -1,19 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- one_pass (0.1.0)
5
- dispel (~> 0.0)
4
+ one_pass (0.3.0)
6
5
  thor (~> 0.19)
6
+ ttyname (~> 1.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
11
  bump (0.5.3)
12
12
  coderay (1.1.1)
13
- curses (1.0.2)
14
13
  diff-lcs (1.2.5)
15
- dispel (0.0.7)
16
- curses
17
14
  method_source (0.8.2)
18
15
  pry (0.10.3)
19
16
  coderay (~> 1.1.0)
@@ -35,6 +32,7 @@ GEM
35
32
  rspec-support (3.4.1)
36
33
  slop (3.6.0)
37
34
  thor (0.19.1)
35
+ ttyname (1.0.0)
38
36
 
39
37
  PLATFORMS
40
38
  ruby
data/README.markdown CHANGED
@@ -26,3 +26,8 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/sethvo
26
26
  ## License
27
27
 
28
28
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
29
+
30
+ ## Todo
31
+
32
+ * [ ] Check for prerequisite external applications before calling them (pinentry, pbcopy)
33
+ * [ ] Detect OS to use appropriate clipboard utility
data/exe/one-pass CHANGED
@@ -5,3 +5,5 @@ require 'OnePass'
5
5
  require 'OnePass/cli'
6
6
 
7
7
  app = OnePass::CLI.start ARGV
8
+
9
+ trap("SIGINT") { exit }
@@ -1,5 +1,3 @@
1
- require 'dispel'
2
-
3
1
  module OnePass
4
2
  # OnePass Application
5
3
  class Application
@@ -9,85 +7,22 @@ module OnePass
9
7
  @vault_path = get_vault vault_path
10
8
  @vault = OpVault.new @vault_path
11
9
 
12
- @vault.unlock password_entry
13
- @vault.load_items
14
- end
15
-
16
- def password_entry
17
- accumulator = []
18
- Dispel::Screen.open do |screen|
19
- map = Dispel::StyleMap.new(screen.lines)
20
- config = {
21
- map: map,
22
- width: screen.columns,
23
- height: screen.lines,
24
- mode: :password
25
- }
26
- screen.draw *draw_password_box(accumulator.length, config)
27
-
28
- Dispel::Keyboard.output do |key|
29
- case key
30
- when :enter
31
- case config[:mode]
32
- when :cancel
33
- raise 'Cancel'
34
- else
35
- break
36
- end
37
- when :backspace
38
- accumulator.pop
39
- when :down
40
- config[:mode] = config[:mode] == :password ? :ok : config[:mode]
41
- when :up
42
- config[:mode] = :password
43
- when :left
44
- config[:mode] = config[:mode] == :password ? config[:mode] : :ok
45
- when :right
46
- config[:mode] = config[:mode] == :password ? config[:mode] : :cancel
47
- else
48
- accumulator.push key if config[:mode] == :password
49
- end
50
- screen.draw *draw_password_box(accumulator.length, config)
10
+ error_message = nil
11
+ prompter = OnePass::Password.new(vault_path: @vault_path)
12
+ loop do
13
+ password = prompter.prompt error_message
14
+ exit if password.nil? # cancelled
15
+ begin
16
+ @vault.unlock password
17
+ @vault.load_items
18
+ break
19
+ rescue => error
20
+ error_message = error.message
21
+ next
51
22
  end
52
23
  end
53
- accumulator.join
54
- end
55
-
56
- def draw_password_box(pw_length, config)
57
- message = 'Please enter your 1Password master password for the following vault:'
58
- min_width = [message, @vault_path].max_by(&:length).length
59
- prefix = 'Master Password: '
60
-
61
- offset_left = (config[:width] - (min_width + 4)) / 2
62
- offset_top = (config[:height] - 8) / 2
63
- left = ' ' * offset_left
64
- third = min_width / 3
65
-
66
- password_string = ("*" * pw_length).ljust(min_width - prefix.length, '_')
67
- buttons = '<OK>'.center(third) + ' ' * (min_width - (third * 2)) + '<Cancel>'.center(third)
68
-
69
- box = ("\n" * offset_top)
70
- box += "#{left}┏#{'━' * (min_width + 2)}┓\n"
71
- box += "#{left}┃ #{message.ljust(min_width)} ┃\n"
72
- box += "#{left}┃ #{@vault_path.ljust(min_width)} ┃\n"
73
- box += "#{left}┃ #{' ' * min_width} ┃\n"
74
- box += "#{left}┃ #{prefix}#{password_string} ┃\n"
75
- box += "#{left}┃#{' ' * (min_width + 2)}┃\n"
76
- box += "#{left}┃ #{buttons} ┃\n"
77
- box += "#{left}┗#{'━' * (min_width + 2)}┛\n"
78
-
79
- cursor_top = offset_top + (config[:mode] == :password ? 4 : 6)
80
- cursor_left = offset_left
81
- case config[:mode]
82
- when :ok
83
- cursor_left += third / 2
84
- when :cancel
85
- cursor_left += min_width - third + third / 2 - 2
86
- else
87
- cursor_left += prefix.length + pw_length + 2
88
- end
89
-
90
- [box, config[:map], [cursor_top, cursor_left]]
24
+ ensure
25
+ prompter.done
91
26
  end
92
27
 
93
28
  def get_vault(vault_path = nil)
data/lib/OnePass/cli.rb CHANGED
@@ -2,14 +2,21 @@ require 'io/console'
2
2
  require 'thor'
3
3
 
4
4
  require 'OnePass/application'
5
+ require 'OnePass/password'
5
6
 
6
7
  module OnePass
7
8
  # OnePass CLI
8
9
  class CLI < Thor
9
10
  SHOW_OPTIONS = %w( all username password url uuid title )
10
11
 
12
+ map %w[--version -v] => :__version
13
+ desc "--version, -v", "Print the current version"
14
+ def __version
15
+ puts "#{File.basename $0} version #{OnePass::VERSION}"
16
+ end
17
+
11
18
  desc 'login', 'Save a 1Password vault and verify password'
12
- option :vault, aliases: '-v', type: :string, banner: 'Specify a vault path'
19
+ option :vault, aliases: '-v', type: :string, banner: 'Specify a vault path', required: true
13
20
  def login
14
21
  OnePass::Application.save options.vault
15
22
  end
@@ -39,7 +46,12 @@ module OnePass
39
46
  app = OnePass::Application.new
40
47
  reply_type = type.keys.first.to_sym
41
48
  reply = app.show name, reply_type
42
- puts reply_type == :all ? JSON.pretty_generate(reply) : reply
49
+ if options.clip
50
+ IO.popen('pbcopy', 'w') { |f| f << (reply_type == :all ? JSON.generate(reply) : reply) }
51
+ else
52
+ print reply_type == :all ? JSON.pretty_generate(reply) : reply
53
+ puts if $stdout.isatty
54
+ end
43
55
  end
44
56
 
45
57
  desc 'search QUERY', 'Perform fuzzy search for items in your vault, shows uuid, title and username'
@@ -64,6 +64,10 @@ module OnePass
64
64
  raise 'Incorrect password'
65
65
  end
66
66
 
67
+ def unlocked?
68
+ !!@master_key && !!@overview_key
69
+ end
70
+
67
71
  def lock
68
72
  @master_key = @master_mac_key = nil
69
73
  end
@@ -0,0 +1,80 @@
1
+ require 'ttyname'
2
+
3
+ module OnePass
4
+ # Fork out to `pinentry` for password
5
+ class Password
6
+ DESCRIPTION = 'Please enter your 1Password master password for the following vault:'
7
+ DEFAULT = {
8
+ title: '1Password CLI',
9
+ prompt: 'Master Password: '
10
+ }
11
+
12
+ def initialize(opts = {})
13
+ @config = OpenStruct.new DEFAULT.merge(opts)
14
+ @config.description ||= "#{DESCRIPTION}%0a#{@config.vault_path}" if @config.vault_path
15
+ end
16
+
17
+ def prompt(error_message = nil)
18
+ @config.error = error_message
19
+ @pipe = IO.popen 'pinentry', 'r+'
20
+ check
21
+ send_settings
22
+ get_password
23
+ @password
24
+ end
25
+
26
+ def done
27
+ send 'BYE'
28
+ @pipe.close
29
+ end
30
+
31
+ private
32
+
33
+ def send_settings
34
+ command 'SETTITLE', @config.title
35
+ command 'SETPROMPT', @config.prompt
36
+ command 'SETERROR', @config.error if @config.error
37
+ command 'SETDESC', @config.description
38
+
39
+ option 'ttytype', ENV['TERM']
40
+ option 'ttyname', $stdin.ttyname
41
+ option 'display', ENV['DISPLAY']
42
+ end
43
+
44
+ def get_password
45
+ @password = ''
46
+ send 'GETPIN'
47
+ while true
48
+ case response = @pipe.gets
49
+ when /^D .*/
50
+ @password = response[2..-1].chomp
51
+ when /^OK/
52
+ break
53
+ else
54
+ @password = nil
55
+ break
56
+ end
57
+ end
58
+ rescue Interrupt
59
+ @password = nil
60
+ end
61
+
62
+ def command(command, option = nil)
63
+ send command, option
64
+ check
65
+ end
66
+
67
+ def option(name, value)
68
+ command 'OPTION', "#{name}=#{value}"
69
+ end
70
+
71
+ def send(command, option = nil)
72
+ @pipe.puts "#{command}#{option ? ' ' + option : ''}"
73
+ end
74
+
75
+ def check
76
+ response = @pipe.gets
77
+ raise 'bad response' unless response.start_with? 'OK'
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module OnePass
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/one_pass.gemspec CHANGED
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_runtime_dependency "dispel", "~> 0.0"
31
30
  spec.add_runtime_dependency "thor", "~> 0.19"
31
+ spec.add_runtime_dependency "ttyname", "~> 1.0"
32
32
 
33
33
  spec.add_development_dependency "bundler", "~> 1.11"
34
34
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: one_pass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seth Voltz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-29 00:00:00.000000000 Z
11
+ date: 2016-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: dispel
14
+ name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.0'
19
+ version: '0.19'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.0'
26
+ version: '0.19'
27
27
  - !ruby/object:Gem::Dependency
28
- name: thor
28
+ name: ttyname
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.19'
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.19'
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +120,7 @@ files:
120
120
  - lib/OnePass/application.rb
121
121
  - lib/OnePass/cli.rb
122
122
  - lib/OnePass/op_vault.rb
123
+ - lib/OnePass/password.rb
123
124
  - lib/OnePass/version.rb
124
125
  - one_pass.gemspec
125
126
  homepage: https://sethvoltz.github.com/one_pass