purse 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.
@@ -0,0 +1,62 @@
1
+ module Purse
2
+ class Note
3
+ attr_reader :path, :name, :encrypted, :options
4
+ attr_accessor :data
5
+
6
+ def initialize(path, name, data, options = {})
7
+ Purse.check_for_parameter('path', path)
8
+ Purse.check_for_parameter('name', name)
9
+ @path = path
10
+ @name = name
11
+ @options = options
12
+ if options[:encrypted]
13
+ @encrypted = data
14
+ else
15
+ @data = data
16
+ end
17
+ end
18
+
19
+ def self.load(path, name, options = {})
20
+ note = Note.new(path, name, nil)
21
+ raise MissingFile, "Tried to load #{note.file_path} but it does not exist" unless File.readable?(note.file_path)
22
+ encrypted_data = File.read(note.file_path)
23
+ Note.new(path, name, encrypted_data, options.merge(:encrypted => true))
24
+ end
25
+
26
+ def save(password)
27
+ Purse.check_for_parameter('password', password)
28
+ encrypt(password)
29
+ File.open(file_path, 'w') {|f| f << @encrypted }
30
+ self
31
+ end
32
+
33
+ def encrypt(password)
34
+ Purse.check_for_parameter('password', password)
35
+ blowfish = Crypt::Blowfish.new(password)
36
+ @encrypted = blowfish.encrypt_string(@data)
37
+ end
38
+
39
+ def decrypt(password)
40
+ Purse.check_for_parameter('password', password)
41
+ blowfish = Crypt::Blowfish.new(password)
42
+ @data = blowfish.decrypt_string(@encrypted)
43
+ end
44
+
45
+ def encrypted?
46
+ @encrypted && (!@data || @data.blank?)
47
+ end
48
+
49
+ def delete
50
+ File.unlink(file_path)
51
+ end
52
+
53
+ def file_path
54
+ File.join(path, file_name)
55
+ end
56
+
57
+ def file_name
58
+ "#{name}.note"
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,80 @@
1
+ module Purse
2
+ class Pocket
3
+ attr_reader :path
4
+
5
+ def initialize(path)
6
+ Purse.check_for_parameter('path', path)
7
+ @path = File.expand_path(path)
8
+ end
9
+
10
+ def init
11
+ FileUtils.mkdir_p(@path) unless File.readable?(@path)
12
+ git
13
+ end
14
+
15
+ def delete
16
+ FileUtils.rm_rf(@path)
17
+ end
18
+
19
+ def find(name)
20
+ Purse.check_for_parameter('name', name)
21
+ note = notes.find {|note| note.name == name }
22
+ note ? note : raise(Purse::MissingFile, "Could note find the note named #{note}")
23
+ end
24
+
25
+ def edit(name)
26
+ Purse.check_for_parameter('name', name)
27
+ begin
28
+ note = find(name)
29
+ rescue Purse::MissingFile
30
+ note = Note.new(path, name, nil)
31
+ end
32
+ yield(note)
33
+ @notes = load_notes
34
+ end
35
+
36
+ def notes
37
+ @notes ||= load_notes
38
+ end
39
+
40
+ def notes_paths
41
+ Dir[File.join(@path, '*.note')]
42
+ end
43
+
44
+ def load_notes
45
+ notes_paths.collect {|note_path| Note.load(File.dirname(note_path), File.basename(note_path, '.note'))}
46
+ end
47
+
48
+ def re_encrypt(password)
49
+ Purse.check_for_parameter('password', password)
50
+ notes.collect {|n| n.save(password) }
51
+ end
52
+
53
+ def commit
54
+ git.add('.')
55
+ return if git.status.changed.empty?
56
+ git.commit_all("Changes via Purse #{Time.now}")
57
+ end
58
+
59
+ def remote
60
+ git.remotes.first
61
+ end
62
+
63
+ def set_remote(remote_url)
64
+ git.add_remote('origin', remote_url)
65
+ end
66
+
67
+ def push
68
+ git.push('origin')
69
+ end
70
+
71
+ def pull
72
+ git.pull('origin')
73
+ end
74
+
75
+ protected
76
+ def git
77
+ @git ||= Git.init(@path)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,57 @@
1
+ module Purse
2
+ class Settings
3
+
4
+ class << self
5
+ def default_path
6
+ File.join(File.expand_path('~'), '.purse', 'settings.yml')
7
+ end
8
+
9
+ def path
10
+ @path ||= default_path
11
+ end
12
+
13
+ def path=(new_path)
14
+ raise MissingParameter unless new_path.is_a?(String)
15
+ @path = new_path
16
+ @loaded = false
17
+ end
18
+
19
+ def load
20
+ save unless File.readable?(path)
21
+ @settings = YAML.load_file(path)
22
+ @loaded = true
23
+ end
24
+
25
+ def loaded?
26
+ @loaded ||= false
27
+ end
28
+
29
+ def save
30
+ FileUtils.mkdir_p(File.dirname(path))
31
+ File.open(path, 'w') {|f| f << YAML::dump(settings) }
32
+ end
33
+
34
+ def get(key)
35
+ load unless loaded?
36
+ settings[key.to_s]
37
+ end
38
+
39
+ def set(key, value, should_save = true)
40
+ settings[key.to_s] = value
41
+ save if should_save
42
+ end
43
+
44
+ def settings
45
+ @settings ||= {}
46
+ end
47
+
48
+ def settings=(new_settings)
49
+ return unless new_settings.is_a?(Hash)
50
+ new_settings.each do |k, v|
51
+ set(k, v, false)
52
+ end
53
+ save
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,9 @@
1
+ module Purse
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper.rb'
2
+
3
+ class TestCli < Test::Unit::TestCase
4
+
5
+ context "Purse" do
6
+ context "Cli" do
7
+ context "run" do
8
+ setup do
9
+ HighLine.any_instance.stubs(:say)
10
+ @pocketname = 'test_purse_data'
11
+ end
12
+
13
+
14
+ # purse pursename #=> initialize or pull
15
+ context "purse pursename" do
16
+ should "call list" do
17
+ Cli.expects(:list).with(@pocketname).once
18
+ Cli.run([@pocketname])
19
+ end
20
+ end
21
+
22
+ # purse pursename notename
23
+ context "purse pursename notename" do
24
+
25
+ context "if the note exists" do
26
+ should "call init then call find and then display" do
27
+ notename = 'test123'
28
+ Cli.expects(:find).with(@pocketname,notename).once
29
+ Cli.run([@pocketname, notename])
30
+ end
31
+ end
32
+ end
33
+
34
+ # purse pursename notename --edit #=> open in EDITOR save and push
35
+ context "purse pursename notename --edit" do
36
+ should "call init edit" do
37
+ notename = 'jagger'
38
+ Cli.expects(:edit).with(@pocketname,notename).once
39
+ Cli.run([@pocketname, notename, '--edit'])
40
+ end
41
+ end
42
+
43
+ # purse pursename push
44
+ # purse pursename pull
45
+ # purse settings/ purse # rerun settings
46
+
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,206 @@
1
+ require 'test_helper.rb'
2
+
3
+ class TestNote < Test::Unit::TestCase
4
+
5
+ context "Purse" do
6
+ context "Note" do
7
+
8
+ context "an instance" do
9
+ setup do
10
+ @path = purse_path
11
+ @note = Note.new(@path, 'sander', 'Nonsense', :method => :blowfish, :store_as => :yaml)
12
+ end
13
+
14
+ context "new" do
15
+
16
+ should "require path" do
17
+ assert_raise(MissingParameter) do
18
+ Note.new(nil,'sander','Sander nonsense')
19
+ end
20
+ end
21
+
22
+ should "require name" do
23
+ assert_raise(MissingParameter) do
24
+ Note.new(purse_path, '', 'Sander nonsense')
25
+ end
26
+ end
27
+
28
+ context "initializing with regular data" do
29
+ should "set @path" do
30
+ assert_equal @path, @note.path
31
+ end
32
+
33
+ should "set @name" do
34
+ assert_equal 'sander', @note.name
35
+ end
36
+
37
+ should "set @data" do
38
+ assert_equal 'Nonsense', @note.data
39
+ end
40
+
41
+ should "save extra args as options" do
42
+ assert @note.options.is_a?(Hash)
43
+ assert_equal :blowfish, @note.options[:method]
44
+ end
45
+ end
46
+
47
+ context "initializing with encrypted data" do
48
+ setup do
49
+ @note = Note.new(purse_path, 'sander', 'ENCRYPTED DATA', :encrypted => true)
50
+ end
51
+
52
+ should "set @path" do
53
+ assert_equal purse_path, @note.path
54
+ end
55
+
56
+ should "set @name" do
57
+ assert_equal 'sander', @note.name
58
+ end
59
+
60
+ should "not set @data" do
61
+ assert_nil @note.data
62
+ end
63
+
64
+ should "set @encrypted" do
65
+ assert_equal 'ENCRYPTED DATA', @note.encrypted
66
+ end
67
+ end
68
+ end
69
+
70
+ context "file_name" do
71
+ should "return #name.note" do
72
+ assert_equal @note.name + '.note', @note.file_name
73
+ end
74
+ end
75
+
76
+ context "file_path" do
77
+ should "return path/name.note" do
78
+ assert_equal File.join(@note.path, @note.name + '.note'), @note.file_path
79
+ end
80
+ end
81
+
82
+ context "save" do
83
+
84
+ should "require password" do
85
+ assert_raise(MissingParameter) do
86
+ @note.save(nil)
87
+ end
88
+ end
89
+
90
+ context "with password" do
91
+ setup do
92
+ @password = '12345'
93
+ Crypt::Blowfish.any_instance.expects(:encrypt_string).with(@note.data).returns('ENCRYPTED DATA')
94
+ @note.save(@password)
95
+ end
96
+
97
+ should "encrypt data and place in @encrypted" do
98
+ assert_equal 'ENCRYPTED DATA', @note.encrypted
99
+ end
100
+
101
+ should "write to file in path with #name" do
102
+ assert File.readable?(@note.file_path)
103
+ assert_equal @note.encrypted, File.read(@note.file_path)
104
+ end
105
+
106
+ # teardown do
107
+ # File.unlink(purse_path, 'sander')
108
+ # end
109
+ end
110
+ end
111
+
112
+ context "encrypt" do
113
+ # blowfish = Crypt::Blowfish.new("A key up to 56 bytes long")
114
+ # plainBlock = "ABCD1234"
115
+ # encryptedBlock = blowfish.encrypt_block(plainBlock)
116
+ # decryptedBlock = blowfish.decrypt_block(encryptedBlock)
117
+
118
+ should "require password" do
119
+ assert_raise(MissingParameter) do
120
+ @note.encrypt(nil)
121
+ end
122
+ end
123
+
124
+ context "with password" do
125
+ setup do
126
+ @password = 'Test123'
127
+ Crypt::Blowfish.any_instance.expects(:encrypt_string).with(@note.data).returns('ENCRYPTED DATA')
128
+ @note.encrypt(@password)
129
+ end
130
+
131
+ should "save encrypted data to encrypted" do
132
+ assert_equal 'ENCRYPTED DATA', @note.encrypted
133
+ end
134
+ end
135
+ end
136
+
137
+ context "decrypt" do
138
+ setup do
139
+ @note = Note.new(purse_path, 'sander', 'ENCRYPTED DATA', :encrypted => true)
140
+ end
141
+
142
+ should "require password" do
143
+ assert_raise(MissingParameter) do
144
+ @note.decrypt(nil)
145
+ end
146
+ end
147
+
148
+ context "with password" do
149
+ setup do
150
+ @password = 'Test123'
151
+ Crypt::Blowfish.any_instance.expects(:decrypt_string).with(@note.encrypted).returns('Nonsense')
152
+ @note.decrypt(@password)
153
+ end
154
+
155
+ should "save decrypted data to @data" do
156
+ assert_equal 'Nonsense', @note.data
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ context "on the class" do
163
+ context "load" do
164
+
165
+ should "require path" do
166
+ assert_raise(MissingParameter) do
167
+ Note.load(nil, 'sander')
168
+ end
169
+ end
170
+
171
+ should "name" do
172
+ assert_raise(MissingParameter) do
173
+ Note.load(nil, 'sander')
174
+ end
175
+ end
176
+
177
+ should "raise error if file can not be found" do
178
+ assert_raise(MissingFile) do
179
+ Note.load(purse_path, "file_#{rand(5)}")
180
+ end
181
+ end
182
+
183
+ context "with a saved encrypted file" do
184
+ setup do
185
+ # Crypt::Blowfish.any_instance.expects(:decrypt_block).with('ENCRYPTED DATA').returns('Nonsense')
186
+ @note = Note.load(purse_path, 'sander')
187
+ end
188
+
189
+ should "return Note" do
190
+ assert @note.is_a?(Note)
191
+ end
192
+
193
+ should "set @encrypted" do
194
+ assert_equal 'ENCRYPTED DATA', @note.encrypted
195
+ end
196
+
197
+ should "not set @data" do
198
+ assert_nil @note.data
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ end