passwordsafe 0.0.4 → 0.0.5

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