one_pass 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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