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