passwordsafe 0.0.4 → 0.0.5

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.
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- passwordsafe (0.0.3)
4
+ passwordsafe (0.0.4)
5
+ clipboard
5
6
  highline
6
7
  thor
7
8
 
@@ -13,6 +14,7 @@ GEM
13
14
  cucumber (~> 0.10.0)
14
15
  background_process (1.2)
15
16
  builder (3.0.0)
17
+ clipboard (0.9.7)
16
18
  cucumber (0.10.0)
17
19
  builder (>= 2.1.2)
18
20
  diff-lcs (~> 1.1.2)
@@ -34,7 +36,7 @@ GEM
34
36
  diff-lcs (~> 1.1.2)
35
37
  rspec-mocks (2.3.0)
36
38
  term-ansicolor (1.0.5)
37
- thor (0.14.3)
39
+ thor (0.14.6)
38
40
 
39
41
  PLATFORMS
40
42
  ruby
@@ -43,7 +45,5 @@ DEPENDENCIES
43
45
  aruba
44
46
  bundler
45
47
  cucumber
46
- highline
47
48
  passwordsafe!
48
49
  rspec
49
- thor
data/History.md CHANGED
@@ -1,3 +1,6 @@
1
+ == 0.0.4
2
+ * New feature: `password list`
3
+
1
4
  == 0.0.3
2
5
  * New feature: `password get name`
3
6
 
data/README.md CHANGED
@@ -9,17 +9,26 @@ Based on 'Tutorial: Build your own password safe with Ruby!' at http://rbjl.net/
9
9
  password add name password
10
10
  Use passwordsafe to add a password with NAME to the safe. The utility will prompt for a master password to use to encrypt the file. *Do NOT loose your master password, it is unrecoverable!*
11
11
 
12
+ password change name password
13
+ Change an existing named password to this new password.
14
+
15
+ password generate name [--length]
16
+ Generate a new password with name, accepts an optional length argument.
17
+
12
18
  password get name
13
19
  Use passwordsafe to retrive an existing password out of your safe. The utility will prompt for a master password.
14
20
 
15
21
  password list
16
22
  List all the existing password names in the safe.
17
23
 
24
+ password remove name
25
+ Remove an existing password from your safe.
18
26
 
19
27
  ## Not Implemented yet
20
28
 
21
- password remove name
22
- password help
29
+ # Contributers
30
+
31
+ * polarblau https://github.com/polarblau
23
32
 
24
33
  # Note on Patches/Pull Requests
25
34
 
@@ -3,7 +3,6 @@ Feature: Add
3
3
  As a user
4
4
  I want to be able to add my passwords to the passwordsafe
5
5
 
6
-
7
6
  Scenario: Add a new password
8
7
  When I run "password add name pa$$word" interactively
9
8
  And I type "masterpa$$"
@@ -0,0 +1,16 @@
1
+ Feature: Add
2
+ In order to not having to remove and re-add my passwords
3
+ As a user
4
+ I want to be able to change a password
5
+
6
+ Scenario: Change password
7
+ Given A safe exists with masterpassword "masterpa$$" and a "name" key
8
+ When I run "password change name newpa$$word" interactively
9
+ And I type "masterpa$$"
10
+ Then the output should contain "password for name has been updated"
11
+
12
+ Scenario: Change a password for a key that doesn't exist
13
+ Given A safe exists with masterpassword "masterpa$$" and a "name" key
14
+ When I run "password change name2 newpa$$word" interactively
15
+ And I type "masterpa$$"
16
+ Then the output should contain "name2 does not exist in this safe."
@@ -0,0 +1,27 @@
1
+ Feature: Add
2
+ In order to store a safe password
3
+ As a user
4
+ I want to be able to generate a safe password and store it
5
+
6
+ Scenario: Generate and add new password
7
+ Given A safe exists with masterpassword "masterpa$$"
8
+ When I run "password generate name" interactively
9
+ And I type "masterpa$$"
10
+ Then the output should contain "generated and added to safe"
11
+ And the clipboard should contain the password for the "name" key
12
+
13
+ Scenario: Generate a password with a certain length
14
+ Given A safe exists with masterpassword "masterpa$$"
15
+ When I run "password generate name --length 12" interactively
16
+ And I type "masterpa$$"
17
+ Then the output should contain "generated and added to safe"
18
+ And the clipboard should contain the password for the "name" key
19
+
20
+ Scenario: Generate a password with a name that exists
21
+ Given A safe exists with masterpassword "masterpa$$" and a "name" key
22
+ When I run "password generate name" interactively
23
+ And I type "masterpa$$"
24
+ Then the output should contain "Key already exists in keyring"
25
+ And the output should not contain "generated and added to safe"
26
+
27
+
@@ -8,10 +8,10 @@ Feature: Get
8
8
  When I run "password get name" interactively
9
9
  And I type "masterpa$$"
10
10
  Then the output should contain "name: "
11
-
11
+ And the clipboard should contain the password for the "name" key
12
+
12
13
  Scenario: Get a password with a name that does not exist
13
14
  Given A safe exists with masterpassword "masterpa$$" and a "name" key
14
15
  When I run "password get name2" interactively
15
16
  And I type "masterpa$$"
16
- Then the output should contain "name2 does not exist in this safe."
17
-
17
+ Then the output should contain "name2 does not exist in this safe."
@@ -0,0 +1,16 @@
1
+ Feature: Remove
2
+ In order to keep my password list up-to-date
3
+ As a user
4
+ I want to be able to remove a password
5
+
6
+ Scenario: Remove a password
7
+ Given A safe exists with masterpassword "masterpa$$" and a "name" key
8
+ When I run "password remove name" interactively
9
+ And I type "masterpa$$"
10
+ Then the output should contain "entry has been removed"
11
+
12
+ Scenario: Remove a password for a key that doesn't exist
13
+ Given A safe exists with masterpassword "masterpa$$" and a "name" key
14
+ When I run "password remove name2" interactively
15
+ And I type "masterpa$$"
16
+ Then the output should contain "name2 does not exist in this safe."
@@ -1,21 +1,33 @@
1
1
  require 'passwordsafe/safe'
2
2
  require 'passwordsafe/keyring'
3
3
  require 'passwordsafe/cli'
4
+ require 'clipboard'
5
+
6
+ Given /^A safe exists with masterpassword "([^"]*)"$/ do |masterpass|
7
+ in_current_dir do
8
+ @safe = PasswordSafe::Safe.new(PasswordSafe::CLI::DEFAULTSAFE, masterpass)
9
+ end
10
+ end
4
11
 
5
12
  Given /^A safe exists with masterpassword "([^"]*)" and a "([^"]*)" key$/ do |masterpass, key_name|
6
13
  in_current_dir do
7
- safe = PasswordSafe::Safe.new(PasswordSafe::CLI::DEFAULTSAFE, masterpass)
8
- PasswordSafe::Keyring.new(safe).add key_name, "dummypass"
14
+ @safe = PasswordSafe::Safe.new(PasswordSafe::CLI::DEFAULTSAFE, masterpass)
15
+ PasswordSafe::Keyring.new(@safe).add key_name, "dummypass"
9
16
  end
10
17
  end
11
18
 
12
19
  Given /^A safe exists with masterpassword "([^"]*)" and "([^"]*)" keys$/ do |masterpass, keys|
13
20
  in_current_dir do
14
- safe = PasswordSafe::Safe.new(PasswordSafe::CLI::DEFAULTSAFE, masterpass)
21
+ @safe = PasswordSafe::Safe.new(PasswordSafe::CLI::DEFAULTSAFE, masterpass)
15
22
 
16
23
  keys.to_i.times do |i|
17
- PasswordSafe::Keyring.new(safe).add "pass#{i}", "dummypass"
24
+ PasswordSafe::Keyring.new(@safe).add "pass#{i}", "dummypass"
18
25
  end
19
26
  end
20
27
  end
21
28
 
29
+ Then /^the clipboard should contain the password for the "([^"]*)" key$/ do |key_name|
30
+ password = PasswordSafe::Keyring.new(@safe).get key_name
31
+ password.should eq(Clipboard.paste)
32
+ end
33
+
@@ -3,5 +3,6 @@ require 'aruba/cucumber'
3
3
 
4
4
  After do |s|
5
5
  remove_file(PasswordSafe::CLI::DEFAULTSAFE)
6
+ Clipboard.clear
6
7
  end
7
8
 
@@ -17,6 +17,19 @@ module PasswordSafe
17
17
  puts "password #{name} added to safe"
18
18
  end
19
19
  end
20
+
21
+ desc "generate NAME", "Generate a new PASSWORD and add it to the keyring with NAME"
22
+ method_options :length => 8
23
+ def generate name
24
+ safe = make_safe
25
+ begin
26
+ password = PasswordSafe::Keyring.new(safe).generate(name, options[:length])
27
+ rescue PasswordSafe::Keyring::KeyExistsException => msg
28
+ puts "#{msg}"
29
+ else
30
+ puts "password #{password} generated and added to safe"
31
+ end
32
+ end
20
33
 
21
34
  desc "get NAME", "Get an existing password with name NAME from keyring"
22
35
  def get name
@@ -28,6 +41,30 @@ module PasswordSafe
28
41
  puts "#{name}: #{password}"
29
42
  end
30
43
  end
44
+
45
+ desc "remove NAME", "Remove an existing passoword with name NAME from keyring"
46
+ def remove name
47
+ safe = make_safe
48
+ begin
49
+ PasswordSafe::Keyring.new(safe).remove(name)
50
+ rescue PasswordSafe::Keyring::KeyMissingException => msg
51
+ puts "#{msg}"
52
+ else
53
+ puts "entry has been removed"
54
+ end
55
+ end
56
+
57
+ desc "change NAME PASSWORD", "Change the password for an existing name NAME to password PASSWORD"
58
+ def change name, password
59
+ safe = make_safe
60
+ begin
61
+ PasswordSafe::Keyring.new(safe).change(name, password)
62
+ rescue PasswordSafe::Keyring::KeyMissingException => msg
63
+ puts "#{msg}"
64
+ else
65
+ puts "password for #{name} has been updated"
66
+ end
67
+ end
31
68
 
32
69
  desc "list", "List the names of all the existing passwords in the safe"
33
70
  def list
@@ -1,8 +1,10 @@
1
1
  require 'passwordsafe/safe'
2
+ require 'clipboard'
2
3
 
3
4
  module PasswordSafe
4
5
  class Keyring
5
6
  class KeyExistsException < StandardError; end
7
+ class KeyMissingException < StandardError; end
6
8
 
7
9
  def initialize safe = nil
8
10
  @safe = safe
@@ -22,24 +24,47 @@ module PasswordSafe
22
24
  @ring.store(name, password)
23
25
  @safe.write_safe @ring
24
26
  end
27
+
28
+ def change name, password
29
+ raise KeyMissingException, "#{name} does not exist in this safe.", caller unless @ring.has_key?(name)
30
+ @ring[name] = password
31
+ @safe.write_safe @ring
32
+ end
25
33
 
26
- def get name
27
- @ring[name]
34
+ def generate name, length = 8
35
+ raise KeyExistsException, "Key already exists in keyring, if you'd like to add it remove the existing key", caller if @ring.has_key?(name)
36
+ password = generate_password(length)
37
+ @ring.store(name, password)
38
+ @safe.write_safe @ring
39
+ Clipboard.copy(password)
40
+ password
28
41
  end
29
42
 
30
- def list
31
- @ring.keys
43
+ def get name
44
+ raise KeyMissingException, "#{name} does not exist in this safe.", caller unless @ring.has_key?(name)
45
+ password = @ring[name]
46
+ Clipboard.copy(password)
47
+ password
32
48
  end
33
49
 
34
50
  def remove name
51
+ raise KeyMissingException, "#{name} does not exist in this safe.", caller unless @ring.has_key?(name)
35
52
  @ring.delete(name)
36
53
  @safe.write_safe @ring
37
54
  end
38
55
 
56
+ def list
57
+ @ring.keys
58
+ end
59
+
39
60
  private
40
61
  def load_from_safe
41
62
  @safe.read_safe
42
63
  end
64
+
65
+ def generate_password(len)
66
+ Array.new(len/2) { rand(256) }.pack('C*').unpack('H*').first
67
+ end
43
68
  end
44
69
  end
45
70
 
@@ -1,4 +1,4 @@
1
1
  module Passwordsafe
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
4
4
 
@@ -26,5 +26,6 @@ Gem::Specification.new do |s|
26
26
 
27
27
  s.add_dependency "thor"
28
28
  s.add_dependency "highline"
29
+ s.add_dependency "clipboard"
29
30
  end
30
31
 
@@ -1,9 +1,14 @@
1
1
  require 'spec_helper'
2
2
  require 'passwordsafe/keyring'
3
+ require 'clipboard'
3
4
 
4
5
  describe PasswordSafe::Keyring do
5
6
  let(:safe) { mock PasswordSafe::Safe, :read_safe => {}, :write_safe => nil }
6
7
  let(:keyring) { PasswordSafe::Keyring.new(safe) }
8
+
9
+ after (:each) do
10
+ Clipboard.clear
11
+ end
7
12
 
8
13
  it "expects to get a Safe to read/write" do
9
14
  safe.should_receive(:is_a?).and_return(true)
@@ -13,7 +18,6 @@ describe PasswordSafe::Keyring do
13
18
  end
14
19
 
15
20
  describe "length" do
16
-
17
21
  it "returns the number of keys in the keyring" do
18
22
  keyring.should respond_to(:length)
19
23
  keyring.length.should be_a(Integer)
@@ -21,7 +25,6 @@ describe PasswordSafe::Keyring do
21
25
  end
22
26
 
23
27
  describe "add" do
24
-
25
28
  it "adds a key to the keyring" do
26
29
  keyring.should respond_to(:add).with(2).arguments
27
30
  keyring.add("name", "password")
@@ -37,19 +40,49 @@ describe PasswordSafe::Keyring do
37
40
  end
38
41
  end
39
42
 
43
+ describe "generate" do
44
+ it "adds a generated password to the keyring" do
45
+ keyring.should respond_to(:generate).with(1).arguments
46
+ keyring.generate("name")
47
+ keyring.length.should eq(1)
48
+ end
49
+ it "generates a password" do
50
+ keyring.should respond_to(:generate).with(1).arguments
51
+ password = keyring.generate("name")
52
+ keyring.get("name").should eq(password)
53
+ end
54
+ it "generates a password of default length '8'" do
55
+ keyring.generate("name").length.should eq(8)
56
+ end
57
+ it "generates a password of a specified length" do
58
+ keyring.generate("name", 12).length.should eq(12)
59
+ end
60
+ it "throws an error when generating passord for a duplicate key name" do
61
+ keyring.generate("name")
62
+ expect{keyring.generate("name")}.to raise_error()
63
+ end
64
+ it "should copy the generated password to the clipboard" do
65
+ password = keyring.generate("name")
66
+ Clipboard.paste.should eq(password)
67
+ end
68
+ end
69
+
40
70
  describe "get" do
41
-
42
71
  it "gets a key from the keyring" do
43
72
  safe.stub(:read_safe).and_return({"name" => "password"})
44
73
  keyring.get("name").should eq("password")
45
74
  end
46
- it "returns nil if the key does not exist" do
47
- keyring.get("name").should be_nil
75
+ it "throws an error if a key does not exist" do
76
+ expect{keyring.get("name")}.to raise_error()
77
+ end
78
+ it "should copy the retrieved password to the clipboard" do
79
+ safe.stub(:read_safe).and_return({"name" => "password"})
80
+ password = keyring.get("name")
81
+ Clipboard.paste.should eq(password)
48
82
  end
49
83
  end
50
84
 
51
85
  describe "list" do
52
-
53
86
  it "returns a list of existing key names" do
54
87
  safe.should_receive(:read_safe).and_return({"first" => "password", "second" => "password"})
55
88
  keyring.list.should eq(["first", "second"])
@@ -58,19 +91,46 @@ describe PasswordSafe::Keyring do
58
91
  keyring.list.should eq([])
59
92
  end
60
93
  end
94
+
95
+ describe "change" do
96
+ it "responds to 'change'" do
97
+ safe.stub(:read_safe).and_return({"name" => "password"})
98
+ keyring.should respond_to(:change).with(2).arguments
99
+ end
100
+ it "throws an error if a key does not exist" do
101
+ expect{keyring.change("name", "password")}.to raise_error()
102
+ end
103
+ it "updates the password" do
104
+ safe.stub(:read_safe).and_return({"name" => "password"})
105
+ keyring.get("name").should eq("password")
106
+ keyring.change("name", "newpassword")
107
+ keyring.get("name").should eq("newpassword")
108
+ end
109
+ it "updates the modified keyring to the safe" do
110
+ safe.stub(:read_safe).and_return({"name" => "password"})
111
+ safe.should_receive(:write_safe).with({"name" => "newpassword"})
112
+ keyring.change("name", "newpassword")
113
+ end
114
+ end
61
115
 
62
116
  describe "remove" do
63
-
117
+ it "responds to 'remove'" do
118
+ safe.stub(:read_safe).and_return({"name" => "password"})
119
+ keyring.should respond_to(:remove).with(1).arguments
120
+ end
64
121
  it "removes an existing key" do
65
122
  safe.should_receive(:read_safe).and_return({"first" => "password", "second" => "password"})
66
123
  keyring.remove("first")
67
- keyring.get("first").should eq(nil)
124
+ expect{keyring.get("first")}.to raise_error()
68
125
  end
69
126
  it "saves the modified keyring to the safe" do
70
127
  safe.should_receive(:read_safe).and_return({"first" => "password", "second" => "password"})
71
128
  safe.should_receive(:write_safe).with({"second" => "password"})
72
129
  keyring.remove("first")
73
130
  end
131
+ it "throws an error if a key does not exist" do
132
+ expect{keyring.remove("name")}.to raise_error()
133
+ end
74
134
  end
75
135
  end
76
136
 
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passwordsafe
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 4
9
- version: 0.0.4
4
+ prerelease:
5
+ version: 0.0.5
10
6
  platform: ruby
11
7
  authors:
12
8
  - thecatwasnot
@@ -14,7 +10,7 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-01-04 00:00:00 -06:00
13
+ date: 2011-03-07 00:00:00 -06:00
18
14
  default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
@@ -25,8 +21,6 @@ dependencies:
25
21
  requirements:
26
22
  - - ">="
27
23
  - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
24
  version: "0"
31
25
  type: :development
32
26
  version_requirements: *id001
@@ -38,8 +32,6 @@ dependencies:
38
32
  requirements:
39
33
  - - ">="
40
34
  - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
35
  version: "0"
44
36
  type: :development
45
37
  version_requirements: *id002
@@ -51,8 +43,6 @@ dependencies:
51
43
  requirements:
52
44
  - - ">="
53
45
  - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
46
  version: "0"
57
47
  type: :development
58
48
  version_requirements: *id003
@@ -64,8 +54,6 @@ dependencies:
64
54
  requirements:
65
55
  - - ">="
66
56
  - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
57
  version: "0"
70
58
  type: :development
71
59
  version_requirements: *id004
@@ -77,8 +65,6 @@ dependencies:
77
65
  requirements:
78
66
  - - ">="
79
67
  - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
68
  version: "0"
83
69
  type: :runtime
84
70
  version_requirements: *id005
@@ -90,11 +76,20 @@ dependencies:
90
76
  requirements:
91
77
  - - ">="
92
78
  - !ruby/object:Gem::Version
93
- segments:
94
- - 0
95
79
  version: "0"
96
80
  type: :runtime
97
81
  version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: clipboard
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ type: :runtime
92
+ version_requirements: *id007
98
93
  description: Small command line app for storing passwords
99
94
  email:
100
95
  - thecatwasnot@gmail.com
@@ -115,8 +110,11 @@ files:
115
110
  - Rakefile
116
111
  - bin/password
117
112
  - features/add.feature
113
+ - features/change.feature
114
+ - features/generate.feature
118
115
  - features/get.feature
119
116
  - features/list.feature
117
+ - features/remove.feature
120
118
  - features/step_definitions/safe_steps.rb
121
119
  - features/support/env.rb
122
120
  - lib/passwordsafe.rb
@@ -145,21 +143,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
143
  requirements:
146
144
  - - ">="
147
145
  - !ruby/object:Gem::Version
148
- segments:
149
- - 0
150
146
  version: "0"
151
147
  required_rubygems_version: !ruby/object:Gem::Requirement
152
148
  none: false
153
149
  requirements:
154
150
  - - ">="
155
151
  - !ruby/object:Gem::Version
156
- segments:
157
- - 0
158
152
  version: "0"
159
153
  requirements: []
160
154
 
161
155
  rubyforge_project: passwordsafe
162
- rubygems_version: 1.3.7
156
+ rubygems_version: 1.5.0
163
157
  signing_key:
164
158
  specification_version: 3
165
159
  summary: Small command line app for storing passwords