pwss 0.0.3 → 0.1.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 +4 -4
- data/README.textile +50 -30
- data/bin/pwss +65 -23
- data/lib/pwss.rb +43 -36
- data/lib/pwss/cipher.rb +37 -3
- data/lib/pwss/entry.rb +5 -3
- data/lib/pwss/fileops.rb +2 -0
- data/lib/pwss/version.rb +1 -1
- data/pwss.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d81cc493cb6f1b3dc7f917cdfa7fcbb81c844af4
|
4
|
+
data.tar.gz: 44c566b64b9fc0cf9b72f00a0396a9a72a400180
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33cbef0aa13c6f8cf89313fddb500a289917e4c0c1e380b77b9494b85eee0c446601091573d01525e11ac2c704ced7312283e7adb2e4b2c0c99873a27f315bcc
|
7
|
+
data.tar.gz: aab0df3a4bff00ec6157e442d878706312209f4085ffa96cab604e7208d6bed0f3269f2e01724a03211df77b9cda74d1026349674643e8bb4649968380623370
|
data/README.textile
CHANGED
@@ -4,68 +4,82 @@ A password manager in the spirit of "pws":https://github.com/janlelis/pws.
|
|
4
4
|
|
5
5
|
Features:
|
6
6
|
|
7
|
-
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
|
12
|
-
*
|
7
|
+
* Each entry stores: title, username, password, url, description
|
8
|
+
* A file (or safe) can store many entries
|
9
|
+
* The user can manage different files (safes)
|
10
|
+
* CRUD (create, read, update, delete) commands are available to
|
11
|
+
operate on entries and safes
|
12
|
+
* pwss can generate completely random passwords for you
|
13
|
+
* Safes can be encrypted (to improve security)
|
14
|
+
* Encrypted safes can be decrypted (for instance to batch process
|
15
|
+
entries, to migrate to another tool, or to manually edit entries)
|
16
|
+
* Entries are human readable and editable (when not encrypted)
|
13
17
|
|
14
18
|
h2. Installation
|
15
19
|
|
16
20
|
Add this line to your application's Gemfile:
|
17
21
|
|
18
|
-
|
22
|
+
bc. gem 'pwss'
|
19
23
|
|
20
24
|
And then execute:
|
21
25
|
|
22
|
-
|
26
|
+
bc. $ bundle
|
23
27
|
|
24
28
|
Or install it yourself as:
|
25
29
|
|
26
|
-
|
30
|
+
bc. $ gem install pwss
|
27
31
|
|
28
32
|
h2. Usage
|
29
33
|
|
30
|
-
*Getting started.* @pwss@ stores passwords in YAML
|
34
|
+
*Getting started.* @pwss@ stores passwords in a YAML file (also called "password safe" in the following), possibly encrypted.
|
31
35
|
|
32
36
|
A typical usage scenario is the following:
|
33
37
|
|
34
38
|
# @pwss init@ will create a new encrypted password safe in @~/.pwss.yaml.enc@
|
35
39
|
# @pwss add@ will add a new entry to the file
|
36
|
-
# @pwss get entry@ will retrieve all entries whose *title* contains @entry@
|
40
|
+
# @pwss get entry@ will retrieve all entries whose *title* contains @entry@ and make the password of the chosen entry available in the clipboard
|
37
41
|
|
38
|
-
*Using multiple safes.* If you want to create
|
42
|
+
*Using multiple safes.* If you want to create multiple password safes or store the password safe in a non-standard location, use the @-f@ (@--filename@) option:
|
39
43
|
|
40
44
|
# @pwss -f MYFILE init@
|
41
45
|
# @pwss -f MYFILE add@
|
42
46
|
# @pwss -f MYFILE get@
|
43
47
|
|
44
|
-
*
|
48
|
+
*Controlling how long passwords are made available* Use the @-w@ option to determine how long the password is made available in the clipboard. For instance:
|
49
|
+
|
50
|
+
bc. $ pwss get my_email -w 3
|
51
|
+
|
52
|
+
will retrieve entry whose title is @my_email@ and make the password available in the clipboard for @2@ seconds.
|
53
|
+
|
54
|
+
Use @0@ to keep the password in the clipboard till a key is pressed.
|
55
|
+
|
56
|
+
*Automatically Generated Password* pwss can automatically generate passwords for entries which are added or updated, using the @-g LENGTH@ option, where @LENGTH@ is the length of the password to generate. If you want to generate password including only alphabetic and numeric characters, use the @-a@ option. *The passwords are made available in the clipboard, so that it can be used as needed*.
|
45
57
|
|
46
58
|
For instance:
|
47
59
|
|
48
|
-
|
49
|
-
|
50
|
-
|
60
|
+
bc. $ pwss update my_email -g 10 -a -w 20
|
61
|
+
|
62
|
+
will update the @my_email@ entry, by replacing the existing password with one of length @10@ automatically generated by @pwss@; the password contains only alphabetic characters and digits. The new password will be made available in the clipboard for @20@ seconds.
|
63
|
+
|
64
|
+
*Encrypted and Plain Files.* @pwss@ works equally well with encrypted and plain files. More in details, the file extension determines whether @pwss@ tries to decrypt/encrypt the file or not. The @.enc@ extension tells @pwss@ that the file is encrypted; any other extension will tell @pwss@ to treat the file as plain text.
|
65
|
+
|
66
|
+
For instance:
|
67
|
+
|
68
|
+
bc. $ pwss -f a.yaml.enc init
|
51
69
|
|
52
|
-
will store the password in
|
70
|
+
will store the password in the *encrypted* file @a.yaml.enc@.
|
53
71
|
|
54
72
|
By contrast,
|
55
73
|
|
56
|
-
|
57
|
-
$ pwss -f a.yaml get entry
|
58
|
-
</pre>
|
74
|
+
bc. $ pwss -f a.yaml get entry
|
59
75
|
|
60
|
-
will try to retrieve @entry@ from file @a.yaml
|
76
|
+
will try to retrieve @entry@ from file @a.yaml@; the file is assumed to be in plain text by @pwss@ which will not ask for a master password, nor will try to decrypt it.
|
61
77
|
|
62
|
-
Encrypting important passwords is a good idea. However, if you use @pwss@ to store non-critical infomation, prefer to edit the password safe with a text editor, or use another application for managing encryption and decryption, using @pwss@ with the file in plain format might be more convenient.
|
78
|
+
Encrypting important passwords is a good idea. (Just in case you were looking for a witty statement.) However, if you use @pwss@ to store non-critical infomation, prefer to edit the password safe with a text editor, or use another application for managing encryption and decryption, using @pwss@ with the file in plain format might be more convenient.
|
63
79
|
|
64
80
|
*Moving from plain to encrypted.* Use the @encrypt@ and @decrypt@ commands at any time to move from the plain to the encrypted format.
|
65
81
|
|
66
|
-
|
67
|
-
$ pwss -f YOURFILE encrypt
|
68
|
-
</pre>
|
82
|
+
bc. $ pwss -f YOURFILE encrypt
|
69
83
|
|
70
84
|
will encrypt @YOURFILE@ while @decrypt@ will perform the opposite operation.
|
71
85
|
|
@@ -78,11 +92,11 @@ In this scenario, you can use the following commands to get started:
|
|
78
92
|
|
79
93
|
To add entries to the password safe, use the @add@ command. If you prefer to operate on the file using a text editor, you can also use the @decrypt@ and @encrypt@ commands.
|
80
94
|
|
95
|
+
*Defining your entries.* @pwss@ requires entries to have only a @title@ and a @password@ field. If you want you can define and store your own records in the yaml files.
|
96
|
+
|
81
97
|
*Getting Help.*
|
82
98
|
|
83
|
-
|
84
|
-
$ pwss
|
85
|
-
</pre>
|
99
|
+
bc. $ pwss
|
86
100
|
|
87
101
|
will show all command options.
|
88
102
|
|
@@ -120,12 +134,18 @@ Example
|
|
120
134
|
|
121
135
|
Notice that only @title@ and @password@ are required.
|
122
136
|
|
137
|
+
h2. Changelog
|
138
|
+
|
139
|
+
* *Release 0.1.0*
|
140
|
+
** the update command now allows one to update the password or any other field of existing entries
|
141
|
+
** a simple password generator allows pwss to generate a random password
|
142
|
+
** most commands make the password of the selected entry available in the clipboard (useful, for instance, if you automatically generate a password)
|
143
|
+
** a destroy command allows one to delete an entry from a safe. Similar to get, all entries matching a query are shown. The user is then asked to select which entry has to be deleted or stop. User confirmation is required even in case of a single match.
|
144
|
+
|
123
145
|
h2. License and Additional Disclaimer
|
124
146
|
|
125
147
|
Licensed under the terms of the MIT License.
|
126
148
|
|
127
|
-
*Make sure you backup your important data and do not rely solely on @pwss@ to store your critical data.*
|
128
|
-
|
129
149
|
h2. Contributing
|
130
150
|
|
131
151
|
1. Fork it ( http://github.com/<my-github-username>/pwss/fork )
|
data/bin/pwss
CHANGED
@@ -20,20 +20,24 @@ PWSS is a password safe, in the spirit of pws
|
|
20
20
|
Features:
|
21
21
|
|
22
22
|
* Each entry stores: title, username, password, url, description
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
|
27
|
-
* Safes can be
|
23
|
+
* A file (or safe) can store many entries
|
24
|
+
* The user can manage different files (safes)
|
25
|
+
* CRUD (create, read, update, delete) commands are available to
|
26
|
+
operate on entries and safes
|
27
|
+
* Safes can be encrypted
|
28
|
+
* Encrypted safes can be decrypted, for instance, to batch process
|
29
|
+
entries, to migrate to another tool, or to manually edit entries
|
30
|
+
* Entries are human-readable (and editable), when not encrypted
|
28
31
|
EOS
|
29
32
|
|
30
|
-
p.syntax "pwss
|
31
|
-
p.option 'filename', '
|
33
|
+
p.syntax "pwss <subcommand> [options] [args]"
|
34
|
+
p.option 'filename', '-f FILE', '--filename FILE', 'Password file'
|
35
|
+
p.option 'wait', '-w SECS', '--wait SECS', 'Number of seconds password is available in the clipboard (use 0 for interactive).'
|
32
36
|
|
33
37
|
p.command(:init) do |c|
|
34
38
|
c.syntax "init"
|
35
|
-
c.description
|
36
|
-
|
39
|
+
c.description 'Init a new password file (= password safe)'
|
40
|
+
|
37
41
|
c.action do |args, opts|
|
38
42
|
filename = opts['filename'] || DEFAULT_FILENAME
|
39
43
|
|
@@ -55,7 +59,7 @@ EOS
|
|
55
59
|
end
|
56
60
|
|
57
61
|
p.command(:list) do |c|
|
58
|
-
c.syntax "list
|
62
|
+
c.syntax "list"
|
59
63
|
c.description "List all entries in a safe"
|
60
64
|
|
61
65
|
c.action do |args, opts|
|
@@ -70,31 +74,37 @@ EOS
|
|
70
74
|
|
71
75
|
p.command(:get) do |c|
|
72
76
|
c.syntax "get string"
|
73
|
-
c.description "Get
|
74
|
-
c.option 'interactive', '--interactive', '-i', 'Wait for user input to clean password.'
|
77
|
+
c.description "Get password for entry matching <string> in the title field"
|
75
78
|
|
76
79
|
c.action do |args, opts|
|
77
|
-
filename = opts['filename']
|
78
|
-
|
79
|
-
|
80
|
+
filename = opts['filename'] || DEFAULT_FILENAME
|
81
|
+
waiting = opts['wait'] ? opts['wait'].to_i : 30
|
82
|
+
|
80
83
|
string, _ = file2string filename
|
81
84
|
entries = YAML::load(string) || Array.new
|
82
85
|
|
83
|
-
Pwss::get args.join(" "), entries
|
86
|
+
password = Pwss::get args.join(" "), entries
|
87
|
+
Cipher.password_to_clipboard password, waiting
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
87
91
|
p.command(:add) do |c|
|
88
|
-
c.syntax "add
|
92
|
+
c.syntax "add"
|
89
93
|
c.description "Add an entry to a password safe"
|
90
94
|
|
95
|
+
c.option "generate", "-g LENGTH", "--generate LENGTH", "automatically generate a password of length LENGTH"
|
96
|
+
c.option "alnum", "-a", "--alnum", "use only alphanumeric characters for the generated password"
|
97
|
+
|
91
98
|
c.action do |args, opts|
|
92
99
|
filename = opts['filename'] || DEFAULT_FILENAME
|
100
|
+
waiting = opts['wait'] ? opts['wait'].to_i : 30
|
101
|
+
length = opts['generate'] ? opts['generate'].to_i : 0
|
102
|
+
|
93
103
|
string, password = file2string filename
|
94
104
|
|
95
105
|
# ask for a new entry
|
96
106
|
pe = Pwss::Entry.new
|
97
|
-
pe.ask
|
107
|
+
pe.ask length, opts['alnum']
|
98
108
|
|
99
109
|
# add the entry to the safe
|
100
110
|
entries = YAML::load(string) || Array.new
|
@@ -109,20 +119,39 @@ EOS
|
|
109
119
|
|
110
120
|
FileOps::backup filename
|
111
121
|
FileOps::save filename, new_string
|
122
|
+
|
123
|
+
puts "Entry added."
|
124
|
+
|
125
|
+
# make password available in the clipboard
|
126
|
+
Cipher.password_to_clipboard pe.entry["password"], waiting
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
115
130
|
p.command(:update) do |c|
|
116
|
-
c.syntax "update
|
117
|
-
c.description "Update
|
131
|
+
c.syntax "update a field of an existing entry"
|
132
|
+
c.description "Update some field of an existing entry (default: password)"
|
133
|
+
|
134
|
+
c.option 'field', '--field FIELD', 'Field to update (if not specified, update the password field)'
|
135
|
+
c.option "generate", "-g LENGTH", "--generate LENGTH", "generate a password of length LENGTH"
|
136
|
+
c.option "alnum", "-a", "--alnum", "use only alphabetic and numeric characters for the generated password"
|
118
137
|
|
119
138
|
c.action do |args, opts|
|
120
139
|
filename = opts['filename'] || DEFAULT_FILENAME
|
140
|
+
waiting = opts['wait'] ? opts['wait'].to_i : 30
|
141
|
+
length = opts['generate'] ? opts['generate'].to_i : 0
|
142
|
+
field = opts['field']
|
143
|
+
|
121
144
|
string, password = file2string filename
|
122
145
|
|
123
146
|
# load entries and update
|
124
147
|
entries = YAML::load(string) || Array.new
|
125
|
-
|
148
|
+
|
149
|
+
if field then
|
150
|
+
entries, entry_password = Pwss::update_field args.join(" "), entries, field
|
151
|
+
else
|
152
|
+
# update password
|
153
|
+
entries, entry_password = Pwss::update args.join(" "), entries, length, opts["alnum"]
|
154
|
+
end
|
126
155
|
|
127
156
|
# check status of input file and encrypt if necessary
|
128
157
|
if FileOps::encrypted? filename then
|
@@ -133,13 +162,23 @@ EOS
|
|
133
162
|
|
134
163
|
FileOps::backup filename
|
135
164
|
FileOps::save filename, new_string
|
165
|
+
|
166
|
+
puts "Entry updated."
|
167
|
+
|
168
|
+
# copy to clipboard the new password
|
169
|
+
Cipher.password_to_clipboard entry_password, waiting
|
136
170
|
end
|
137
171
|
end
|
138
172
|
|
139
173
|
|
140
174
|
p.command(:destroy) do |c|
|
141
|
-
c.syntax "
|
142
|
-
c.description "
|
175
|
+
c.syntax "destroy string"
|
176
|
+
c.description "Show entries matching <string> and let the user select one to destroy"
|
177
|
+
|
178
|
+
# Look for entries matching string, offer the user to select one of the
|
179
|
+
# matching entries, and destroy the entry.
|
180
|
+
# The command asks for confirmation even if there is only one matching entry.
|
181
|
+
# Destroyed entries cannot be recovered (unless you dig in the backup file).
|
143
182
|
|
144
183
|
c.action do |args, opts|
|
145
184
|
filename = opts['filename'] || DEFAULT_FILENAME
|
@@ -158,6 +197,8 @@ EOS
|
|
158
197
|
|
159
198
|
FileOps::backup filename
|
160
199
|
FileOps::save filename, new_string
|
200
|
+
|
201
|
+
puts "Entry deleted."
|
161
202
|
end
|
162
203
|
end
|
163
204
|
|
@@ -198,6 +239,7 @@ EOS
|
|
198
239
|
dec_filename = filename.sub(/\.enc$/,"")
|
199
240
|
FileOps::save dec_filename, decrypted
|
200
241
|
puts "A decrypted copy now lives in #{dec_filename}"
|
242
|
+
puts "You might want to check everything is ok and delete #{filename}, if you wish."
|
201
243
|
end
|
202
244
|
end
|
203
245
|
|
data/lib/pwss.rb
CHANGED
@@ -7,51 +7,47 @@ require 'yaml'
|
|
7
7
|
|
8
8
|
module Pwss
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
def self.get search_string, entries, interactive
|
10
|
+
def self.get search_string, entries
|
13
11
|
id = choose_entry search_string, entries
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
# puts "Selected entry:\n"
|
18
|
-
# print_entry id, entries[id]
|
19
|
-
|
20
|
-
#
|
21
|
-
# make the password available and then forget it
|
22
|
-
#
|
23
|
-
password = entries[id]["password"]
|
24
|
-
system("echo #{password} | pbcopy")
|
13
|
+
entries[id]["password"]
|
14
|
+
end
|
25
15
|
|
26
|
-
if interactive
|
27
|
-
puts "\nPassword available in clipboard: press any key when you are done."
|
28
|
-
STDIN.getc
|
29
|
-
else
|
30
|
-
puts "\nPassword available in clipboard for #{WAITING_PERIOD} seconds."
|
31
|
-
sleep(WAITING_PERIOD)
|
32
|
-
end
|
33
16
|
|
34
|
-
|
35
|
-
|
17
|
+
def self.update search_string, entries, length, alnum
|
18
|
+
id = choose_entry search_string, entries, true
|
36
19
|
|
20
|
+
password = Cipher.check_or_generate "new password for entry", length, alnum
|
37
21
|
|
38
|
-
def self.update search_string, entries
|
39
|
-
id = choose_entry search_string, entries
|
40
|
-
password = Cipher::check_password
|
41
22
|
entries[id]["password"] = password
|
42
|
-
entries
|
23
|
+
entries[id]["updated_at"] = Date.today
|
24
|
+
|
25
|
+
return entries, password
|
43
26
|
end
|
44
27
|
|
28
|
+
def self.update_field search_string, entries, field
|
29
|
+
id = choose_entry search_string, entries, true
|
30
|
+
|
31
|
+
field_value = Readline.readline("\nEnter new value for #{field}: ")
|
32
|
+
|
33
|
+
entries[id][field] = field_value
|
34
|
+
entries[id]["updated_at"] = Date.today
|
35
|
+
password = entries[id]["password"]
|
36
|
+
|
37
|
+
return entries, password
|
38
|
+
end
|
39
|
+
|
45
40
|
|
46
41
|
def self.destroy search_string, entries
|
47
|
-
id = choose_entry search_string, entries
|
42
|
+
id = choose_entry search_string, entries, true
|
43
|
+
|
48
44
|
entries.delete_at(id) if id != -1
|
49
45
|
entries
|
50
46
|
end
|
51
47
|
|
52
48
|
|
53
49
|
def self.list entries
|
54
|
-
index = 0
|
50
|
+
index = 0
|
55
51
|
entries.each do |element|
|
56
52
|
print_entry index, element
|
57
53
|
index += 1
|
@@ -64,11 +60,13 @@ module Pwss
|
|
64
60
|
# Let the user select an entry from data
|
65
61
|
# (data is a YAML string with an array of entries)
|
66
62
|
#
|
67
|
-
def self.choose_entry search_string, entries
|
63
|
+
def self.choose_entry search_string, entries, confirm_even_if_one = false
|
68
64
|
# here we have a nuisance: we want the user to choose one entry
|
69
65
|
# by relative id (e.g. the third found), but we need to return
|
70
|
-
# the absolute id
|
71
|
-
#
|
66
|
+
# the absolute id (to update the right entry in the safe)
|
67
|
+
#
|
68
|
+
# ... so we just keep track of the real ids with an array
|
69
|
+
# the relative id is the index in the array
|
72
70
|
|
73
71
|
index = 0
|
74
72
|
found = Array.new
|
@@ -81,20 +79,29 @@ module Pwss
|
|
81
79
|
end
|
82
80
|
|
83
81
|
if found.size == 0 then
|
84
|
-
printf "
|
85
|
-
|
82
|
+
printf "No entry matches the search criteria.\n"
|
83
|
+
exit -1
|
86
84
|
end
|
87
85
|
|
88
|
-
if found.size > 1 then
|
89
|
-
printf "\nVarious matches.
|
86
|
+
if found.size > 1 or confirm_even_if_one then
|
87
|
+
printf "\nVarious matches." if found.size > 1
|
88
|
+
printf "\nSelect entry by ID (0..#{found.size-1}) or -1 to exit: "
|
89
|
+
|
90
90
|
id = STDIN.gets.chomp.to_i
|
91
|
+
while (id < -1 or id >= found.size)
|
92
|
+
printf "Select entry by ID (0..#{found.size-1}) or -1 to exit: "
|
93
|
+
id = STDIN.gets.chomp.to_i
|
94
|
+
end
|
95
|
+
if id == -1 then
|
96
|
+
exit -1
|
97
|
+
end
|
91
98
|
else
|
92
99
|
id = 0
|
93
100
|
end
|
94
101
|
|
95
102
|
found[id]
|
96
103
|
end
|
97
|
-
|
104
|
+
|
98
105
|
#
|
99
106
|
# Print entry
|
100
107
|
#
|
data/lib/pwss/cipher.rb
CHANGED
@@ -24,11 +24,11 @@ module Cipher
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Ask for a password twice and make sure it is entered the same
|
27
|
-
def self.check_password prompt="master password
|
27
|
+
def self.check_password prompt="master password"
|
28
28
|
match = false
|
29
29
|
while ! match
|
30
|
-
password = ask_password "Enter #{prompt}"
|
31
|
-
repeat = ask_password "Repeat #{prompt}"
|
30
|
+
password = ask_password "Enter #{prompt}: "
|
31
|
+
repeat = ask_password "Repeat #{prompt}: "
|
32
32
|
match = (password == repeat)
|
33
33
|
|
34
34
|
if match == false then
|
@@ -37,4 +37,38 @@ module Cipher
|
|
37
37
|
end
|
38
38
|
password
|
39
39
|
end
|
40
|
+
|
41
|
+
# Ask for a password (twice) or generate one, if length is greater than 0
|
42
|
+
def self.check_or_generate prompt, length=0, alnum=false
|
43
|
+
length > 0 ? generate_password(length, alnum) : check_password(prompt)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# make the password available to the clipboard.
|
48
|
+
#
|
49
|
+
def self.password_to_clipboard password, counter = 30
|
50
|
+
system("printf \"%s\" \"#{password}\" | pbcopy")
|
51
|
+
|
52
|
+
if counter <= 0
|
53
|
+
puts "\nPassword available in clipboard: press enter when you are done."
|
54
|
+
STDIN.getc
|
55
|
+
else
|
56
|
+
puts "\nPassword available in clipboard for #{counter} seconds."
|
57
|
+
sleep(counter)
|
58
|
+
end
|
59
|
+
|
60
|
+
system("echo ahahahahaha | pbcopy")
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Generate a random password
|
66
|
+
# (Adapted from: http://randompasswordsgenerator.net/tutorials/ruby-random-password-generator.html)
|
67
|
+
def self.generate_password(length=8, alnum=false)
|
68
|
+
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ1234567890'
|
69
|
+
chars += '!@#$%^&*()_+=[]{}<>/~,.;:|' if not alnum
|
70
|
+
Array.new(length) { chars[rand(chars.length)].chr }.join
|
71
|
+
end
|
72
|
+
|
73
|
+
|
40
74
|
end
|
data/lib/pwss/entry.rb
CHANGED
@@ -14,8 +14,9 @@ module Pwss
|
|
14
14
|
FIELDS = {
|
15
15
|
"title" => ["Readline.readline('title: ')", "'title'"],
|
16
16
|
"username" => ["Readline.readline('username: ')", "''"],
|
17
|
-
"password" => ["Cipher.
|
18
|
-
"
|
17
|
+
"password" => ["Cipher.check_or_generate('password for entry', length, alnum)", "''"],
|
18
|
+
"created_at" => ["", "Date.today"],
|
19
|
+
"updated_at" => ["", "nil"],
|
19
20
|
"url" => ["Readline.readline('url: ')", "''"],
|
20
21
|
"description" => ["get_lines", "''"]
|
21
22
|
}
|
@@ -28,7 +29,8 @@ module Pwss
|
|
28
29
|
end
|
29
30
|
|
30
31
|
# interactively ask from command line all fields specified in FIELDS
|
31
|
-
|
32
|
+
# arguments length and alnum are for password generation
|
33
|
+
def ask length, alnum
|
32
34
|
FIELDS.keys.each do |key|
|
33
35
|
@entry[key] = (eval FIELDS[key][INPUT_F]) || (eval FIELDS[key][DEFAULT])
|
34
36
|
end
|
data/lib/pwss/fileops.rb
CHANGED
@@ -16,6 +16,7 @@ module FileOps
|
|
16
16
|
file = File.open(filename, "wb")
|
17
17
|
file.write data
|
18
18
|
file.close
|
19
|
+
puts "Password safe #{filename} updated."
|
19
20
|
end
|
20
21
|
|
21
22
|
# check if the extension is ".enc"
|
@@ -25,6 +26,7 @@ module FileOps
|
|
25
26
|
|
26
27
|
def self.backup filename
|
27
28
|
FileUtils::cp filename, filename + "~"
|
29
|
+
puts "Backup copy of password safe created in #{filename}~."
|
28
30
|
end
|
29
31
|
|
30
32
|
end
|
data/lib/pwss/version.rb
CHANGED
data/pwss.gemspec
CHANGED
@@ -27,6 +27,6 @@ Distinguishing features:
|
|
27
27
|
spec.add_development_dependency "bundler", "~> 1.5"
|
28
28
|
spec.add_development_dependency "rake"
|
29
29
|
|
30
|
-
spec.add_runtime_dependency 'mercenary', '~> 0.3.
|
30
|
+
spec.add_runtime_dependency 'mercenary', '~> 0.3.4', '>= 0.3.4'
|
31
31
|
spec.add_runtime_dependency 'encryptor', '~> 1.3.0', '>= 1.3.0'
|
32
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pwss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adolfo Villafiorita
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,20 +44,20 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.3.
|
47
|
+
version: 0.3.4
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0.3.
|
50
|
+
version: 0.3.4
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
55
|
- - "~>"
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: 0.3.
|
57
|
+
version: 0.3.4
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.3.
|
60
|
+
version: 0.3.4
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: encryptor
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|