pwrb 0.0.1

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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jianwei Han
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # Pwrb
2
+
3
+ Pwrb is a password management gem based on GPG.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'pwrb'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install pwrb
18
+
19
+ ## Usage
20
+
21
+ ``` sh
22
+ pwrb -h
23
+ ```
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
5
+ require 'pwrb'
6
+ require 'optparse'
7
+
8
+ begin
9
+ options = {}
10
+
11
+ optparse = OptionParser.new do |opts|
12
+ opts.banner = "Usage: pw add|update|edit|list|copy|remove [user@domain] [options]"
13
+ opts.separator ""
14
+ opts.separator "Specific options:"
15
+
16
+ opts.on('-h', '--help', 'Display help message') do
17
+ puts opts
18
+ exit
19
+ end
20
+
21
+ opts.on('-p', '--print', 'Print password in text') do
22
+ options[:print] = true
23
+ end
24
+ end
25
+
26
+ optparse.parse!
27
+
28
+ aliases = {'cp' => 'copy',
29
+ 'ls' => 'list',
30
+ 'up' => 'update',
31
+ 'create' => 'add',
32
+ 'rm' => 'remove',
33
+ 'delete' => 'remove',
34
+ 'del' => 'remove'}
35
+
36
+ cmd = ARGV.shift
37
+ cmd = aliases[cmd] if aliases[cmd]
38
+
39
+ unless ['list', 'copy', 'update', 'remove', 'add', 'edit'].include?(cmd)
40
+ puts "Command not found: #{cmd}" if cmd
41
+ puts optparse
42
+ exit 1
43
+ end
44
+
45
+ pattern = ARGV.shift
46
+ abort("Unknown arguments: #{ARGV}") unless ARGV.empty?
47
+
48
+ if pattern
49
+ args = pattern.split('@', -1)
50
+
51
+ abort("Unknow pattern: #{pattern}") if args.length > 2
52
+
53
+ options[:site] = args.last
54
+ options[:user] = args.first if args.length == 2
55
+ end
56
+
57
+ Pwrb::PasswordDB.new(options).send cmd
58
+ end
@@ -0,0 +1,202 @@
1
+ require "pwrb/version"
2
+
3
+ require 'clipboard'
4
+ require 'gpgme'
5
+ require 'json'
6
+ require 'highline/import'
7
+ require 'tabularize'
8
+ require 'securerandom'
9
+
10
+ module Pwrb
11
+ class PasswordDB
12
+ def initialize(options=nil)
13
+ @filename = File.expand_path('~/.pw')
14
+ @filename = File.readlink(@filename) if File.symlink?(@filename)
15
+ @options = options
16
+ @crypto = GPGME::Crypto.new
17
+
18
+ read_safe
19
+ @selected = @data.select{ |item| match(item, @options) }
20
+ end
21
+
22
+ def read_safe(password=nil)
23
+ if File.file?(@filename)
24
+ @password = password || ask_for_password("Enter master passphrase")
25
+ plain_data = @crypto.decrypt(File.open(@filename), :password => @password).to_s
26
+ @data = JSON.parse(plain_data, :symbolize_names => true)
27
+ else
28
+ create_safe(password)
29
+ end
30
+ end
31
+
32
+ def write_safe
33
+ plain_data = JSON.generate(@data)
34
+ plain_data.force_encoding('ASCII-8BIT')
35
+ @crypto.encrypt(plain_data, :output => File.open(@filename, 'w+'))
36
+ end
37
+
38
+ def create_safe(password=nil)
39
+ puts "No password file detected, creating one at #{@filename}"
40
+ @password = ask_for_password("Enter master passphrase", confirm = true) unless @password == password
41
+
42
+ FileUtils.mkdir_p(File.dirname(@filename))
43
+ @data = []
44
+ write_safe
45
+ File.chmod(0600, @filename)
46
+ end
47
+
48
+ def to_s
49
+ "<*******>"
50
+ end
51
+
52
+ def user_match(item, user)
53
+ /#{user}/i =~ item[:user]
54
+ end
55
+
56
+ def site_match(item, site)
57
+ /#{site}/i =~ item[:site] || /#{site}/i =~ item[:url]
58
+ end
59
+
60
+ def match(item, options)
61
+ user_match(item, options[:user]) && site_match(item, options[:site])
62
+ end
63
+
64
+ def ask_for_password(prompt, confirm=false)
65
+ password = ask(prompt + ": ") { |q| q.echo = false; q.validate = /\A.+\Z/ }
66
+ if confirm
67
+ password_confirm = ask_for_password(prompt + " again")
68
+
69
+ if password == password_confirm
70
+ password
71
+ else
72
+ puts "Password mismatch, try again!"
73
+ ask_for_password(prompt, true)
74
+ end
75
+ else
76
+ password
77
+ end
78
+ end
79
+
80
+ def ask_for_selection
81
+ case
82
+ when @selected.empty?
83
+ puts "Record not exists!"
84
+ nil
85
+ when @selected.length == 1
86
+ @selected.first
87
+ else
88
+ list
89
+ choose = ask('Which one? ', Integer) { |q| q.in = 0..@selected.length-1 }
90
+ @selected[choose]
91
+ end
92
+ end
93
+
94
+ def ask_for_item(init={})
95
+ item = init
96
+
97
+ item[:user] = ask("User name? ") { |q| q.default = init[:user] || @options[:user]; q.validate = /\A\S+\Z/ }
98
+ item[:email] = ask("Email? ") { |q| q.default = init[:email] }
99
+ item[:site] = ask("Site? ") { |q| q.default = init[:site] || @options[:site]; q.validate = /\A.+\Z/ }
100
+ item[:url] = ask("URL? ") { |q| q.default = init[:url] || @options[:site] }
101
+
102
+ item
103
+ end
104
+
105
+ def ask_for_confirm
106
+ confirm = ask("Are you sure? ") { |q| q.validate = /\A(y|yes|n|no)\Z/i }
107
+ ['y', 'yes'].include?(confirm)
108
+ end
109
+
110
+ def timestamp
111
+ Date.today.strftime("%Y%m%d")
112
+ end
113
+
114
+ def list
115
+ return if @selected.empty?
116
+
117
+ table = Tabularize.new
118
+ table << %w[# ID User Password Site Date]
119
+ table.separator!
120
+
121
+ @selected.each_with_index do |item, index|
122
+ user = item[:user]
123
+ user += "<%s>" % item[:email] unless item[:email].empty?
124
+ site = "%s[%s]" % [item[:site], item[:url]]
125
+ password = (@options[:print] ? item[:password] : "***")
126
+
127
+ table << [index.to_s, item[:id].split('-').first, user, password, site, item[:date]]
128
+ end
129
+
130
+ puts table
131
+ end
132
+
133
+ def copy
134
+ target = ask_for_selection
135
+ seconds = 10
136
+
137
+ if target
138
+ original_clipboard_content = Clipboard.paste
139
+ sleep 0.1
140
+ Clipboard.copy target[:password]
141
+ puts "Password for #{target[:site]} is in clipboard for #{seconds} seconds"
142
+ begin
143
+ sleep seconds
144
+ rescue Interrupt
145
+ Clipboard.copy original_clipboard_content
146
+ raise
147
+ end
148
+ Clipboard.copy original_clipboard_content
149
+ end
150
+ end
151
+
152
+ def update
153
+ target = ask_for_selection
154
+
155
+ if target
156
+ target[:password] = ask_for_password("Enter new password", confirm = true)
157
+ target[:date] = timestamp
158
+ write_safe
159
+ puts "Update complete!"
160
+ end
161
+ end
162
+
163
+
164
+ def add
165
+ item = ask_for_item
166
+
167
+ item[:id] = SecureRandom.uuid
168
+ item[:password] = ask_for_password("Enter password", confirm = true)
169
+ item[:date] = timestamp
170
+
171
+ if ask_for_confirm
172
+ @data << item
173
+ write_safe
174
+ puts "Added #{item[:user]}@#{item[:site]}!"
175
+ end
176
+ end
177
+
178
+ def edit
179
+ target = ask_for_selection
180
+
181
+ if target
182
+ ask_for_item(target)
183
+ if ask_for_confirm
184
+ target[:date] = timestamp
185
+ write_safe
186
+ puts "Update #{target[:user]}@#{target[:site]}!"
187
+ end
188
+ end
189
+ end
190
+
191
+ def remove
192
+ target = ask_for_selection
193
+
194
+ if target && ask_for_confirm
195
+ @data.delete(target)
196
+ write_safe
197
+ puts "#{target[:user]}@#{target[:site]} Removed!"
198
+ end
199
+ end
200
+
201
+ end
202
+ end
@@ -0,0 +1,3 @@
1
+ module Pwrb
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pwrb/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "pwrb"
8
+ gem.version = Pwrb::VERSION
9
+ gem.authors = ["Jianwei Han"]
10
+ gem.email = ["hanjianwei@gmail.com"]
11
+ gem.description = %q{pwrb is a cli password management software.}
12
+ gem.summary = %q{pwrb is a command line password management software based on GPG. Please run `pwrb -h` for more information. }
13
+ gem.homepage = "https://github.com/hanjianwei/pwrb"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency('gpgme', "~> 2.0.1")
21
+ gem.add_runtime_dependency('tabularize', "~> 0.2.9")
22
+ gem.add_runtime_dependency('clipboard', "~> 1.0.1")
23
+ gem.add_runtime_dependency('highline', "~> 1.6.15")
24
+
25
+ gem.add_development_dependency "bundler", ">= 1.2.3"
26
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pwrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jianwei Han
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: gpgme
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: tabularize
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.2.9
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.2.9
46
+ - !ruby/object:Gem::Dependency
47
+ name: clipboard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.1
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: highline
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.6.15
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.6.15
78
+ - !ruby/object:Gem::Dependency
79
+ name: bundler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.2.3
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.2.3
94
+ description: pwrb is a cli password management software.
95
+ email:
96
+ - hanjianwei@gmail.com
97
+ executables:
98
+ - pwrb
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - Gemfile
104
+ - LICENSE.txt
105
+ - README.md
106
+ - Rakefile
107
+ - bin/pwrb
108
+ - lib/pwrb.rb
109
+ - lib/pwrb/version.rb
110
+ - pwrb.gemspec
111
+ homepage: https://github.com/hanjianwei/pwrb
112
+ licenses: []
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 1.8.24
132
+ signing_key:
133
+ specification_version: 3
134
+ summary: pwrb is a command line password management software based on GPG. Please
135
+ run `pwrb -h` for more information.
136
+ test_files: []